主函数: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