Linux字符界面 MP3播放器
写在前面:大家好,我是草莓橙须圆。毕业之前在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播放器相关推荐
- linux下面的 mp3播放器xmms
linux下面的mp3播放器xmms 首先去下载,可以下载可执行文件或者是源代码,我提倡下载二进制的可执行程序,这个是一个 安装包. 网址: 下载之后就是安装了,用强行安装,否则可能会出现一下比如说g ...
- 基于嵌入式Linux的MP3播放器的设计与实现
摘要:本文详细介绍了嵌入式系统的特点以及嵌入式系统开发的流程,分析基于嵌入式Linux的MP3播放器的关键技术,设计和实现了一种基于嵌入式系统的 MP3 播放器.该播放器利用 QT 技术和开源的音频解 ...
- alin的学习之路:嵌入式课程设计总结(基于Linux的Qt版MP3播放器)
嵌入式课程设计总结(基于Linux的Qt版MP3播放器) 废话不多写直接上图上代码,其中有很多不规范的地方,希望大佬们指正. 1.课设题目 设计一个MP3播放器,要求:使用Linux下的madplay ...
- java mp3播放器 无界面
一.服务器端: 最近没有系统学习的计划,看了开源的YOYOPlayer(一个相当强大的播放器软件,基于java编写),心里痒痒,比较肤浅的学习下javasound. javasound是比较小巧的底层 ...
- OrangePi PC 玩Linux主线内核踩坑之旅(四)之变身MP3播放器
主线内核Linux跑起来后,我们就可以用香橙派做一些简单的应用了.既然是简单的应用,那便是说基本上无需再添加额外的硬件即可实现相应的功能,"变身MP3播放器"便是一例.当然,耳机或 ...
- 安卓MP3播放器开发实例(1)之音乐列表界面
学习安卓开发有一年了,想想这一年的努力,确实也收获了不少.也找到了比較如意的工作. 今天准备分享一个以前在初学阶段练习的一个项目.通过这个项目我真正的找到了开发安卓软件的感觉,从此逐渐步入安卓开发的正 ...
- linux ipod驱动程序,佳能 iPod Classic 驱动程序下载-更新佳能软件(MP3播放器)
Apple iPod Classic 驱动程序下载 如何手动下载和更新: iPod Classic 设备的默认驱动程序版本可以通过 %%os%% 或 Windows® 更新获取. 内置驱动程序支持Cl ...
- java mp3播放器 ×××面
一.服务器端: 最近没有系统学习的计划,看了开源的YOYOPlayer(一个相当强大的播放器软件,基于java编写),心里痒痒,比较肤浅的学习下javasound. javasound是比较小巧的底层 ...
- 嵌入式linux音频播放器设计,基于嵌入式Linux下Madplay音频播放器设计论文.docx
基于嵌入式Linux下Madplay音频播放器设计论文 滁州职业技术学院计算机应用技术专业毕业论文PAGE I 滁州职业技术学院信息工程系--2015届计算机应用专业毕业论文 姓 名: 周杰 班 级: ...
最新文章
- 实体类是个什么东西!答金色海洋同学的疑问
- 清空SQL Server数据库中所有表数据的方法(转)
- 【数值分析】微分求积:复化梯形、复化辛浦生
- python3精要(21)-函数(2)
- linux I/O-记录锁(record lock)
- LINUX 下的逆向 用 IDA 分析,样本逆向中系统调用的识别方法
- db2 删除索引_程序员必须了解的知识点——你搞懂mysql索引机制了吗?
- 爬虫代码分析(1)--下载小说
- python程序怎样在手机上_python手机文件怎么上传至电脑?
- 数据结构和算法:线性表链式存储的简单实现
- Android 屏幕旋转的多种状态
- ​阿里云SAE助力百富旅行实现Serverless+微服务完美结合
- Rsync 实现远程同步
- 软件测试周刊(第21期):不要告诉我你想干什么
- 等保2.0|二级等保和三级等保要求对比
- 向武 清华大学 计算机,哥哥保送弟弟全市第二 双胞胎如何同时上清华?
- 吊打大厂:内核级安卓系统优化软件 | 雪豹速清app官网下载
- 7.绘制统计图形——堆积折线图、间断条形图和阶梯图
- 【趣学算法】一棋盘的麦子
- GK 1424 L劳易测标签识别开关