player_ui.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. #include <rtgui/rtgui.h>
  2. #include <rtgui/image.h>
  3. #include <rtgui/rtgui_system.h>
  4. #include <rtgui/widgets/view.h>
  5. #include <rtgui/widgets/workbench.h>
  6. #include <string.h>
  7. #include <dfs_posix.h>
  8. #include "player_ui.h"
  9. #include "player_bg.h"
  10. #include "play_list.h"
  11. #include "listview.h"
  12. #include "filelist.h"
  13. #include "play.hdh"
  14. #include "stop.hdh"
  15. static rtgui_image_t *background = RT_NULL;
  16. static struct rtgui_view* function_view;
  17. static struct rtgui_view* home_view;
  18. static struct rtgui_workbench* workbench;
  19. static rtgui_timer_t* info_timer;
  20. static rt_thread_t player_ui_tid = RT_NULL;
  21. static enum PLAYER_MODE player_mode = PLAYER_STOP;
  22. static enum PLAYER_STEP next_step = PLAYER_STEP_STOP;
  23. static struct tag_info tinfo;
  24. void player_set_position(rt_uint32_t position)
  25. {
  26. tinfo.position = position / (tinfo.bit_rate / 8);
  27. }
  28. void info_timer_timeout(rtgui_timer_t* timer, void* parameter)
  29. {
  30. struct rtgui_dc* dc;
  31. rtgui_color_t saved;
  32. dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(home_view));
  33. if (dc == RT_NULL) return ;
  34. saved = RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(home_view));
  35. RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(home_view)) = RTGUI_RGB(206, 231, 255);
  36. rtgui_dc_draw_hline(dc, 14, 14 + (tinfo.position * 212)/ tinfo.duration,
  37. 75);
  38. RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(home_view)) = saved;
  39. rtgui_dc_end_drawing(dc);
  40. }
  41. rt_uint32_t read_line(int fd, char* line, rt_uint32_t line_size)
  42. {
  43. char *pos, *next;
  44. rt_uint32_t length;
  45. length = read(fd, line, line_size);
  46. if (length > 0)
  47. {
  48. pos = strstr(line, "\r\n");
  49. if (pos == RT_NULL)
  50. {
  51. pos = strstr(line, "\n");
  52. next = pos ++;
  53. }
  54. else next = pos + 2;
  55. if (pos != RT_NULL)
  56. {
  57. *pos = '\0';
  58. /* move back */
  59. lseek(fd, -(length - (next - line)), SEEK_CUR);
  60. length = pos - line;
  61. }
  62. else length = 0;
  63. }
  64. rt_kprintf("line %s\n", line);
  65. return length;
  66. }
  67. static void player_update_tag_info(struct rtgui_dc* dc)
  68. {
  69. rtgui_rect_t rect;
  70. char line[32];
  71. rtgui_color_t saved;
  72. saved = rtgui_dc_get_color(dc);
  73. rtgui_dc_set_color(dc, black);
  74. rect.x1 = 0; rect.y1 = 0;
  75. rect.x2 = 240; rect.y2 = 65;
  76. /* draw background */
  77. background = rtgui_image_create_from_file("hdc",
  78. "/resource/bg.hdc", RT_FALSE);
  79. if (background != RT_NULL)
  80. {
  81. rtgui_image_blit(background, dc, &rect);
  82. rtgui_image_destroy(background);
  83. background = RT_NULL;
  84. }
  85. else
  86. {
  87. rtgui_dc_fill_rect(dc, &rect);
  88. }
  89. /* draw playing information */
  90. rect.x1 = 28; rect.y1 = 12;
  91. rect.x2 = 220; rect.y2 = rect.y1 + 16;
  92. if (player_mode == PLAYER_STOP)
  93. {
  94. rt_snprintf(line, sizeof(line),
  95. "网络收音机");
  96. rtgui_dc_draw_text(dc, line, &rect);
  97. }
  98. else
  99. rtgui_dc_draw_text(dc, tinfo.title, &rect);
  100. rect.x1 = 28; rect.y1 = 39;
  101. rect.x2 = 220; rect.y2 = 59;
  102. if (player_mode == PLAYER_STOP)
  103. {
  104. rt_snprintf(line, sizeof(line),
  105. "radio.rt-thread.org");
  106. rtgui_dc_draw_text(dc, line, &rect);
  107. }
  108. else
  109. rtgui_dc_draw_text(dc, tinfo.artist, &rect);
  110. if ((tinfo.duration != 0) && player_mode != PLAYER_STOP)
  111. {
  112. rect.x1 = rect.x2 - 64;
  113. rt_snprintf(line, sizeof(line), "%02d:%02d:%02d",
  114. tinfo.duration / 360, tinfo.duration / 60, tinfo.duration % 60);
  115. rtgui_dc_draw_text(dc, line, &rect);
  116. }
  117. rtgui_dc_set_color(dc, saved);
  118. }
  119. void play_mp3_file(const char* fn)
  120. {
  121. struct rtgui_dc* dc;
  122. /* get music tag information */
  123. mp3_get_info(fn, &tinfo);
  124. if (tinfo.title[0] == '\0')
  125. rt_snprintf(tinfo.title, sizeof(tinfo.title), "<未知名音乐>");
  126. /* set player mode */
  127. player_mode = PLAYER_PLAY_FILE;
  128. dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(home_view));
  129. if (dc != RT_NULL)
  130. {
  131. rtgui_rect_t play_rect;
  132. rtgui_image_t *button;
  133. /* update tag information */
  134. player_update_tag_info(dc);
  135. /* update play button */
  136. button = rtgui_image_create_from_mem("hdc",
  137. play_hdh, sizeof(play_hdh), RT_FALSE);
  138. play_rect.x1 = 32; play_rect.y1 = 92;
  139. play_rect.x2 = 61; play_rect.y2 = 114;
  140. rtgui_image_blit(button, dc, &play_rect);
  141. rtgui_image_destroy(button);
  142. rtgui_dc_end_drawing(dc);
  143. }
  144. rtgui_view_show(home_view, RT_FALSE);
  145. rt_kprintf("play file: %s\n", fn);
  146. player_play_file(fn);
  147. }
  148. void function_filelist(void* parameter)
  149. {
  150. rtgui_rect_t rect;
  151. filelist_view_t *view;
  152. rtgui_widget_get_rect(RTGUI_WIDGET(workbench), &rect);
  153. view = filelist_view_create(workbench, "/", "*.*", &rect);
  154. if (view != RT_NULL)
  155. {
  156. if (rtgui_view_show(RTGUI_VIEW(view), RT_TRUE) == RTGUI_MODAL_OK)
  157. {
  158. char fn[64];
  159. /* get open file */
  160. rt_snprintf(fn, 64, "%s/%s", view->current_directory,
  161. view->items[view->current_item].name);
  162. if (strstr(view->items[view->current_item].name , ".mp3") != RT_NULL ||
  163. strstr(view->items[view->current_item].name , ".MP3") != RT_NULL)
  164. {
  165. /* clear old play list */
  166. play_list_clear();
  167. play_list_append(fn);
  168. player_mode = PLAYER_PLAY_FILE;
  169. next_step = PLAYER_STEP_STOP;
  170. play_mp3_file(play_list_start());
  171. }
  172. else if (strstr(view->items[view->current_item].name , ".m3u") != RT_NULL ||
  173. strstr(view->items[view->current_item].name , ".M3U") != RT_NULL)
  174. {
  175. /* read all of music filename to a list */
  176. int fd;
  177. char line[64];
  178. fd = open(fn, O_RDONLY, 0);
  179. if (fd >= 0)
  180. {
  181. rt_uint32_t length;
  182. length = read_line(fd, line, sizeof(line));
  183. if (strcmp(line, "#EXTM3U") == 0)
  184. {
  185. /* clear old play list */
  186. play_list_clear();
  187. do
  188. {
  189. length = read_line(fd, line, sizeof(line));
  190. if (length > 0)
  191. {
  192. if (line[0] != '/')
  193. {
  194. rt_snprintf(fn, sizeof(fn),
  195. "%s/%s", view->current_directory, line);
  196. play_list_append(fn);
  197. }
  198. else play_list_append(line);
  199. }
  200. } while (length > 0);
  201. }
  202. close(fd);
  203. if (play_list_items() > 0)
  204. {
  205. player_mode = PLAYER_PLAY_FILE;
  206. next_step = PLAYER_STEP_NEXT;
  207. play_mp3_file(play_list_start());
  208. }
  209. }
  210. }
  211. else if (strstr(view->items[view->current_item].name , ".wav") != RT_NULL ||
  212. strstr(view->items[view->current_item].name , ".WAV") != RT_NULL)
  213. {
  214. }
  215. }
  216. /* destroy view */
  217. filelist_view_destroy(view);
  218. }
  219. return;
  220. }
  221. void function_device(void* parameter)
  222. {
  223. rtgui_view_t *view;
  224. extern rtgui_view_t* device_view_create(rtgui_workbench_t* workbench);
  225. view = device_view_create(workbench);
  226. if (view != RT_NULL)
  227. {
  228. rtgui_view_show(view, RT_FALSE);
  229. }
  230. return;
  231. }
  232. void function_player(void* parameter)
  233. {
  234. rtgui_view_show(home_view, RT_FALSE);
  235. return;
  236. }
  237. void function_action(void* parameter)
  238. {
  239. rt_kprintf("item action!\n");
  240. return;
  241. }
  242. struct list_item function_list[] =
  243. {
  244. {"选择电台", RT_NULL, function_action, RT_NULL},
  245. {"更新电台", RT_NULL, function_action, RT_NULL},
  246. {"播放文件", RT_NULL, function_filelist, RT_NULL},
  247. {"设备信息", RT_NULL, function_device, RT_NULL},
  248. {"选项设置", RT_NULL, function_action, RT_NULL},
  249. {"返回播放器", RT_NULL, function_player, RT_NULL},
  250. };
  251. static rt_bool_t home_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
  252. {
  253. if (event->type == RTGUI_EVENT_PAINT)
  254. {
  255. struct rtgui_dc* dc;
  256. struct rtgui_rect rect;
  257. rtgui_color_t saved;
  258. dc = rtgui_dc_begin_drawing(widget);
  259. if (dc == RT_NULL) return RT_FALSE;
  260. rtgui_widget_get_rect(widget, &rect);
  261. saved = RTGUI_WIDGET_FOREGROUND(widget);
  262. /* draw background */
  263. background = rtgui_image_create_from_file("hdc",
  264. "/resource/bg.hdc", RT_FALSE);
  265. if (background != RT_NULL)
  266. {
  267. rtgui_image_t *play;
  268. rtgui_rect_t play_rect;
  269. rtgui_image_blit(background, dc, &rect);
  270. rtgui_image_destroy(background);
  271. background = RT_NULL;
  272. if (player_mode == PLAYER_STOP)
  273. play = rtgui_image_create_from_mem("hdc",
  274. stop_hdh, sizeof(stop_hdh), RT_FALSE);
  275. else
  276. play = rtgui_image_create_from_mem("hdc",
  277. play_hdh, sizeof(play_hdh), RT_FALSE);
  278. play_rect.x1 = 32; play_rect.y1 = 92;
  279. play_rect.x2 = 61; play_rect.y2 = 114;
  280. rtgui_image_blit(play, dc, &play_rect);
  281. rtgui_image_destroy(play);
  282. }
  283. else
  284. {
  285. rtgui_dc_fill_rect(dc, &rect);
  286. }
  287. /* draw playing information */
  288. rtgui_dc_set_color(dc, black);
  289. {
  290. char line[32];
  291. rect.x1 = 28; rect.y1 = 12;
  292. rect.x2 = 220; rect.y2 = rect.y1 + 16;
  293. if (player_mode == PLAYER_STOP)
  294. {
  295. rt_snprintf(line, sizeof(line),
  296. "网络收音机");
  297. rtgui_dc_draw_text(dc, line, &rect);
  298. }
  299. else
  300. rtgui_dc_draw_text(dc, tinfo.title, &rect);
  301. rect.x1 = 28; rect.y1 = 39;
  302. rect.x2 = 220; rect.y2 = 59;
  303. if (player_mode == PLAYER_STOP)
  304. {
  305. rt_snprintf(line, sizeof(line),
  306. "radio.rt-thread.org");
  307. rtgui_dc_draw_text(dc, line, &rect);
  308. }
  309. else
  310. rtgui_dc_draw_text(dc, tinfo.artist, &rect);
  311. if (tinfo.duration != 0)
  312. {
  313. rect.x1 = rect.x2 - 64;
  314. rt_snprintf(line, sizeof(line), "%02d:%02d:%02d",
  315. tinfo.duration / 360, tinfo.duration / 60, tinfo.duration % 60);
  316. rtgui_dc_draw_text(dc, line, &rect);
  317. }
  318. }
  319. RTGUI_WIDGET_FOREGROUND(widget) = RTGUI_RGB(82, 199, 16);
  320. rtgui_dc_draw_hline(dc, 14, 226, 75);
  321. RTGUI_WIDGET_FOREGROUND(widget) = saved;
  322. if (player_mode == PLAYER_PLAY_FILE)
  323. {
  324. char line[32];
  325. rt_uint32_t index;
  326. struct play_item* item;
  327. rect.x1 = 20; rect.y1 = 150;
  328. rect.x2 = 220; rect.y2 = 168;
  329. for (index = 0; index < play_list_items() && index < 8; index ++)
  330. {
  331. item = play_list_item(index);
  332. rtgui_dc_draw_text(dc, item->title, &rect);
  333. rect.x1 = rect.x2 - 64;
  334. rt_snprintf(line, sizeof(line), "%02d:%02d:%02d",
  335. item->duration / 360,
  336. item->duration / 60,
  337. item->duration % 60);
  338. rtgui_dc_draw_text(dc, line, &rect);
  339. /* move to next item */
  340. rect.x1 = 20;
  341. rect.y1 += 18; rect.y2 += 18;
  342. }
  343. }
  344. rtgui_dc_end_drawing(dc);
  345. return RT_FALSE;
  346. }
  347. else if (event->type == RTGUI_EVENT_KBD)
  348. {
  349. struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event;
  350. if (ekbd->type == RTGUI_KEYDOWN)
  351. {
  352. switch (ekbd->key)
  353. {
  354. case RTGUIK_RIGHT:
  355. if (player_mode == PLAYER_PLAY_FILE && play_list_items() > 0)
  356. {
  357. player_stop();
  358. next_step = PLAYER_STEP_NEXT;
  359. }
  360. break;
  361. case RTGUIK_LEFT:
  362. if (player_mode == PLAYER_PLAY_FILE && play_list_items() > 0)
  363. {
  364. player_stop();
  365. next_step = PLAYER_STEP_PREV;
  366. }
  367. break;
  368. case RTGUIK_RETURN:
  369. if (player_is_playing() == RT_TRUE)
  370. {
  371. player_stop();
  372. next_step = PLAYER_STEP_STOP;
  373. }
  374. else
  375. {
  376. if ((player_mode == PLAYER_STOP) && (play_list_items() > 0))
  377. {
  378. next_step = PLAYER_STEP_NEXT;
  379. play_mp3_file(play_list_current_item());
  380. }
  381. }
  382. break;
  383. case RTGUIK_DOWN:
  384. rtgui_view_show(function_view, RT_FALSE);
  385. break;
  386. }
  387. }
  388. return RT_FALSE;
  389. }
  390. else if (event->type == RTGUI_EVENT_COMMAND)
  391. {
  392. struct rtgui_event_command* ecmd = (struct rtgui_event_command*)event;
  393. switch (ecmd->command_id)
  394. {
  395. case PLAYER_REQUEST_PLAY_SINGLE_FILE:
  396. case PLAYER_REQUEST_PLAY_LIST:
  397. rtgui_timer_start(info_timer);
  398. break;
  399. case PLAYER_REQUEST_STOP:
  400. {
  401. rtgui_timer_stop(info_timer);
  402. switch (next_step)
  403. {
  404. case PLAYER_STEP_STOP:
  405. {
  406. struct rtgui_dc* dc;
  407. rtgui_color_t saved;
  408. rtgui_image_t *button;
  409. rtgui_rect_t play_rect;
  410. player_mode = PLAYER_STOP;
  411. dc = rtgui_dc_begin_drawing(widget);
  412. if (dc == RT_NULL) return RT_FALSE;
  413. player_update_tag_info(dc);
  414. RTGUI_WIDGET_FOREGROUND(widget) = RTGUI_RGB(82, 199, 16);
  415. rtgui_dc_draw_hline(dc, 14, 226, 75);
  416. /* update play button */
  417. button = rtgui_image_create_from_mem("hdc",
  418. stop_hdh, sizeof(stop_hdh), RT_FALSE);
  419. play_rect.x1 = 32; play_rect.y1 = 92;
  420. play_rect.x2 = 61; play_rect.y2 = 114;
  421. rtgui_image_blit(button, dc, &play_rect);
  422. rtgui_image_destroy(button);
  423. RTGUI_WIDGET_FOREGROUND(widget) = saved;
  424. rtgui_dc_end_drawing(dc);
  425. }
  426. break;
  427. case PLAYER_STEP_NEXT:
  428. if (play_list_is_end() == RT_TRUE)
  429. {
  430. struct rtgui_dc* dc;
  431. rtgui_color_t saved;
  432. rtgui_image_t *button;
  433. rtgui_rect_t play_rect;
  434. /* set stat */
  435. next_step = PLAYER_STEP_STOP;
  436. player_mode = PLAYER_STOP;
  437. /* update UI */
  438. dc = rtgui_dc_begin_drawing(widget);
  439. if (dc == RT_NULL) return RT_FALSE;
  440. player_update_tag_info(dc);
  441. RTGUI_WIDGET_FOREGROUND(widget) = RTGUI_RGB(82, 199, 16);
  442. rtgui_dc_draw_hline(dc, 14, 226, 75);
  443. /* update play button */
  444. button = rtgui_image_create_from_mem("hdc",
  445. stop_hdh, sizeof(stop_hdh), RT_FALSE);
  446. play_rect.x1 = 32; play_rect.y1 = 92;
  447. play_rect.x2 = 61; play_rect.y2 = 114;
  448. rtgui_image_blit(button, dc, &play_rect);
  449. rtgui_image_destroy(button);
  450. RTGUI_WIDGET_FOREGROUND(widget) = saved;
  451. rtgui_dc_end_drawing(dc);
  452. }
  453. else
  454. {
  455. play_mp3_file(play_list_next());
  456. next_step = PLAYER_STEP_NEXT;
  457. }
  458. break;
  459. case PLAYER_STEP_PREV:
  460. play_mp3_file(play_list_prev());
  461. next_step = PLAYER_STEP_NEXT;
  462. break;
  463. };
  464. }
  465. break;
  466. default:
  467. break;
  468. }
  469. return RT_FALSE;
  470. }
  471. return rtgui_view_event_handler(widget, event);
  472. }
  473. rt_bool_t player_workbench_event_handler(rtgui_widget_t *widget, rtgui_event_t *event)
  474. {
  475. if (event->type == RTGUI_EVENT_KBD)
  476. {
  477. struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event;
  478. if ((ekbd->type == RTGUI_KEYUP) && ekbd->key == RTGUIK_HOME)
  479. {
  480. /* active home view */
  481. if (workbench->current_view != home_view)
  482. {
  483. rtgui_view_show(home_view, RT_FALSE);
  484. return RT_FALSE;
  485. }
  486. }
  487. }
  488. return rtgui_workbench_event_handler(widget, event);
  489. }
  490. static void player_entry(void* parameter)
  491. {
  492. rt_mq_t mq;
  493. rtgui_rect_t rect;
  494. mq = rt_mq_create("ply_ui", 256, 4, RT_IPC_FLAG_FIFO);
  495. rtgui_thread_register(rt_thread_self(), mq);
  496. /* create information timer */
  497. info_timer = rtgui_timer_create(RT_TICK_PER_SECOND,
  498. RT_TIMER_FLAG_PERIODIC,
  499. info_timer_timeout, RT_NULL);
  500. workbench = rtgui_workbench_create("main", "workbench");
  501. if (workbench == RT_NULL) return;
  502. rtgui_widget_set_event_handler(RTGUI_WIDGET(workbench), player_workbench_event_handler);
  503. /* add home view */
  504. home_view = rtgui_view_create("Home");
  505. rtgui_widget_set_event_handler(RTGUI_WIDGET(home_view), home_view_event_handler);
  506. rtgui_workbench_add_view(workbench, home_view);
  507. /* this view can be focused */
  508. RTGUI_WIDGET(home_view)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
  509. /* set widget focus */
  510. rtgui_widget_focus(RTGUI_WIDGET(home_view));
  511. rtgui_view_show(home_view, RT_FALSE);
  512. /* add function view */
  513. rtgui_widget_get_rect(RTGUI_WIDGET(workbench), &rect);
  514. function_view = (struct rtgui_view*)list_view_create(function_list,
  515. sizeof(function_list)/sizeof(struct list_item),
  516. &rect);
  517. rtgui_workbench_add_view(workbench, function_view);
  518. rtgui_workbench_event_loop(workbench);
  519. rtgui_thread_deregister(rt_thread_self());
  520. rt_mq_delete(mq);
  521. }
  522. void player_notify_play(void)
  523. {
  524. struct rtgui_event_command ecmd;
  525. RTGUI_EVENT_COMMAND_INIT(&ecmd);
  526. ecmd.type = RTGUI_CMD_USER_INT;
  527. ecmd.command_id = PLAYER_REQUEST_PLAY_SINGLE_FILE;
  528. rtgui_thread_send(player_ui_tid, &ecmd.parent, sizeof(ecmd));
  529. }
  530. void player_notify_stop()
  531. {
  532. struct rtgui_event_command ecmd;
  533. RTGUI_EVENT_COMMAND_INIT(&ecmd);
  534. ecmd.type = RTGUI_CMD_USER_INT;
  535. ecmd.command_id = PLAYER_REQUEST_STOP;
  536. rtgui_thread_send(player_ui_tid, &ecmd.parent, sizeof(ecmd));
  537. }
  538. void player_ui_init()
  539. {
  540. player_ui_tid = rt_thread_create("ply_ui", player_entry, RT_NULL,
  541. 4096, 25, 5);
  542. if (player_ui_tid != RT_NULL)
  543. rt_thread_startup(player_ui_tid);
  544. }