接上一篇文章(没有界面的mp3)这次使他添加了界面操控,使操纵更加简单
首先要用GUI工具,我用的是GUI-guider如下图
设计界面根据自己的想法来设计就好具体操作就略过重点放在代码实现
设计好自己的界面后代码生成后试运行成功后就可以进入下一步
进入播放器生成的代码文件中用code打开工程
这是我的工程目录
根据上一篇的代码基础移植到此工程即可
具体步骤如下
1.添加所需要的头文件
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <glob.h>
#include <signal.h>
#include <dirent.h>
#include <sys/stat.h>
2.创建全局变量(子进程要用)和fun函数的移植和退出函数的移植
extern int i=0;//播放歌曲的序号
extern glob_t mp3={0};
extern pid_t pid=0;
extern int flag=0;//暂停和播放的标志位
void fun (int a)
{
if(i<0)
{
printf("此歌序号为最小\n");
i=0;
}
if(i>=mp3.gl_pathc)
{
printf("此歌序号为最大\n");
i=mp3.gl_pathc-1;
}
int num=0;
pid_t p=waitpid(pid,&num,WNOHANG);//判断子进程是否是正常退出
if(p==pid)
{
if(WIFEXITED(num))//正常退出,播放下一首
{
i++;
if(i>=mp3.gl_pathc)
{
printf("已经达到最后一首歌,即将从头播放\n");
i=0;
}
pid=fork();
if(pid==0)
{
execlp("mpg123","mpg123",mp3.gl_pathv[i],NULL);
}
}
else//不正常退出
{
pid=fork();
if(pid==0)
{
execlp("mpg123","mpg123",mp3.gl_pathv[i],NULL);
}
}
}
}
void tuichu (void)
{
signal(17,SIG_IGN);//取消信号改造函数
kill(pid,9);//结束进程
system("stty echo");
printf("\033[?25h");//回显
}
把上次无界面mp3中的主函数稍作修改插入进main函数中
int main(int argc, char ** argv)
{
(void) argc; /*Unused*/
(void) argv; /*Unused*/
/*Initialize LittlevGL*/
lv_init();
/*Initialize the HAL (display, input devices, tick) for LittlevGL*/
hal_init();
/*Create a GUI-Guider app */
setup_ui(&guider_ui);
events_init(&guider_ui);
custom_init(&guider_ui);
//从这里开始插入!!!!!!!!!!!!!!!!!!!!
atexit(tuichu);//设置系统退出函数
glob("/home/ping/音乐/mp3文件/*.mp3",0,NULL,&mp3);//获取mp3文件
for(int i=0;i<mp3.gl_pathc;i++)
{
printf("%d\t%s\n",i,mp3.gl_pathv[i]);//打印这个目录下所有的mp3文件名
}
pid=fork();//创建子进程
if(pid>0)
{
signal(17,fun);//信号改造函数
}
if(pid==0)
{
kill(getpid(),19);
execlp("mpg123","mpg123",mp3.gl_pathv[i],NULL);//播放mp3音乐
}
//插到这里结束!!!!!!!!!!!!!!!!!!!!!!!
while(1) {
/* Periodically call the lv_task handler.
* It could be done in a timer interrupt or an OS task too.*/
lv_task_handler();
usleep(5 * 1000);
#ifdef SDL_APPLE
SDL_Event event;
while(SDL_PollEvent(&event)) {
#if USE_MOUSE != 0
mouse_handler(&event);
#endif
#if USE_KEYBOARD
keyboard_handler(&event);
#endif
#if USE_MOUSEWHEEL != 0
mousewheel_handler(&event);
#endif
}
#endif
}
return 0;
}
然后可以利用搜索找到你的按钮文件中进行具体操作(别忘了在此之前引用主函数的头文件和全局变量)
/*
* Copyright 2024 NXP
* SPDX-License-Identifier: MIT
*/
#include "events_init.h"
#include <stdio.h>
#include "lvgl/lvgl.h"
#include <stdio.h>
#include <stdio.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <glob.h>
#include <signal.h>
#include <dirent.h>
#include <sys/stat.h>
extern int i;
extern glob_t mp3;
extern pid_t pid;
extern int flag;
void events_init(lv_ui *ui)
{
}
static void screen_imgbtn_2event_handler(lv_obj_t * obj, lv_event_t event)
{
switch (event)
{
case LV_EVENT_PRESSED:
{
if(flag==0)
{
flag=1;
kill(pid,18);
printf("播放\n");
break;
}
else if (flag==1)
{
flag=0;
kill(pid,19);
printf("暂停\n");
break;
}
}
break;
default:
break;
}
}
static void screen_imgbtn_3event_handler(lv_obj_t * obj, lv_event_t event)
{
switch (event)
{
case LV_EVENT_PRESSED:
{
i++;
kill(pid,14);
printf("下一曲\n");
break;
}
break;
default:
break;
}
}
static void screen_imgbtn_4event_handler(lv_obj_t * obj, lv_event_t event)
{
switch (event)
{
case LV_EVENT_PRESSED:
{
i--;
kill(pid,14);
printf("上一曲\n");
break;
}
break;
default:
break;
}
}
void events_init_screen(lv_ui *ui)
{
lv_obj_set_event_cb(ui->screen_imgbtn_2, screen_imgbtn_2event_handler);
lv_obj_set_event_cb(ui->screen_imgbtn_3, screen_imgbtn_3event_handler);
lv_obj_set_event_cb(ui->screen_imgbtn_4, screen_imgbtn_4event_handler);
}
然后在该项目这个路径下使用自带的make文件来编译此项目
出现Linking simulator之后表示编译完成生成文件然后在这个路径下启动
执行效果如下图所示
因为有设置了退出函数所以直接关闭界面也可以自动杀死子进程不会出现父进程退出子进程还在放歌的局面