当前位置: 首页 > news >正文

用链表、信号,实现简易MP3项目

链表实现MP3

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <glob.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>

typedef struct MP3Node
{
	char *filename;//数据域,存储指针,里面存储歌曲名
	struct MP3Node *next;//指针域
}MP3Node;

void mp3_dvd();
void mp3_caidanname(char * dir1);
void kill_kill(MP3Node *head);
MP3Node *upup(MP3Node *head,MP3Node *nowmusic, char *dir1);
MP3Node *nextnext(MP3Node *head,MP3Node *nowmusic, char *dir1);
void free_head(MP3Node *head);

pid_t pid;//全局变量

int main(int argc, char *argv[])
{
	char *dir1 = argv[1];//输入要播放的目录
	mp3_caidanname(dir1);
	return 0;
}

void mp3_dvd(char *dir1, char *filename)
{
	raise(19);//子进程近来先暂停播放
	char path[100];
	snprintf(path, sizeof(path), "%s/%s", dir1,filename);
	execlp("mpg123","mpg123",path,NULL);
	exit(EXIT_FAILURE);// 确保子进程退出
}

void mp3_caidanname(char * dir1)
{
	int count = 0;//记录歌曲数量
	
	MP3Node *head = NULL;//头指针
	MP3Node *tail = NULL;//尾指针
	MP3Node *nowmusic = NULL;//现在播放的歌曲
	
	DIR *dirp = NULL;
	dirp = opendir(dir1);//打开目录
	if(dirp == NULL)
	{
		perror("opendir");
	}
	struct dirent *dent = NULL;
	while((dent = readdir(dirp)))
	{
		if(dent->d_type == 8)//DT_REG,普通文件
		{
			char *filename = dent->d_name;//歌曲名字全存到数据域中
			//if(strstr(filename, ".mp3")) ,,char *strstr(const char *haystack, const char *needle);
			//strstr()函数返回一个指向haystack中第一次出现needle的指针。如果未找到子字符串,则返回NULL。
			if(strstr(filename, ".mp3"))
			{
				count++;
				MP3Node *newfile = (MP3Node *)malloc(sizeof(MP3Node));//重新定义一个newfile保存刚的filename
				newfile->filename = strdup(filename);//strdup从堆上分配一块内存,并将传入的字符串复制到这块内存中,然后返回这块内存的指针
				newfile->next = NULL;
				if(head == NULL)//第一次运行为空
				{
					head = newfile;//头指针不动
					tail = newfile;
				}
				else//第二次往后链接
				{
					tail->next = newfile;//尾指针往后连接
					tail = newfile;
				}
			}
		}
	}
	closedir(dirp); // 关闭目录
	if(count == 0)
	{
		printf("此文件夹无歌曲!\n");
		free_head(head);
		return ;
	}
	
	/*glob_t fn = {0};//显示歌单
	glob("./mp3file/*.mp3", 0, NULL, &fn);
	for(int i = 0; i < fn.gl_pathc; i++)
	{
		printf("%d.%s\n", i+1,fn.gl_pathv[i]);//glob函数打印歌单
	}
	globfree(&fn);*/
	
	printf("歌单如下:\n");
	MP3Node *menu = head;
	int i = 1;
	while(menu != NULL)
	{
		printf("%d.%s\n", i++, menu->filename);
		menu = menu->next;
	}
	
	int nummusic = 0;//选择要播放的音乐
	printf("请选择要播放的音乐:\n");
	scanf("%d", &nummusic);
	nowmusic = head;//nowmusic指向第一个歌曲
	for(int i = 1; i < nummusic; i++)//遍历找到选中的歌曲,例如num = 2,执行一次循环
	{
		nowmusic = nowmusic->next;//找到第2个数据
	}
	
	pid = fork();
	if(pid == -1)
	{
		perror("fork");
		free_head(head);
		return ;
	}
	else if(pid == 0)
	{
		mp3_dvd(dir1,nowmusic->filename);
	}
	else
	{
		int val = 0;
		
		while(1)
		{
			waitpid(pid, NULL, WNOHANG);//检测子进程是否结束
			if(waitpid(pid, NULL, WNOHANG) > 0)//子进程结束返回pid号
			{
				nowmusic = nowmusic->next;
				if(nowmusic == NULL)
				{
					printf("所有歌曲播放完毕!\n");//循环播放
                    			break;
				}
			}
			printf("1,播放 2,暂停 3,上一首 4,下一首 0,退出\n");
			system("stty echo");//开回显
			printf("\033[?25h");//显示光标
			scanf("%d",&val);
			switch(val)
			{
				case 0: kill_kill(head); return ;
				case 1: kill(pid, 18); break;//继续
				case 2: kill(pid, 19); break;//暂停
				case 3: nowmusic = upup(head, nowmusic, dir1); break;//上一首
				case 4: nowmusic = nextnext(head, nowmusic, dir1); break; //下一首
			}
		}
	}
}

