Linux下实现Mplayer播放器的源码

main.c

#include<stdlib.h>
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<time.h>
#include"MusicList.h"
#include"order.h"

int main(){
	PNODE music_head = CreateMusicList();
	
	char buf[100];
	char data[100];
	int cmd;
	srand(time(NULL));
	
	while(1){
		printf("dai_mplayer#");

		//清空数组
		memset(buf, 0, sizeof(buf));
		memset(data, 0, sizeof(data));

		//把输入字符串保存在buf中
		fgets(buf, sizeof(buf), stdin);

		//得到主命令
		cmd = Analysis(buf, data);
		printf("cmd:%d\n", cmd);
		printf("data:%s\n", data);
		
		//执行相应的函数
		order(music_head, cmd, data);
		
	}
	
}

MusicList.c

#include<stdlib.h>
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include"MusicList.h"

//创建头结点,将歌曲加载到链表
PNODE CreateMusicList();

//添加歌曲
void InsertMusicList(PNODE head, const char *name);

//刷新歌曲的id
static void FreshId(PNODE head, PNODE p);

//显示全部歌曲
void DisplayMusicList(PNODE head);

//删除歌曲
void DeleteMusicList(PNODE head, const int id);

//清除全部歌曲
void ClearMusicList(PNODE head);

//销毁歌曲列表
void DestoryMusicList(NODE **head);

//从文件中读取歌曲到链表中
static void ReadMusicList(PNODE head);

//把歌曲从链表中写到文件
void WriteMusicList(PNODE head);

//传入歌曲id,获得歌曲的路径
extern  char * GetNameMusicList(PNODE head, int id);

//判断是否重复添加歌曲
extern int JudgeRepitionList(PNODE head, const char *name);

//判断链表是否为空
static int IsEmptyList(PNODE head);



PNODE CreateMusicList(){
	PNODE head = (PNODE)malloc(sizeof(NODE));
	head->name = NULL;//保存歌曲的路径和名字
	head->id = 0;
	head->next = head;
	head->prior = head;
	
	ReadMusicList(head);
	
	return head;
}




void InsertMusicList(PNODE head, const char *name){
	printf("insertmusiclist\n");
	PNODE pnew = (PNODE)malloc(sizeof(NODE));
	assert(pnew);
	
	pnew->name = (char *)malloc(strlen(name) + 1);
	strcpy(pnew->name, name);
	pnew->id = head->id + 1;
	head->id++;
	
	pnew->prior = head->prior;
	head->prior->next = pnew;
	pnew->next = head;
	head->prior = pnew;
	
	WriteMusicList(head);
}

void DeleteMusicList(PNODE head, const int id){
	PNODE p = head->next;
	while(p != head){
		if(p->id == id){
			FreshId(head,p->next);
			p->next->prior = p->prior;
			p->prior->next = p->next;
			free(p->name);
			free(p);
			
			//歌曲的总数-1
			head->id--;
			
			WriteMusicList(head);
			
			return;
		}
		p = p->next;
	}
}

static void FreshId(PNODE head, PNODE p){
	//将链表后面的歌曲id都-1
	while(p != head){
		p->id--;
		p = p->next;
	}
}

void DisplayMusicList(PNODE head){
	PNODE p = head->next;
	while(p != head){
		printf("id:%d\tmusicname:%s\n", p->id, p->name);
		p = p->next;
	}
	return;
}

//判断链表是否为空
static int IsEmptyList(PNODE head){
	if(head->next == head){
		return 1;
	}
	return 0;
}

void ClearMusicList(PNODE head){
	
	PNODE p = head->next;
	while(!IsEmptyList(head)){
		p->next->prior = p->prior;
		p->prior->next = p->next;
		free(p->name);
		free(p);
		p = head->next;
	}
	head->id =0;
	
}

void DestoryMusicList(NODE **head){
	ClearMusicList(*head);
	free(*head);
	*head = NULL;
}

