使用Mplayer实现MP3功能

核心功能

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;
}

项目流程图

项目挑战

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

项目收获

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

结语

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据抓取技术在视频内容监控与快速读取中的应用

引言 在数字化时代&#xff0c;视频内容的快速读取和监控对于内容提供商来说至关重要。思通数科的OPEN-SPIDER抓取技术为这一需求提供了高效的解决方案。 OPEN-SPIDER技术概述 OPEN-SPIDER是思通数科开发的一种先进的数据抓取技术&#xff0c;它能够&#xff1a; - 高效地从各…

Qt 音频编程实战项目

一Qt 音频基础知识 QT multimediaQMediaPlayer 类&#xff1a;媒体播放器&#xff0c;主要用于播放歌曲、网络收音 机等功能。QMediaPlaylist 类&#xff1a;专用于播放媒体内容的列表。 二 音频项目实战程序 //版本5.12.8 .proQT core gui QT multimedia greate…

基于深度学习的电影推荐系统

1 项目介绍 1.1 研究目的和意义 在电子商务日益繁荣的今天&#xff0c;精准预测商品销售数据成为商家提升运营效率、优化库存管理以及制定营销策略的关键。为此&#xff0c;开发了一个基于深度学习的商品销售数据预测系统&#xff0c;该系统利用Python编程语言与Django框架&a…

在RockyLinux上安装Solr8.11(新版本)

在RockyLinux上安装Solr8.11&#xff08;新版本&#xff09; 安装准备安装java环境 安装Solr下载修改配置开放端口验证一下 安装准备 安装java环境 搜索提供可安装的包 yum search java 我们在这里看到有很多&#xff0c;我这里安装的1.8版本。我们这里选择描述为Runtime en…

斯坦福大学博士在GitHub发布的漫画机器学习小抄,竟斩获129k标星

斯坦福大学数据科学博士Chris Albon在GitHub上发布了一份超火的机器学习漫画小抄&#xff0c;发布仅仅一天就斩获GitHub榜首标星暴涨120k&#xff0c;小编有幸获得了一份并把它翻译成中文版本&#xff0c;今天给大家分享出来&#xff01; 轻松的画风配上让人更容易理解的文字讲…

万字总结GBDT原理、核心参数以及调优思路

万字总结GBDT原理、核心参数以及调优思路 在机器学习领域&#xff0c;梯度提升决策树&#xff08;Gradient Boosting Decision Tree, GBDT&#xff09;以其卓越的预测性能和强大的模型解释能力而广受推崇。GBDT通过迭代地构建决策树&#xff0c;每一步都在前一步的残差上进行优…

【力扣高频题】042.接雨水问题

上一篇我们通过采用 双指针 的方法解决了 经典 容器盛水 问题 &#xff0c;本文我们接着来学习一道在面试中极大概率会被考到的经典题目&#xff1a;接雨水 问题 。 42. 接雨水 给定 n 个非负整数&#xff0c;表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子…

【高校科研前沿】中国农业大学姚晓闯老师等人在农林科学Top期刊发表长篇综述:深度学习在农田识别中的应用

文章简介 论文名称&#xff1a;Deep learning in cropland field identification: A review&#xff08;深度学习在农田识别中的应用&#xff1a;综述&#xff09; 第一作者及单位&#xff1a;Fan Xu&#xff08;中国农业大学土地科学与技术学院&#xff09; 通讯作者及单位&…

【电路笔记】-C类放大器

C类放大器 文章目录 C类放大器1、概述2、C类放大介绍3、C类放大器的功能4、C 类放大器的效率5、C类放大器的应用:倍频器6、总结1、概述 尽管存在差异,但我们在之前有关 A 类、B 类和 AB 类放大器的文章中已经看到,这三类放大器是线性或部分线性的,因为它们在放大过程中再现…

【WebGIS平台】传统聚落建筑科普数字化建模平台

基于上述概括出建筑单体的特征部件&#xff0c;本文利用互联网、三维建模和地理信息等技术设计了基于浏览器/服务器&#xff08;B/S&#xff09;的传统聚落建筑科普数字化平台。该平台不仅实现了对传统聚落建筑风貌从基础到复杂的数字化再现&#xff0c;允许用户轻松在线构建从…