void kill_kill(MP3Node *head)
{
	kill(pid, 9); //杀死子进程
	free_head(head);
	printf("退出播放器。\n");
}

MP3Node *upup(MP3Node *head,MP3Node *nowmusic, char *dir1)
{
	if(nowmusic == head)
	{
		printf("已经是第一首歌\n");
		system("stty echo");//开回显
		printf("\033[?25h");//显示光标
	}
	else
	{
		MP3Node *up_name = head;//定义上一首指向头指针
		while(up_name->next != nowmusic)//上一首!=当前歌曲
		{
			up_name = up_name->next;//找到上一首歌曲
		}
		nowmusic = up_name;//把当前歌曲更新为上一首
		kill(pid, 9); // 杀掉当前子进程
		pid = fork();//重新创建紫禁城
		if(pid == -1)
		{
			perror("fork");
		}
		else if(pid == 0)
		{
			mp3_dvd(dir1, nowmusic->filename);
		}
	}
	return nowmusic;
}


MP3Node *nextnext(MP3Node *head,MP3Node *nowmusic, char *dir1)
{
	if(nowmusic->next == NULL)
	{
		printf("已经是最后一首了!\n");
		system("stty echo");//开回显
		printf("\033[?25h");//显示光标
	}
	else
	{
		nowmusic = nowmusic->next;
		kill(pid, 9); // 杀掉当前子进程
		pid = fork();//重新创建子进程
		if(pid == -1)
		{
			perror("fork");
		}
		else if(pid == 0)
		{
			
			mp3_dvd(dir1, nowmusic->filename);
		}
	}
	return nowmusic;
}

void free_head(MP3Node *head)
{
	while(head  != NULL)//释放连表
	{
		MP3Node *temp = head;//临时变量存储头指针
		head = head->next;
		free(temp->filename);//释放strdup返回的歌曲名指针
		free(temp);//保存一次head释放一次temp
	}
}

用链表,改造成信号实现MP3

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <glob.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>

typedef struct MP3Node
{
	char *filename;//数据域,存储指针,里面存储歌曲名
	struct MP3Node *next;//指针域
}MP3Node;

void mp3_dvd();
void mp3_caidanname(char * dir1);
void kill_kill(MP3Node *head);
MP3Node *upup(MP3Node *head,MP3Node *nowmusic);
MP3Node *nextnext(MP3Node *nowmusic);
void signal_up_next(int signum);
void free_head(MP3Node *head);
void cleanFun(void);


pid_t pid;//全局变量
MP3Node *nowmusic = NULL;//现在播放的歌曲
MP3Node *head1 = NULL;
int again = 0;

char *dir1;

int main(int argc, char *argv[])
{
	dir1 = argv[1];//输入要播放的目录
	mp3_caidanname(dir1);
	return 0;
}

void mp3_dvd(char *dir1, char *filename)
{
	raise(19);//子进程近来先暂停播放
	char path[100];
	//printf("即将播放\n");"-q"
	snprintf(path, sizeof(path), "%s/%s", dir1,filename);
	execlp("mpg123","mpg123", "-k 9000",path,NULL);
	exit(EXIT_FAILURE);// 确保子进程退出
}

