前几天在千锋做了一个歌词歌曲同步的项目,今天我分享出来
main.c中
/* ************************************************************************
* Filename: main.c
* Description:
* Version: 1.0
* Created: 2020年03月09日 20时18分38秒
* Revision: none
* Compiler: gcc
* Author: YOUR NAME (),
* Company:
* ************************************************************************/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <unistd.h>
#include"main.h"
#include"vd.h"
void test(LRC*head);
int main(int argc, char *argv[])
{
char *file_data=NULL;
long file_len = 0;
FILE *fp = NULL;
fp = fopen("简单爱.lrc","r");
if(fp == NULL)
{
perror("fopen");
return;
}
//需求:一次性的将文件数据 读取到 内存中
//1、得到文件的总大小
//a、使用fseek 将文件指针 定位到文件尾部
fseek(fp, 0, 2);
//b、使用ftell计算文件的偏移量 == 文件的总大小
file_len = ftell(fp);
//c、使用rewind复位文件流指针
rewind(fp);
//2、根据文件的总大小 合理申请 内存空间
file_data = (char *)calloc(1,file_len+1);//+1的目的 内存末尾存放'\0'
if(file_data == NULL)
{
fclose(fp);
return;
}
//3、一次性 将文件数据 读入到 内存空间
fread(file_data, file_len, 1, fp);
//4、遍历读取到的文件内容
//printf("file_len=%ld\n", file_len);
//printf("%s\n", file_data);
char *ar2[128] = {NULL};//定义一个数组来存放分割好的函数
int i=0;
ar2[i]=strtok(file_data ,"\r\n");//第一次分割
int m=0;
while(ar2[i]!=NULL)//第二次以后的分割
{
i++;
ar2[i]=strtok(NULL,"\r\n");
m=i;
}
//printf("%d\n",m);
/*
i=0;
while(ar2[i] != NULL)
{
printf("%s\n",ar2[i]);
i++;
}
*/
int n=0;
int t=0;
LRC tmp;
LRC *head={NULL};
char *p[4]={"歌名","歌手","专辑","制作"};
for(n=0;n<4;n++)
{
char tmp[128]="";
sscanf(ar2[n],"%*[^:]:%[^]]",tmp);//ppp‐‐简单
cusor_moveto(15,n+1);
printf("%s:%s\n",p[n],tmp);
//cusor_moveto(20,n);
//printf("%s\n",ppp);
}
n=4;
for(n=4;n<m;n++)
{
char *str_lrc = ar2[n];
while(*str_lrc == '[')
str_lrc +=10;
char *str_time = ar2[n];
while(*str_time == '[')
{
int m = 0,s = 0;
int time = 0;
sscanf(str_time,"[%d:%d.64]", &m,&s);
time =m*60+s;//以秒为单位
//将时间 和 歌词 一一对应 放入 结构体
tmp.time = time;
strcpy(tmp.lrc, str_lrc);
//printf("%d,%s\n",time,str_lrc);
//调用链表的有序插入函数
head = insert_link(head,tmp);
//分析下一个时间
str_time += 10;
}
}
test(head);
return 0;
}
void test(LRC*head)
{
char buf1[128]="";
char buf2[128]="";
char buf3[128]="";
char buf4[128]="";
//启动maplayer(见后面)
mplayer_play("简单爱.mp3");
int i=0;
while(1)
{
cusor_moveto(20,3);
printf("\r%02d:%02d",i/60,i%60);
fflush(stdout);
//到链表查询
LRC *ret = search_link(head,i);
if(ret != NULL)
{
//滚起来
strcpy(buf1,buf2);
strcpy(buf2,buf3);
strcpy(buf3,buf4);
strcpy(buf4, ret->lrc);
cusor_moveto(15,6);
printf("%s", buf1);
cusor_moveto(15,7);
printf("%s", buf2);
cusor_moveto(15,8);
printf("%s", buf3);
cusor_moveto(15,9);
set_fg_color(COLOR_RED);
printf("%s", buf4);//当前歌词
set_fg_color(COLOR_BLACK);
fflush(stdout);
//printf("%s\n", ret->lrc);
}
sleep(1);//休眠1s
i++;
}
}
/*
//判断链表是否存在
if(head == NULL)
{
printf("link not found\n");
return;
}
else//链表存在
{
LRC *pb =head;
do
{
//访问节点内容
printf("time=%d, lrc=%s\n", pb->time,pb->lrc);
pb=pb->next;
}
while (pb != NULL);
}
return;
*/
main.h中
/* ************************************************************************
* Filename: main.h
* Description:
* Version: 1.0
* Created: 2020年03月09日 21时04分53秒
* Revision: none
* Compiler: gcc
* Author: YOUR NAME (),
* Company:
* ************************************************************************/
#ifndef __MAIN_H__
#define __MAIN_H__
typedef struct stu //名字是stu
{
int time;
char lrc[128];
struct stu *next;
}LRC;//类型是LRC
#endif
extern void mplayer_play(char * song_path);
extern LRC *insert_link(LRC*head,LRC ccc);
extern LRC *search_link(LRC*head,int k);
vd.c中
/* ************************************************************************
* Filename: vd.c
* Description:
* Version: 1.0
* Created: 2020年03月11日 11时16分57秒
* Revision: none
* Compiler: gcc
* Author: YOUR NAME (),
* Company:
* ************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "vd.h"
void cusor_moveto(int x, int y)
{// ESC[y;xH
printf("\033[%d;%dH",y,x);
fflush(stdout);
}
//保存光标位置
void cusor_get_pos(void)
{// ESC[s
printf("\033[s");
fflush(stdout);
}
//恢复光标位置
void cusor_set_pos(void)
{// ESC[u
printf("\033[u");
fflush(stdout);
}
//隐藏光标
void cusor_hide(void)
{
printf("\033[?25l");
}
//显示光标
void cusor_show(void)
{
printf("\33[?25h");
}
//清屏
void clear_screen(void)
{// ESC[2J
printf("\033[2J");
fflush(stdout);
}
/*
COLOR_RED 红
COLOR_BLACK 黑
COLOR_GREEN 绿
COLOR_BLUE 蓝
COLOR_YELLOW 黄
COLOR_WHITE 白
COLOR_CYAN 青
COLOR_MAGENTA 洋红
*/
//设置前景颜色
void set_fg_color(int color)
{// ESC[#m
printf("\033[%dm",color);
fflush(stdout);
}
//设置背景颜色
void set_bg_color(int color)
{// ESC[#m
printf("\033[%dm",(color+10));
fflush(stdout);
}
vd.h中
/* ************************************************************************
* Filename: vd.h
* Description:
* Version: 1.0
* Created: 2020年03月11日 11时17分17秒
* Revision: none
* Compiler: gcc
* Author: YOUR NAME (),
* Company:
* ************************************************************************/
#ifndef _VD_H_
#define _VD_H_
#define COLOR_RED 31
#define COLOR_BLACK 30
#define COLOR_GREEN 32
#define COLOR_BLUE 34
#define COLOR_YELLOW 33
#define COLOR_WHITE 37
#define COLOR_CYAN 36
#define COLOR_MAGENTA 35
/*
COLOR_RED 红
COLOR_BLACK 黑
COLOR_GREEN 绿
COLOR_BLUE 蓝
COLOR_YELLOW 黄
COLOR_WHITE 白
COLOR_CYAN 青
COLOR_MAGENTA 洋红
*/
extern void cusor_moveto(int x, int y);//光标跳转到 y行 x列
extern void cusor_get_pos(void);//保存光标位置
extern void cusor_hide(void);//隐藏光标
extern void cusor_show(void);//显示光标
extern void cusor_set_pos(void);//恢复光标位置
extern void clear_screen(void);//清屏
extern void set_fg_color(int color);//设置字体前景色
extern void set_bg_color(int color);//设置字体背景色
#endif //_VD_H_
vs.c中
/* ************************************************************************
* Filename: vs.c
* Description:
* Version: 1.0
* Created: 2020年03月09日 21时05分41秒
* Revision: none
* Compiler: gcc
* Author: YOUR NAME (),
* Company:
* ************************************************************************/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <unistd.h>
#include"main.h"
LRC *search_link(LRC*head,int i);
void mplayer_play(char * song_path);
LRC *insert_link( LRC*head,LRC ccc)
{
//1.给待插入的节点pi申请对空间
LRC *pi=(LRC*)calloc(1,sizeof(LRC));
if(pi == NULL)
{
perror("calloc");
return head;
}
//2.将ccc 的内容 赋值给*pi
*pi = ccc;//有点疑问-------
pi->next=NULL;
//3.链表节点pi的插入
if(head == NULL)//链表不存在
{
head = pi;
return head;
}
else//存在
{
//a、寻找插入点
LRC *pb = head, *pf = head;
while(pb->time < pi->time && pb->next != NULL)
{
pf = pb;
pb = pb->next;
}
//b、插入点的判断
if(pb->time >= pi->time)//头部 中部插入
{
if(pb == head)//头部之前插入
{
pi->next = head;
head = pi;
return head;
}
else//中部插入
{
pf->next = pi;
pi->next = pb;
return head;
}
}
else//尾部插入
{
pb->next = pi;
return head;
}
}
}
LRC *search_link(LRC *head, int k)
{
//1、判断链表是否存在
if(head == NULL)//不存在
{
printf("link not found\n");
}
else//链表存在
{
LRC *pb = head;
do
{
if(pb->time==k)
{
return pb;
}
else
{
pb=pb->next;
}
} while (pb->next!=NULL);
}
return NULL;
}
void mplayer_play(char * song_path)
{
pid_t pid;
pid=fork();
if(pid<0)
{
perror("fork");
}
else if(pid==0)
{
close(1);
close(2);
execlp("mplayer","mplayer","-slave","-quiet",song_path,NULL);
exit(0);
}
else
;
}