功能背景参考一。
note:播放/暂停主要时给进程发送停止和恢复信号,进程并没有退出。以下为c语言例程源码。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#define MAX_SONGS 3
char *songs[MAX_SONGS] = {
"/mnt/hgfs/share/poxiao.mp3",
"/mnt/hgfs/share/talk_anymore.mp3",
"/mnt/hgfs/share/attention.mp3"
};
int current_song = 0;
int play_mode = 0; // 0: 单曲播放, 1: 单曲循环, 2: 列表循环
pid_t player_pid = 0;
int is_paused = 0; // 标记是否处于暂停状态
void handle_sigchld(int sig) {
int status;
pid_t pid = waitpid(-1, &status, WUNTRACED | WCONTINUED);
if (pid > 0 && pid == player_pid) {
if (WIFEXITED(status)) {
// 子进程已正常结束
printf("歌曲播放结束\n");
if (play_mode == 1) { // 单曲循环
play_song(current_song);
} else if (play_mode == 2) { // 列表循环
current_song = (current_song + 1) % MAX_SONGS;
play_song(current_song);
} else {
player_pid = 0; // 单曲播放,播放结束后不再继续
}
} else if (WIFSTOPPED(status)) {
// 子进程已停止,通常不需要在这里做太多处理
printf("歌曲播放暂停\n");
} else if (WIFCONTINUED(status)) {
// 子进程已继续,通常也不需要在这里做太多处理
// 但可以重置某些状态或记录日志
printf("歌曲播放继续\n");
}
}
}
void play_song(int song_index) {
if (player_pid > 0) {
if (is_paused) {
kill(player_pid, SIGCONT); // 先恢复播放
is_paused = 0;
usleep(50000); // 短暂等待恢复播放的信号生效
}
kill(player_pid, SIGTERM);
waitpid(player_pid, NULL, 0);
}
player_pid = fork();
if (player_pid == 0) {
// 子进程: 播放歌曲
execlp("ffplay", "ffplay", "-nodisp", "-autoexit", songs[song_index], NULL);
perror("Failed to play song");
exit(1);
} else if (player_pid > 0) {
// 父进程: 设置SIGCHLD信号处理函数
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = handle_sigchld;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sigaction(SIGCHLD, &sa, NULL);
is_paused = 0; // 播放开始时重置暂停状态
}
}
void toggle_play_pause() {
if (player_pid > 0) {
if (is_paused) {
kill(player_pid, SIGCONT);
is_paused = 0;
printf("继续播放\n");
} else {
kill(player_pid, SIGSTOP);
is_paused = 1;
printf("暂停播放\n");
}
}
}
void play_next_song() {
current_song = (current_song + 1) % MAX_SONGS;
play_song(current_song);
}
void play_previous_song() {
current_song = (current_song - 1 + MAX_SONGS) % MAX_SONGS;
play_song(current_song);
}
void select_play_mode() {
play_mode = (play_mode + 1) % 3;
const char *mode_names[] = {"单曲播放", "单曲循环", "列表循环"};
printf("播放模式: %s\n", mode_names[play_mode]);
}
int main() {
int command;
while (1) {
printf("请输入指令: ");
scanf("%d", &command);
switch (command) {
case 1:
if (player_pid == 0) {
play_song(current_song);
} else {
toggle_play_pause();
}
break;
case 2:
play_next_song();
break;
case 3:
play_previous_song();
break;
case 4:
select_play_mode();
break;
default:
printf("无效的指令\n");
break;
}
}
return 0;
}