三、结束播放

该文描述了一个音乐播放器的控制逻辑,涉及父进程如何通过发送信号(SIGKILL,SIGSTOP,SIGCONT)来控制子进程和孙进程的生命周期,包括开始播放、停止播放、暂停和继续播放的功能。在暂停和继续时,使用SIGSTOP和SIGCONT信号来暂停和恢复子孙进程。此外,还实现了上一首和下一首歌曲的切换,通过结束当前音乐进程并选择新的歌曲来实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

父进程把子孙进程杀死就可以了

select.c

else if (FD_ISSET(g_buttonfd, &tmpfd))    //按键有数据可读
        {
            int id = get_key_id();
            switch (id)
            {
                case 1:
                    start_play();
                    break;
                case 2:
                    stop_play();
                    break;

player.c

void stop_play()
{
    if (g_start_flag == 0)//如果未播放,直接返回
    {
        return;
    }

    //读取共享内存,获取pid
    shm s;
    memset(&s, 0, sizeof(s));  //清空内存空间
    memcpy(&s, g_addr, sizeof(s)); //把内存空间的数据拷贝到s中

    //kill(s.grand_pid, SIGKILL);    //结束子进程
    //kill(s.child_pid, SIGKILL);    //结束孙进程
    //需要先杀死子进程,负责的话杀死孙进程,子进程还会创建一个孙进程
    kill(s.child_pid, SIGKILL);      //结束子进程
    kill(s.grand_pid, SIGKILL);      //结束孙进程
    
    g_start_flag = 0;//更新播放标志
}

player.c

#ifndef PLAYER_H
#define PLAYER_H

#include <unistd.h>

#define MUSICPATH   "/root/music_list/"
//#define MUSICPATH   "/mount/usb/"
#define SHMKEY     1234
#define SHMSIZE    4096

#define SEQUENCEMODE    1
#define RANDOM          2
#define CIRCLE          3

//共享内存数据
struct shm
{
    int play_mode;
    char cur_name[64];
    pid_t ppid;
    pid_t child_pid;
    pid_t grand_pid;
};
typedef struct shm shm;

int InitShm();
void GetMusic();
void start_play();
void stop_play();
#endif

暂停继续:通过信号继续

select.c

case 3:
                    suspend_play();
                    break;
                case 4:
                    continue_play();
                    break;

player.h

#ifndef PLAYER_H
#define PLAYER_H

#include <unistd.h>

//#define MUSICPATH   "/root/music_list/"
#define MUSICPATH   "/mount/usb/"
#define SHMKEY     1234
#define SHMSIZE    4096

#define SEQUENCEMODE    1
#define RANDOM          2
#define CIRCLE          3

//共享内存数据
struct shm
{
    int play_mode;
    char cur_name[64];
    pid_t ppid;
    pid_t child_pid;
    pid_t grand_pid;
};
typedef struct shm shm;

int InitShm();
void GetMusic();
void start_play();
void stop_play();
void suspend_play();
void continue_play();
#endif

暂停前提正在播放或者已经暂停了都不可以

通过信号让子孙进程停止

player.c

void suspend_play()
{
    if (g_start_flag == 0 || g_suspend_flag == 1)
    {
        return;
    }

    //读取共享内存,获取pid
    shm s;
    memset(&s, 0, sizeof(s));
    memcpy(&s, g_addr, sizeof(s));

    kill(s.grand_pid, SIGSTOP);     //暂停孙进程
    kill(s.child_pid, SIGSTOP);     //暂停子进程

    g_suspend_flag = 1;
}

继续:

没有播放没法继续,如果没有暂停没法继续

void continue_play()
{
    if (g_start_flag == 0 || g_suspend_flag == 0)
    {
        return;
    }

    //读取共享内存,获取pid
    shm s;
    memset(&s, 0, sizeof(s));
    memcpy(&s, g_addr, sizeof(s));

    kill(s.grand_pid, SIGCONT);     //暂停孙进程
    kill(s.child_pid, SIGCONT);     //暂停子进程

    g_suspend_flag = 0;
}

上一首:

信号杀死再选择一首歌

select.c

                case 5:
                    prior_play();
                    break;
                case 6:
                    next_play();
                    break;

pleyer.h

void prior_play();
void next_play();

player.c实现

做一些判断

1、现在正在播放

2、暂停也不能上一首

只有播放才能切换上一首

3、先结束当前音乐

void prior_play()
{
    if (g_start_flag == 0 || g_suspend_flag == 1)
    {
        return;
    }

    //读取共享内存,获取pid
    shm s;
    memset(&s, 0, sizeof(s));
    memcpy(&s, g_addr, sizeof(s));

    //kill(s.grand_pid, SIGKILL);    //结束子进程
    //kill(s.child_pid, SIGKILL);    //结束孙进程
    
    kill(s.child_pid, SIGKILL);      //结束子进程
    kill(s.grand_pid, SIGKILL);      //结束孙进程

    g_start_flag = 0;

    char name[64] = {0};
    PriorMusic(s.cur_name, s.play_mode, name);
    play_music(name);    
    g_start_flag = 1;
}

link.c

void PriorMusic(const char *cur, int mode, char *prior)//当前播放,播放模式,上一首
{
    if (mode == SEQUENCEMODE || mode == CIRCLE)//如果顺序播放或者循环播放
    {
        Node *p = head->next; //新节点指向头节点的下一个
        while (strcmp(p->music_name, cur) != 0) //移动新节点到当前播放位置
        {
            p = p->next;
        }

        if (p == head->next) //屏蔽头结点,指向头结点的下一首
        {
            printf("%s\n", head->prior->music_name);
            strcpy(prior, head->prior->music_name);
        }
        else//如果不是头结点,直接指向上一首就可以了
        {
            strcpy(prior, p->prior->music_name);
        }
        return;
    }
    else //如果不是循环或者单曲循环就是随机播放,上一首用一个随机种子随机找一首
    {
        Node *p = head->next;
        srand(time(NULL));
        int num = rand() % 100;

        int i;
        for (i = 0; i < num; i++)
        {
            p = p->next;
        }

        if (p == head)
        {
            strcpy(prior, p->next->music_name);
        }
        else
        {
            strcpy(prior, p->music_name);
        }

        return;
    }
}

下一首:

player.c

void next_play()
{
    if (g_start_flag == 0 || g_suspend_flag == 1)//停止播放或者已经暂停直接返回
    {
        return;
    }

    //读取共享内存,获取pid
    shm s;
    memset(&s, 0, sizeof(s));
    memcpy(&s, g_addr, sizeof(s));

    //kill(s.grand_pid, SIGKILL);    //结束子进程
    //kill(s.child_pid, SIGKILL);    //结束孙进程
    
    kill(s.child_pid, SIGKILL);      //结束子进程
    kill(s.grand_pid, SIGKILL);      //结束孙进程

    g_start_flag = 0;

    char name[64] = {0};
    NextMusic(s.cur_name, s.play_mode, name);
    play_music(name);    
    g_start_flag = 1;
}
void NextMusic(const char *cur, int mode, char *next)
{
    if (mode == SEQUENCEMODE || mode == CIRCLE)
    {
        Node *p = head->next;
        while (strcmp(p->music_name, cur) != 0)
        {
            p = p->next;
        }

        if (p->next == head)
        {
            strcpy(next, head->next->music_name);
        }
        else
        {
            strcpy(next, p->next->music_name);
        }
        return;
    }
    else 
    {
        Node *p = head->next;
        srand(time(NULL));
        int num = rand() % 100;

        int i;
        for (i = 0; i < num; i++)
        {
            p = p->next;
        }

        if (p == head)
        {
            strcpy(next, p->next->music_name);
        }
        else
        {
            strcpy(next, p->music_name);
        }

        return;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值