Java线程池及面试题

1.线程池介绍 顾名思义&#xff0c;线程池就是管理一系列线程的资源池&#xff0c;其提供了一种限制和管理线程资源的方式。每个线程池还维护一些基本统计信息&#xff0c;例如已完成任务的数量。 总结一下使用线程池的好处&#xff1a; 降低资源消耗。通过重复利用已创建的…

去除Win32 Tab Control控件每个选项卡上的深色对话框背景

一般情况下&#xff0c;我们是用不带边框的对话框来充当Tab Control的每个选项卡的内容的。 例如&#xff0c;主对话框IDD_TABBOX上有一个Tab Control&#xff0c;上面有两个选项卡&#xff0c;第一个选项卡用的是IDD_DIALOG1充当内容&#xff0c;第二个用的则是IDD_DIALOG2。I…

Git本地仓库的搭建与使用

目录 一、前言 二、Linux下搭建 git 仓库 三、Windows下搭建 git 仓库 一、前言 做项目时&#xff0c;我们常常需要将自己的代码进行托管&#xff0c;但有时候 Github 的速度属实叫人流泪。有的人会选择 Gitee 等进行托管代码&#xff0c;这当然是可以的。那如果没有其他代码…

linux使用chattr与lsattr设置文件/目录防串改

背景 linux服务器下,防止某个文件/目录被串改(增删改),可以使用chattr与lsattr设置,这是一种保护机制,用于防止意外地修改或删除重要的文件内容。 chattr与lsattr使用 1.设置目录 图中/tmp/zhk,设置目录属性文件可能被设置为不可更改(immutable)或者只追加(append …

java Web学习笔记(一)

1. 前置学习知识 JavaScript学习笔记 CSS3学习笔记 html学习笔记 2. Tomcat介绍 前端App的运行环境&#xff1a; 服务器 --> JRE --> Tomcat --> App Tomcat目录文件介绍 bin:该目录下存放的是二进制可执行文件&#xff0c;如果是安装版&#xff0c;那么这个目…

leetcode判断二分图

判断二分图 图的问题肯定要用到深度优先遍历或者广度优先遍历&#xff0c;但又不是单纯的深度优先遍历算法和广度优先遍历算法&#xff0c;而是需要在遍历的过程中加入与解决题目相关的逻辑。 题干中说了&#xff0c;这个图可能不是连通图&#xff0c;这个提示有什么作用呢&a…

【状态估计】非线性非高斯系统的状态估计——离散时间的批量估计

上一篇文章介绍了离散时间的递归估计&#xff0c;本文着重介绍离散时间的批量估计。 上一篇位置&#xff1a;【状态估计】非线性非高斯系统的状态估计——离散时间的递归估计。 离散时间的批量估计问题 最大后验估计 目标函数 利用高斯-牛顿法来解决估计问题的非线性版本&a…

了解Adam和RMSprop优化算法

优化算法是机器学习和深度学习模型训练中至关重要的部分。本文将详细介绍Adam&#xff08;Adaptive Moment Estimation&#xff09;和RMSprop&#xff08;Root Mean Square Propagation&#xff09;这两种常用的优化算法&#xff0c;包括它们的原理、公式和具体代码示例。 RMS…

Studying-代码随想录训练营day34| 62.不同路径、63.不同路径II、343.整数拆分、96.不同的二叉搜索树

第34天&#xff0c;动态规划part02&#xff0c;牢记五部曲步骤&#xff0c;编程语言&#xff1a;C 目录 62.不同路径 63.不同路径II 343.整数拆分 96.不同的二叉搜索树 总结 62.不同路径 文档讲解&#xff1a;代码随想录不同路径 视频讲解&#xff1a;手撕不同路径 题目…

AI赋能,全面筑牢防线:重点非煤矿山重大灾害风险防控系统探析

一、背景需求 随着工业化和现代化的快速发展&#xff0c;非煤矿山作为重要的资源开采基地&#xff0c;其安全生产问题日益受到社会各界的广泛关注。非煤矿山在开采过程中&#xff0c;面临着诸多重大灾害风险&#xff0c;如滑坡、坍塌、水害、火灾等&#xff0c;这些灾害一旦发…