linux下的音乐mv播放器:使用 C 语言与 libcurl 实现 MV 搜索与播放及 API 联动

目录

一、引言

二、用到的工具

1. C 语言编译器

2. libcurl 库

3. mpv 播放器

三、安装教程

1. 安装 GCC(以 Windows 系统为例,通过 MinGW 安装)

2. 安装 libcurl 库

Linux 系统(以 Ubuntu 为例)

3. 安装 mpv 播放器

Linux 系统(以 Ubuntu 为例)

四、代码详解

1. 引入头文件

2. 写入回调函数

3. JSON 字段提取函数

4. 提取 MV 信息的包装函数

5. 主函数

五、总结

一、引言

在数字化娱乐时代,我们常常希望能够通过简单的命令行操作,快速搜索并播放喜欢的 MV。本文将详细介绍如何使用 C 语言结合libcurl库实现一个实用的 MV 搜索与播放工具,并且在找到 MV 信息后,联动另一个 API 获取相关内容,实现功能的拓展。通过本文的学习,你将掌握 C 语言中网络请求的基本操作、JSON 数据解析以及命令行程序的开发技巧。

#include <stdio.h>
#include <curl/curl.h>
#include <stdlib.h>
#include <string.h>

// 通用写入回调函数,将数据写入缓冲区
size_t write_callback(void* contents, size_t size, size_t nmemb, void* userp) {
    size_t realsize = size * nmemb;
    char* ptr = (char*)userp;
    strncat(ptr, (char*)contents, realsize);
    return realsize;
}

// 从JSON响应中提取指定字段的值
int extract_json_field(const char* response, const char* prefix, char* value, size_t value_size) {
    const char* start = strstr(response, prefix);
    if (start == NULL) return 0;

    start += strlen(prefix);
    const char* end = strchr(start, '"');
    if (end == NULL || (size_t)(end - start) >= value_size) return 0;

    strncpy(value, start, end - start);
    value[end - start] = '\0';
    return 1;
}

// 提取MV链接的包装函数
int extract_mv_url(const char* res, char* url, size_t s) {
    return extract_json_field(res, "\"url\": \"", url, s);
}

// 提取MV名称的包装函数
int extract_mv_name(const char* res, char* name, size_t s) {
    return extract_json_field(res, "\"mv_name\": \"", name, s);
}

// 提取MV歌手的包装函数
int extract_mv_singer(const char* res, char* singer, size_t s) {
    return extract_json_field(res, "\"mv_singer\": \"", singer, s);
}

int main(void) {
    CURL* curl;
    char response[8192] = { 0 };
    char mv_url[512] = { 0 }, mv_name[256] = { 0 }, mv_singer[256] = { 0 };
    int exit_flag = 0;

    curl_global_init(CURL_GLOBAL_DEFAULT);

    while (!exit_flag) {
        memset(response, 0, sizeof(response));
        memset(mv_url, 0, sizeof(mv_url));
        memset(mv_name, 0, sizeof(mv_name));
        memset(mv_singer, 0, sizeof(mv_singer));

        printf("\n请输入歌曲名称(输入exit退出): ");
        char search_song[100];
        scanf("%99s", search_song);

        // 清除输入缓冲区
        while (getchar() != '\n');

        if (strcmp(search_song, "exit") == 0) break;

        curl = curl_easy_init();
        if (curl) {
            // 构造并发送获取MV信息的请求
            char url[512];
            snprintf(url, sizeof(url), "https://xiaoapi.cn/API/mv.php?type=kg&msg=%s&n=1", search_song);
            curl_easy_setopt(curl, CURLOPT_URL, url);
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, response);

            if (curl_easy_perform(curl) == CURLE_OK) {
                // 提取MV的各项信息
                int valid = extract_mv_url(response, mv_url, sizeof(mv_url))
                    & extract_mv_name(response, mv_name, sizeof(mv_name))
                    & extract_mv_singer(response, mv_singer, sizeof(mv_singer));

                if (valid && mv_url[0]) {
                    // 调用新的API获取内容
                    CURL* new_curl = curl_easy_init();
                    char new_response[8192] = { 0 };
                    if (new_curl) {
                        curl_easy_setopt(new_curl, CURLOPT_URL, "https://api.vvhan.com/api/text/love");
                        curl_easy_setopt(new_curl, CURLOPT_WRITEFUNCTION, write_callback);
                        curl_easy_setopt(new_curl, CURLOPT_WRITEDATA, new_response);

                        if (curl_easy_perform(new_curl) == CURLE_OK) {
                            // 同时输出MV信息和新API的响应内容
                            printf("\n找到MV:\n  歌曲:%s\n  歌手:%s\n", mv_name, mv_singer);
                            printf("  播放链接:%s\n", mv_url);
                            printf("来自 https://api.vvhan.com/api/text/love 的响应:\n%s\n", new_response);
                        } else {
                            fprintf(stderr, "请求 https://api.vvhan.com/api/text/love 失败\n");
                        }

                        curl_easy_cleanup(new_curl);
                    }

                    char cmd[1024];
                    snprintf(cmd, sizeof(cmd), "mpv --no-terminal \"%s\"", mv_url);
                    system(cmd);
                } else {
                    printf("未找到完整MV信息,请尝试其他歌曲\n");
                }
            }
            curl_easy_cleanup(curl);
        }
    }

    curl_global_cleanup();
    printf("\n感谢使用,再见!\n");
    return 0;
}

