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

项目流程图

项目挑战

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

项目收获

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

结语

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

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

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

相关文章

gpt-4o看图说话-根据图片回答问题

问题&#xff1a;中国的人口老龄化究竟有多严重&#xff1f; 代码下实现如下&#xff1a;&#xff08;直接调用openai的chat接口&#xff09; import os import base64 import requests def encode_image(image_path): """ 对图片文件进行 Base64 编码 输入…

Nacos2.X 配置中心源码分析:客户端如何拉取配置、服务端配置发布客户端监听机制

文章目录 Nacos配置中心源码总流程图NacosClient源码分析获取配置注册监听器 NacosServer源码分析配置dump配置发布 Nacos配置中心源码 总流程图 Nacos2.1.0源码分析在线流程图 源码的版本为2.1.0 &#xff0c;并在配置了下面两个启动参数&#xff0c;一个表示单机启动&#…

pytest-yaml-sanmu(六):YAML数据驱动测试

如果说 pytest 中哪些标记使用得最多&#xff0c;那无疑是 parametrize 了&#xff0c; 它为用例实现了参数化测试的能力&#xff0c;进而实现了数据驱动测试的能力。 1. 使用标记 parametrize 的使用需要提高两个内容&#xff1a; 参数名 参数值 pytest 在执行用例时&…

【LeetCode刷题笔记】LeetCode.11.盛最多水的容器

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 更多算法知识专栏&#xff1a;算法分析&#x1f525; 给大家跳段街舞感谢…

020-GeoGebra中级篇-几何对象之点与向量

本文概述了在GeoGebra中如何使用笛卡尔或极坐标系输入点和向量。用户可以通过指令栏输入数字和角度&#xff0c;使用工具或指令创建点和向量。在笛卡尔坐标系中&#xff0c;示例如“P(1,0)”&#xff1b;在极坐标系中&#xff0c;示例如“P(1;0)”或“v(5;90)”。文章还介绍了点…

Python大数据分析——决策树和随机森林

Python大数据分析——决策树和随机森林 决策树决策树节点字段的选择信息熵条件熵信息增益信息增益率 基尼指数条件基尼指数基尼指数增益 决策树函数 随机森林函数 决策树 图中的决策树呈现自顶向下的生长过程&#xff0c;深色的椭圆表示树的根节点&#xff1b;浅色的椭圆表示树…

Raylib 实现超大地图放大缩小与两种模式瓦片地图刷新

原理&#xff1a; 一种刷新模式&#xff1a; 在宫格内整体刷新&#xff0c;类似九宫格移动到边缘&#xff0c;则九宫格整体平移一个宫格&#xff0c;不过这里是移动一个瓦片像素&#xff0c;实际上就是全屏刷新&#xff0c;这个上限是 笔记本 3060 70帧 100*100个瓦片每帧都…

思维+并查集,1670C - Where is the Pizza?

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 1670C - Where is the Pizza? 二、解题报告 1、思路分析 考虑两个数组a&#xff0c;b的每个位置只能从a&#xff0c;b中挑一个 不妨记posa[x]为x在a中位置&#xff0c;posb同理 我们假如位置i挑选a[i]&a…

Java--instanceof和类型转换

1.如图&#xff0c;Object&#xff0c;Person&#xff0c;Teacher&#xff0c;Student四类的关系已经写出来了&#xff0c;由于实例化的是Student类&#xff0c;因此&#xff0c;与Student类存在关系的类在使用instanceof时都会输出True&#xff0c;而无关的都会输出False&…

小试牛刀--对称矩阵压缩存储

学习贺利坚老师对称矩阵压缩存储 数据结构实践——压缩存储的对称矩阵的运算_计算压缩存储对称矩阵 a 与向量 b 的乘积-CSDN博客 本人解析博客 矩阵存储和特殊矩阵的压缩存储_n阶对称矩阵压缩-CSDN博客 版本更新日志 V1.0: 对老师代码进行模仿 , 我进行名字优化, 思路代码注释 …

