Linux系统下基于mplayer媒体播放器源码

主函数:main.c

#include "public.h"
#include "serial.h"

musicfile_t *pmusic; //记录正在播放哪一首
int main(void)
{
    struct list_head phead;

    INIT_LIST_HEAD(&phead);
    mkfifo("/tmp/myfifo", 0777);

    creat_musiclist(&phead);
    
    pid_t pid1;

    pid1 = fork();

    if (pid1 < 0)
    {
        ERR_MSG("file to fork");
        return -1;
    }
    if (pid1 == 0)
    {
        int fd;
        char tmpbuff[64] = {0};

        fd = opendev("/dev/ttyUSB1");
        set_port(fd, 9600, 8, 1, 'N');

        while (1)
        {
            memset(tmpbuff, 0, sizeof(tmpbuff));
            read(fd, tmpbuff, sizeof(tmpbuff));
            printf("%s\n", tmpbuff);
            
            if(strncmp(tmpbuff, "user_interrupt", 14) == 0)  
            {
                    
            }   
            else if(strncmp(tmpbuff, "play_start", 10) == 0)  
            {
                playMedia(pmusic);
            }

            else if(strncmp(tmpbuff, "play_pause", 10) == 0)  
            {
                playPause();
            }   
            else if(strncmp(tmpbuff, "play_stop", 9) == 0)  
            {
                Stop();
            }
            else if(strncmp(tmpbuff, "next_media", 10) == 0)  
            {
                nextMusic();
            }   
            else if(strncmp(tmpbuff, "previous_media", 14) == 0)  
            {
                preMusic();
            }  
	    }
    }


    signal(SIGCHLD, ModeOfWork);
    showTerminal();	                //显示菜单
    while (1)
	{
        int n = 0; 
		printf("请选择:");
		scanf("%d", &n);			//输入需要选择的功能序号

		switch (n)					//条件分支进行选择执行相应功能
		{
            case 1: show_music(&phead); //查看播放链表
            break;
            case 2: playPause();
            break;
            case 3: Stop();
            break;
            case 4: preMusic();
            break;
            case 5: nextMusic();
            break;
            case 6: addSpeed();
            break;
            case 7: seekPosition();
            break;
            case 8: changeModeOfWork();
            break;
            case 9: distory_musiclist(&phead);
                    exit(0);
            break;
		}
        getchar();
        showTerminal();         //显示菜单
	}

    distory_musiclist(&phead);
    return 0;
}

功能函数:

#include "public.h"
// 声明全局变量
extern musicfile_t *pmusic;

MplayerStat_en MplayerStat; //播放状态
MplayerSpeed_en Mplayerspend; //播放速度
MplayerMode_en MplayerMode  = MPLAYER_MODE_SINGLE; //播放模式
pid_t pid = -1;
int fileNum = 0;
struct list_head *head = NULL;



int Pause(void);
int ContinuePlayback(void);


//打印媒体播放器菜单
int showTerminal(void)
{
	printf("============= 媒体播放器 =============\n");
	printf("1.查看播放列表\n");
	printf("2.开始/暂停\n");
	printf("3.停止\n");
	printf("4.上一曲\n");
	printf("5.下一曲\n");
	printf("6.快进\n");
	printf("7.定位\n");
	printf("8.播放方式\n");
	printf("9.退出\n");
	printf("======================================\n");

	return 0;
}

