mirror of
https://github.com/mpv-player/mpv
synced 2025-03-25 04:38:01 +00:00
cue: read more metadata
Make handling of metadata slightly more generic, and add reading of the "PERFORMER" fields. There are some more fields, but for now let's leave it at this. TRACK-specific PERFORMER fields have to be read from the per-chapter metadata (somewhat obscure). Fixes #2328.
This commit is contained in:
parent
24f34c9e8e
commit
ae7212963e
32
demux/cue.c
32
demux/cue.c
@ -24,6 +24,7 @@
|
||||
|
||||
#include "misc/bstr.h"
|
||||
#include "common/common.h"
|
||||
#include "common/tags.h"
|
||||
|
||||
#include "cue.h"
|
||||
|
||||
@ -37,6 +38,7 @@ enum cue_command {
|
||||
CUE_TRACK,
|
||||
CUE_INDEX,
|
||||
CUE_TITLE,
|
||||
CUE_PERFORMER,
|
||||
};
|
||||
|
||||
static const struct {
|
||||
@ -51,7 +53,7 @@ static const struct {
|
||||
{ CUE_UNUSED, "CDTEXTFILE" },
|
||||
{ CUE_UNUSED, "FLAGS" },
|
||||
{ CUE_UNUSED, "ISRC" },
|
||||
{ CUE_UNUSED, "PERFORMER" },
|
||||
{ CUE_PERFORMER, "PERFORMER" },
|
||||
{ CUE_UNUSED, "POSTGAP" },
|
||||
{ CUE_UNUSED, "PREGAP" },
|
||||
{ CUE_UNUSED, "REM" },
|
||||
@ -160,17 +162,19 @@ bool mp_probe_cue(struct bstr data)
|
||||
struct cue_file *mp_parse_cue(struct bstr data)
|
||||
{
|
||||
struct cue_file *f = talloc_zero(NULL, struct cue_file);
|
||||
f->tags = talloc_zero(f, struct mp_tags);
|
||||
|
||||
data = skip_utf8_bom(data);
|
||||
|
||||
char *filename = NULL;
|
||||
// Global metadata, and copied into new tracks.
|
||||
struct cue_track proto_track = {0};
|
||||
struct cue_track *cur_track = &proto_track;
|
||||
struct cue_track *cur_track = NULL;
|
||||
|
||||
while (data.len) {
|
||||
struct bstr param;
|
||||
switch (read_cmd(&data, ¶m)) {
|
||||
int cmd = read_cmd(&data, ¶m);
|
||||
switch (cmd) {
|
||||
case CUE_ERROR:
|
||||
talloc_free(f);
|
||||
return NULL;
|
||||
@ -179,19 +183,29 @@ struct cue_file *mp_parse_cue(struct bstr data)
|
||||
f->num_tracks += 1;
|
||||
cur_track = &f->tracks[f->num_tracks - 1];
|
||||
*cur_track = proto_track;
|
||||
cur_track->tags = talloc_zero(f, struct mp_tags);
|
||||
break;
|
||||
}
|
||||
case CUE_TITLE:
|
||||
cur_track->title = read_quoted(f, ¶m);
|
||||
case CUE_PERFORMER: {
|
||||
static const char *metanames[] = {
|
||||
[CUE_TITLE] = "title",
|
||||
[CUE_PERFORMER] = "performer",
|
||||
};
|
||||
struct mp_tags *tags = cur_track ? cur_track->tags : f->tags;
|
||||
mp_tags_set_bstr(tags, bstr0(metanames[cmd]), param);
|
||||
break;
|
||||
}
|
||||
case CUE_INDEX: {
|
||||
int type = read_int_2(¶m);
|
||||
double time = read_time(¶m);
|
||||
if (type == 1) {
|
||||
cur_track->start = time;
|
||||
cur_track->filename = filename;
|
||||
} else if (type == 0) {
|
||||
cur_track->pregap_start = time;
|
||||
if (cur_track) {
|
||||
if (type == 1) {
|
||||
cur_track->start = time;
|
||||
cur_track->filename = filename;
|
||||
} else if (type == 0) {
|
||||
cur_track->pregap_start = time;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
struct cue_file {
|
||||
struct cue_track *tracks;
|
||||
int num_tracks;
|
||||
struct mp_tags *tags;
|
||||
};
|
||||
|
||||
struct cue_track {
|
||||
@ -32,7 +33,7 @@ struct cue_track {
|
||||
double start; // corresponds to INDEX 01
|
||||
char *filename;
|
||||
int source;
|
||||
char *title;
|
||||
struct mp_tags *tags;
|
||||
};
|
||||
|
||||
bool mp_probe_cue(struct bstr data);
|
||||
|
@ -924,7 +924,8 @@ static void demux_init_cuesheet(struct demuxer *demuxer)
|
||||
if (f) {
|
||||
for (int n = 0; n < f->num_tracks; n++) {
|
||||
struct cue_track *t = &f->tracks[n];
|
||||
demuxer_add_chapter(demuxer, t->title, t->start, -1);
|
||||
int idx = demuxer_add_chapter(demuxer, "", t->start, -1);
|
||||
mp_tags_merge(demuxer->chapters[idx].metadata, t->tags);
|
||||
}
|
||||
}
|
||||
talloc_free(f);
|
||||
|
@ -38,7 +38,7 @@
|
||||
#define PROBE_SIZE 512
|
||||
|
||||
struct priv {
|
||||
bstr data;
|
||||
struct cue_file *f;
|
||||
};
|
||||
|
||||
static void add_source(struct timeline *tl, struct demuxer *d)
|
||||
@ -150,15 +150,8 @@ static void build_timeline(struct timeline *tl)
|
||||
|
||||
add_source(tl, tl->demuxer);
|
||||
|
||||
struct cue_file *f = mp_parse_cue(p->data);
|
||||
if (!f) {
|
||||
MP_ERR(tl, "CUE: error parsing input file!\n");
|
||||
goto out;
|
||||
}
|
||||
talloc_steal(ctx, f);
|
||||
|
||||
struct cue_track *tracks = f->tracks;
|
||||
size_t track_count = f->num_tracks;
|
||||
struct cue_track *tracks = p->f->tracks;
|
||||
size_t track_count = p->f->num_tracks;
|
||||
|
||||
if (track_count == 0) {
|
||||
MP_ERR(tl, "CUE: no tracks found!\n");
|
||||
@ -224,10 +217,8 @@ static void build_timeline(struct timeline *tl)
|
||||
};
|
||||
chapters[i] = (struct demux_chapter) {
|
||||
.pts = timeline[i].start,
|
||||
.metadata = talloc_zero(tl, struct mp_tags),
|
||||
.metadata = mp_tags_dup(tl, tracks[i].tags),
|
||||
};
|
||||
// might want to include other metadata here
|
||||
mp_tags_set_str(chapters[i].metadata, "title", tracks[i].title);
|
||||
starttime += duration;
|
||||
}
|
||||
|
||||
@ -261,9 +252,18 @@ static int try_open_file(struct demuxer *demuxer, enum demux_check check)
|
||||
struct priv *p = talloc_zero(demuxer, struct priv);
|
||||
demuxer->priv = p;
|
||||
demuxer->fully_read = true;
|
||||
p->data = stream_read_complete(s, demuxer, 1000000);
|
||||
if (p->data.start == NULL)
|
||||
|
||||
bstr data = stream_read_complete(s, p, 1000000);
|
||||
if (data.start == NULL)
|
||||
return -1;
|
||||
p->f = mp_parse_cue(data);
|
||||
talloc_steal(p, p->f);
|
||||
if (!p->f) {
|
||||
MP_ERR(demuxer, "error parsing input file!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mp_tags_merge(demuxer->metadata, p->f->tags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user