ARM裸机:一步步点亮LED(汇编)

硬件工作原理及原理图查阅 LED物理特性介绍 LED本身有2个接线点&#xff0c;一个是LED的正极&#xff0c;一个是LED的负极。LED这个硬件的功能就是点亮或者不亮&#xff0c;物理上想要点亮一颗LED只需要给他的正负极上加正电压即可&#xff0c;要熄灭一颗LED只需要去掉电压即可…

2024 Q3 NAND闪存价格|企业级依然猛涨,消费级放缓

在企业领域持续投资于服务器基础设施&#xff0c;特别是在人工智能应用的推动下&#xff0c;企业级SSD需求增加的同时&#xff0c;消费电子市场却依旧疲软。加之NAND供应商在2024年下半年积极扩大生产&#xff0c;预计到2024年第三季度&#xff0c;NAND闪存供应充足率将上升至2…

jQuery 笔记

一、什么是jQuery 框架&#xff1a;半成品软件 Jquery就是封装好的js 本质上还是js jQuery是一个快速、简洁的JavaScript**框架**&#xff0c;是继Prototype之后又一个优秀的**JavaScript代码库**&#xff08;*或JavaScript框架*&#xff09;。 JQuery:封装好的代码库。有一…

程序设计——领域驱动设计

程序设计的所有原则和方法论都是追求一件事——简单——功能简单、依赖简单、修改简单、理解简单。因为只有简单才好用&#xff0c;简单才好维护。因此&#xff0c;不应该以评论艺术品的眼光来评价程序设计是否优秀&#xff0c;程序设计的艺术不在于有多复杂多深沉&#xff0c;…

JVM原理(二三):JVM虚拟机线程安全的实现方法

1. 互斥同步 互斥同步(MutualExclusion&Synchronization)是一种最常见也是最主要的并发正确性保障手段。同步是指在多个线程并发访问共享数据时&#xff0c;保证共享数据在同一个时刻只被一条(或者是一些&#xff0c;当使用信号量的时候)线程使用。而互斥是实现同步的一种…

3d模型墙模糊怎么回事?---模大狮模型网

在展览3D模型设计行业中&#xff0c;技术细节常常是设计师们需要面对和解决的关键问题之一。其中&#xff0c;3D模型墙模糊的现象可能会影响整个展览的视觉效果和观众的体验。本文将深入探讨这一问题的起因及解决方法&#xff0c;帮助设计师们更好地处理类似挑战。 一、问题的起…

MySQL架构优化及SQL优化

变更项目的整体架构是性能收益最大的方式。主要涉及两方面&#xff0c;一方面是从整个项目角度&#xff0c;引入一些中间件优化整体性能&#xff0c;另一方面是调整MySQL的部署架构&#xff0c;确保能承载更大的流量访问&#xff0c;提高数据层的整体吞吐。 1. 引入缓存中间件…

不用服务器 | 我搭建了一个属于自己的GPT聊天应用!!!

原文地址&#xff1a;aiutools.fun/archives/5118 平台限制部分内容未显示&#xff0c;详情请访问原文。 展示 不废话&#xff0c;直接上干货&#xff01; 我这里搭建的Lobe Chat 支持 聊天TTS & STT 语音会话文生图各种优秀的插件 下面搭建好的样子 前期准备 需要…

基于jeecgboot-vue3的Flowable流程-集成仿钉钉流程(四)支持json和xml的显示

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 1、相应的界面前端代码 <template><div class"formDesign"><FlowDesign :process"process" :fields"fields" :readOnly"readOnly&quo…

算法之工程化内容(2)—— Git常用命令

目录 1. git初始化配置 2. 新建仓库 3. 工作区——>暂存区——>本地仓库 4. git reset回退版本 5. 查看差异 git diff 6. 删除文件git rm 7. .gitignore 8. vscode操作git 9. git分支、合并和删除 10. 解决合并冲突 11. 回退和rebase 12. 添加远程仓库 参考链接&#xff…