void AllMusic::resync() { m_done_loading = false; QString aquery = "SELECT music_songs.song_id, music_artists.artist_name, music_comp_artists.artist_name AS compilation_artist, " "music_albums.album_name, music_songs.name, music_genres.genre, music_songs.year, " "music_songs.track, music_songs.length, CONCAT_WS('/', " "music_directories.path, music_songs.filename) AS filename, " "music_songs.rating, music_songs.numplays, music_songs.lastplay, music_albums.compilation, " "music_songs.format " "FROM music_songs " "LEFT JOIN music_directories ON music_songs.directory_id=music_directories.directory_id " "LEFT JOIN music_artists ON music_songs.artist_id=music_artists.artist_id " "LEFT JOIN music_albums ON music_songs.album_id=music_albums.album_id " "LEFT JOIN music_artists AS music_comp_artists ON music_albums.artist_id=music_comp_artists.artist_id " "LEFT JOIN music_genres ON music_songs.genre_id=music_genres.genre_id " "ORDER BY music_songs.song_id;"; QString filename, artist, album, title, compartist; MSqlQuery query(MSqlQuery::InitCon()); if (!query.exec(aquery)) MythDB::DBError("AllMusic::resync", query); m_root_node->clear(); m_all_music.clear(); m_numPcs = query.size() * 2; m_numLoaded = 0; if (query.isActive() && query.size() > 0) { while (query.next()) { filename = query.value(9).toString(); if (!filename.contains("://")) filename = m_startdir + filename; Metadata *temp = new Metadata( filename, query.value(1).toString(), // artist query.value(2).toString(), // compilation artist query.value(3).toString(), // album query.value(4).toString(), // title query.value(5).toString(), // genre query.value(6).toInt(), // year query.value(7).toInt(), // track no. query.value(8).toInt(), // length query.value(0).toInt(), // id query.value(10).toInt(), // rating query.value(11).toInt(), // playcount query.value(12).toDateTime(), // lastplay (query.value(13).toInt() > 0), // compilation query.value(14).toString()); // format // Don't delete temp, as PtrList now owns it m_all_music.append(temp); // compute max/min playcount,lastplay for all music if (query.at() == 0) { // first song m_playcountMin = m_playcountMax = temp->PlayCount(); m_lastplayMin = m_lastplayMax = temp->LastPlay().toTime_t(); } else { int playCount = temp->PlayCount(); double lastPlay = temp->LastPlay().toTime_t(); m_playcountMin = min(playCount, m_playcountMin); m_playcountMax = max(playCount, m_playcountMax); m_lastplayMin = min(lastPlay, m_lastplayMin); m_lastplayMax = max(lastPlay, m_lastplayMax); } m_numLoaded++; } } else { VERBOSE(VB_IMPORTANT, "MythMusic hasn't found any tracks! " "That's ok with me if it's ok with you."); } // To find this data quickly, build a map // (a map to pointers!) music_map.clear(); MetadataPtrList::iterator it = m_all_music.begin(); for (; it != m_all_music.end(); ++it) music_map[(*it)->ID()] = *it; // Build a tree to reflect current state of // the metadata. Once built, sort it. buildTree(); sortTree(); m_done_loading = true; }
int Playlist::writeTree(GenericTree *tree_to_write_to, int a_counter) { // compute max/min playcount,lastplay for this playlist int playcountMin = 0; int playcountMax = 0; double lastplayMin = 0.0; double lastplayMax = 0.0; typedef map<QString, uint32_t> AlbumMap; AlbumMap album_map; AlbumMap::iterator Ialbum; QString album; typedef map<QString, uint32_t> ArtistMap; ArtistMap artist_map; ArtistMap::iterator Iartist; QString artist; uint idx = 0; SongList::const_iterator it = songs.begin(); for (; it != songs.end(); ++it, ++idx) { if (!(*it)->getCDFlag()) { if ((*it)->getValue() == 0) { VERBOSE(VB_IMPORTANT, LOC_ERR + kID0err); } if ((*it)->getValue() > 0) { // Normal track Metadata *tmpdata = all_available_music->getMetadata((*it)->getValue()); if (tmpdata) { if (tmpdata->isVisible()) { if (0 == idx) { // first song playcountMin = playcountMax = tmpdata->PlayCount(); lastplayMin = lastplayMax = tmpdata->LastPlay().toTime_t(); } else { if (tmpdata->PlayCount() < playcountMin) playcountMin = tmpdata->PlayCount(); else if (tmpdata->PlayCount() > playcountMax) playcountMax = tmpdata->PlayCount(); if (tmpdata->LastPlay().toTime_t() < lastplayMin) lastplayMin = tmpdata->LastPlay().toTime_t(); else if (tmpdata->LastPlay().toTime_t() > lastplayMax) lastplayMax = tmpdata->LastPlay().toTime_t(); } } // pre-fill the album-map with the album name. // This allows us to do album mode in album order album = tmpdata->Album(); // pre-fill the artist map with the artist name and song title artist = tmpdata->Artist() + "~" + tmpdata->Title(); } if ((Ialbum = album_map.find(album)) == album_map.end()) album_map.insert(AlbumMap::value_type(album,0)); if ((Iartist = artist_map.find(artist)) == artist_map.end()) artist_map.insert(ArtistMap::value_type(artist,0)); } } } // populate the sort id into the album map uint32_t album_count = 1; for (Ialbum = album_map.begin(); Ialbum != album_map.end(); Ialbum++) { Ialbum->second = album_count; album_count++; } // populate the sort id into the artist map uint32_t count = 1; for (Iartist = artist_map.begin(); Iartist != artist_map.end(); Iartist++) { Iartist->second = count; count++; } int RatingWeight = 2; int PlayCountWeight = 2; int LastPlayWeight = 2; int RandomWeight = 2; parent->FillIntelliWeights(RatingWeight, PlayCountWeight, LastPlayWeight, RandomWeight); for (it = songs.begin(); it != songs.end(); ++it) { if (!(*it)->getCDFlag()) { if ((*it)->getValue() == 0) { VERBOSE(VB_IMPORTANT, LOC_ERR + kID0err); } if ((*it)->getValue() > 0) { // Normal track Metadata *tmpdata = all_available_music->getMetadata((*it)->getValue()); if (tmpdata && tmpdata->isVisible()) { QString a_string = QString("%1 ~ %2") .arg(tmpdata->FormatArtist()) .arg(tmpdata->FormatTitle()); GenericTree *added_node = tree_to_write_to->addNode( a_string, (*it)->getValue(), true); ++a_counter; added_node->setAttribute(0, 1); added_node->setAttribute(1, a_counter); // regular order added_node->setAttribute(2, rand()); // random order // // Compute "intelligent" weighting // int rating = tmpdata->Rating(); int playcount = tmpdata->PlayCount(); double lastplaydbl = tmpdata->LastPlay().toTime_t(); double ratingValue = (double)(rating) / 10; double playcountValue, lastplayValue; if (playcountMax == playcountMin) playcountValue = 0; else playcountValue = ((playcountMin - (double)playcount) / (playcountMax - playcountMin) + 1); if (lastplayMax == lastplayMin) lastplayValue = 0; else lastplayValue = ((lastplayMin - lastplaydbl) / (lastplayMax - lastplayMin) + 1); double rating_value = (RatingWeight * ratingValue + PlayCountWeight * playcountValue + LastPlayWeight * lastplayValue + RandomWeight * (double)rand() / (RAND_MAX + 1.0)); uint32_t integer_rating = (int) (4000001 - rating_value * 10000); // "intelligent" order added_node->setAttribute(3, integer_rating); // "intellegent/album" order uint32_t album_order; album = tmpdata->Album(); if ((Ialbum = album_map.find(album)) == album_map.end()) { // we didn't find this album in the map, // yet we pre-loaded them all. we are broken, // but we just set the track order to 1, since there // is no real point in reporting an error album_order = 1; } else { album_order = Ialbum->second * 100; } album_order += tmpdata->Track(); added_node->setAttribute(4, album_order); // "artist" order, sorts by artist name then track title // uses the pre-prepared artist map to do this uint32_t integer_order; artist = tmpdata->Artist() + "~" + tmpdata->Title(); if ((Iartist = artist_map.find(artist)) == artist_map.end()) { // we didn't find this track in the map, // yet we pre-loaded them all. we are broken, // but we just set the track order to 1, since there // is no real point in reporting an error integer_order = 1; } else { integer_order = Iartist->second; } added_node->setAttribute(5, integer_order); } } if ((*it)->getValue() < 0) { // it's a playlist, recurse (mildly) Playlist *level_down = parent->getPlaylist(((*it)->getValue()) * -1); if (level_down) { a_counter = level_down->writeTree(tree_to_write_to, a_counter); } } } else { Metadata *tmpdata = all_available_music->getMetadata((*it)->getValue()); if (tmpdata) { QString a_string = QString("(CD) %1 ~ %2") .arg(tmpdata->FormatArtist()).arg(tmpdata->FormatTitle()); if (tmpdata->FormatArtist().length() < 1 || tmpdata->FormatTitle().length() < 1) { a_string = QString("(CD) Track %1").arg(tmpdata->Track()); } GenericTree *added_node = tree_to_write_to->addNode(a_string, (*it)->getValue(), true); ++a_counter; added_node->setAttribute(0, 1); added_node->setAttribute(1, a_counter); // regular order added_node->setAttribute(2, rand()); // random order added_node->setAttribute(3, rand()); // "intelligent" order } } } return a_counter; }