1 /*
2  * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3  *
4  */
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stdint.h>
9 #include <string.h>
10 #include <signal.h>
11 #include <errno.h>
12 
13 #include "uvoice_os.h"
14 #include "uvoice_types.h"
15 #include "uvoice_mlist.h"
16 
17 #include "uvoice_config.h"
18 
19 
20 #define SOURCE_LIST_INDEX_KEY		"mlist_index"
21 
22 
23 typedef struct {
24 	int count;
25 	int index;
26 	char source[128];
27 	os_mutex_t lock;
28 } mlist_t;
29 
30 static mlist_t *g_src_list;
31 
mlist_source_show(void)32 int mlist_source_show(void)
33 {
34 	mlist_t *src_list = g_src_list;
35 	char *listpath;
36 	os_file_t *list_fp;
37 	char file_name[128];
38 	int index = 0;
39 	char *ptr = NULL;
40 	int len;
41 
42 	if (!src_list) {
43 		M_LOGE("src_list null !\n");
44 		return -1;
45 	}
46 
47 	os_mutex_lock(src_list->lock, OS_WAIT_FOREVER);
48 
49 	len = strlen(PLAYER_SOURCE_LIST_DIR) +
50 		strlen(PLAYER_SOURCE_LIST_NAME) + 4;
51 	listpath = snd_zalloc(len, AFM_EXTN);
52 	if (!listpath) {
53 		M_LOGE("alloc list path failed !\n");
54 		os_mutex_unlock(src_list->lock);
55 		return -1;
56 	}
57 
58 	snprintf(listpath, len, "%s/%s",
59 		PLAYER_SOURCE_LIST_DIR, PLAYER_SOURCE_LIST_NAME);
60 
61 	list_fp = os_fopen(listpath, "r");
62 	if (!list_fp) {
63 		M_LOGE("list not found, please scan\n");
64 		snd_free(listpath);
65 		os_mutex_unlock(src_list->lock);
66 		return -1;
67 	}
68 
69 	while (!os_feof(list_fp)) {
70 		memset(file_name, 0, sizeof(file_name));
71 		os_fgets(file_name, sizeof(file_name), list_fp);
72 
73 		if (file_name[strlen(file_name) - 1] == '\n')
74 			file_name[strlen(file_name) - 1] = '\0';
75 
76 		ptr = strchr(file_name, '/');
77 		if (!ptr)
78 			continue;
79 
80 		ptr += 1;
81 		index = atoi(ptr);
82 
83 		ptr = strchr(ptr, '/');
84 		if (!ptr)
85 			continue;
86 
87 		ptr += 1;
88 		M_LOGI("No.%d %s\n", index, ptr);
89 	}
90 
91 	os_fclose(list_fp);
92 	snd_free(listpath);
93 	os_mutex_unlock(src_list->lock);
94 	return 0;
95 }
96 
mlist_source_scan(void)97 int mlist_source_scan(void)
98 {
99 	mlist_t *src_list = g_src_list;
100 	char *listpath;
101 	int listpath_len;
102 	os_file_t *list_fp;
103 	os_dir_t *dir;
104 	os_dirent_t *content = NULL;
105 	media_format_t format = MEDIA_FMT_UNKNOWN;
106 	int index = 0;
107 	bool curr_source_found = false;
108 	int ret;
109 
110 	if (!src_list) {
111 		M_LOGE("src_list null !\n");
112 		return -1;
113 	}
114 
115 	os_mutex_lock(src_list->lock, OS_WAIT_FOREVER);
116 
117 	ret = access(PLAYER_SOURCE_LIST_DIR, F_OK);
118 	if (ret) {
119 		ret = os_mkdir(PLAYER_SOURCE_LIST_DIR);
120 		if (ret) {
121 			M_LOGE("create %s failed %d!\n",
122 				PLAYER_SOURCE_LIST_DIR, ret);
123 			os_mutex_unlock(src_list->lock);
124 			return -1;
125 		}
126 		M_LOGD("create dir: %s\n", PLAYER_SOURCE_LIST_DIR);
127 	}
128 
129 	listpath_len = strlen(PLAYER_SOURCE_LIST_DIR) +
130 		strlen(PLAYER_SOURCE_LIST_NAME) + 2;
131 	listpath = snd_zalloc(listpath_len, AFM_EXTN);
132 	if (!listpath) {
133 		M_LOGE("alloc list path failed !\n");
134 		os_mutex_unlock(src_list->lock);
135 		return -1;
136 	}
137 
138 	snprintf(listpath, listpath_len, "%s/%s",
139 		PLAYER_SOURCE_LIST_DIR, PLAYER_SOURCE_LIST_NAME);
140 
141 	list_fp = os_fopen(listpath, "w+");
142 	if (!list_fp) {
143 		M_LOGE("open %s failed !\n", listpath);
144 		snd_free(listpath);
145 		os_mutex_unlock(src_list->lock);
146 		return -1;
147 	}
148 
149 	dir = os_opendir(PLAYER_SOURCE_LIST_DIR);
150 	if (!dir) {
151 		M_LOGE("open %s failed !\n", PLAYER_SOURCE_LIST_DIR);
152 		os_fclose(list_fp);
153 		snd_free(listpath);
154 		os_mutex_unlock(src_list->lock);
155 		return -1;
156 	}
157 
158 	while (1) {
159 		content = os_readdir(dir);
160 		if (!content)
161 			break;
162 
163 #ifdef __os_alios_things__
164 		if (content->d_type & (AM_DIR | AM_HID | AM_ARC | AM_SYS))
165 			continue;
166 #else
167 		if (!(content->d_type & (DT_REG)))
168 			continue;
169 #endif
170 
171 		format = MEDIA_FMT_UNKNOWN;
172 		format_parse_byname(content->d_name, &format);
173 		if (format == MEDIA_FMT_UNKNOWN)
174 			continue;
175 
176 		if (strlen(content->d_name) + strlen("fs:") +
177 				strlen(PLAYER_SOURCE_LIST_DIR) > 126)
178 			continue;
179 
180 		index++;
181 		if (os_fprintf(list_fp, "/%d/%s\n", index, content->d_name) < 0) {
182 			M_LOGE("write list failed !\n");
183 			index--;
184 			continue;
185 		}
186 
187 		if (src_list->index > 0) {
188 
189 			if (strlen(src_list->source) <=
190 				(strlen("fs:") + strlen(PLAYER_SOURCE_LIST_DIR) + 1)) {
191 				M_LOGE("source name invalid\n");
192 				continue;
193 			}
194 
195 			if (!strncmp(content->d_name, (char *)src_list->source +
196 				strlen("fs:") + strlen(PLAYER_SOURCE_LIST_DIR) + 1,
197 				strlen(content->d_name))) {
198 				curr_source_found = true;
199 				if (src_list->index != index) {
200 					M_LOGI("update index %d\n", index);
201 					src_list->index = index;
202 					ret = os_kv_set(SOURCE_LIST_INDEX_KEY,
203 							&src_list->index,
204 							sizeof(src_list->index), 0);
205 					if (ret) {
206 						M_LOGW("kv set failed %d!\n", ret);
207 						ret = -1;
208 						goto __exit;
209 					}
210 				}
211 			}
212 		}
213 
214 		//M_LOGD("No.%d %s\n", index, content->d_name);
215 	}
216 
217 	if (src_list->count != index)
218 		src_list->count = index;
219 	M_LOGD("list count %d\n", src_list->count);
220 
221 __exit:
222 	os_closedir(dir);
223 	os_fclose(list_fp);
224 	snd_free(listpath);
225 
226 	if (!curr_source_found && src_list->index > 0) {
227 		M_LOGD("set default index\n");
228 		src_list->index = 0;
229 		os_mutex_unlock(src_list->lock);
230 		if (mlist_index_set(1)) {
231 			M_LOGE("set index failed !\n");
232 			ret = -1;
233 		}
234 	} else {
235 		os_mutex_unlock(src_list->lock);
236 	}
237 
238 	return ret;
239 }
240 
mlist_source_get(int index,char * path,int len)241 int mlist_source_get(int index, char *path, int len)
242 {
243 	mlist_t *src_list = g_src_list;
244 	char file_name[128];
245 	int listpath_len;
246 	char *listpath;
247 	os_file_t *list_fp;
248 	char *ptr = NULL;
249 	int file_index = 0;
250 	int ret = -1;
251 
252 	if (!src_list) {
253 		M_LOGE("src_list null !\n");
254 		return -1;
255 	}
256 
257 	if (!path) {
258 		M_LOGE("path null !\n");
259 		return -1;
260 	}
261 
262 	if (len < 0) {
263 		M_LOGE("len %d invalid!\n", len);
264 		return -1;
265 	}
266 
267 	os_mutex_lock(src_list->lock, OS_WAIT_FOREVER);
268 
269 	if (index <= 0 || index > src_list->count) {
270 		M_LOGE("index %d count %d\n",
271 			index, src_list->count);
272 		os_mutex_unlock(src_list->lock);
273 		return -1;
274 	}
275 
276 	listpath_len = strlen(PLAYER_SOURCE_LIST_DIR) +
277 		strlen(PLAYER_SOURCE_LIST_NAME) + 4;
278 	listpath = snd_zalloc(listpath_len, AFM_EXTN);
279 	if (!listpath) {
280 		M_LOGE("alloc list path failed !\n");
281 		os_mutex_unlock(src_list->lock);
282 		return -1;
283 	}
284 
285 	snprintf(listpath, listpath_len, "%s/%s",
286 		PLAYER_SOURCE_LIST_DIR, PLAYER_SOURCE_LIST_NAME);
287 
288 	list_fp = os_fopen(listpath, "r");
289 	if (!list_fp) {
290 		M_LOGE("open %s failed !\n", listpath);
291 		snd_free(listpath);
292 		os_mutex_unlock(src_list->lock);
293 		return -1;
294 	}
295 
296 	while (!os_feof(list_fp)) {
297 		memset(file_name, 0, sizeof(file_name));
298 		os_fgets(file_name, sizeof(file_name), list_fp);
299 
300 		if (file_name[strlen(file_name) - 1] == '\n')
301 			file_name[strlen(file_name) - 1] = '\0';
302 
303 		ptr = strchr(file_name, '/');
304 		if (!ptr)
305 			continue;
306 		ptr += 1;
307 
308 		file_index = atoi(ptr);
309 		if (file_index <= 0)
310 			continue;
311 
312 		//M_LOGD("index %d, name: %s\n", file_index, file_name);
313 
314 		if (file_index == index) {
315 
316 			ptr = strchr(ptr, '/');
317 			if (!ptr)
318 				continue;
319 			ptr += 1;
320 
321 			if (strchr(ptr, '/'))
322 				continue;
323 
324 			if (strlen(ptr) + strlen("fs:") +
325 					strlen(PLAYER_SOURCE_LIST_DIR) + 2 > len) {
326 				M_LOGE("name %s length %d too long !\n",
327 					ptr, strlen(ptr));
328 				ret = -1;
329 				break;
330 			}
331 
332 			snprintf(path, len, "fs:%s/%s",
333 					PLAYER_SOURCE_LIST_DIR, ptr);
334 			//M_LOGD("found /%d/%s\n", index, path);
335 
336 			ret = 0;
337 			break;
338 		}
339 	}
340 
341 	os_fclose(list_fp);
342 	snd_free(listpath);
343 
344 	os_mutex_unlock(src_list->lock);
345 	return ret;
346 }
347 
mlist_source_del(int index)348 int mlist_source_del(int index)
349 {
350 	mlist_t *src_list = g_src_list;
351 	char file_path[128];
352 	int ret = 0;
353 
354 	if (!src_list) {
355 		M_LOGE("src_list null !\n");
356 		return -1;
357 	}
358 
359 	memset(file_path, 0, sizeof(file_path));
360 
361 	if (mlist_source_get(index, file_path, sizeof(file_path))) {
362 		M_LOGE("get source name failed !\n");
363 		return -1;
364 	}
365 
366 	if (strncmp(file_path, "fs:", strlen("fs:"))) {
367 		M_LOGE("source path invalid !\n");
368 		return -1;
369 	}
370 
371 	if (unlink((char *)file_path + strlen("fs:"))) {
372 		M_LOGE("delete %s failed !\n", file_path);
373 		return -1;
374 	}
375 
376 	os_mutex_lock(src_list->lock, OS_WAIT_FOREVER);
377 
378 	if (src_list->index == index && index != 1) {
379 		M_LOGD("set default index\n");
380 		src_list->index = 1;
381 		ret = os_kv_set(SOURCE_LIST_INDEX_KEY,
382 			&src_list->index,
383 			sizeof(src_list->index), 0);
384 		if (ret) {
385 			M_LOGE("kv set failed %d!\n", ret);
386 			os_mutex_unlock(src_list->lock);
387 			return -1;
388 		}
389 
390 		memset(src_list->source, 0, sizeof(src_list->source));
391 		os_mutex_unlock(src_list->lock);
392 		if (mlist_source_get(src_list->index,
393 				src_list->source,
394 				sizeof(src_list->source))) {
395 			M_LOGE("get source name failed !\n");
396 			return -1;
397 		}
398 	} else {
399 		os_mutex_unlock(src_list->lock);
400 	}
401 
402 	if (mlist_source_scan()) {
403 		M_LOGE("scan source failed !\n");
404 		return -1;
405 	}
406 
407 	M_LOGI("%s delete\n", file_path);
408 	return 0;
409 }
410 
mlist_index_get(int * index)411 int mlist_index_get(int *index)
412 {
413 	mlist_t *src_list = g_src_list;
414 	int kv_len;
415 	int ret = 0;
416 
417 	if (!src_list) {
418 		M_LOGE("src_list null !\n");
419 		return -1;
420 	}
421 
422 	os_mutex_lock(src_list->lock, OS_WAIT_FOREVER);
423 
424 	kv_len = sizeof(src_list->index);
425 
426 	if (src_list->index == 0) {
427 		ret = os_kv_get(SOURCE_LIST_INDEX_KEY,
428 			&src_list->index, &kv_len);
429 		os_mutex_unlock(src_list->lock);
430 		if (ret == -ENOENT) {
431 			M_LOGD("set default index\n");
432 			if (mlist_index_set(1)) {
433 				M_LOGE("set source index failed !\n");
434 				return -1;
435 			}
436 		} else if (ret) {
437 			M_LOGE("kv get failed %d!\n", ret);
438 			return -1;
439 		}
440 	} else {
441 		os_mutex_unlock(src_list->lock);
442 	}
443 
444 	if (strlen(src_list->source) <= 0) {
445 		if (mlist_source_get(src_list->index,
446 				src_list->source, sizeof(src_list->source))) {
447 			M_LOGE("get source name failed !\n");
448 			return -1;
449 		}
450 	}
451 
452 	*index = src_list->index;
453 	M_LOGD("No.%d %s\n", *index,
454 		(char *)src_list->source + strlen("fs:") +
455 		strlen(PLAYER_SOURCE_LIST_DIR) + 1);
456 
457 	return 0;
458 }
459 
mlist_index_set(int index)460 int mlist_index_set(int index)
461 {
462 	mlist_t *src_list = g_src_list;
463 	int kv_len;
464 	int ret = 0;
465 
466 	if (!src_list) {
467 		M_LOGE("src_list null !\n");
468 		return -1;
469 	}
470 
471 	os_mutex_lock(src_list->lock, OS_WAIT_FOREVER);
472 
473 	kv_len = sizeof(src_list->index);
474 
475 	if (src_list->index != index) {
476 		src_list->index = index;
477 		ret = os_kv_set(SOURCE_LIST_INDEX_KEY,
478 				&src_list->index,
479 				sizeof(src_list->index), 0);
480 		if (ret) {
481 			M_LOGE("kv set failed %d!\n", ret);
482 			os_mutex_unlock(src_list->lock);
483 			return -1;
484 		}
485 
486 		M_LOGI("update source index %d\n", src_list->index);
487 
488 		os_mutex_unlock(src_list->lock);
489 
490 		memset(src_list->source, 0, sizeof(src_list->source));
491 		if (mlist_source_get(index, src_list->source,
492 				sizeof(src_list->source))) {
493 			M_LOGE("get source name failed !\n");
494 			return -1;
495 		}
496 	} else {
497 		os_mutex_unlock(src_list->lock);
498 	}
499 
500 	return 0;
501 }
502 
mlist_init(void)503 int mlist_init(void)
504 {
505 	mlist_t *src_list;
506 	int index = 0;
507 
508 	src_list = snd_zalloc(sizeof(mlist_t), AFM_EXTN);
509 	if (!src_list) {
510 		M_LOGE("alloc src list failed !\n");
511 		return -1;
512 	}
513 
514 	src_list->lock = os_mutex_new();
515 
516 	g_src_list = src_list;
517 
518 	if (mlist_source_scan()) {
519 		M_LOGE("scan source failed !\n");
520 		return -1;
521 	}
522 
523 	if (mlist_index_get(&index)) {
524 		M_LOGE("get source index failed !\n");
525 		return -1;
526 	}
527 
528 	M_LOGD("mlist init\n");
529 	return 0;
530 }
531 
mlist_deinit(void)532 int mlist_deinit(void)
533 {
534 	mlist_t *src_list = g_src_list;
535 	if (!src_list) {
536 		M_LOGE("src_list null !\n");
537 		return -1;
538 	}
539 
540 	os_mutex_free(src_list->lock);
541 	snd_free(src_list);
542 	g_src_list = NULL;
543 
544 	M_LOGD("mlist free\n");
545 	return 0;
546 }
547 
548