void ReadMusicList(PNODE head){

	FILE *fp = fopen("/home/dai/Linux/project/Mplayer/music_list.txt","r");
	if(fp == NULL){
		return;
	}
	char buf[200] = {0};
	while(fgets(buf, sizeof(buf), fp)){
		buf[strlen(buf) - 1] = 0;
		InsertMusicList(head, buf);
		memset(buf, 0, sizeof(buf));
	}
	
	fclose(fp);
}

void WriteMusicList(PNODE head){
	FILE *fp = fopen("/home/dai/Linux/project/Mplayer/music_list.txt", "w");
	

	PNODE p = head->next;
	
	while(p != head){
		
		fputs(p->name, fp);
		fputs("\n", fp);
		p = p->next;
	}
	
	fclose(fp);
}

extern  char * GetNameMusicList(PNODE head, int id){
	PNODE p = head->next;
	
	while(p != head){
		if(p->id == id){
			return p->name;
		}
		p = p->next;
	}
	return NULL;
}

extern int JudgeRepitionList(PNODE head, const char *name){
	PNODE p = head->next;
	while(p != head){
		if(strcmp(p->name, name) == 0){
			return 0;
		}
		p = p->next;
	}
	
	return 1;
}

MusicList.h

#ifndef _MUSICLIST_H_
#define _MUSICLIST_H_

//链表的节点类型
typedef struct node{
	char *name;
	int id;
	struct node *next;
	struct node *prior;
}NODE, *PNODE;

extern PNODE CreateMusicList();
extern void InsertMusicList(PNODE head, const char *name);
extern void DisplayMusicList(PNODE head);
extern void DeleteMusicList(PNODE head, const int id);
extern void ClearMusicList(PNODE head);
extern void DestoryMusicList(NODE **head);
extern char * GetNameMusicList(PNODE head, int id);
extern int JudgeRepitionList(PNODE head, const char *name);
extern void WriteMusicList(PNODE head);

#endif

order.c

#include<string.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<dirent.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
#include<assert.h>
#include"order.h"
#include"MusicList.h"

//playstatus是一个共用体,来表示播放的状态
enum PlayStatus playstatus = STOP;

enum PlayMode playmode = LOOP;

int playindex = 0;

float music_len = 0;
float playpos = 0.0;

//向管道文件发送命令
static void SendCmd(char *cmd);
//添加歌曲到链表中
static void AddMusic(PNODE head, char *src);

//将mp3文件添加到列表中
void InsertMp3(PNODE head, const char *src);

//分析得到的指令
extern int Analysis(char *buf, char *src){
	
	buf[strlen(buf) - 1] = 0;
	char *p = NULL;
	if(buf == NULL){
		return -1;
	}
	if((p = strchr(buf, ' ')) != NULL){
		*p = 0;
		strcpy(src, p+1);
	}
	if(strcmp(buf, "help") == 0){
		return 1;
	}
	else if(strcmp(buf, "list") == 0){
		return 2;
	}
	else if(strcmp(buf, "quit") == 0){
		return 3;
	}
	else if(strcmp(buf, "addmusic") == 0){
		return 4;
	}
	else if(strcmp(buf, "addmusicdir") == 0){
		return 5;
	}
	else if(strcmp(buf, "play") == 0){
		if(src == NULL){
			printf("music is empty\n");
			return 0;
		}
		else{
			return 6;
		}
	}
	else if(strcmp(buf, "volume") == 0){
		return 7;
	}
	else if(strcmp(buf, "mute") == 0){
		return 8;
	}
	else if(strcmp(buf, "pause") == 0){
		return 9;
	}
	else if(strcmp(buf, "seek") == 0){
		return 10;
	}
	else if(strcmp(buf, "model") == 0){
		return 11;
	}
	else if(strcmp(buf, "next") == 0){
		return 12;
	}
	else if(strcmp(buf, "delete") == 0){
		return 13;
	}
	else if(strcmp(buf, "front") == 0){
		return 14;
	}
	else{
		printf("please input help\n");
	}
}