//创建链表并存储
int creat_musiclist(struct list_head *phead)
{
    head = phead;
    pmusic = list_entry(phead, musicfile_t, node);
    DIR *dir = opendir("/home/linux/Music");
    if (dir == NULL) {
        perror("Failed to open directory");
        return -1;
    }

    MplayerStat = MPLAYER_STAT_FREE;
    struct dirent *music;
    char *str = NULL;

    while ((music = readdir(dir)) != NULL)
    {
        str = music->d_name;
        while (*str != '.' && *str != '\0')
        {
            str++;
        }

        if (*str == '\0')
        {
            continue;
        }
        
        if (strcmp(str, ".mp3") == 0 || strcmp(str, ".mp4") == 0 || strcmp(str, ".avi") == 0|| strcmp(str, ".rmvb") == 0|| strcmp(str, ".flv") == 0)
        {
            fileNum++;
            musicfile_t *pdata = NULL;

            pdata = malloc(sizeof(musicfile_t));
            if (pdata == NULL)
            {
                return -1;
            }

            strcpy(pdata->filepath, "/home/linux/Music/");
            strcat(pdata->filepath, music->d_name);

            strcpy(pdata->name, music->d_name);
            list_add(&pdata->node, phead);
            
        }
    }


    closedir(dir);
    return 0;
}

//查看目录
int show_music(struct list_head *phead)
{
    struct list_head *ptmpnode1 = NULL;
    if (list_empty(phead)) {
        printf("No music files found\n");
        return -1;
    }
    musicfile_t *ptmpnode = NULL;
    printf("============= 音乐列表 =============\n");
    list_for_each_entry(ptmpnode, phead, node) 
    {
        printf("%s\n", ptmpnode->name);
    }
    printf("====================================\n");

    while (1)
    {  
        ptmpnode1 = phead;
        int i = 0;
        int n;
        printf("请输入你要打开的音乐或视频:\n(输入0返回上一级)\n");
        scanf("%d", &n);

        if (n == 0)
        {
            break;
        }

        if (MplayerStat != MPLAYER_STAT_FREE)
        {
            kill(pid, SIGKILL);
        }
        for (i = 0; i < n; i++)
        {
           ptmpnode1 = ptmpnode1->next;
        }
        
        playMedia(list_entry(ptmpnode1, musicfile_t, node));
    }
    pmusic = list_entry(ptmpnode1, musicfile_t, node);
    
    return 0;
}

int  playMedia(musicfile_t *ptmpmusic)
{
    if (head == &ptmpmusic->node)
    {
        ptmpmusic = list_entry((&ptmpmusic->node)->next, musicfile_t, node);
        pmusic = ptmpmusic;
    }
    pid = fork();

    if (pid < 0)
    {
        ERR_MSG("file to fork");
        return -1;
    }
    if (pid == 0)
    {
        close(1);	//关闭stdout
		close(2);	//关闭stderr
		execlp("mplayer", "mplayer", "-slave", "-input", "file=/tmp/myfifo", ptmpmusic->filepath, NULL);
        
    }

    MplayerStat = MPLAYER_STAT_PLAY; //播放状态

    
    return 0;
}


int Stop()
{
    int fd = 0;

    fd = open("/tmp/myfifo", O_RDWR);
    if (-1 == fd)
    {
        ERR_MSG("file to open");
    }

    write(fd, "quit\n", 5);
    close(fd);
    
    kill(pid, SIGKILL);

    MplayerStat = MPLAYER_STAT_FREE;

    return 0;
}

int playPause(void)
{
    if (MplayerStat == MPLAYER_STAT_FREE)
    {
        show_music(&pmusic->node);
        MplayerStat = MPLAYER_STAT_PAUSE;
    }else if (MplayerStat == MPLAYER_STAT_PLAY)
    {
        Pause();
        MplayerStat = MPLAYER_STAT_PAUSE;
    }else if (MplayerStat == MPLAYER_STAT_PAUSE)
    {
        ContinuePlayback();
        MplayerStat = MPLAYER_STAT_PLAY;
    }
    return 0;
}

//暂停播放
int Pause(void)
{
    int fd = 0;

    fd = open("/tmp/myfifo", O_RDWR);
    if (-1 == fd)
    {
        ERR_MSG("file to open!");
        return -1;
    }

    write(fd, "pause\n", 6);

    close(fd);

    MplayerStat = MPLAYER_STAT_PAUSE;

	return 0;
}

