You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在树莓派上用C脚本实现MIDI文件循环播放列表?

用C实现树莓派MIDI曲目循环播放并自动重启

当然可以实现,既然你已经能用aplaymidi命令播放单个MIDI文件,完全不需要直接解析MIDI协议——直接在C程序里调用这个命令,配合目录遍历和进程等待就能实现循环播放+自动重启的需求。下面是具体实现方案:

核心思路

  1. 遍历指定目录,收集所有.mid/.midi格式的文件
  2. 对每个MIDI文件,通过fork()+exec()调用aplaymidi命令播放,等待播放完成后再进入下一首
  3. 一轮曲目全部播放完成后,调用系统重启命令
  4. 循环上述流程(直到重启执行)

完整代码实现

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>

#define MIDI_DIR "/home/user/Music"  // 替换为你的MIDI文件目录
#define MIDI_PORT "14"               // 你的MIDI端口号

// 播放单个MIDI文件,等待播放完成
int play_midi(const char *file_path) {
    pid_t pid = fork();
    if (pid == -1) {
        perror("fork failed");
        return -1;
    } else if (pid == 0) {
        // 子进程执行aplaymidi命令
        execlp("aplaymidi", "aplaymidi", "-p", MIDI_PORT, file_path, NULL);
        // 如果execlp执行失败,打印错误并退出子进程
        perror("execlp failed to run aplaymidi");
        exit(EXIT_FAILURE);
    } else {
        // 父进程等待子进程结束,确保播放完成
        int status;
        waitpid(pid, &status, 0);
        return WIFEXITED(status) ? WEXITSTATUS(status) : -1;
    }
}

// 遍历目录,收集所有MIDI文件的完整路径
int collect_midi_files(const char *dir, char ***files, size_t *count) {
    DIR *dir_ptr = opendir(dir);
    if (!dir_ptr) {
        perror("failed to open directory");
        return -1;
    }

    struct dirent *entry;
    size_t capacity = 8;  // 初始容量,自动扩容
    *files = malloc(capacity * sizeof(char*));
    *count = 0;

    while ((entry = readdir(dir_ptr)) != NULL) {
        // 跳过目录和非MIDI文件
        if (entry->d_type != DT_REG) continue;
        
        const char *ext = strrchr(entry->d_name, '.');
        if (ext && (strcmp(ext, ".mid") == 0 || strcmp(ext, ".midi") == 0)) {
            // 扩容检查
            if (*count >= capacity) {
                capacity *= 2;
                char **temp = realloc(*files, capacity * sizeof(char*));
                if (!temp) {
                    perror("realloc failed");
                    closedir(dir_ptr);
                    return -1;
                }
                *files = temp;
            }

            // 拼接完整文件路径
            size_t path_len = strlen(dir) + strlen(entry->d_name) + 2;
            (*files)[*count] = malloc(path_len);
            snprintf((*files)[*count], path_len, "%s/%s", dir, entry->d_name);
            (*count)++;
        }
    }

    closedir(dir_ptr);
    return 0;
}

int main() {
    char **midi_files;
    size_t file_count;

    // 收集MIDI文件
    if (collect_midi_files(MIDI_DIR, &midi_files, &file_count) != 0) {
        fprintf(stderr, "Failed to collect MIDI files\n");
        return EXIT_FAILURE;
    }

    if (file_count == 0) {
        fprintf(stderr, "No MIDI files found in directory: %s\n", MIDI_DIR);
        free(midi_files);
        return EXIT_FAILURE;
    }

    // 循环播放所有曲目,完成后重启
    while (1) {
        printf("Starting new playback cycle (%zu tracks)\n", file_count);
        for (size_t i = 0; i < file_count; i++) {
            printf("Now playing: %s\n", midi_files[i]);
            if (play_midi(midi_files[i]) != 0) {
                fprintf(stderr, "Warning: Failed to play %s, skipping...\n", midi_files[i]);
            }
        }

        printf("Playback cycle completed. Initiating reboot...\n");
        // 执行重启命令(需要sudo权限)
        system("sudo reboot");
        
        // 如果重启命令未执行成功,退出循环(避免无限尝试)
        break;
    }

    // 释放内存
    for (size_t i = 0; i < file_count; i++) {
        free(midi_files[i]);
    }
    free(midi_files);

    return EXIT_SUCCESS;
}

编译与运行说明

  1. 编译代码:在终端执行
    gcc midi_player.c -o midi_player
    
  2. 运行程序:由于重启需要管理员权限,执行:
    sudo ./midi_player
    
  3. 前置检查:
    • 确保aplaymidi已安装,若未安装执行sudo apt install alsa-utils
    • 替换代码中的MIDI_DIR为你的实际MIDI文件存储目录
    • 若不想每次输入sudo密码,可以修改sudoers配置(需谨慎):
      • 执行sudo visudo
      • 添加一行:your_username ALL=(ALL) NOPASSWD: /path/to/midi_player(替换为你的用户名和程序路径)

内容的提问来源于stack exchange,提问作者Brandon McDonald

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 17:50:45