编译 -运行

gcc -o music_player music_player.c -lcurl
./music_player

二、用到的工具

1. C 语言编译器

C 语言是一种通用的、高效的编程语言,广泛应用于系统软件、嵌入式开发以及高性能计算等领域。我们将使用 C 语言编写核心代码,常见的 C 语言编译器有GCC(GNU Compiler Collection)和Clang。在 Linux 和 macOS 系统上,GCC通常已经预装;在 Windows 系统上,可以通过安装 MinGW 或 Cygwin 来获取GCC编译器。

2. libcurl 库

libcurl是一个功能强大的开源库,用于在程序中进行网络请求操作,支持多种协议(如 HTTP、HTTPS、FTP 等)。它提供了丰富的 API 接口,方便开发者在不同的编程语言中实现网络通信功能。在我们的项目中,将使用libcurl库发送 HTTP 请求,获取 MV 相关信息以及其他 API 的响应数据。

3. mpv 播放器

mpv是一款自由、开源的多媒体播放器,支持多种音频和视频格式,具有强大的功能和高度的可定制性。我们将使用mpv播放器来播放搜索到的 MV,通过在命令行中调用mpv命令实现自动播放。

三、安装教程

1. 安装 GCC(以 Windows 系统为例,通过 MinGW 安装)

2. 安装 libcurl 库

Linux 系统(以 Ubuntu 为例)
  1. 打开终端,输入以下命令安装libcurl库及其开发包:
sudo apt-get update
sudo apt-get install libcurl4-openssl-dev
  1. 安装完成后,系统会自动将libcurl库的头文件和链接库文件安装到相应的目录(通常是/usr/include/usr/lib)。

3. 安装 mpv 播放器

Linux 系统(以 Ubuntu 为例)

打开终端,输入以下命令安装mpv播放器:

sudo apt-get install mpv

四、代码详解

1. 引入头文件

#include <stdio.h>
#include <curl/curl.h>
#include <stdlib.h>
#include <string.h>
  • stdio.h:提供标准输入输出函数,如printfscanf等。
  • curl/curl.h:引入libcurl库的头文件,用于网络请求操作。
  • stdlib.h:包含一些通用的函数,如内存分配函数mallocfree,以及进程终止函数exit等。
  • string.h:提供字符串处理函数,如strcpystrcatstrcmp等。

2. 写入回调函数

size_t write_callback(void* contents, size_t size, size_t nmemb, void* userp) {
    size_t realsize = size * nmemb;
    char* ptr = (char*)userp;
    strncat(ptr, (char*)contents, realsize);
    return realsize;
}

该函数是libcurl库的写入回调函数,用于将从网络请求中接收到的数据写入指定的缓冲区。contents指向接收到的数据,size表示每个数据块的大小,nmemb表示数据块的数量,userp是用户自定义的指针,指向用于存储数据的缓冲区。函数将接收到的数据追加到缓冲区中,并返回实际写入的数据大小。

3. JSON 字段提取函数

int extract_json_field(const char* response, const char* prefix, char* value, size_t value_size) {
    const char* start = strstr(response, prefix);
    if (start == NULL) return 0;

    start += strlen(prefix);
    const char* end = strchr(start, '"');
    if (end == NULL || (size_t)(end - start) >= value_size) return 0;

    strncpy(value, start, end - start);
    value[end - start] = '\0';
    return 1;
}

此函数用于从 JSON 格式的响应数据中提取指定字段的值。它首先在响应字符串response中查找指定的前缀prefix,找到后计算字段值的起始和结束位置,然后将字段值复制到value缓冲区中,并确保不会超出缓冲区的大小。如果成功提取到字段值,则返回 1;否则返回 0。

4. 提取 MV 信息的包装函数

int extract_mv_url(const char* res, char* url, size_t s) {
    return extract_json_field(res, "\"url\": \"", url, s);
}

int extract_mv_name(const char* res, char* name, size_t s) {
    return extract_json_field(res, "\"mv_name\": \"", name, s);
}

int extract_mv_singer(const char* res, char* singer, size_t s) {
    return extract_json_field(res, "\"mv_singer\": \"", singer, s);
}

