[audio] Fix 'Uninitialized pointer field' defect on test code
[platform/core/multimedia/mm-hal-interface.git] / testcase / audio / parser.cpp
1 #include <iostream>
2 #include <json.h>
3 #include <assert.h>
4 #include <string.h>
5 #include <string>
6
7 #include "parser.hh"
8
9 #define DEVICE_FILE_OBJECT                  "device-files"
10 #define DEVICE_TYPE_PROP_PLAYBACK_DEVICES   "playback-devices"
11 #define DEVICE_TYPE_PROP_CAPTURE_DEVICES    "capture-devices"
12 #define DEVICE_TYPE_PROP_DEVICE_STRING      "device-string"
13 #define DEVICE_TYPE_PROP_ROLE               "role"
14
15 /* device-files example
16         device-files : {
17                 playback-devices : [
18                         {
19                                 device-string : alsa:sprdphone,0,
20                                 role : { normal : rate=44100 }
21                         }
22                         {
23                                 device-string : alsa:VIRTUALAUDIOW,0,
24                                 role : { call-voice : rate=16000 channels=1 tsched=0 alternate_rate=16000 }
25                         }
26                 ]
27                 capture-devices : [
28                         {
29                                 device-string : alsa:sprdphone,0,
30                                 role : { normal : rate=44100 }
31                         }
32                 ]
33         }
34 */
35
36 using namespace std;
37
38 CDeviceMapParser::CDeviceMapParser()
39         : m_json_obj(nullptr), m_json_device_files_obj(nullptr)
40 {
41         open_json("/etc/pulse/device-map.json");
42 }
43
44 CDeviceMapParser::CDeviceMapParser(const char* map_file)
45         : m_json_obj(nullptr), m_json_device_files_obj(nullptr)
46 {
47         open_json(map_file);
48 }
49
50 CDeviceMapParser::~CDeviceMapParser()
51 {
52         close_json();
53 }
54
55 void CDeviceMapParser::open_json(const char* json_file)
56 {
57         m_json_obj = json_object_from_file(json_file);
58         if (!m_json_obj) {
59                 cout << "Read device-map " << json_file << " failed" << endl;
60                 return;
61         }
62
63         if (!json_object_object_get_ex(m_json_obj, DEVICE_FILE_OBJECT, &m_json_device_files_obj)) {
64                 cout << "Get device files object failed" << endl;
65                 return;
66         }
67         if (!json_object_is_type(m_json_device_files_obj, json_type_object)) {
68                 cout << "json object type failed" << endl;
69                 json_object_put(m_json_obj);
70                 m_json_obj = nullptr;
71                 return;
72         }
73
74         cout << DEVICE_FILE_OBJECT << " : {" << endl;
75 }
76
77 void CDeviceMapParser::close_json()
78 {
79         if (!m_json_obj)
80                 return;
81
82         json_object_put(m_json_obj);
83
84         cout << "}" << endl;
85 }
86
87 void CDeviceMapParser::parse_playback()
88 {
89         json_object *playback_devices_o = nullptr;
90
91         if (!json_object_object_get_ex(m_json_device_files_obj, DEVICE_TYPE_PROP_PLAYBACK_DEVICES, &playback_devices_o)) {
92                 cout << "failed to get playback" << endl;
93                 return;
94         }
95
96         cout << "  " << DEVICE_TYPE_PROP_PLAYBACK_DEVICES << " : ["  << endl;
97         parse_device_file_array_object(playback_devices_o, m_playback);
98         cout << "  ]" << endl;
99 }
100
101 void CDeviceMapParser::parse_capture()
102 {
103         json_object *capture_devices_o = nullptr;
104
105         if (!json_object_object_get_ex(m_json_device_files_obj, DEVICE_TYPE_PROP_CAPTURE_DEVICES, &capture_devices_o)) {
106                 cout << "failed to get capture" << endl;
107                 return;
108         }
109
110         cout << "  " << DEVICE_TYPE_PROP_CAPTURE_DEVICES << " : ["  << endl;
111         parse_device_file_array_object(capture_devices_o, m_capture);
112         cout << "  ]" << endl;
113 }
114
115 void CDeviceMapParser::get_device(string& s, string& card, string& device_num)
116 {
117         // eg. alsa:0,0
118         string delimiter = ",";
119         string s1(s.substr(s.find_last_of(':') + 1));
120
121         // eg. 0,0
122         size_t pos = s1.find(delimiter);
123         string token(s1.substr(0, pos));
124         s1.erase(0, pos + delimiter.length());
125
126         card.assign(token);
127         device_num.assign(s1);
128 }
129
130 void CDeviceMapParser::get_single_param(string& s, int& rate, int& channels)
131 {
132         // eg. rate=44100
133         string delimiter = "=";
134         size_t pos = s.find(delimiter);
135         string token = s.substr(0, pos);
136         s.erase(0, pos + delimiter.length());
137
138         if (token.compare("rate") == 0)
139                 rate = stoi(s);
140         else if (token.compare("channels") == 0)
141                 channels = stoi(s);
142 }
143
144 void CDeviceMapParser::get_params(string& s, int& rate, int& channels)
145 {
146         // eg. rate=44100 channels=1
147         string delimiter = " ";
148         size_t pos = 0;
149         string token;
150         string s1(s);
151
152         while ((pos = s1.find(delimiter)) != string::npos) {
153                 token = s1.substr(0, pos);
154                 get_single_param(token, rate, channels);
155                 s1.erase(0, pos + delimiter.length());
156         }
157         get_single_param(s1, rate, channels);
158 }
159
160
161 void CDeviceMapParser::dump_devices()
162 {
163         string card, device_num;
164         int rate = -1, channels = -1;
165
166         get_playback(card, device_num, rate, channels);
167         get_capture(card, device_num, rate, channels);
168 }
169
170 void CDeviceMapParser::get_playback(string& card, string& device_num, int& rate, int& channels)
171 {
172         parse_playback();
173
174         get_device(m_playback.first, card, device_num);
175         get_params(m_playback.second, rate, channels);
176         cout << "  1. PLAYBACK" << endl;
177         cout << "     > card=" << card << ", device=" << device_num << endl;
178         cout << "     > rate=" << rate << ", channels=" << channels << endl << endl;
179 }
180
181 void CDeviceMapParser::get_capture(string& card, string& device_num, int& rate, int& channels)
182 {
183         parse_capture();
184
185         get_device(m_capture.first, card, device_num);
186         get_params(m_capture.second, rate, channels);
187         cout << "  2. CAPTURE" << endl;
188         cout << "     > card=" << card << ", device=" << device_num << endl;
189         cout << "     > rate=" << rate << ", channels=" << channels << endl;
190 }
191
192 void CDeviceMapParser::parse_device_string_object(json_object *device_string_o, string& device_string)
193 {
194         assert(device_string_o);
195         assert(json_object_is_type(device_string_o, json_type_string));
196
197         // object example
198         //   device-string : alsa:sprdphone,0,
199
200         device_string.assign(json_object_get_string(device_string_o));
201
202         cout << "      " << DEVICE_TYPE_PROP_DEVICE_STRING << " : " << device_string << "," << endl;
203 }
204
205 void CDeviceMapParser::parse_device_role_object(json_object *device_role_o, string& device_params)
206 {
207         struct json_object_iterator it, it_end;
208
209         assert(device_role_o);
210         assert(json_object_is_type(device_role_o, json_type_object));
211
212         // <object example>
213         //   role : { normal : rate=44100 }
214
215         it = json_object_iter_begin(device_role_o);
216         it_end = json_object_iter_end(device_role_o);
217
218         while (!json_object_iter_equal(&it, &it_end)) {
219                 if (strcmp(json_object_iter_peek_name(&it), "normal") == 0) {
220                         device_params.assign(json_object_get_string(json_object_iter_peek_value(&it)));
221                         cout << "      " << DEVICE_TYPE_PROP_ROLE << " : {  normal : " << device_params << " }" << endl;
222                         break;
223                 }
224
225                 json_object_iter_next(&it);
226         }
227 }
228
229 void CDeviceMapParser::parse_device_file_object(json_object *device_file_o, pair<string, string>& device)
230 {
231         json_object *device_file_prop_o = nullptr;
232         string device_string, device_param;
233
234         assert(device_file_o);
235         assert(json_object_is_type(device_file_o, json_type_object));
236
237         // <object example>
238         //      device-string : alsa:sprdphone,0,
239         //      role : { normal : rate=44100 }
240
241         // parse role
242         if (!json_object_object_get_ex(device_file_o, DEVICE_TYPE_PROP_ROLE, &device_file_prop_o)) {
243                 cout << "Get device role object failed" << endl;
244                 return;
245         }
246         parse_device_role_object(device_file_prop_o, device_param);
247
248         if (device_param.empty()) {
249                 cout << "      " << "[E] This is not a normal device..skip" << endl;
250                 return;
251         }
252
253         // parse device-string
254         if (!json_object_object_get_ex(device_file_o, DEVICE_TYPE_PROP_DEVICE_STRING, &device_file_prop_o)) {
255                 cout << "Get device-string object failed" << endl;
256                 return;
257         }
258         parse_device_string_object(device_file_prop_o, device_string);
259
260         // store device information
261         device = make_pair(device_string, device_param);
262 }
263
264 void CDeviceMapParser::parse_device_file_array_object(json_object *device_file_array_o, pair<string, string>& device)
265 {
266         int num, idx;
267         json_object *device_file_o = nullptr;
268
269         assert(device_file_array_o);
270         assert(json_object_is_type(device_file_array_o, json_type_array));
271
272         // <object example>
273         //  {
274         //        device-string : alsa:sprdphone,0,
275         //        role : { normal : rate=44100 }
276         //  }
277
278         // ToDo : this might be replaced with iterator such as foreach?
279         num = json_object_array_length(device_file_array_o);
280         for (idx = 0; idx < num; idx++) {
281                 if (!(device_file_o = json_object_array_get_idx(device_file_array_o, idx))) {
282                         cout << "Get device file object failed" << endl;
283                         return;
284                 }
285
286                 cout << "    {" << endl;
287                 parse_device_file_object(device_file_o, device);
288                 cout << "    }" << endl;
289         }
290 }