使用Mplayer实现MP3功能

news2024/9/20 16:43:44

核心功能

1. 界面设计

项目首先定义了一个clearscreen函数,用于清空屏幕,为用户界面的更新提供了便利。yemian函数负责显示主菜单界面,提供了包括查看播放列表、播放控制、播放模式选择等在内的9个选项。

2. 文件格式支持

is_supported_file函数用于检测文件扩展名,确保只有支持的视频和音频文件被播放器处理。目前支持的格式包括.mp4.avi等。

3. 文件列表展示

print_file_list函数遍历指定目录,列出所有支持的视频文件,并由allnum变量记录文件总数。

4. 播放控制

open_file函数根据用户选择打开相应的视频文件,并使用mplayer命令行工具进行播放。通过execvp系统调用,我们可以启动mplayer进程并传递必要的参数。

5. 命令发送

send_command_to_mplayer函数通过命名管道与mplayer进程通信,发送播放控制命令,如停止、暂停、快进等。

6. 播放模式

control_mplayer函数实现了一个循环,根据用户输入的选项,执行不同的播放控制逻辑。它还处理了播放模式的切换,包括列表循环、单曲循环和随机播放。

7. 多进程管理

项目使用了fork系统调用创建子进程来运行mplayer,并通过管道与主进程通信,实现了进程间的同步和数据传递。

项目代码

#include <stdio.h>
#include<time.h>
#include<string.h>
#include<stdlib.h>
#include <unistd.h>
#include <termios.h>
#include<dirent.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <errno.h>

void clearscreen() {
	printf("\033[2J");
}

void yemian() 
{

	clearscreen();
	printf("                  +-----------------------------------+\n");
	printf("                  |          视频播放器               |\n");
	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");
}

int is_supported_file(const char *filename) {
	const char *extensions[] = {".mp4", ".avi", ".flv", ".wma", ".rmvb", ".mp3", ".rm",NULL}; // 支持的文件扩展名
	const char **ext = extensions; 
	while (*ext != NULL) {
		if (strstr(filename, *ext) != NULL) {
			return 1;
		}
		ext++;
	}
	return 0;
}

int allnum;
int print_file_list(DIR *dir) {
	struct dirent *entry;
	int i=1;
	while ((entry = readdir(dir)) != NULL) {
		if (is_supported_file(entry->d_name)) {
			printf("                  |%d %s                    \n",i++, entry->d_name);
		}
	}
	return i-1;
}

void print_file_list2() {
	int i=1;
	printf("                  |%d list_cycle                   \n",i++);
	printf("                  |%d single_cycle                    \n",i++);
	printf("                  |%d random_cycle                    \n",i++);
}

int open_file(DIR *dir, const char *base_path, int n) {
	struct dirent *entry;
	int count = 0;
	rewinddir(dir);
	while ((entry = readdir(dir)) != NULL) {
		if (is_supported_file(entry->d_name)) {
			count++;
			if (count == n) {
				char full_path[1024];
				snprintf(full_path, sizeof(full_path), "%s%s%s", base_path,"/", entry->d_name);
				char *argv[] = {"mplayer", "-slave", "-quiet", "-input", "file=/tmp/fifofile", full_path, NULL};
				if(execvp("mplayer", argv) == -1) {
					perror("execvp failed");
				}
				break;
			}
		}
	}
	return count;
}

int page2(const char *dirname) {
	clearscreen();
	printf("                  +-----------------------------------+\n");
	printf("                  |       视频文件播放列表            |\n");
	printf("                  +-----------------------------------+\n");
	DIR *dir = opendir(dirname);
	if (dir == NULL) {
		perror("打开目录失败");
	}
	printf("                  |以下是可播放的视频文件列表:         |\n");
	int t= print_file_list(dir);
	closedir(dir);
	printf("                  +-----------------------------------+\n");
	return t;
}

int page3() {
	clearscreen();
	printf("                  +-----------------------------------+\n");
	printf("                  |  请选择你的播放模式               |\n");
	printf("                  +-----------------------------------+\n");
	print_file_list2();
	printf("                  |                                   |\n");
	printf("                  +-----------------------------------+\n");
}

int position;
char temp[1000];
void func1(const char*dirname,int n) {

	DIR *dir = opendir(dirname);
	if (dir == NULL) {
		perror("打开目录失败");
	}
	open_file(dir,dirname,n);
	closedir(dir);
}

#define FIFO_NAME "/tmp/fifofile"
void send_command_to_mplayer(const char *command) {
	int fd_fifo = open(FIFO_NAME, O_WRONLY);
	if (fd_fifo < 0) {
		perror("open FIFO for writing");
		return;
	}
	write(fd_fifo, command, strlen(command));
	close(fd_fifo);
}