void mp3_caidanname(char * dir1)
{
	int count = 0;//记录歌曲数量
	
	
	MP3Node *head = NULL;//头指针
	MP3Node *tail = NULL;//尾指针
	DIR *dirp = NULL;
	dirp = opendir(dir1);//打开目录
	if(dirp == NULL)
	{
		perror("opendir");
	}
	struct dirent *dent = NULL;
	while((dent = readdir(dirp)))
	{
		if(dent->d_type == 8)//DT_REG,普通文件
		{
			char *filename = dent->d_name;//歌曲名字全存到数据域中
			//if(strstr(filename, ".mp3")) ,,char *strstr(const char *haystack, const char *needle);
			//strstr()函数返回一个指向haystack中第一次出现needle的指针。如果未找到子字符串,则返回NULL。
			if(strstr(filename, ".mp3"))
			{
				count++;
				MP3Node *newfile = (MP3Node *)malloc(sizeof(MP3Node));//重新定义一个newfile保存刚的filename
				newfile->filename = strdup(filename);//strdup从堆上分配一块内存,并将传入的字符串复制到这块内存中,然后返回这块内存的指针
				newfile->next = NULL;
				if(head == NULL)//第一次运行为空
				{
					head = newfile;//头指针不动
					head1 = head;//为了循环播放释放
					tail = newfile;
				}
				else//第二次往后链接
				{
					tail->next = newfile;//尾指针往后连接
					tail = newfile;
				}
			}
		}
	}
	closedir(dirp); // 关闭目录
	if(count == 0)
	{
		printf("此文件夹无歌曲!\n");
		free_head(head);
		return ;
	}
	
	/*glob_t fn = {0};//显示歌单
	glob("./mp3file/*.mp3", 0, NULL, &fn);
	for(int i = 0; i < fn.gl_pathc; i++)
	{
		printf("%d.%s\n", i+1,fn.gl_pathv[i]);//glob函数打印歌单
	}
	globfree(&fn);*/
	
	printf("歌单如下:\n");
	MP3Node *menu = head;
	int i = 1;
	while(menu != NULL)
	{
		printf("%d.%s\n", i++, menu->filename);
		menu = menu->next;
	}
	
	int nummusic = 0;//选择要播放的音乐
	printf("请选择要播放的音乐:\n");
	scanf("%d", &nummusic);
	nowmusic = head;//nowmusic指向第一个歌曲
	for(int i = 1; i < nummusic; i++)//遍历找到选中的歌曲,例如num = 2,执行一次循环
	{
		nowmusic = nowmusic->next;//找到第2个数据
	}
	pid = fork();
	if(pid == -1)
	{
		perror("fork");
		free_head(head);
		return ;
	}
	else if(pid == 0)
	{
		//mp3_dvd(dir1,nowmusic->filename);
	}
	else
	{
        	signal(17, signal_up_next); // 注册信号处理函数,子进程稍有改变就会发信号
        	atexit(cleanFun);
		int val = 0;
		while(1)
		{
			system("stty echo");//开回显
			printf("\033[?25h");//显示光标
			printf("-----------------------------------------------\n");
			printf("---1,播放 2,暂停 3,上一首 4,下一首 0,退出------\n");
			printf("-----------------------------------------------\n");
			
			scanf("%d",&val);
			while(getchar() != '\n');//清空缓冲区
			switch(val)
			{
				case 0: kill_kill(head); return ;
				case 1: kill(pid, 18); break;//继续
				case 2: kill(pid, 19); break;//暂停
				case 3: 
						nowmusic = upup(head, nowmusic);
						kill(pid, 9); break;//上一首
				case 4: 
						nowmusic = nextnext(nowmusic);
						kill(pid, 9); break; //下一首
				default: printf("无效输入,请重新选择。\n");
			}
		}
	}
}

void kill_kill(MP3Node *head)
{
	kill(pid, 9); //杀死子进程
	free_head(head);
	printf("退出播放器。\n");
}

MP3Node *upup(MP3Node *head,MP3Node *nowmusic)
{
	MP3Node *head2 = head;
	MP3Node *nowmusic1 = nowmusic;
	if(nowmusic == head)
	{
		system("clear");
		printf("--------------\n");
		printf("已经是第一首歌\n");
		printf("--------------\n");
		return nowmusic;
	}
	else
	{
		MP3Node *up_name = head2;//定义上一首指向头指针
		MP3Node *pre = NULL;//定义临时变量指向当前节点
		while(up_name != NULL && up_name->next != nowmusic1)//上一首!=当前歌曲
		{
			pre = up_name;
			up_name = up_name->next;//找到上一首歌曲
		}
		if(pre != NULL)
		{
			return pre; // 如果没有上一首歌,则返回当前歌
		}
		else
		{
			return nowmusic;
		}
	}
	
}


MP3Node *nextnext(MP3Node *nowmusic)
{
	MP3Node *nowmusic1 = nowmusic;
	if(nowmusic1->next == NULL)
	{
		system("clear");
		printf("--------------\n");
		printf("已经是最后一首了!\n");
		printf("--------------\n");
		return nowmusic1;
	}
	else
	{
		nowmusic1 = nowmusic->next;
	}
	return nowmusic1;
}

void signal_up_next(int signum)// 信号处理函数
{
	pid_t tmp=0;
	printf("--进入改造函数--\n");
	if(signum == 17)
	{
		int wstatus=0;
		tmp = waitpid(pid, &wstatus, WNOHANG);
		printf("p = %d, pid = %d\n", tmp,pid);
		if(tmp == pid && again == 0)
		{
			printf("子进程死亡\n");
			if(WIFEXITED(wstatus))
			{
				nowmusic = nowmusic->next;
				if(nowmusic == NULL)
				{
					printf("所有歌曲播放完毕!\n");//循环播放
					kill_kill(head1);
				}
			}
			pid = fork();//父进程回到主函数while,子进程放歌
			if(pid == 0)
			{
		  		mp3_dvd(dir1, nowmusic->filename);
			}
		}
	}
	if(signum == 18)
	{
		pid = fork();
		if(pid == 0)
		{
	  		mp3_dvd(dir1,nowmusic->filename);
		}
	}
}


