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

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

项目流程图

项目挑战

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

项目收获

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

结语

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 前端调用有道翻译
  • FPGA设计之跨时钟域(CDC)设计篇(1)----亚稳态到底是什么?
  • 牛市中途深度调整,一览下半场值得关注的 Solana 生态五大潜力项目
  • arm环境安装达梦数据库
  • Linux之免费证书工具certbot安装和使用
  • 设计模式探索:适配器模式
  • 关于ppmlhdfe和possion两个命令回归显示观测值不同
  • 掌握计算机网络基础:从零开始的指南
  • 基于conda包的环境创建、激活、管理与删除
  • 鸿蒙语言基础类库:【@ohos.util.HashMap (非线性容器HashMap)】
  • mes系统在新材料行业中的应用价值
  • 谷粒商城-个人笔记(集群部署篇三)
  • 定义变量和声明变量、定义类和声明类
  • 哈喽GPT-4o,程序员如何通过GPT-4o提高办公效率
  • Score matching
  • 2018天猫双11|这就是阿里云!不止有新技术,更有温暖的社会力量
  • Angular 2 DI - IoC DI - 1
  • angular2 简述
  • Consul Config 使用Git做版本控制的实现
  • CSS中外联样式表代表的含义
  • ESLint简单操作
  • Java超时控制的实现
  • Median of Two Sorted Arrays
  • MQ框架的比较
  • Nacos系列:Nacos的Java SDK使用
  • vue-loader 源码解析系列之 selector
  • Windows Containers 大冒险: 容器网络
  • 高度不固定时垂直居中
  • 搞机器学习要哪些技能
  • 回流、重绘及其优化
  • 可能是历史上最全的CC0版权可以免费商用的图片网站
  • 问题之ssh中Host key verification failed的解决
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • # Redis 入门到精通(八)-- 服务器配置-redis.conf配置与高级数据类型
  • # 计算机视觉入门
  • #Linux(Source Insight安装及工程建立)
  • #pragam once 和 #ifndef 预编译头
  • (6)设计一个TimeMap
  • (C++17) std算法之执行策略 execution
  • (C++哈希表01)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第5章第5节(delphi中的指针)
  • (第二周)效能测试
  • (二)springcloud实战之config配置中心
  • (附源码)springboot家庭财务分析系统 毕业设计641323
  • (附源码)计算机毕业设计高校学生选课系统
  • (十七)Flink 容错机制
  • (一)【Jmeter】JDK及Jmeter的安装部署及简单配置
  • (转)fock函数详解
  • ./indexer: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object fil
  • .NET Framework 3.5中序列化成JSON数据及JSON数据的反序列化,以及jQuery的调用JSON
  • .net 开发怎么实现前后端分离_前后端分离:分离式开发和一体式发布
  • .net 前台table如何加一列下拉框_如何用Word编辑参考文献
  • .NET 使用 ILMerge 合并多个程序集,避免引入额外的依赖
  • .net 重复调用webservice_Java RMI 远程调用详解,优劣势说明
  • .net反混淆脱壳工具de4dot的使用