当前位置:   article > 正文

mplayer播放器管道重构版_视频播放器播放音乐在开发板上的代码管道传输

视频播放器播放音乐在开发板上的代码管道传输

主要实现及功能:

1,播放,暂停及继续,上一页下一页,上一首下一首和退出

2,歌曲结束根据播放模式来自动下一首

3,可根据不同格式导入歌曲

4,ANSI控制码实现简单的界面制作

5, 通过管道来向mplayer播放器发送指令

6, 在播歌曲滑动显示

主要技术点:

父进程捕捉SIGCHLD信号通过信号处理函数wait收尸来获得mplayer的退出状态,当mplayer正常结束时,信号处理函数创建一个分离的线程重新打开mplayer播放器根据播放模式来自动播放下一首,main线程通过temp标志位来获取mplayer的控制权

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <glob.h>
  5. #include <signal.h>
  6. #include <sys/types.h>
  7. #include <sys/time.h>
  8. #include <sys/stat.h>
  9. #include <unistd.h>
  10. #include <termios.h>
  11. #include <fcntl.h>
  12. #include <sys/wait.h>
  13. #include <pthread.h>
  14. #include "mplayer.h"
  15. #include "double_link.h"
  16. #define PATTERN "/home/ll/Music/*.mp3"
  17. #define FIFOPATH "music.fifo"
  18. #define MUSICSIZE 256
  19. #define OPTSIZE 512
  20. #define NAMEBUFSIZE 256
  21. #define ROW 15
  22. #define LINE 10
  23. /* 音乐名字数组*/
  24. char musicBuff[MUSICSIZE] = {0};
  25. /* 链表头结点 */
  26. LList_st *head = NULL;
  27. /* 链表当前位置 */
  28. llist *cur = NULL;
  29. /* 进程号 */
  30. pid_t pid;
  31. /* golb参数 */
  32. glob_t buff;
  33. /* 播放模式 */
  34. int playWay = ORDER;
  35. /* 播放器状态 */
  36. int tmp = 0;
  37. /* 主界面 */
  38. void interface()
  39. {
  40. int i, j, k;
  41. printf("\033[2J\033[5;25H\033[44m--====================--------------------\033[0m\n");
  42. printf("%c[6;25H",'\033');
  43. for (i = 0; i < ROW; i++)
  44. {
  45. printf("\033[44m||\033[0m");
  46. for (j = 0; j < LINE; j++)
  47. {
  48. printf(" ");
  49. }
  50. printf("\033[44m||\t\t||\033[0m\n\033[24C");
  51. }
  52. printf("\033[6;35H%s\n","歌单");
  53. printf("\033[6;53H\033[42m%s\033[0m\n","按键说明");
  54. printf("\033[8;52H%s\n","播放 'b'");
  55. printf("\033[9;52H%s\n","暂停 'p'");
  56. printf("\033[10;52H%s\n","退出 'q'");
  57. printf("\033[12;52H%s\n","上一首 'a'");
  58. printf("\033[13;52H%s\n","下一首 'd'");
  59. printf("\033[15;52H%s\n","上一页 'w'");
  60. printf("\033[16;52H%s\n","下一页 's'");
  61. printf("\033[18;52H\033[42m%s\033[0m\n"," 播放模式 ");
  62. printf("\033[21;25H\033[44m--====================--------------------\033[0m\n");
  63. }
  64. /* 歌曲路径和名字导入链表 */
  65. LList_st *loading()
  66. {
  67. int i, ret;
  68. musicNode name;
  69. LList_st *head = NULL;
  70. head = llist_create(sizeof(name));
  71. if (head == NULL)
  72. {
  73. fprintf(stderr,"llist_create() faild\n");
  74. exit(1);
  75. }
  76. glob(PATTERN,0,NULL,&buff);
  77. for (i = 0; i < buff.gl_pathc; i++)
  78. {
  79. strncpy(name.musicName,buff.gl_pathv[i],NAMESIZE);
  80. ret = llist_insert(head,&name,BEHIND);
  81. if (ret < 0)
  82. {
  83. fprintf(stderr,"llist_insert() fail\n");
  84. exit(1);
  85. }
  86. }
  87. return head;
  88. }
  89. /* 从链表中获取歌曲名字 */
  90. char *getNameFromLink(void *record)
  91. {
  92. musicNode *dest = record;
  93. return dest->musicName;
  94. }
  95. /* 获取不包含路径的名字 */
  96. char *getRealName(char *name)
  97. {
  98. char *pos = NULL;
  99. pos = strrchr(name,'/');
  100. if (pos == NULL)
  101. return name;
  102. return pos+1;
  103. }
  104. /* 模式显示 */
  105. void showPatten()
  106. {
  107. if (playWay == ORDER)
  108. printf("\033[19;52H%s\n"," 顺序播放 ");
  109. else if (playWay == SIGLOOP)
  110. printf("\033[19;52H%s\n"," 循环播放 ");
  111. else
  112. printf("\033[19;52H%s\n"," 随机播放 ");
  113. }
  114. /* 歌曲页数 */
  115. int songPage()
  116. {
  117. int i;
  118. int firstPage = 0;
  119. for (i = 0; i < buff.gl_pathc; i++)
  120. {
  121. if (strcmp(buff.gl_pathv[i],getNameFromLink(cur->data)) == 0)
  122. {
  123. firstPage = i;
  124. break;
  125. }
  126. }
  127. return firstPage;
  128. }
  129. /* 歌单的滑动显示,因为ansi控制码不好控制,根据需求自行添加 */
  130. /*
  131. void *curSongNameList(void *argc)
  132. {
  133. int i, j, len;
  134. int count;
  135. char *buf = (char *)argc;
  136. len = strlen(buf);
  137. while (1)
  138. {
  139. for (j = 0; j < len; j += 3)
  140. {
  141. count = SIZE;
  142. printf("\033[10;40H");
  143. for (i = j; i < len && (i - j) < 3*N; i++)
  144. {
  145. printf("%c",buf[i]);
  146. }
  147. fflush(stdout);
  148. usleep(700000);
  149. printf("\033[10;40H");
  150. while (count--)
  151. printf(" ");
  152. pthread_testcancel();
  153. }
  154. }
  155. }
  156. */
  157. /* 歌单展示
  158. *当当前链表歌曲和播放歌曲一样时,以红色背景色显示
  159. *
  160. */
  161. void showList(llist *cur,enum song_way pageTmp)
  162. {
  163. char *name = NULL;
  164. char nameBuf[NAMEBUFSIZE] = {0};
  165. int i = 0;
  166. int n = 0;
  167. int firstPage;
  168. firstPage = songPage(cur);
  169. i = 12 * (firstPage / 12);
  170. if (i % 12 == 0)
  171. {
  172. interface();
  173. }
  174. printf("\033[8;31H");
  175. if (pageTmp == NEXT)
  176. {
  177. if (i + 12 < buff.gl_pathc)
  178. i += 12;
  179. }
  180. else if (pageTmp == LAST)
  181. {
  182. if (i - 12 >= 0)
  183. i -= 12;
  184. }
  185. for (; i < buff.gl_pathc && n < 12; i++, n++)
  186. {
  187. name = getRealName(buff.gl_pathv[i]);
  188. if (strlen(name) < 18)
  189. {
  190. if (i == firstPage)
  191. printf("\033[41m%s\033[0m\n\033[30C",name);
  192. else
  193. printf("%s\n\033[30C",name);
  194. }
  195. else
  196. {
  197. if (i == firstPage)
  198. printf("\033[41m%s\033[0m\n\033[30C",strncpy(nameBuf,name,9));
  199. else
  200. printf("%s\n\033[30C",strncpy(nameBuf,name,18));
  201. }
  202. }
  203. showPatten();
  204. }
  205. /* 线程函数,根据播放模式不同来播放下一首 */
  206. void *playPat(void *args)
  207. {
  208. int n;
  209. if (playWay == ORDER)
  210. {
  211. cur = cur->next;
  212. if (cur == &head->head)
  213. cur = cur->next;
  214. strncpy(musicBuff,getNameFromLink(cur->data),MUSICSIZE);
  215. showList(cur,0);
  216. fflush(stdout);
  217. pid = fork();
  218. createProgress(pid, musicBuff);
  219. }
  220. else if (playWay == SIGLOOP)
  221. {
  222. fflush(stdout);
  223. pid = fork();
  224. createProgress(pid, musicBuff);
  225. }
  226. else
  227. {
  228. srand((unsigned int)time(NULL));
  229. n = (1 + rand() % 10);
  230. while (n--)
  231. {
  232. cur = cur->next;
  233. }
  234. if (cur == &head->head)
  235. cur = cur->next;
  236. strncpy(musicBuff,getNameFromLink(cur->data),MUSICSIZE);
  237. showList(cur,0);
  238. fflush(stdout);
  239. pid = fork();
  240. createProgress(pid,musicBuff);
  241. }
  242. tmp = 1;
  243. }
  244. /* 信号函数,接到信号时判断子进程是否正常结束,如果正常结束就根据播放模式播放下一首 */
  245. void actionHandler(int s)
  246. {
  247. int status;
  248. pthread_t tid;
  249. wait(&status);
  250. if (WIFEXITED(status))
  251. {
  252. pthread_create(&tid, NULL, playPat, NULL);
  253. pthread_detach(tid);
  254. tmp = 0;
  255. }
  256. }
  257. /* 创建子进程播放歌曲并将3个标准流置null */
  258. void createProgress(pid_t pid,char *musicBuff)
  259. {
  260. int fd;
  261. if (pid < 0)
  262. {
  263. perror("fork()");
  264. exit(1);
  265. }
  266. if (pid == 0)
  267. {
  268. fd = open("/dev/null",O_RDWR);
  269. if (fd < 0)
  270. {
  271. perror("open()");
  272. exit(1);
  273. }
  274. dup2(fd,0);
  275. dup2(fd,1);
  276. dup2(fd,2);
  277. if (fd > 2)
  278. close(fd);
  279. execlp("mplayer", "mplayer", "-slave", "-quiet", "-input", "file=music.fifo", musicBuff, NULL);
  280. perror("execlp()");
  281. exit(1);
  282. }
  283. }
  284. /* 导入歌曲 */
  285. void loadfile()
  286. {
  287. int fd;
  288. char optName[OPTSIZE] = {0};
  289. fd = open(FIFOPATH, O_WRONLY);
  290. if (fd < 0)
  291. {
  292. perror("open()");
  293. exit(1);
  294. }
  295. sprintf(optName, "%s %s\n", "loadfile", musicBuff);
  296. write(fd, optName, strlen(optName));
  297. close(fd);
  298. }
  299. /* 歌曲暂停 */
  300. void songPause()
  301. {
  302. int fd;
  303. fd = open(FIFOPATH, O_WRONLY);
  304. if (fd < 0)
  305. {
  306. perror("open()");
  307. exit(1);
  308. }
  309. write(fd, "pause\n", strlen("pause\n"));
  310. close(fd);
  311. }
  312. /* 歌曲退出 */
  313. void songStop()
  314. {
  315. int fd;
  316. fd = open(FIFOPATH, O_WRONLY);
  317. if (fd < 0)
  318. {
  319. perror("open()");
  320. exit(1);
  321. }
  322. write(fd, "quit\n", strlen("quit\n"));
  323. close(fd);
  324. }
  325. /* 运行函数
  326. * 关闭系统回显和getchar()以\n结尾的设置
  327. *
  328. * flag播放状态 0:未播放 1:正在播放 2:暂停
  329. * tmp检测第一次是否创建了子进程,防止意外杀死主进程 0:未创建子进程 1:已创建子进程
  330. *
  331. */
  332. void operationFunction()
  333. {
  334. struct termios new,old;
  335. struct sigaction sa;
  336. char ch;
  337. tcgetattr(0,&old);
  338. tcgetattr(0,&new);
  339. new.c_lflag = new.c_lflag & ~(ICANON | ECHO);
  340. new.c_cc[VMIN] = 1;
  341. new.c_cc[VTIME] = 0;
  342. tcsetattr(0,TCSANOW,&new);
  343. printf("\033[?25l"); //隐藏光标
  344. interface();
  345. unlink(FIFOPATH);
  346. if (mkfifo(FIFOPATH, 0666) < 0)
  347. {
  348. perror("mkfifo()");
  349. exit(1);
  350. }
  351. sa.sa_handler = actionHandler;
  352. sigemptyset(&sa.sa_mask);
  353. sa.sa_flags = 0;
  354. sigaction(SIGCHLD, &sa, NULL);
  355. head = loading();
  356. cur = head->head.next;
  357. showList(cur,0);
  358. while(1)
  359. {
  360. ch = getchar();
  361. switch (ch)
  362. {
  363. /* 播放 */
  364. case 'b':
  365. if (tmp == 0)
  366. {
  367. if (cur == NULL)
  368. cur = cur->next;
  369. strncpy(musicBuff,getNameFromLink(cur->data),MUSICSIZE);
  370. showList(cur,0);
  371. fflush(stdout);
  372. pid = fork();
  373. tmp = 1;
  374. createProgress(pid,musicBuff);
  375. }
  376. break;
  377. /* 上一页 */
  378. case 'w':
  379. interface();
  380. showList(cur,LAST);
  381. break;
  382. /* 下一页 */
  383. case 's':
  384. interface();
  385. showList(cur,NEXT);
  386. break;
  387. /* 上一首 */
  388. case 'a':
  389. cur = cur->prev;
  390. if (cur == &head->head)
  391. cur = cur->prev;
  392. strncpy(musicBuff,getNameFromLink(cur->data),MUSICSIZE);
  393. showList(cur,0);
  394. if (tmp == 1)
  395. loadfile();
  396. break;
  397. /* 下一首 */
  398. case 'd':
  399. cur = cur->next;
  400. if (cur == &head->head)
  401. cur = cur->next;
  402. strncpy(musicBuff,getNameFromLink(cur->data),MUSICSIZE);
  403. showList(cur, 0);
  404. if (tmp == 1)
  405. loadfile();
  406. break;
  407. /* 暂停 | 恢复播放 */
  408. case 'p':
  409. if (tmp == 1)
  410. songPause();
  411. break;
  412. case 't':
  413. playWay++;
  414. if (playWay > 3)
  415. playWay = 1;
  416. showPatten();
  417. break;
  418. default:
  419. break;
  420. }
  421. /* 退出 */
  422. if (ch == 'q')
  423. {
  424. if (tmp)
  425. {
  426. songStop();
  427. kill(pid, SIGKILL);
  428. }
  429. break;
  430. }
  431. }
  432. tcsetattr(0,TCSANOW,&old); //还原终端原始设置
  433. printf("\033[?25h\033[2J");
  434. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/830434
推荐阅读
相关标签
  

闽ICP备14008679号