写在前面:大家好,我是草莓橙须圆。毕业之前在CSDN和微信公众号活跃
欢迎关注我的公众号:【草莓橙须圆】
微信公众号主要就是更新大学生或者考研党的日常
CSDN主要就是学习Java过程中总结的笔记,以及编程分享

这篇文章主要是给大家分享字符界面 MP3播放器

本次基于 Ubuntu18.04,64位环境下的字符界面 MP3播放器,对于字符界面 MP3播放器:主要包括,执行播放指令,开创子进程允许各类模式播放,通过文件进行沟通,通过主界面的提示,以及输入的字符判断要执行的操作。拥有下一曲,上一曲,暂停,播放,显示目录点歌,对应每个选项又有相应的功能操作,通过杀死之前的子进程,打开另一个子进程,进行切歌,模式其切换等功能

首先先安装madplay:


因为网络问题无法安装madplay
解决办法:
无法下载 http://archive.ubuntu.com/ubuntu/·····暂时不能解析域名,解决办法

已经madplay配置完成

代码:

1.头文件:madplay.h说明:实现madplay的控制,包括播放play、暂停suspend、开始start、下一首next、上一首previous#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>#include "madplay.h"#ifdef MADPLAY_DEBUG
int main()
{pid_t pid;char *name = "./music/happy.mp3";pid = play(name);printf("child pid: %d\n", pid);char con;printf("suspend?");scanf("%c", &con);getchar();printf("\n");if('y' == con)suspend(pid);printf("continue?");scanf("%c", &con);getchar();if('y' == con)continuePlay(pid);printf("end?");scanf("%c", &con);printf("\n");end(pid);return 0;
}
#endif/* 成功则返回进程pid,失败则返回0 */
int play(char *name)
{pid_t pid;int status;if((pid = fork()) < 0){perror("Fork error\n");return 0;}else if(0 == pid){waitpid(getppid(), &status, 0); // 等待父进程结束execlp("madplay", "madplay","-q", name, (char*)0);return 0;}else{return pid;    }
}int suspend(pid_t pid)
{kill(pid, SIGSTOP);return 0;
}int continuePlay(pid_t pid)
{kill(pid, SIGCONT);return 0;
}int end(pid_t pid)
{kill(pid, SIGINT);return 0;
}
2.文件名:madplay.h#ifndef MADPLAY_H
#define MADPLAY_H包含四个功能函数的声明。
int play(char *name);   //播放int suspend(pid_t pid);  //暂停int continuePlay(pid_t pid);  //继续播放int end(pid_t pid);
3.文件名:music_list.c
头文件:music_list.h说明:music结构体双向循环链表的具体实现#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "music_list.h"int bSearch(int funcFlag, music_list *mList, char *value, int low, int high);/*
int main()
{music_list *mList;mList = createMusicList();char *name = "abcd";musicListInsert(mList, name);musicListDisplay(mList);return 0;
}
*/music_list * createMusicList()
{music_list *mList;mList = (music_list *)malloc(sizeof(music_list));if(NULL == mList){perror("mList malloc fail\n");exit(1);}mList->length = 0;mList->mHead = NULL;return mList;
}int musicListInsert(music_list *mList, char *name)
{music *mNew;mNew = (music *)malloc(sizeof(music));if(NULL == mNew){perror("mNew malloc fail\n");exit(1);}mNew->name = name;if(NULL == mList->mHead) // 初始节点{mNew->next = mNew;mNew->prev = mNew;mList->mHead = mNew;
#ifdef MUSIC_LIST_DEBUG    printf("init next: %s\n", mList->mHead->next->name);printf("init prev: %s\n", mList->mHead->prev->name);
#endif}else{int pos = bSearch(0, mList, name, 0, mList->length - 1); // 得到插入位置
#ifdef MUSIC_LIST_DEBUGprintf("bsearch success\n");printf("pos: %d\n", pos);
#endifmusic *tmp; // tmp指向pos位置的节点tmp = locateMusic(mList, pos);mNew->next = (tmp);mNew->prev = (tmp)->prev;
#ifdef MUSIC_LIST_DEBUGprintf("mNew->next: %s\n", mNew->next->name); printf("mNew->prev: %s\n", mNew->prev->name);
#endiftmp->prev->next = mNew;
#ifdef MUSIC_LIST_DEBUGprintf("(mList->mHead + pos)->prev->next: %s\n", (tmp)->prev->next->name);
#endiftmp->prev = mNew;
#ifdef MUSIC_LIST_DEBUG      printf("(mList->mHead + pos)->prev: %s\n", (tmp)->prev->name);
#endifif(0 == pos) // 插入在链表头mList->mHead = mNew;}(mList->length)++;return 0;
}int bSearch(int funcFlag, music_list *mList, char *value, int low, int high)
{   // funcFlag = 0: musicListInsert// funcFlag = 1: musicFind or musicListDeleteint mid = (low + high) / 2;music *tmp; // tmp指向mid节点tmp = locateMusic(mList, mid);// printf("low: %d, high: %d, mid: %d\n", low, high, mid);if(0 == funcFlag){if(high - low <= 1) // a[low]为比value小的最大值,a[high]为比value大的最小值return high;}if(1 == funcFlag) // musicFind{//printf("value:%s, tmp->name: %s",value, tmp->name);if(strcmp(value, tmp->name) == 0)return mid; // 文件存在,返回所在链表位置if((high - low) <= 0)return -1; // 文件不存}int r = strcmp(value, tmp->name);if(r < 0)   return bSearch(funcFlag, mList, value, low, mid);if(r > 0)return bSearch(funcFlag, mList, value, mid, high);
}int musicListDisplay(music_list *mList)
{music *tmp;tmp = mList->mHead;printf("%s\n", tmp->name);int i;for(i = 1; i < mList->length; ++i){tmp = tmp->next;printf("%s\n", tmp->name);}printf("\n\n");return 0;
}/* 存在返回所在链表位置,不存在返回-1 */
int musicFind(music_list *mList, char *name)
{return bSearch(1, mList, name, 0, mList->length - 1);
}/* 将tmp指向mList第pos位置 */
music *  locateMusic(music_list *mList, int pos)
{music *tmp = mList->mHead;int i;for(i = 0; i < pos; ++i)tmp = tmp->next;return tmp;
}
4.   * 文件名:music_list.h* 说明:music结构体定义,为循环双向链表* 相关文件:music_list.c#ifndef MUSIC_LIST_H
#define MUSIC_LIST_Htypedef struct node
{char *name;// char *singer;// int size;struct node *next;struct node *prev;
}music;typedef struct musicLst
{int length;music *mHead;
}music_list;music_list * createMusicList();
int musicListInsert(music_list *mList, char *name);
int musicListDisplay(music_list *mList);
int musicListDelete(music_list *mList, char *name);
int musicFind(music_list *mList, char *name);
music * locateMusic(music_list *mList, int pos);#endif
5.   文件名:readFileList.c
头文件:readFileList.h
说明:linux下读取目录并获得mp3文件,将文件信息存入mList#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "music_list.h"// char *basePath = "/home/zhang/VM_CentOS_5/share/music";int readFileList(const char *basePath, music_list *mList)
{DIR *dir;struct dirent *ptr;// char base[1000];/* 读取目录,将mp3文件的文件名存入.music_list */    if((dir = opendir(basePath)) == NULL){perror("Open dir error.\n");exit(1);}while((ptr = readdir(dir)) != NULL){if(8 == ptr->d_type) // 文件{int i = 0;int flag = 0;while('\0' != ptr->d_name[i]){if('.' == ptr->d_name[i]){if(0 != flag)flag = 0;++flag;}else if(1 == flag && 'm' == ptr->d_name[i])++flag;else if(2 == flag && 'p' == ptr->d_name[i])++flag;else if(3 == flag && '3' == ptr->d_name[i]){if('\0' ==  ptr->d_name[i + 1]) // 是mp3文件{musicListInsert(mList, ptr->d_name);break;}flag = 0;}else if(0 != flag)flag = 0;++i;}}/*else if(4 == ptr->d_type) // 目录{memset(base, '\0', sizeof(base));strcpy(base, basePath);strcat(base, "/");strcat(base, ptr->d_name);readFileList(base);}*/}closedir(dir);return 0;
}
6.  文件名:readFileList.h相关文件:readFileList.c#ifndef readFileList_H
#define readFileList_Hint readFileList(const char *basePath, music_list *mList);#endif
7. 主函数:main.c程序主要实现功能:上一首,下一首,暂停/播放,以及查看歌曲#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>#include "music_list.h"
#include "readFileList.h"
#include "madplay.h"char getCommand(char *arg);
int execCommand(char command, char *arg, pid_t *pid, music_list *mList, int *pos, int *quit);int sCommand(char *arg, pid_t *pid, music_list *mList, int *pos);
int uCommand(pid_t *pid, music_list *mList, int *pos);
int cCommand(pid_t *pid);
int nCommand(pid_t *pid, music_list *mList, int *pos);
int pCommand(pid_t *pid, music_list *mList, int *pos);
int qCommand(pid_t *pid, int *pos, int *quit);int getMusicFileDir(char *basePath);
int getMusicDir(music_list *mList, char *name, int *pos, int nextLast);int displayHelp();int main()
{char command;              // 控制指令char arg[256];                 // 指令参数char musicFilePath[256];   // 音乐文件所在文件的路径music_list *mList;         // 音乐信息双向链表int *pos;             // 当前播放的音乐在链表中的位置pos = (int *)malloc(sizeof(int));*pos = -1;pid_t *pid;                // 音乐进程pidpid = (pid_t *)malloc(sizeof(pid_t));int *quit;quit = (int *)malloc(sizeof(int));*quit = 0;mList = createMusicList();          // 初始化音乐信息双向链表getMusicFileDir(musicFilePath);     // 获取音乐文件所在文件的路径readFileList(musicFilePath, mList); // 读取音乐信息并完成链表/* 主界面 */printf("--------------------------------Music player------------------------------------\n\n");printf("| The player can only play MP3 now.(or forever)\n");printf("| To Learn more about the player, open the instruction manual (<h> or <H>).\n\n");printf("--------------------------------------------------------------------------------");printf("\n\n");while(0 == *quit){command = getCommand(arg);         // 读指令execCommand(command, arg, pid, mList, pos, quit);  // 执行指令}return 0;
}/* command *//* 读取指令和参数 */
char getCommand(char *arg)
{char res = '0'; // 指令char input[256];printf("Input command: ");fgets(input, 256, stdin);input[strlen(input) - 1] = '\0';/* Trim */int i = 0;while(' ' == input[i]) // 去除前空格++i;if('\0' != input[i]) // fget会在字符串尾加'\n'res = input[i];  // 获得第一各有效字符    if('s' == res || 'S' == res){strcpy(arg, "\0");if(' ' != input[++i] || '\0' == input[i]) // 为非空格或无参数return 'E';++i;strcat(arg, &input[i]);    }else // 无参数指令,检测指令是否有错{while('\0' != input[++i]){if(' ' != input[i]){res = 'E';break;}}}return res;
}/* 指令执行 */
int execCommand(char command, char *arg, pid_t *pid, music_list *mList, int *pos, int *quit)
{   switch(command){/* 播放 */case 's':case 'S':if(sCommand(arg, pid, mList, pos) == -1)printf("ERROR: Fail to play!\n");break;/* 暂停 */case 'u':case 'U':if(uCommand(pid, mList, pos) == -1)printf("ERRPR: No music is playing!\n");break;case 'n':case 'N':nCommand(pid, mList, pos);break;case 'c':case 'C':cCommand(pid);break;case 'p':case 'P':pCommand(pid, mList, pos);break;/* 显示音乐列表 */case 'l':case 'L':musicListDisplay(mList);break;/* 显示“帮助” */case 'h':case 'H':displayHelp();break;/* 退出 */case 'q':case 'Q':qCommand(pid, pos, quit);break;default:printf("ERROR: Invalid command!\n");}  return 0;
}/* 播放 */
int sCommand(char *arg, pid_t *pid, music_list *mList, int *pos)
{getMusicDir(mList, arg, pos, 0); // arg为音乐文件路径if(-1 == *pos) // 文件不存在{printf("ERROR: File not exist!\n");return -1;}else{*pid = play(arg);printf("Playing...\n");return 0;}
}/* 暂停 */
int uCommand(pid_t *pid, music_list *mList, int *pos)
{if(-1 == *pos) // 无音乐播放return -1;else{suspend(*pid);return 0;}
}/*  */
int cCommand(pid_t *pid)
{continuePlay(*pid);return 0;
}/* 下一首 */
int nCommand(pid_t *pid, music_list *mList, int *pos)
{if(-1 != *pid)end(*pid);char name[256];getMusicDir(mList, name, pos, 1);*pid = play(name);printf("Playing...\n");return 0;
}/* 上一首 */
int pCommand(pid_t *pid, music_list *mList, int *pos)
{if(-1 != *pos) // 结束未结束的播放end(*pid);char name[256];getMusicDir(mList, name, pos, 2);*pid = play(name);printf("Playing...\n");return 0;
}/* 退出 */
int qCommand(pid_t *pid, int *pos, int *quit)
{if(-1 != *pos) // 结束未结束的播放end(*pid);*quit = 1;return 0;
}/* display  */int displayHelp()
{printf("\nYou can use instructions as follows to control the Music.\n");printf("------------------------------------------------------------------------\n\n");printf("1.<s> : Input 's' + music's name, start play the music.\n");printf("2.<u> : Suspend what is playing.\n");printf("3.<c> : Continue to play the song.\n");printf("4.<n> : Play the next one.\n");printf("5.<p> : Play the previous one.\n");printf("6.<l> : Output your music list on the screen.\n");printf("7.<q> : Quit the Music. \n");printf("------------------------------------------------------------------------\n");return 0;
}/* file *//* 获取音乐文件所在文件的路径 */
int getMusicFileDir(char *basePath)
{FILE *fstream;fstream = fopen(".music_config", "r"); // .music_config保存音乐文件所在文件的路径// 默认为./musicwhile(fgets(basePath, 256, fstream) != NULL){if('#' != basePath[0])             // #为注释{basePath[strlen(basePath) - 1] = '\0';break;}}fclose(fstream);return 0;
}/* 获取音乐文件路径 */
int getMusicDir(music_list *mList, char *name, int *pos, int nextLast)
{if(0 == nextLast) // 由name指定的歌{   *pos = musicFind(mList, name); // 文件在链表中位置if(-1 == *pos) // 文件不存在return -1;}    else{music *tmp;tmp = locateMusic(mList, *pos); // 指向当前播放的歌曲if(1 == nextLast) // 下一首{strcpy(name, tmp->next->name);++(*pos);}else // 上一首{strcpy(name, tmp->prev->name);--(*pos);}}char path[256] = "./music/";strcat(path, name);strcpy(name, path);return 0;
}
8.Makefile
# makefile
mp3player:main.o music_list.o readFileList.o madplay.ogcc -o mp3player main.o music_list.o readFileList.o madplay.o
main.o:main.c music_list.h readFileList.hgcc -c main.c
music_list.o:music_list.c music_list.hgcc -c music_list.c
readFileList.o:readFileList.c readFileList.hgcc -c readFileList.c
madplay.o:madplay.c madplay.hgcc -c madplay.cclean:rm -f *.o
执行Makefile文件,生成.o文件

运行结果:

  • 在命令行下使用简单的命令就可控制音乐的播放。
  • music_config文件保存着音乐目录。
  • 同一时刻只能播放一首音乐。
  • 可以暂停或者继续播放。
  • 可以循环播放下一首或者上一首
  • 输入h或者H来显示哪些命令可用。



    已经把完整的代码打包在了我账号的下载资源里,是整个实验的成果,需要自取。

Linux字符界面 MP3播放器相关推荐

  1. linux下面的 mp3播放器xmms

    linux下面的mp3播放器xmms 首先去下载,可以下载可执行文件或者是源代码,我提倡下载二进制的可执行程序,这个是一个 安装包. 网址: 下载之后就是安装了,用强行安装,否则可能会出现一下比如说g ...

  2. 基于嵌入式Linux的MP3播放器的设计与实现

    摘要:本文详细介绍了嵌入式系统的特点以及嵌入式系统开发的流程,分析基于嵌入式Linux的MP3播放器的关键技术,设计和实现了一种基于嵌入式系统的 MP3 播放器.该播放器利用 QT 技术和开源的音频解 ...

  3. alin的学习之路:嵌入式课程设计总结(基于Linux的Qt版MP3播放器)

    嵌入式课程设计总结(基于Linux的Qt版MP3播放器) 废话不多写直接上图上代码,其中有很多不规范的地方,希望大佬们指正. 1.课设题目 设计一个MP3播放器,要求:使用Linux下的madplay ...

  4. java mp3播放器 无界面

    一.服务器端: 最近没有系统学习的计划,看了开源的YOYOPlayer(一个相当强大的播放器软件,基于java编写),心里痒痒,比较肤浅的学习下javasound. javasound是比较小巧的底层 ...

  5. OrangePi PC 玩Linux主线内核踩坑之旅(四)之变身MP3播放器

    主线内核Linux跑起来后,我们就可以用香橙派做一些简单的应用了.既然是简单的应用,那便是说基本上无需再添加额外的硬件即可实现相应的功能,"变身MP3播放器"便是一例.当然,耳机或 ...

  6. 安卓MP3播放器开发实例(1)之音乐列表界面

    学习安卓开发有一年了,想想这一年的努力,确实也收获了不少.也找到了比較如意的工作. 今天准备分享一个以前在初学阶段练习的一个项目.通过这个项目我真正的找到了开发安卓软件的感觉,从此逐渐步入安卓开发的正 ...

  7. linux ipod驱动程序,佳能 iPod Classic 驱动程序下载-更新佳能软件(MP3播放器)

    Apple iPod Classic 驱动程序下载 如何手动下载和更新: iPod Classic 设备的默认驱动程序版本可以通过 %%os%% 或 Windows® 更新获取. 内置驱动程序支持Cl ...

  8. java mp3播放器 ×××面

    一.服务器端: 最近没有系统学习的计划,看了开源的YOYOPlayer(一个相当强大的播放器软件,基于java编写),心里痒痒,比较肤浅的学习下javasound. javasound是比较小巧的底层 ...

  9. 嵌入式linux音频播放器设计,基于嵌入式Linux下Madplay音频播放器设计论文.docx

    基于嵌入式Linux下Madplay音频播放器设计论文 滁州职业技术学院计算机应用技术专业毕业论文PAGE I 滁州职业技术学院信息工程系--2015届计算机应用专业毕业论文 姓 名: 周杰 班 级: ...

最新文章

  1. 实体类是个什么东西!答金色海洋同学的疑问
  2. 清空SQL Server数据库中所有表数据的方法(转)
  3. 【数值分析】微分求积:复化梯形、复化辛浦生
  4. python3精要(21)-函数(2)
  5. linux I/O-记录锁(record lock)
  6. LINUX 下的逆向 用 IDA 分析,样本逆向中系统调用的识别方法
  7. db2 删除索引_程序员必须了解的知识点——你搞懂mysql索引机制了吗?
  8. 爬虫代码分析(1)--下载小说
  9. python程序怎样在手机上_python手机文件怎么上传至电脑?
  10. 数据结构和算法:线性表链式存储的简单实现
  11. Android 屏幕旋转的多种状态
  12. ​阿里云SAE助力百富旅行实现Serverless+微服务完美结合
  13. Rsync 实现远程同步
  14. 软件测试周刊(第21期):不要告诉我你想干什么
  15. 等保2.0|二级等保和三级等保要求对比
  16. 向武 清华大学 计算机,哥哥保送弟弟全市第二 双胞胎如何同时上清华?
  17. 吊打大厂:内核级安卓系统优化软件 | 雪豹速清app官网下载
  18. 7.绘制统计图形——堆积折线图、间断条形图和阶梯图
  19. 【趣学算法】一棋盘的麦子
  20. GK 1424 L劳易测标签识别开关

热门文章

  1. 用D触发器和必要的门电路设计可控同步计数器
  2. 民航机场生产网该如何进行安全防护?
  3. html5 xdwlnjs cn,XDW,丝印Marking-电子元件丝印查询
  4. angular7 + ng-zorro-antd 开发问题小记
  5. 怎么查看单片机程序占多少RAM 、ROM
  6. R| ggseg 绘制统计结果
  7. 网易有道2017校园招聘编程题——洗牌
  8. CompareNoCase 比较两个字符串,不区分大小写
  9. 中兴新支点国产操作系统安装使用QQ的体验,很好用
  10. GNU make manual 翻译(十二)