@@ -0,0 +1,166 @@
const std = @import("std");
const Allocator = std.mem.Allocator;
const player = @import("root.zig");
pub fn lookup(
arena: Allocator,
http_client: *std.http.Client,
recording_id: []const u8,
) !Response {
var server_header_buffer: [16 * 1024]u8 = undefined;
var json_read_buffer: [16 * 1024]u8 = undefined;
var req = try http_client.open(.GET, .{
.scheme = "https",
.host = "musicbrainz.org",
.path = try std.fmt.allocPrint(arena, "/ws/2/recording/{s}", .{recording_id}),
.query = "inc=work-rels+artist-credits+releases+discids",
}, .{
.server_header_buffer = &server_header_buffer,
.headers = .{
.user_agent = .{ .override = player.http_user_agent },
},
.extra_headers = &.{
.{ .name = "accept", .value = "application/json" },
},
});
defer req.deinit();
try req.send(.{ .raw_uri = true });
try req.wait();
if (req.response.status != .ok)
return error.HttpRequestFailed;
const content_type = req.response.content_type orelse
return error.HttpResponseMissingContentType;
const mime_type_end = std.mem.indexOf(u8, content_type, ";") orelse content_type.len;
const mime_type = content_type[0..mime_type_end];
if (!std.ascii.eqlIgnoreCase(mime_type, "application/json"))
return error.HttpResponseNotJson;
const raw_json = json_read_buffer[0..(try req.readAll(&json_read_buffer))];
const response = try std.json.parseFromSliceLeaky(Response, arena, raw_json, .{
.ignore_unknown_fields = true,
});
return response;
}
pub const Response = struct {
//disambiguation: []u8,
title: []u8,
@"artist-credit": []ArtistCredit,
//id: []u8,
relations: []Relation,
@"first-release-date": []u8,
//length: f64,
releases: []Release,
//video: bool,
};
pub const ArtistCredit = struct {
//artist: Artist,
//joinphrase: []u8,
name: []u8,
};
pub const Artist = struct {
@"sort-name": []u8,
disambiguation: []u8,
@"type-id": []u8,
type: []u8,
id: []u8,
name: []u8,
};
pub const Relation = struct {
//attributes: [][]u8,
work: Work,
//"attribute-values": {},
//ended: bool,
//@"attribute-ids": AttributeIds,
//@"source-credit": []u8,
//@"target-credit": []u8,
//@"end": null,
//direction: []u8,
//@"type-id": []u8,
//type: []u8,
//@"begin": null,
//@"target-type": []u8,
};
pub const Release = struct {
//id: []u8,
//country: []u8,
//packaging: []u8,
//@"status-id": []u8,
//@"release-events": []ReleaseEvent,
//barcode: []u8,
//status: []u8,
//@"text-representation": TextRepresentation,
media: []Media,
//quality: []u8,
//disambiguation: []u8,
title: []u8,
//date: []u8,
//@"artist-credit": []ArtistCredit,
//@"packaging-id": []u8,
};
pub const Media = struct {
format: []u8,
position: u32,
//@"discs": []Disc,
@"track-count": u32,
//tracks: []Track,
@"track-offset": u32,
title: []u8,
//@"format-id": []u8,
};
pub const Track = struct {
title: []u8,
@"artist-credit": []ArtistCredit,
number: []u8,
length: f64,
position: u32,
id: []u8,
};
pub const Work = struct {
id: []u8,
type: []u8,
disambiguation: []u8,
@"type-id": []u8,
title: []u8,
languages: [][]u8,
iswcs: [][]u8,
//@"attributes": [],
language: []u8,
};
pub const AttributeIds = struct {
cover: []u8,
};
pub const ReleaseEvent = struct {
area: Area,
date: []u8,
};
pub const TextRepresentation = struct {
script: []u8,
language: []u8,
};
pub const Area = struct {
@"sort-name": []u8,
//@"type-id": null,
disambiguation: []u8,
@"iso-3166-1-codes": [][]u8,
//@"type": null,
name: []u8,
id: []u8,
};