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 = NULL; while (data.len) { struct bstr param; int cmd = read_cmd(&data, ¶m); switch (cmd) { case CUE_ERROR: talloc_free(f); return NULL; case CUE_TRACK: { MP_TARRAY_GROW(f, f->tracks, f->num_tracks); 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: 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 (cur_track) { if (type == 1) { cur_track->start = time; cur_track->filename = filename; } else if (type == 0) { cur_track->pregap_start = time; } } break; } case CUE_FILE: // NOTE: FILE comes before TRACK, so don't use cur_track->filename filename = read_quoted(f, ¶m); break; } } return f; }
static int d_open(demuxer_t *demuxer, enum demux_check check) { struct priv *p = demuxer->priv = talloc_zero(demuxer, struct priv); if (check != DEMUX_CHECK_FORCE) return -1; char *demux = "+lavf"; if (demuxer->stream->uncached_type == STREAMTYPE_CDDA) demux = "+rawaudio"; char *t = NULL; stream_control(demuxer->stream, STREAM_CTRL_GET_DISC_NAME, &t); if (t) { mp_tags_set_bstr(demuxer->metadata, bstr0("TITLE"), bstr0(t)); talloc_free(t); } // Initialize the playback time. We need to read _some_ data to get the // correct stream-layer time (at least with libdvdnav). stream_peek(demuxer->stream, 1); reset_pts(demuxer); p->slave = demux_open(demuxer->stream, demux, NULL, demuxer->global); if (!p->slave) return -1; // So that we don't miss initial packets of delayed subtitle streams. demux_set_stream_autoselect(p->slave, true); // Can be seekable even if the stream isn't. demuxer->seekable = true; // With cache enabled, the stream can be seekable. This causes demux_lavf.c // (actually libavformat/mpegts.c) to seek sometimes when reading a packet. // It does this to seek back a bit in case the current file position points // into the middle of a packet. demuxer->stream->seekable = false; add_dvd_streams(demuxer); add_streams(demuxer); add_stream_chapters(demuxer); return 0; }
void mp_tags_set_str(struct mp_tags *tags, const char *key, const char *value) { mp_tags_set_bstr(tags, bstr0(key), bstr0(value)); }