mplayer项目(linux环境)

基本功能

  1. 播放歌曲
  2. 前台控制:播放、暂停、上一首、下一首。
  3. 显示当前歌曲列表。
  4. 显示歌曲信息(歌曲总长度、当前播放时间、歌曲进度百分比、歌手名)。
  5. 自动播放下一首。
  6. 同步显示歌词(扩展)。

流程图

mplayer项目(linux环境)_第1张图片


mplayer启动方式

execlp("mplayer", "mplayer", "-slave", "-quiet", "-idle", "-input", "file=./cmdfifo", name, NULL);
//cmdfifo是命名管道,当写入命令数据后,mplayer自动读取执行
//name是带路径的歌曲名称

参数:

  1. -slave 运行在从模式,从命令行读取以新行(\n)分隔开的命令行。
  2. -quiet 使得控制台输出消息较少。
  3. -idle 播放至文件结尾后,mplayer不退出。
  4. -input file=./cmdfifo 通过命令管道 ./cmdfifo获取命令。
  5. ./ShapeofMyHeart.mp3 歌曲的路径 +文件名。
  6. NULL exec 系统调用必备。

Mplayer在 slave模式下常用的命令

  1. loadfile string //播放 string指定的歌曲
  2. volume x 1 //设置音量
  3. mute 1/0 //静音开关, 1:静音, 0:取消静音
  4. pause //暂停 //取消暂停
  5. seek value //快进或退的秒数, value为正时,快进; value为负时,快退。
  6. get_percent_pos //获取文件的播放进度(百分比: 0-100)
  7. get_time_pos //获得文件的当前位置,以秒为单位,精确到小数点后 1位。
  8. get_file_name //获得当前播放的文件名
  9. get_time_length //获得文件的长度,以秒为单位
  10. get_meta_album //获得文件的“专辑”元数据
  11. get_meta_artist //获得文件的“艺术家”元数据
  12. get_meta_commnet //获得文件的“评论”元数据
  13. get_meta_genre //获得文件的“流派”元数据
  14. get_meta_title //获得文件的“标题”元数据
  15. get_meta_year //获得文件的“年份”元数据

程序下载

https://download.csdn.net/download/mrhjlong/9625748


main.c 代码

自我批评:
程序应减少使用较多的全局变量,防止函数里重命名就行覆盖,产生问题。
项目整体结构还可以调整地更好、更加清晰明了。

/*************************************************************************
	> File Name: mplayer.c
	> Author: mrhjlong
	> Mail: [email protected] 
	> Created Time: 2016年07月23日 星期六 15时27分19秒
 ************************************************************************/

#include "songplay.h"

extern int flag;	//显示数据标志	1:显示  0:不显示
extern Song *pnow;	//当前歌曲结点指针
extern Song *plast;	//最后一个歌曲结点指针(使用的是双向链表,不是双向循环链表,可以改进)
extern int clsthread;	//关闭线程标志
extern int flagpause;	//暂停标志
extern int fdpp[2];		//无名管道
extern sem_t sem;		//信号量

int main(void)
{
	List_head *linklist = get_song_list("./");
	node_print(linklist);
	pnow = linklist->head;
	char name[NAMESIZE] = {0};
	strcat(name, "./");
	strcat(name, pnow->name);
	
	int ret = sem_init(&sem, 0, 1);  //信号量初始化
	if(ret == -1)
		err_sys("sem_init error");
	
	if(access("./cmdfifo", F_OK) == 0) //判断命名管道是否存在,有则删除,重新新建
	{
	//	printf("cmdfifo exist\n");
		unlink("./cmdfifo");
		mkfifo("./cmdfifo", 0777);
	}
	else
	{
		mkfifo("./cmdfifo", 0777);
	}

	if(pipe(fdpp) < 0)
		err_sys("pipe error");
	
	fcntl(fdpp[0], F_SETFL, O_NONBLOCK); //无名管道设为非阻塞

	pid_t pid = fork();  //创建进程
	if(pid < 0)
		err_sys("fork error");
	else if(pid == 0)  //子进程
	{	
		close(fdpp[0]);
		dup2(fdpp[1], 1);   //将标准输出定向到无名管道的写入
		execlp("mplayer", "mplayer", "-slave", "-quiet", "-idle", "-input", "file=./cmdfifo", name, NULL);	//命名管道cmdfifo有命令数据,mplayer会自动读取
	}
	else   //父进程
	{
		close(fdpp[1]);
		sleep(1);
		
		pthread_t get_tid1, get_tid2, get_tid3;
		ret = 0;
		
		//创建处理线程
		ret = pthread_create(&get_tid1, NULL, getcmd_thread, (List_head *)linklist);
		if(ret != 0)
			err_sys("pthread_create error");
		
		ret = pthread_create(&get_tid2, NULL, datacmd_thread, NULL);
		if(ret != 0)
			err_sys("pthread_create error");
		
		//sleep(1);
		//char data[1024] = {0};
		//read(fd[0], data, 1024); //清除冗余信息
		ret = pthread_create(&get_tid3, NULL, read_thread, (List_head *)linklist);
		if(ret != 0)
			err_sys("pthread_create error");
			
		//等待线程结束		
		pthread_join(get_tid1, NULL);
		pthread_join(get_tid2, NULL);
		pthread_join(get_tid3, NULL);
		sem_destroy(&sem);  //销毁信号量
		list_destroy(linklist);   //销毁链表
	}
	
	//sleep(1);
	return 0;
}


songplay.h 代码

/*************************************************************************
	> File Name: songplay.h
	> Author: mrhjlong
	> Mail: [email protected] 
	> Created Time: 2016年07月24日 星期日 13时08分01秒
 ************************************************************************/

#ifndef __SONGPLAY_H
#define __SONGPLAY_H

#include
#include"common.h"
#include"songplay.h"
#include
#include
#include
#include
#include
#include

#define NAMESIZE 50

struct song
{
	char name[NAMESIZE];
	struct song *next;
	struct song *prev;
};

struct list_head
{
	struct song *head;
	int song_num;
};

typedef struct song Song;
typedef struct list_head List_head;

//创建链表头
List_head *head_create(void);

//创建结点
Song *node_create(char *name);

//添加结点到链表尾部
void node_insert_tail(List_head *linklist, Song *pSong);

//打印整张链表
void node_print(List_head *linklist);

//查找结点数据,返回结点地址,失败返回NULL
Song *node_search(List_head *linklist, char *name);

//销毁整张链表
void list_destroy(List_head *linklist);

//获得歌曲链表
List_head *get_song_list(char *pathname);

//带空格的歌曲名转换格式,空格前加"\"
void chgform(char *name);

//切换歌曲
void chgsong(char *name);

//处理线程读取的数据
void deal_data(char *data);

//获取按键输入命令-线程
void *getcmd_thread(void *arg);

//读取数据并处理-线程
void *read_thread(void *arg);

//定时发送命令获取数据-线程
void *datacmd_thread(void *arg);

#endif


你可能感兴趣的:(小程序,mplayer,linux,进程,线程,管道)