static void SendCmd(char *cmd){
	
	
	if(access("fifo", F_OK)){
		mkfifo("fifo", 0666);
	}
	printf("%s\n", cmd);
	int fd = open("fifo", O_WRONLY);
	write(fd, cmd, strlen(cmd));
	close(fd);
}

static void AddMusic(PNODE head, char *src){
	InsertMusicList(head, src);
	printf("Insert Success\n");
}

void AddMusicDir(PNODE head, const char *src){
	
	struct stat st;
	int ret = stat(src, &st);
	
	if(ret < 0){
		return;
	}
	if(S_ISDIR(st.st_mode)){
		char newname[300];
		DIR *dir = opendir(src);
		if(dir == NULL){
			return;
		}
		struct dirent *ent;
		while((ent = readdir(dir)) != NULL){
			if(strcmp(ent->d_name, ".") ==0 || strcmp(ent->d_name, "..") == 0){
				continue;
			}
			strcpy(newname, src);
			strcat(newname, "/");
			strcat(newname, ent->d_name);
			AddMusicDir(head, newname);
		}
	}
	InsertMp3(head, src);
	
}

void InsertMp3(PNODE head, const char *src){
	char buf[10];
	char *p;
	if((p = strchr(src, '.')) != NULL){
		strcpy(buf, p+1);
	}
	if(strcmp(buf, "mp3") ==0){
		if(JudgeRepitionList(head, src) == 1)
		InsertMusicList(head, src);
	}
	
	return;
}

void Slice(PNODE head){
	char buf[200];
	char *p;
	if(playmode == RAND){	
		playindex = rand() %head->id + 1;
	}
	else if(playmode == LOOP){
		playindex++;
		if(playindex > head->id){
			playindex = 1;
		}
	}
	sprintf(buf, "loadlife %s\n", GetNameMusicList(head, playindex));
	SendCmd(buf);
}

void *revicems(void *arg){
	int fd = ((TT *)arg)->fd;
	PNODE head = ((TT *)arg)->head;
	free(arg);
	char buf[200] = {0};
	int ret;
	char *p;

	while((ret = read(fd, buf, sizeof(buf))) > 0){
	
		if(p = strstr(buf, "ANS_LENGTH") ){
			sscanf(p, "ANS_LENGTH=%f", &music_len);
			printf("A:%.1f\n", music_len);
			SendCmd("get_time_pos\n");
		}
		if(p = strstr(buf, "ANS_TIME_POSITION")){
			
			sscanf(p, "ANS_TIME_POSITION=%f", &playpos);
			printf("B:%.1f\n", playpos);
			
			if(playstatus != PAUSE){
				usleep(100000);	
				SendCmd("get_time_pos\n");
			}
			if(playstatus  == SLICE){
				continue;
			}
			if(playpos+0.2 > music_len && music_len > 0.5){
				
				playstatus = SLICE;
				Slice(head);
				SendCmd("get_time_length\n");
			}
		}
	}
}

void PlayMusic(PNODE head, char *buf){
	int id =atoi(buf);
	playindex = id;
	char *p = NULL;
	char musicname[100];
	p = GetNameMusicList(head, id);
	
	if(playstatus == STOP){
		
		static int Pfd[2];
		playstatus = PLAY;
		pipe(Pfd);
		pid_t pid = vfork();
		if(pid < 0){
			return;
		}
		else if(pid == 0){

			if(access("fifo", F_OK)){

			mkfifo("fifo", 0666);
		}
			close(Pfd[0]);
			dup2(Pfd[1], 1);
			close(2);
			execl("/usr/bin/mplayer","mplayer","-slave","-idle","-quiet","-input","file=./fifo",p,NULL);
		}
		else{
			SendCmd("get_time_length\n");
			pthread_t tid1;
			pthread_t tid2;
			TT *p = (TT *)malloc(sizeof(TT));
			assert(p);
			p->fd = Pfd[0];
			p->head = head;
			pthread_create(&tid1, NULL, revicems, p);
			//pthread_create(&tid2, NULL, showlrc, lrc);
		}
		
	}
	else{
		char cmd[100] = {0};
		sprintf(cmd, "loadfile %s\n", p);
		SendCmd(cmd);
		SendCmd("get_time_length\n");
	}
}