//继续播放
int ContinuePlayback(void)
{
    int fd = 0;

    fd = open("/tmp/myfifo", O_RDWR);

    if (-1 == fd)
    {
        ERR_MSG("file to open!");
    }

    write(fd, "pause\n", 6);
    
    close(fd);

    MplayerStat = MPLAYER_STAT_PLAY;
       
    
}
//切换下一曲
int nextMusic(void)
{
	kill(pid, SIGKILL);
    
    pmusic = list_entry((&pmusic->node)->next, musicfile_t, node);
	playMedia(pmusic);
	return 0;
}

//切换上一曲
int preMusic(void)
{
	kill(pid, SIGKILL);
    if (head == pmusic->node.prev)
    {
        pmusic = list_entry(head->prev, musicfile_t, node);
        
    }else
    {
        pmusic = list_entry((&pmusic->node)->prev, musicfile_t, node);
    }
	playMedia(pmusic);
	
	return 0;
}
//加速视频播放
int addSpeed(void)
{
	int fd = -1;
	char cmdbuf[128] = {0};
	int n = -1;

	fd = open("/tmp/myfifo", O_RDWR);
	if (-1 == fd)
	{
		ERR_MSG("open myfifo failed!fail to pause!");
		return -1;
	}

	printf("请输入你需要设置的视频速度:");
	scanf("%d", &n);
	getchar();
	sprintf(cmdbuf, "speed_set %d\n", n);
	write(fd, cmdbuf, strlen(cmdbuf));

	printf("当前播放%d倍速!\n", n);
	if (1 == n)
	{
		Mplayerspend = MPLAYER_SPEED_ONE;
	}
	else if (2 == n)
	{
		Mplayerspend = MPLAYER_SPEED_TWO;
	}
	else if (4 == n)
	{
		Mplayerspend = MPLAYER_SPEED_FOUR;
	}

	close(fd);

	return 0;
}

//定位视频播放的位置(秒计时)
int seekPosition(void)
{
	int fd = -1;
	char cmdbuf[128] = {0};
	int n = -1;

	fd = open("/tmp/myfifo", O_RDWR);
	if (-1 == fd)
	{
		ERR_MSG("open myfifo failed!fail to pause!");
		return -1;
	}

	printf("请输入你需要跳转的位置:");
	scanf("%d", &n);
	getchar();
	sprintf(cmdbuf, "seek %d 2\n", n);
	write(fd, cmdbuf, strlen(cmdbuf));

	close(fd);

	return 0;
}

void distory_musiclist(struct list_head *phead)
{
    musicfile_t *ptmpnode1 = NULL;
    musicfile_t *ptmpnode2 = NULL;
    list_for_each_entry_safe(ptmpnode1, ptmpnode2, phead, node)
    {
        free(ptmpnode1);
    }
    return;
}

//顺序循环
int single()
{
    if ((&pmusic->node)->next != NULL)
    {
       nextMusic();
    }
    return 0;
}


int order()
{
    if ((&pmusic->node)->next != NULL)
    {
       playMedia(pmusic);
    }
    return 0;
}
int randommode()
{
    if ((&pmusic->node)->next != NULL)
    {
        int i = 0;
        srand(time(NULL));
    
        // 生成一个随机数
        int random_number = rand() % fileNum;
        for (i = 0; i < random_number; i++)
        {
            pmusic = list_entry((&pmusic->node)->next, musicfile_t, node);
        }
        
        playMedia(pmusic);
    }
    return 0;
}
//切换视频的播放状态
int changeModeOfWork(void)
{
	if (MplayerMode == MPLAYER_MODE_RANDOM)
	{
		MplayerMode = MPLAYER_MODE_SINGLE;
		printf("当前单曲循环\n");
	}
	else if (MplayerMode == MPLAYER_MODE_SINGLE)
	{
		MplayerMode = MPLAYER_MODE_ORDER;
		printf("当前顺序播放\n");
	}
	else if (MplayerMode == MPLAYER_MODE_ORDER)
	{
		MplayerMode = MPLAYER_MODE_RANDOM;
		printf("当前随机播放\n");
	}

	return 0;
}