int mode=1;
void control_mplayer() {
	int command;
	while (1) {
		yemian(); // 显示菜单
		printf("请输入操作选项:");
		scanf("%d", &command);
		switch (command) {
		case 1:
			send_command_to_mplayer("stop\n");
			system("./a.out");
			break;
		case 2:
			send_command_to_mplayer("pause\n");
			break;
		case 3:
			send_command_to_mplayer("stop\n");
			break;
		case 4:
			send_command_to_mplayer("stop\n");
			sleep(1); // 这里只是示例,具体时间需要根据您的程序调整
			if (mkfifo(FIFO_NAME, 0666) == -1 && errno != EEXIST) {
				perror("mkfifo");
				exit(EXIT_FAILURE);
			}
			int pipefd[2];
			if (pipe(pipefd) == -1) {
				perror("pipe");
				exit(EXIT_FAILURE);
			}
			pid_t mplayer_pid = fork();
			if (mplayer_pid == -1) {;
				perror("fork");
				exit(EXIT_FAILURE);
			}
			if (mplayer_pid == 0) {
				close(pipefd[0]);
				write(pipefd[1], &(mode), sizeof(mode));
				if(position>0&&position<(allnum+1))
				{
					if(mode==1&&position!=1)
					{
						position--;
					}
					if(mode==2)
					{
					}
					if(mode==3)
					{
						srand((unsigned int)time(NULL));
						position=1 + (rand() % 3);
					}
				}
				write(pipefd[1], &(position), sizeof(position));
				close(pipefd[1]);
				sleep(1);
				func1(temp,position);
			}
			close(pipefd[1]);
			read(pipefd[0], &mode, sizeof(mode));
			read(pipefd[0], &position, sizeof(position));
			close(pipefd[0]);
			sleep(2); // 等待时间可能需要调整
			control_mplayer();
			unlink(FIFO_NAME);
			waitpid(mplayer_pid, NULL, 0);
			break;
		case 5:
			send_command_to_mplayer("stop\n");
			sleep(1); // 这里只是示例,具体时间需要根据您的程序调整
			if (mkfifo(FIFO_NAME, 0666) == -1 && errno != EEXIST) {
				perror("mkfifo");
				exit(EXIT_FAILURE);
			}
			int pipefd1[2];
			if (pipe(pipefd1) == -1) {
				perror("pipe");
				exit(EXIT_FAILURE);
			}
			pid_t mplayer_pid1 = fork();
			if (mplayer_pid1 == -1) {;
				perror("fork");
				exit(EXIT_FAILURE);
			}
			if (mplayer_pid1 == 0) {
				close(pipefd1[0]);
				write(pipefd1[1], &(mode), sizeof(mode));
				if(position>0&&position<allnum+1)
				{	
					if(mode==1&&position!=allnum)
					{
						position++;
					}
					if(mode==2)
					{
					}
					if(mode==3)
					{
						srand((unsigned int)time(NULL));
						position=1 +(rand()%3);
					}
				}
				write(pipefd1[1], &(position), sizeof(position));
				close(pipefd1[1]);
				sleep(1);
				func1(temp,position);
			}
			close(pipefd1[1]);
			read(pipefd1[0], &mode, sizeof(mode));
			read(pipefd1[0], &position, sizeof(position));
			close(pipefd1[0]);
			sleep(2); // 等待时间可能需要调整
			control_mplayer();
			unlink(FIFO_NAME);
			waitpid(mplayer_pid1, NULL, 0);
			break;
		case 6:
			printf("请你输入你需要播放的倍速");
			float speed_rate;
			scanf("%f",&speed_rate);
			char speed_command[50];
			snprintf(speed_command, sizeof(speed_command), "speed_set %f\n", speed_rate);
			send_command_to_mplayer(speed_command);
			break;
		case 7:
			printf("请你输入你需要定到的位置");
			int num2;
			scanf("%d",&num2);
			char seek_command[50];
			snprintf(seek_command, sizeof(seek_command), "seek %d 1\n",num2);
			send_command_to_mplayer(seek_command);
			break;
		case 8:
			page3();
			printf("请输入您想要的播放模式(1-列表循环,2-单曲循环,3-随机播放):");
			scanf("%d",&mode);
			sleep(2);
			break;
		case 9:
			// 发送退出命令给 MPlayer,然后退出控制循环
			send_command_to_mplayer("quit\n");
			break;
		default:
			printf("未知的命令,请重新输入。\n");
			break;
		}
	}
}

