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; }
std::istream& Path::read_file_path_from(std::istream &is) { std::string s; read_quoted(is, s); set_file_path_from(s); return is; }
static Atomic read_a(char *s, int *len) { if(s[0]=='(') { *len=1; return A_RBRA; } if(s[0]==')') { *len=1; return A_RCET; } if(s[0]=='{') { *len=1; return A_FBRA; } if(s[0]=='}') { *len=1; return A_FCET; } if(s[0]=='[') { *len=1; return A_QBRA; } if(s[0]==']') { *len=1; return A_QCET; } if(s[0]=='.') { *len=1; return A_POINT; } if(s[0]==';') { *len=1; return A_SECO; } if(s[0]==',') { *len=1; return A_COMMA; } if(s[0]=='\'') return read_quoted(s,len,'\''); if(s[0]=='\"') return read_quoted(s,len,'\"'); if(s[0]=='`') { *len=1; return A_RQUOTE; } if(isalpha(s[0]) || s[0]=='_' || s[0]=='~') { int alen; alen=0; while(isalnum(s[alen]) || s[alen]=='_' || s[alen]=='~' ) alen++; *len=alen; return NewAtom(s,alen); } /* test for numbers */ if(isdigit(s[0]) /*|| (s[0]=='-' && isdigit(s[1]))*/ ) { int negflag=0; int alen=0; int lll; if(s[0]=='-') {negflag=1; s++; alen++; } lll=0; while(isdigit(s[lll])) lll++; if((s[lll]=='e' || s[lll]=='E') && (isdigit(s[lll+1]) || s[lll+1]=='-')) { double f=0.0; int eneg=0,exp=0; while(s[0]!='e' && s[0]!='E') { f*=10.0; f+=s[0]-'0'; s++; alen++; } if(negflag) f=-f; s++; alen++; if(s[0]=='-') { s++; alen++; eneg=1; } if(s[0]=='+') { s++; alen++; } while(isdigit(s[0])) { exp*=10; exp+=s[0]-'0'; s++; alen++; } if(eneg) exp=-exp; f*=pow(10.0,exp); *len=alen; return NewFloat(f); } if(s[lll]=='.' && isdigit(s[lll+1])) { double f=0.0; double fact=1.0; while(s[0]!='.') { f*=10.0; f+=s[0]-'0'; s++; alen++; } s++; alen++; while(isdigit(s[0])) { fact/=10.0; f+=fact*(s[0]-'0'); s++; alen++; } if(negflag) f=-f; if(s[0]=='e' || s[0]=='E') { int eneg=0; int exp=0; s++; alen++; if(s[0]=='-') { s++; alen++; eneg=1; } if(s[0]=='+') { s++; alen++; } while(isdigit(s[0])) { exp*=10; exp+=s[0]-'0'; s++; alen++; } if(eneg) exp=-exp; f*=pow(10.0,exp); } *len=alen; return NewFloat(f); } lll=0; while(isdigit(s[0])) { lll*=10; lll+=s[0]-'0'; s++; alen++; } if(negflag) lll=-lll; *len=alen; return NewInteger(lll); } if(ispunct(s[0])) { int alen; alen=0; while(ispunct(s[alen]) && !alone(s[alen]) && !(alen>0 && s[alen-1] == '=' && s[alen]!= '=') ) alen++; *len=alen; return NewAtom(s,alen); } *len=1; return NewAtom("???",0); }
void build_cue_timeline(struct MPContext *mpctx) { void *ctx = talloc_new(NULL); struct bstr data = mpctx->demuxer->file_contents; data = skip_utf8_bom(data); struct cue_track *tracks = NULL; size_t track_count = 0; struct bstr filename = {0}; // Global metadata, and copied into new tracks. struct cue_track proto_track = {0}; struct cue_track *cur_track = &proto_track; while (data.len) { struct bstr param; switch (read_cmd(&data, ¶m)) { case CUE_ERROR: mp_msg(MSGT_CPLAYER, MSGL_ERR, "CUE: error parsing input file!\n"); goto out; case CUE_TRACK: { track_count++; tracks = talloc_realloc(ctx, tracks, struct cue_track, track_count); cur_track = &tracks[track_count - 1]; *cur_track = proto_track; break; } case CUE_TITLE: cur_track->title = read_quoted(¶m); 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; } break; } case CUE_FILE: // NOTE: FILE comes before TRACK, so don't use cur_track->filename filename = read_quoted(¶m); break; } } if (track_count == 0) { mp_msg(MSGT_CPLAYER, MSGL_ERR, "CUE: no tracks found!\n"); goto out; } // Remove duplicate file entries. This might be too sophisticated, since // CUE files usually use either separate files for every single track, or // only one file for all tracks. struct bstr *files = 0; size_t file_count = 0; for (size_t n = 0; n < track_count; n++) { struct cue_track *track = &tracks[n]; track->source = -1; for (size_t file = 0; file < file_count; file++) { if (bstrcmp(files[file], track->filename) == 0) { track->source = file; break; } } if (track->source == -1) { file_count++; files = talloc_realloc(ctx, files, struct bstr, file_count); files[file_count - 1] = track->filename; track->source = file_count - 1; } }