void ModeOfWork(int sig)
{
    
    int status;

	wait(&status);
	if (WIFEXITED(status))
	{	
        if (MplayerMode == MPLAYER_MODE_SINGLE)
        {
            order();
        }

        if (MplayerMode == MPLAYER_MODE_ORDER)
        {
            
            single();
        }

        if (MplayerMode == MPLAYER_MODE_RANDOM)
        {
            randommode();
        }
    }
}

头文件:

#ifndef _PUBLIC_H_
#define _PUBLIC_H_

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "list.h"
#include 
#include 

typedef struct musicfile
{
    struct list_head node;
    char name[256];         //文件名
    char filepath[256];     // 文件路径

}musicfile_t;

/* mplayer 播放速度 */
typedef enum __mplayer_speed__
{
	MPLAYER_SPEED_ONE,
	MPLAYER_SPEED_TWO,
	MPLAYER_SPEED_FOUR,
}MplayerSpeed_en;

/* mplayer 播放状态 */
typedef enum __mplayer_stat__
{
	MPLAYER_STAT_FREE,
	MPLAYER_STAT_PLAY,
	MPLAYER_STAT_PAUSE,
}MplayerStat_en;


/* mplayer 播放模式 */
typedef enum __mplayer_mode__
{
	MPLAYER_MODE_SINGLE,
	MPLAYER_MODE_ORDER,
	MPLAYER_MODE_RANDOM,
}MplayerMode_en;

// 声明全局变量
extern musicfile_t *pmusic;
extern int show_music(struct list_head *phead);
extern int creat_musiclist(struct list_head *phead);
extern void distory_musiclist(struct list_head *phead);
extern int showTerminal(void);
extern int preMusic(void);
extern int nextMusic(void);
extern int playMedia(musicfile_t *ptmpmusic);
extern int Stop(void);
extern void ModeOfWork(int sig);
extern int playPause(void);
extern int addSpeed(void);
extern int seekPosition(void);
int changeModeOfWork(void); //切换视频的播放状态

//打印出错信息
#define ERR_MSG(message) do{\
    printf("[%s%4d]%s:%s\n", __FILE__, __LINE__, message, strerror(errno));\
}while(0)

#define GET_START_TIME do{\
    gettimeofday(&starttime, NULL);\
}while(0)

#define GET_END_TIME do{\
    gettimeofday(&endtime, NULL);\
}while(0)

#define GET_CONST_TIME  (((endtime.tv_sec * 1000000 + endtime.tv_usec) - (starttime.tv_sec * 1000000 + starttime.tv_usec)) / 1000.0)

struct timeval starttime;
struct timeval endtime;
#endif

语音模块功能函数:

#include "serial.h"


/*============================================================
*
*===========================================================*/
int opendev(char *dev)
{
    int fd = open(dev, O_RDWR); // O_NOCTTY O_NDELAY
    if (-1 == fd) 
    {
        fprintf (stderr, "opendev err: %s\n", strerror(errno));
        exit (EXIT_FAILURE);
    }
    return fd;
}

/*============================================================
*
*===========================================================*/

void set_port(int fd, int speed, int databits, int stopbits, int parity)
{
    set_speed (fd, speed);
    if (!set_parity(fd, databits, stopbits, parity)) 
    {
        fprintf (stderr, "set_parity err: %s\n", strerror(errno));
        exit (EXIT_FAILURE);
    }
}

/*============================================================
*
*===========================================================*/

int speed_arr[]= {B38400, B19200, B9600, B4800, B2400, B1200, B300,B38400, B19200, B9600, B4800, B2400, B1200, B300,};
int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300,38400, 19200, 9600, 4800, 2400, 1200, 300, };