int main() {
	if (mkfifo(FIFO_NAME, 0666) == -1 && errno != EEXIST) {
		perror("mkfifo");
		exit(EXIT_FAILURE);
	}
	int pipefd[2];
	if (pipe(pipefd) == -1) {
		perror("pipe");
		exit(EXIT_FAILURE);
	}
	pid_t mplayer_pid = fork();
	if (mplayer_pid == -1) {;
		perror("fork");
		exit(EXIT_FAILURE);
	}

	if (mplayer_pid == 0) {
		close(pipefd[0]);
		char dirname[1024];
		printf("请输入目录路径: ");
		fgets(dirname, sizeof(dirname), stdin);
		size_t len = strlen(dirname);
		if(len > 0 && dirname[len - 1] == '\n') {
			dirname[len - 1] = '\0';
		}
		strcpy(temp,dirname);
		allnum=page2(dirname);
		printf("please input the Video_no");
		int t;
		scanf("%d",&t);

		position=t;
		write(pipefd[1], &position, sizeof(position));
		write(pipefd[1], temp, sizeof(temp));
		write(pipefd[1], &allnum, sizeof(allnum));
		sleep(5);
		func1(dirname,t);
		close(pipefd[1]);
	}

	close(pipefd[1]);
	read(pipefd[0], &position, sizeof(position));
	read(pipefd[0], temp, sizeof(temp));
	read(pipefd[0], &allnum, sizeof(allnum));
	close(pipefd[0]);
	sleep(8); // 等待时间可能需要调整
	control_mplayer();
	unlink(FIFO_NAME);
	waitpid(mplayer_pid, NULL, 0);
	return 0;
}

项目流程图

项目挑战

在开发过程中,我遇到了不少挑战,比如如何优雅地处理用户输入、如何确保进程间通信的可靠性等。通过查阅资料和不断调试,我逐步克服了这些难题。

项目收获

通过这个项目,我不仅提升了自己的编程能力,也对操作系统的原理有了更深入的理解。此外,我还学会了如何设计用户友好的命令行界面,以及如何处理多进程编程中的同步问题。

结语

这个视频播放器项目是我学习旅程中的一个里程碑。我相信,随着技术的不断进步,我将能够开发出更加复杂和功能丰富的应用程序。感谢大家的阅读,希望我的分享能给大家带来一些启发。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1911761.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

详解TCP和UDP通信协议

目录 OSI的七层模型的主要功能 tcp是什么 TCP三次握手 为什么需要三次握手&#xff0c;两次握手不行吗 TCP四次挥手 挥手会什么需要四次 什么是TCP粘包问题&#xff1f;发生的原因 原因 解决方案 UDP是什么 TCP和UDP的区别 网络层常见协议 利用socket进行tcp传输代…

淮北在选择SCADA系统时,哪些因素会影响其稳定性?

关键字:LP-SCADA系统, 传感器可视化, 设备可视化, 独立SPC系统, 智能仪表系统,SPC可视化,独立SPC系统 在选择SCADA系统时&#xff0c;稳定性是一个关键因素&#xff0c;因为它直接影响到生产过程的连续性和安全性。以下是一些影响SCADA系统稳定性的因素&#xff1a; 硬件质量…

如何在 CentOS 上配置本地 YUM 源

引言 CentOS 作为一个流行的企业级 Linux 发行版&#xff0c;依赖 YUM&#xff08;Yellowdog Updater, Modified&#xff09;来管理软件包。YUM 源&#xff08;Repository&#xff09;是软件包存储和分发的中心&#xff0c;它们通常位于互联网上。然而&#xff0c;在某些情况下…

使用clion刷leetcode

如何优雅的使用clion刷leetcode 安装插件&#xff1a;LeetCode Editor) 插件配置&#xff1a; 这样我们每打开一个项目&#xff0c;就会创建类似的文件 我们的项目结构&#xff1a; 我们在题解文件中导入头文件myHeader.h并将新建的文件添加到cmakelists.txt文件&#xff0c;…

数据结构双向循环链表

主程序 #include "fun.h" int main(int argc, const char *argv[]) { double_p Hcreate_head(); insert_head(H,10); insert_head(H,20); insert_head(H,30); insert_head(H,40); insert_tail(H,50); show_link(H); del_tail(H); …

c++内存管理(上)