void free_head(MP3Node *head)
{
	while(head  != NULL)//释放连表
	{
		MP3Node *temp = head;//临时变量存储头指针
		head = head->next;
		free(temp->filename);//释放strdup返回的歌曲名指针
		free(temp);//保存一次head释放一次temp
	}
}

void cleanFun(void)
{
	again = 1;
	kill(pid, 9);
	system("stty echo");//开回显
	printf("\033[?25h");//显示光标
}

信号实现MP3

#include <stdio.h>
#include <glob.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>

void sigFun(int num);
void cleanFun(void);

glob_t pglob;
pid_t pid;
int con;
int again;

int main()
{
	glob("./mp3file/*.mp3", 0, NULL, &pglob);
	for(int i = 0; i < pglob.gl_pathc; i++)
	{
	    printf("%d.%s\n", i+1, pglob.gl_pathv[i]+10);
	}
	pid = fork();
	if(pid < 0)
	{
	    perror("fork");
	    return -1;
	}
	else if(pid == 0)
	{
	    raise(19);
	    execlp("mpg123", "mpg123", pglob.gl_pathv[con],NULL);
	    exit(0);
	}
	signal(17, sigFun);
	atexit(cleanFun);
	while(1)
	{
	    int val = 0;
	    system("stty echo");
        printf("\033[?25h\n");
        printf("0.退出 1.播放 2.暂停 3.上一曲 4.下一曲\n");
        scanf("%d", &val);
        while(getchar() != '\n');
        switch(val)
        {
            case 0: return 0;
            case 1: kill(pid, 18); break;
            case 2: kill(pid, 19); break;
            case 3:
                    con--;
                    if(con == -1)
                    {
                        con = (int)pglob.gl_pathc-1;
                    }
                    kill(pid, 9);
                    break;
            case 4:
                    con++;
                    if(con == (int)pglob.gl_pathc)
                    {
                        con = 0;
                    }
                    kill(pid, 9);
                    break;
            default: break;       
        }
	}
	return 0;
}

void sigFun(int num)
{
    printf("signai == num:%d\n", num);
    int wstatus = 0;
    pid_t ret = 0;
    ret = waitpid(pid, &wstatus, WNOHANG);
    if(ret == pid && again == 0)
    {
        if(WIFEXITED(wstatus))
        {
            con++;
        }
        pid = fork();
        if(pid == 0)
        {
            execlp("mpg123","mpg123",pglob.gl_pathv[con],NULL);
            exit(0);  
        }
    }
}

void cleanFun(void)
{
    again = 1;
    kill(pid, 9);
    system("stty echo");
    printf("\033[?25h\n");
}

相关文章:

  • Docker 安装MySQL
  • 网页布局汇总
  • 【HarmonyOS Next之旅】DevEco Studio使用指南(十三) -> ArkTS/TS代码重构
  • 基础算法训练7
  • leetcode572 另一棵树的子树
  • React 组件样式
  • (已解决)如何安装python离线包及其依赖包 2025最新
  • 计算机操作系统——死锁(详细解释和处理死锁)
  • 编译原理 实验二 词法分析程序自动生成工具实验
  • 解决 Ubuntu 上 Docker 安装与网络问题:从禁用 IPv6 到配置代理
  • 【微知】如何将echo某个数据到文件然后cat出来结合在一起输出?(echo 1 | tee filea; cat fileb | tee fila)
  • 【图像生成之22】CVPR024—SwiftBrush基于变分分数蒸馏的文生图扩散模型
  • LeetCode hot 100—不同路径
  • 软考 系统架构设计师系列知识点之杂项集萃(49)
  • 【力扣hot100题】(093)最长公共子序列
  • 基于 Vue 3 + Express 的网盘资源搜索与转存工具,支持响应式布局,移动端与PC完美适配
  • 关于 Spring Boot 监控方式的详细对比说明及总结表格
  • CAN总线发送方每发送一位,接收方接收一位,但是当在非破坏性仲裁方式失利的情况下是否还能够正确接收数据呢?
  • 【C语言-全局变量】
  • Linux:进程优先级的理解
  • 中山网站建设华联在线/搜索引擎优化论文
  • 嘉兴手机网站开发费用/中国十大公关公司排名
  • 做图用哪个素材网站/全网推广公司
  • 可以在自己家做外卖的网站/百度推广服务费3000元
  • 威海西郊建设集团网站/最新全国疫情实时大数据
  • 织梦茶叶网站模板/怎么发外链