这些函数是对extract_json_field函数的封装,分别用于提取 MV 的链接、名称和歌手信息。通过指定不同的前缀,调用extract_json_field函数实现具体字段的提取。

5. 主函数

int main(void) {
    CURL* curl;
    char response[8192] = { 0 };
    char mv_url[512] = { 0 }, mv_name[256] = { 0 }, mv_singer[256] = { 0 };
    int exit_flag = 0;

    curl_global_init(CURL_GLOBAL_DEFAULT);

    while (!exit_flag) {
        memset(response, 0, sizeof(response));
        memset(mv_url, 0, sizeof(mv_url));
        memset(mv_name, 0, sizeof(mv_name));
        memset(mv_singer, 0, sizeof(mv_singer));

        printf("\n请输入歌曲名称(输入exit退出): ");
        char search_song[100];
        scanf("%99s", search_song);

        // 清除输入缓冲区
        while (getchar() != '\n');

        if (strcmp(search_song, "exit") == 0) break;

        curl = curl_easy_init();
        if (curl) {
            // 构造并发送获取MV信息的请求
            char url[512];
            snprintf(url, sizeof(url), "https://xiaoapi.cn/API/mv.php?type=kg&msg=%s&n=1", search_song);
            curl_easy_setopt(curl, CURLOPT_URL, url);
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, response);

            if (curl_easy_perform(curl) == CURLE_OK) {
                // 提取MV的各项信息
                int valid = extract_mv_url(response, mv_url, sizeof(mv_url))
                    & extract_mv_name(response, mv_name, sizeof(mv_name))
                    & extract_mv_singer(response, mv_singer, sizeof(mv_singer));

                if (valid && mv_url[0]) {
                    // 调用新的API获取内容
                    CURL* new_curl = curl_easy_init();
                    char new_response[8192] = { 0 };
                    if (new_curl) {
                        curl_easy_setopt(new_curl, CURLOPT_URL, "https://api.vvhan.com/api/text/love");
                        curl_easy_setopt(new_curl, CURLOPT_WRITEFUNCTION, write_callback);
                        curl_easy_setopt(new_curl, CURLOPT_WRITEDATA, new_response);

                        if (curl_easy_perform(new_curl) == CURLE_OK) {
                            // 同时输出MV信息和新API的响应内容
                            printf("\n找到MV:\n  歌曲:%s\n  歌手:%s\n", mv_name, mv_singer);
                            printf("  播放链接:%s\n", mv_url);
                            printf("来自 https://api.vvhan.com/api/text/love 的响应:\n%s\n", new_response);
                        } else {
                            fprintf(stderr, "请求 https://api.vvhan.com/api/text/love 失败\n");
                        }

                        curl_easy_cleanup(new_curl);
                    }

                    char cmd[1024];
                    snprintf(cmd, sizeof(cmd), "mpv --no-terminal \"%s\"", mv_url);
                    system(cmd);
                } else {
                    printf("未找到完整MV信息,请尝试其他歌曲\n");
                }
            }
            curl_easy_cleanup(curl);
        }
    }

    curl_global_cleanup();
    printf("\n感谢使用,再见!\n");
    return 0;
}
  • 初始化和变量定义:定义了CURL指针、响应缓冲区、MV 信息缓冲区以及退出标志等变量,并初始化libcurl库。
  • 循环输入:通过一个while循环,持续提示用户输入歌曲名称。如果用户输入exit,则设置退出标志,结束循环。
  • 发送 MV 信息请求:在每次循环中,构造获取 MV 信息的 API 请求 URL,使用libcurl库发送请求,并将响应数据存储在response缓冲区中。
  • 提取 MV 信息:调用extract_mv_urlextract_mv_nameextract_mv_singer函数,从响应数据中提取 MV 的链接、名称和歌手信息。
  • 调用新 API 并输出结果:如果成功提取到完整的 MV 信息,再次使用libcurl库发送请求到https://api.vvhan.com/api/text/love,获取额外的内容。将 MV 信息和新 API 的响应内容同时输出到控制台。
  • 播放 MV:构造mpv播放器的命令,通过system函数调用mpv命令,播放搜索到的 MV。
  • 清理资源:在程序结束前,清理libcurl库的资源,释放相关内存。

五、总结

     通过本文的介绍,我们成功使用 C 语言结合libcurl库实现了一个功能丰富的 MV 搜索与播放工具,并联动了另一个 API 获取额外内容。在这个过程中,我们学习了libcurl库的基本使用方法、JSON 数据解析技巧以及如何在 C 语言中调用外部程序。希望本文对你在 C 语言网络编程和实际项目开发中有所帮助。你可以根据自己的需求,进一步拓展和优化这个程序,例如添加错误处理机制、优化代码结构等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值