目录 引入 分析 说明 C语言中动态内存管理方式 C内存管理方式 new/delete操作内置类型 new和delete操作自定义类型 引入 我们先来看下面的一段代码和相关问题 int globalVar 1; static int staticGlobalVar 1; void Test() { static int staticVar 1; int localVar 1…

影视行业的人工智能与-【机器学习】:案例分析

欢迎关注小知&#xff1a;知孤云出岫 目录 引言AI和ML在影视行业的当前应用AI和ML对影视行业的未来影响案例研究&#xff1a;AI生成动画视频目标工具和库数据收集模型训练视频生成 结论参考文献 引言 人工智能&#xff08;AI&#xff09;和机器学习&#xff08;ML&#xff09…

window.matchMedia

matchMedia() 返回一个新的 MediaQueryList 对象&#xff0c;表示指定的媒体查询字符串解析后的结果。 const width ref(); const myFunction (x) > {if (x.matches) {// 媒体查询document.body.style.backgroundColor "yellow";width.value "yellow&quo…

JavaScript 作用域 与 var、let、const关键字

目录 一、JavaScript 作用域 1、全局作用域 2、函数作用域 3、块级作用域 4、综合示例 5、总结 二、var、let、const 1、var 关键字 2、let 关键字 3、const 关键字 4、总结 5、使用场景 一、JavaScript 作用域 在JavaScript中&#xff0c;作用域是指程序中可访问…

网络编程:TCP

一、tcp编程 注意 1.数据本身有顺序 2.发送和接收次数不需要对应 3. 1. C/S 模式 》服务器/客户端模型 server:socket()-->bind()--->listen()-->accept()-->recv()-->close() client:socket()-->connect()-->send()-->close(); int on 1; setso…

如何学好C++?

首先&#xff0c;对于零基础的想学习C的同学&#xff0c;我想要你们先明白一件事&#xff1a;C是一门极为复杂且难以掌握的编程语言。因此推荐在学习C之前可以先去学习C语言&#xff0c;在拥有了一定的知识储备和编程能力后再学习C会更加的高效和相对轻松。 下面推荐从三个方面…

源码编译安装 LAMP

目录 2.1Apache 网站服务基础 2.1.1 Apache 简介 1.Apache 的起源 2.Apache 的主要特点 2.1.2 安装 httpd 服务器 1.准备工作 2.源码编译及安装 3.确认安装结果​编辑 4.优化执行路径 5.添加 httpd 系统服务 2.2 httpd 服务器的基本配置 2.2.1 Web 站点的部…

锅总反驳李彦宏说的“不要卷模型,要卷应用”

李彦宏的观点是大家不要卷模型&#xff0c;要卷应用&#xff0c;但我认为这种看法是荒谬的。以下是24条反驳李彦宏观点的论点和论据&#xff1a; 模型的准确性直接决定应用的质量和用户体验&#xff1a; 论据&#xff1a;在自然语言处理、计算机视觉等领域&#xff0c;模型的准…

安全求交集PSI

安全求交集定义 求交集的PSI&#xff1a;交集可以被两方看见或其中一方看见&#xff0c;非交集进行保护有两方的PSI半诚实的PSI&#xff1a;攻击者要严格遵守协议&#xff0c;在此基础上得到他人的秘密是做不到的 Two-Party Semi-Honest PSI 挑战一&#xff1a;隐藏非交集元素…

纯前端如何实现Gif暂停、倍速播放

前言 GIF 我相信大家都不会陌生&#xff0c;由于它被广泛的支持&#xff0c;所以我们一般用它来做一些简单的动画效果。一般就是设计师弄好了之后&#xff0c;把文件发给我们。然后我们就直接这样使用&#xff1a; <img src"xxx.gif"/>这样就能播放一个 GIF …

offer题目33:判断是否是二叉搜索树的后序遍历序列

题目描述&#xff1a;输入一个整数数组&#xff0c;判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回true,否则返回false。假设输入的数组的任意两个数字都互不相同。例如&#xff0c;输入数组{5,7,6,9,11,10,8},则返回true,&#xff0c;因为这个整数是下图二叉搜索树…

作业/数据结构/2024/7/8

链表的相关操作作业&#xff1a; 1】 按值修改 2】按值查找&#xff0c;返回当前节点的地址 &#xff08;先不考虑重复&#xff0c;如果有重复&#xff0c;返回第一个&#xff09; 3】 逆置(反转) 4】释放链表 main.c #include "head.h"int main(int argc, con…

6.Python学习:异常和日志

1.异常的抓取 1.1异常的概念 使用异常前&#xff1a; print(1/0)使用异常后&#xff1a;错误提示更加友好&#xff0c;不影响程序继续往下运行 try:print(10/0) except ZeroDivisionError:print("0不能作为分母")1.2异常的抓取 第一种&#xff1a;如果提前知道可…

微软清华提出全新预训练范式,指令预训练让8B模型实力暴涨!实力碾压70B模型

现在的大模型训练通常会包括两个阶段&#xff1a; 一是无监督的预训练&#xff0c;即通过因果语言建模预测下一个token生成的概率。该方法无需标注数据&#xff0c;这意味着可以利用大规模的数据学习到语言的通用特征和模式。 二是指令微调&#xff0c;即通过自然语言指令构建…

核密度估计KDE和概率密度函数PDF(深入浅出)

目录 1. 和密度估计&#xff08;KDE&#xff09;核密度估计的基本原理核密度估计的公式核密度估计的应用Python中的KDE实现示例代码 结果解释解释结果 总结 2. 概率密度函数&#xff08;PDF&#xff09;概率密度函数&#xff08;PDF&#xff09;是怎么工作的&#xff1a;用图画…