static void parse_browse_album(ezxml_t top, struct album_browse* a) { xmlstrncpy(a->name, sizeof a->name, top, "name", -1); xmlstrncpy(a->id, sizeof a->id, top, "id", -1); xmlstrncpy(a->cover_id, sizeof a->cover_id, top, "cover", -1); xmlatoi(&a->year, top, "year", -1); xmlatof(&a->popularity, top, "popularity", -1); xmlstrncpy(a->artist, sizeof a->artist, top, "artist", -1); xmlstrncpy(a->artist_id, sizeof a->artist_id, top, "artist-id", -1); ezxml_t x = ezxml_get(top, "review",-1); if (x) { int len = strlen(x->txt); a->review = malloc(len + 1); memcpy(a->review, x->txt, len+1); } /* TODO: support multiple discs per album */ a->tracks = calloc(1, sizeof(struct track)); ezxml_t disc = ezxml_get(top, "discs",0,"disc", -1); a->num_tracks = parse_tracks(disc, a->tracks, false); /* Copy missing metadata from album to tracks */ int count = 0; for (struct track *t = a->tracks; t; t = t->next) { DSFYstrncpy(t->album, a->name, sizeof t->album); DSFYstrncpy(t->album_id, a->id, sizeof t->album_id); DSFYstrncpy(t->cover_id, a->cover_id, sizeof t->cover_id); t->year = a->year; count++; } }
static void parse_artist(ezxml_t top, struct artist *a) { xmlstrncpy(a->name, sizeof a->name, top, "name", -1); xmlstrncpy(a->id, sizeof a->id, top, "id", -1); xmlstrncpy(a->portrait_id, sizeof a->portrait_id, top, "portrait", 0, "id", -1); xmlatof(&a->popularity, top, "popularity", -1); }
static void parse_album(ezxml_t top, struct album* a) { xmlstrncpy(a->name, sizeof a->name, top, "name", -1); xmlstrncpy(a->id, sizeof a->id, top, "id", -1); xmlstrncpy(a->artist, sizeof a->artist, top, "artist-name", -1); xmlstrncpy(a->artist_id, sizeof a->artist_id, top, "artist-id", -1); xmlstrncpy(a->cover_id, sizeof a->cover_id, top, "cover", -1); xmlatof(&a->popularity, top, "popularity", -1); }
bool xml_parse_browse_artist(struct artist_browse* a, unsigned char* xml, int len, bool high_bitrate) { ezxml_t top = ezxml_parse_str(xml, len); xmlstrncpy(a->name, sizeof a->name, top, "name", -1); xmlstrncpy(a->genres, sizeof a->genres, top, "genres", -1); xmlstrncpy(a->years_active, sizeof a->years_active, top, "years-active",-1); xmlstrncpy(a->id, sizeof a->id, top, "id", -1); xmlstrncpy(a->portrait_id, sizeof a->portrait_id, top, "portrait", 0, "id", -1); xmlatof(&a->popularity, top, "popularity", -1); ezxml_t x = ezxml_get(top, "bios",0,"bio",0,"text",-1); if (x) { int len = strlen(x->txt); a->text = malloc(len + 1); memcpy(a->text, x->txt, len+1); } /* traverse albums */ x = ezxml_get(top, "albums",-1); struct album_browse* prev = NULL; struct album_browse* album = calloc(1, sizeof(struct album_browse)); a->albums = album; int album_count = 0; ezxml_t xalb; for (xalb = ezxml_get(x, "album", -1); xalb; xalb = xalb->next) { if (prev) { album = calloc(1, sizeof(struct album)); prev->next = album; } parse_browse_album(xalb, album, high_bitrate); prev = album; album_count++; } a->num_albums = album_count; ezxml_free(top); return true; }
static void parse_browse_album(ezxml_t top, struct album_browse* a, bool high_bitrate) { xmlstrncpy(a->name, sizeof a->name, top, "name", -1); xmlstrncpy(a->id, sizeof a->id, top, "id", -1); xmlstrncpy(a->artist, sizeof a->artist, top, "artist", -1); xmlstrncpy(a->artist_id, sizeof a->artist_id, top, "artist-id", -1); xmlstrncpy(a->cover_id, sizeof a->cover_id, top, "cover", -1); xmlatoi(&a->year, top, "year", -1); xmlatof(&a->popularity, top, "popularity", -1); a->tracks = calloc(1, sizeof(struct track)); ezxml_t disc = ezxml_get(top, "discs",0,"disc", -1); a->num_tracks = parse_tracks(disc, a->tracks, false, high_bitrate); /* Append extra discs to album */ struct track *last = a->tracks; while (last->next) last = last->next; while ((disc = disc->next)) { int offset = last->tracknumber; last->next = calloc(1, sizeof(struct track)); a->num_tracks += parse_tracks(disc, last->next, false, high_bitrate); do { last = last->next; last->tracknumber += offset; } while (last->next); } /* Copy missing metadata from album to tracks */ int count = 0; for (struct track *t = a->tracks; t; t = t->next) { DSFYstrncpy(t->album, a->name, sizeof t->album); DSFYstrncpy(t->album_id, a->id, sizeof t->album_id); DSFYstrncpy(t->cover_id, a->cover_id, sizeof t->cover_id); t->year = a->year; count++; } }
static void parse_browse_album(ezxml_t top, struct album_browse* a, bool high_bitrate) { xmlstrncpy(a->name, sizeof a->name, top, "name", -1); xmlstrncpy(a->id, sizeof a->id, top, "id", -1); xmlstrncpy(a->cover_id, sizeof a->cover_id, top, "cover", -1); xmlatoi(&a->year, top, "year", -1); xmlatof(&a->popularity, top, "popularity", -1); /* TODO: support multiple discs per album */ a->tracks = calloc(1, sizeof(struct track)); ezxml_t disc = ezxml_get(top, "discs",0,"disc", -1); a->num_tracks = parse_tracks(disc, a->tracks, false, high_bitrate); /* Copy missing metadata from album to tracks */ int count = 0; for (struct track *t = a->tracks; t; t = t->next) { DSFYstrncpy(t->album, a->name, sizeof t->album); DSFYstrncpy(t->album_id, a->id, sizeof t->album_id); DSFYstrncpy(t->cover_id, a->cover_id, sizeof t->cover_id); t->year = a->year; count++; } }
static int parse_tracks(ezxml_t xml, struct track* t, bool ordered, bool high_bitrate) { int track_count = 0; struct track* prev = NULL; struct track* root = t; for (ezxml_t track = ezxml_get(xml, "track",-1); track; track = track->next) { /* is this an ordered list? in that case we have to find the right track struct for every track id */ if (ordered) { char tid[33]; xmlstrncpy(tid, sizeof tid, track, "id", -1); struct track* tt; for (tt = root; tt; tt = tt->next) if (!tt->has_meta_data && !strncmp(tt->track_id, tid, sizeof tt->track_id)) break; /* if we didn't find the id, check if an old, redirected id is used */ if (!tt) { char rid[33]; for (ezxml_t re = ezxml_child(track, "redirect"); re; re = re->next) { strncpy(rid, re->txt, sizeof rid); for (tt = root; tt; tt = tt->next) { /* update to new id */ /* FIXME: This invalidates the playlist checksum */ if (!tt->has_meta_data && !strncmp(tt->track_id, rid, sizeof tt->track_id)) { memcpy (tt->track_id, tid, sizeof tt->track_id); break; } } if (tt) break; } /* we've wasted enough cpu cycles on this track now */ if (!tt) { DSFYDEBUG("!!! error: track id not found: %s\n", tid); continue; } } t = tt; } else if (!t) { t = calloc(1, sizeof(struct track)); prev->next = t; } xmlstrncpy(t->title, sizeof t->title, track, "title", -1); xmlstrncpy(t->album, sizeof t->album, track, "album", -1); xmlstrncpy(t->track_id, sizeof t->track_id, track, "id", -1); xmlstrncpy(t->cover_id, sizeof t->cover_id, track, "cover", -1); xmlstrncpy(t->album_id, sizeof t->album_id, track, "album-id", -1); /* create list of artists */ struct artist* preva = NULL; struct artist* artist = calloc(1, sizeof(struct artist)); t->artist = artist; ezxml_t xid = ezxml_get(track, "artist-id", -1); for (ezxml_t xa = ezxml_get(track, "artist", -1); xa; xa = xa->next) { if (preva) { artist = calloc(1, sizeof(struct artist)); preva->next = artist; } DSFYstrncpy(artist->name, xa->txt, sizeof artist->name); if (xid) { DSFYstrncpy(artist->id, xid->txt, sizeof artist->id); xid = xid->next; } preva = artist; } for ( ezxml_t file = ezxml_get(track, "files",0, "file",-1); file; file = file->next) { char* fmt = (char*)ezxml_attr(file, "format"); if (fmt) { unsigned int bitrate; if (sscanf(fmt,"Ogg Vorbis,%u,", &bitrate)) { if (bitrate > t->file_bitrate) { if (high_bitrate || t->file_bitrate == 0) t->file_bitrate = bitrate; else continue; } } char* id = (char*)ezxml_attr(file, "id"); if (id) { DSFYstrncpy(t->file_id, id, sizeof t->file_id); t->playable = true; } } } for ( ezxml_t restriction = ezxml_get(track, "restrictions", 0, "restriction", -1); restriction; restriction = restriction->next) { char *catalogues = (char*)ezxml_attr(restriction, "catalogues"); if(catalogues && strstr(catalogues, "premium") != NULL) { char* allowed = (char*)ezxml_attr(restriction, "allowed"); if(allowed) { t->allowed = calloc(strlen(allowed)+1, sizeof(char)); DSFYstrncpy(t->allowed, allowed, strlen(allowed)+1); } else { t->allowed = NULL; } char* forbidden = (char*)ezxml_attr(restriction, "forbidden"); if(forbidden) { t->forbidden = calloc(strlen(forbidden)+1, sizeof(char)); DSFYstrncpy(t->forbidden, forbidden, strlen(forbidden)+1); } else { t->forbidden = NULL; } } } xmlatoi(&t->year, track, "year", -1); xmlatoi(&t->length, track, "length", -1); xmlatoi(&t->tracknumber, track, "track-number", -1); xmlatof(&t->popularity, track, "popularity", -1); t->has_meta_data = true; prev = t; t = t->next; track_count++; } return track_count; }
static int parse_tracks(ezxml_t xml, struct track* t, bool ordered) { int track_count = 0; struct track* prev = NULL; struct track* root = t; for (ezxml_t track = ezxml_get(xml, "track",-1); track; track = track->next) { /* is this an ordered list? in that case we have to find the right track struct for every track id */ if (ordered) { char tid[33]; xmlstrncpy(tid, sizeof tid, track, "id", -1); struct track* tt; for (tt = root; tt; tt = tt->next) if (!tt->has_meta_data && !strncmp(tt->track_id, tid, sizeof tt->track_id)) break; /* if we didn't find the id, check if an old, redirected id is used */ if (!tt) { char rid[33]; for (ezxml_t re = ezxml_child(track, "redirect"); re; re = re->next) { strncpy(rid, re->txt, sizeof rid); for (tt = root; tt; tt = tt->next) { /* update to new id */ /* FIXME: This invalidates the playlist checksum */ if (!tt->has_meta_data && !strncmp(tt->track_id, rid, sizeof tt->track_id)) { memcpy (tt->track_id, tid, sizeof tt->track_id); break; } } if (tt) break; } /* we've wasted enough cpu cycles on this track now */ if (!tt) { DSFYDEBUG("!!! error: track id not found: %s\n", tid); continue; } } t = tt; } else if (!t) { t = calloc(1, sizeof(struct track)); prev->next = t; } xmlstrncpy(t->title, sizeof t->title, track, "title", -1); xmlstrncpy(t->album, sizeof t->album, track, "album", -1); xmlstrncpy(t->track_id, sizeof t->track_id, track, "id", -1); xmlstrncpy(t->cover_id, sizeof t->cover_id, track, "cover", -1); xmlstrncpy(t->album_id, sizeof t->album_id, track, "album-id", -1); /* create list of artists */ struct artist* preva = NULL; struct artist* artist = calloc(1, sizeof(struct artist)); t->artist = artist; ezxml_t xid = ezxml_get(track, "artist-id", -1); for (ezxml_t xa = ezxml_get(track, "artist", -1); xa; xa = xa->next) { if (preva) { artist = calloc(1, sizeof(struct artist)); preva->next = artist; } DSFYstrncpy(artist->name, xa->txt, sizeof artist->name); if (xid) { DSFYstrncpy(artist->id, xid->txt, sizeof artist->id); xid = xid->next; } preva = artist; } ezxml_t file = ezxml_get(track, "files",0, "file",-1); if (file) { char* id = (char*)ezxml_attr(file, "id"); if (id) { DSFYstrncpy(t->file_id, id, sizeof t->file_id); t->playable = true; } } xmlatoi(&t->year, track, "year", -1); xmlatoi(&t->length, track, "length", -1); xmlatoi(&t->tracknumber, track, "track-number", -1); xmlatof(&t->popularity, track, "popularity", -1); t->has_meta_data = true; prev = t; t = t->next; track_count++; } return track_count; }