void VolumeMusic(char *cmd){
	char buf[20];
	sprintf(buf, "volume %s 1\n", cmd);
	SendCmd(buf);
}

void MuteMusic(char *cmd){
	char buf[10];
	sprintf(buf, "mute %s\n", cmd);
	SendCmd(buf);
}

void SetPlayMode(char *cmd){
	int flag = atoi(cmd);
	if(flag == 1){
		playmode = SINGLE;
	}
	else if(flag == 2){
		playmode = LOOP;
	}
	else if(flag == 3){
		playmode = RAND;
	}
}

void NextMusic(PNODE head){

	int num = head->id;

	if(playmode == LOOP || playmode == SINGLE){
		playindex++;
		if(playindex > num){
			playindex = 1;
		}
	}
	else{
		playindex = rand() % num +1;
	}

	char *p =GetNameMusicList(head, playindex);
	char buf[100];
	sprintf(buf, "loadfile %s\n", p);
	SendCmd(buf);
	SendCmd("get_time_length\n");
}

void FrontMusic(PNODE head){
	int num = head->id;

	if(playmode == LOOP || playmode == SINGLE){
		playindex--;
		if(playindex == 0){
			playindex = num;
		}
	}
	else{
		playindex = rand() % num +1;
	}

	char *p =GetNameMusicList(head, playindex);
	char buf[100];
	sprintf(buf, "loadfile %s\n", p);
	SendCmd(buf);
	SendCmd("get_time_length\n");
}

void StopMusic(){
	
	if(playstatus == PLAY){
		playstatus = PAUSE;
	}
	else if(playstatus == PAUSE){
		playstatus = PLAY;
		SendCmd("get_time_pos\n");
	}
	usleep(100000);
	
	printf("AAA\n");
	SendCmd("pause\n");
}

void SeekMusic(char *data){
	if(music_len <= 0){
		return;
	}

	int pos = atoi(data);
	float playtime = music_len * (pos / 100.0);
	float p = playtime - playpos;
	char buf[50] = {0};
	sprintf(buf, "seek %.1f", p);
	SendCmd(buf);
}

int order(PNODE head, int cmd, char *data){
	switch(cmd){
		case 0:
			printf("please input music name\n");
			break;
		case 1:
			printf("help:帮助解释命令使用\nlist:查看歌曲");
			break;
		case 2:
			DisplayMusicList(head);
			break;
		case 3:
			if(playstatus != STOP){
				SendCmd("quit\n");
			}
			WriteMusicList(head);
			DestoryMusicList(&head);
			exit(0);
		case 4:
			AddMusic(head, data);
			break;
		case 5:
			AddMusicDir(head, data);
			break;
		case 6:
			PlayMusic(head, data);
			break;
		case 7:
			VolumeMusic(data);
			break;
		case 8:
			MuteMusic(data);
			break;
		case 9:
			StopMusic();
			break;
		case 10:
			SeekMusic(data);
			break;
		case 11:
			SetPlayMode(data);
			break;
		case 12:
			NextMusic(head);
			break;
		case 13:
			
			break;
		case 14:
			FrontMusic(head);
			break;
	}
}

order.h

#ifndef _ORDER_
#define _ORDER_

#include"MusicList.h"

//播放器的播放状态
enum PlayStatus{
	STOP,
	PLAY,
	PAUSE
};

//播放模式
enum PlayMode{
	SINGLE,
	LOOP,
	RAND,
	SLICE
};

typedef struct T{
	int fd;
	PNODE head;
}TT;

//对于输入命令的分析:analysis()函数返回主指令,buf是输入的字符串, src保存并返回附加数据
extern int Analysis(char *buf, char *src);

//根据主命令,执行相应的函数
//参数:(头结点地址,主命令,附件数据。)
extern int order(PNODE head, int cmd, char *data);


#endif


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

正在起飞的蜗牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值