void set_speed(int fd, int speed)
{
    int i;
    int status;
    struct termios opt; //定义了这样一个结构
    
    tcgetattr(fd, &opt); //用来得到机器原端口的默认设置
    for (i = 0; i < sizeof(speed_arr)/sizeof(speed_arr[0]); i++) 
    {
        if (speed == name_arr[i]) 
        {
            tcflush(fd, TCIOFLUSH); //刷新输入输出缓冲
            cfsetispeed(&opt, speed_arr[i]); //这里分别设置
            cfsetospeed(&opt, speed_arr[i]);//这是立刻把rates设置真正写到串口中去
            status = tcsetattr(fd, TCSANOW, &opt);
            if (status != 0)
            perror("tcsetattr fd1"); //设置错误
            return ;

        }
        tcflush(fd,TCIOFLUSH); //同上
    }
}
/*============================================================
*设置数据位、校验位和停止位
*===========================================================*/
int set_parity(int fd, int databits, int stopbits, int parity)
{
    struct termios options; //定义一个结构

    if (tcgetattr(fd, &options) != 0)   
    {
        perror("SetupSerial 1");
        return 0;
    }
    options.c_cflag &= ~CSIZE; //这是设置c_cflag选项不按位数据位掩码
    switch (databits) /*设置数据位数*/
    {
        case 7:
            options.c_cflag |= CS7; //设置c_cflag选项数据位为7位
            break;
        case 8:
            options.c_cflag |= CS8; //设置c_cflag选项数据位为8位
            break;
        default:
            fprintf(stderr,"unsupported data size\n"); //其他的都不支持

        return 0;
    }
    switch (parity) //设置奇偶校验,c_cflag和c_iflag有效
    {
        case 'n':
        case 'N': //无校验 当然都不选
            options.c_cflag &= ~PARENB; /* Clear parity enable */
            options.c_iflag &= ~INPCK; /* Enable parity checking*/
            break;
        case 'o': //奇校验 其中PARENB校验位有效;PARODD奇校验
        case 'O':
            options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
            options.c_iflag |= INPCK; /* Disnable parity checking */
            break;
        case 'e':
        case 'E': //偶校验,奇校验不选就是偶校验了
            options.c_cflag |= PARENB;/* Enable parity */
            options.c_cflag &= ~PARODD;/* 转换为偶效验*/
            options.c_iflag |= INPCK; /* Disnable parity checking */
            break;
        default:
            fprintf(stderr,"Unsupported parity\n");

        return (0);
    }

/* 设置停止位*/
    switch (stopbits) //这是设置停止位数,影响的标志是c_cflag
    {
        case 1:
            options.c_cflag &= ~CSTOPB; //不指明表示一位停止位
            break;
        case 2:
            options.c_cflag |= CSTOPB; //指明CSTOPB表示两位,只有两种可能
            break;
        default:
            fprintf(stderr, "unsupported stop bits\n");

        return (0);
    }
    /* Set input parity option */
    if (parity != 'n') //这是设置输入是否进行校验
    options.c_iflag |= INPCK;
    // 这个地方是用来设置控制字符和超时参数的,一般默认即可。稍微要注意的是c_cc数组的VSTART 和 VSTOP 元素被设定成DC1 和 DC3,代表ASCII 标准的XON和XOFF字符。所以如果在传输这两个字符的时候就传不过去,这时需要把软件流控制屏蔽
    options.c_iflag &= ~(IXON | IXOFF | IXANY);
    options.c_cc[VTIME] = 150; // 15 seconds
    options.c_cc[VMIN] = 0;
    tcflush(fd,TCIFLUSH); //刷新和立刻写进去
    if (tcsetattr(fd,TCSANOW,&options) != 0) 
    {
        perror("SetupSerial 3");
        return 0;
    }

    //在makefile编译中新加入依赖
    return 1;
}
//END FILE

语音模块头文件:

#ifndef __SERIAL_H__
#define __SERIAL_H__

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
/*
* linux
*/
#define GPS_TTY_PORT "/dev/ttyUSB0"

int opendev(char *dev);
void set_speed(int fd, int speed);
int set_parity(int fd,int databits,int stopbits,int parity);
void set_port(int fd, int speed, int databits, int stopbits, int
parity);

#endif

你可能感兴趣的:(linux,运维,服务器)