JSONRPC_STATUS CAudioLibrary::GetAlbumDetails(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { int albumID = (int)parameterObject["albumid"].asInteger(); CMusicDatabase musicdatabase; if (!musicdatabase.Open()) return InternalError; CAlbum album; if (!musicdatabase.GetAlbum(albumID, album, false)) return InvalidParams; std::string path; if (!musicdatabase.GetAlbumPath(albumID, path)) return InternalError; CFileItemPtr albumItem; FillAlbumItem(album, path, albumItem); CFileItemList items; items.Add(albumItem); JSONRPC_STATUS ret = GetAdditionalAlbumDetails(parameterObject, items, musicdatabase); if (ret != OK) return ret; HandleFileItem("albumid", false, "albumdetails", items[0], parameterObject, parameterObject["properties"], result, false); return OK; }
bool CAudioLibrary::FillFileItem(const std::string &strFilename, CFileItemPtr &item, const CVariant ¶meterObject /* = CVariant(CVariant::VariantTypeArray) */) { CMusicDatabase musicdatabase; if (strFilename.empty()) return false; bool filled = false; if (musicdatabase.Open()) { if (CDirectory::Exists(strFilename)) { CAlbum album; int albumid = musicdatabase.GetAlbumIdByPath(strFilename); if (musicdatabase.GetAlbum(albumid, album, false)) { item->SetFromAlbum(album); FillItemArtistIDs(album.GetArtistIDArray(), item); CFileItemList items; items.Add(item); if (GetAdditionalAlbumDetails(parameterObject, items, musicdatabase) == OK) filled = true; } } else { CSong song; if (musicdatabase.GetSongByFileName(strFilename, song)) { item->SetFromSong(song); FillItemArtistIDs(song.GetArtistIDArray(), item); CFileItemList items; items.Add(item); if (GetAdditionalSongDetails(parameterObject, items, musicdatabase) == OK) filled = true; } } } if (item->GetLabel().empty()) { item->SetLabel(CUtil::GetTitleFromPath(strFilename, false)); if (item->GetLabel().empty()) item->SetLabel(URIUtils::GetFileName(strFilename)); } return filled; }
JSONRPC_STATUS CAudioLibrary::SetAlbumDetails(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { int id = (int)parameterObject["albumid"].asInteger(); CMusicDatabase musicdatabase; if (!musicdatabase.Open()) return InternalError; CAlbum album; if (!musicdatabase.GetAlbum(id, album) || album.idAlbum <= 0) return InvalidParams; if (ParameterNotNull(parameterObject, "title")) album.strAlbum = parameterObject["title"].asString(); // Artist names, along with MusicbrainzAlbumArtistID needs to update artist credits // As temp fix just set the album artist description string if (ParameterNotNull(parameterObject, "artist")) { std::vector<std::string> artist; CopyStringArray(parameterObject["artist"], artist); album.strArtistDesc = StringUtils::Join(artist, g_advancedSettings.m_musicItemSeparator); } if (ParameterNotNull(parameterObject, "description")) album.strReview = parameterObject["description"].asString(); if (ParameterNotNull(parameterObject, "genre")) CopyStringArray(parameterObject["genre"], album.genre); if (ParameterNotNull(parameterObject, "theme")) CopyStringArray(parameterObject["theme"], album.themes); if (ParameterNotNull(parameterObject, "mood")) CopyStringArray(parameterObject["mood"], album.moods); if (ParameterNotNull(parameterObject, "style")) CopyStringArray(parameterObject["style"], album.styles); if (ParameterNotNull(parameterObject, "type")) album.strType = parameterObject["type"].asString(); if (ParameterNotNull(parameterObject, "albumlabel")) album.strLabel = parameterObject["albumlabel"].asString(); if (ParameterNotNull(parameterObject, "rating")) album.fRating = parameterObject["rating"].asFloat(); if (ParameterNotNull(parameterObject, "userrating")) album.iUserrating = parameterObject["userrating"].asInteger(); if (ParameterNotNull(parameterObject, "year")) album.iYear = (int)parameterObject["year"].asInteger(); if (!musicdatabase.UpdateAlbum(album)) return InternalError; CJSONRPCUtils::NotifyItemUpdated(); return ACK; }
void CGUIDialogMusicInfo::OnSearch(const CFileItem* pItem) { CMusicDatabase database; database.Open(); if (pItem->HasMusicInfoTag() && pItem->GetMusicInfoTag()->GetDatabaseId() > 0) { CAlbum album; if (database.GetAlbum(pItem->GetMusicInfoTag()->GetDatabaseId(), album)) { std::string strPath; database.GetAlbumPath(pItem->GetMusicInfoTag()->GetDatabaseId(), strPath); SetAlbum(album,strPath); Update(); } } }
bool CMusicInfoLoader::LoadAdditionalTagInfo(CFileItem* pItem) { if (!pItem || pItem->m_bIsFolder || pItem->IsPlayList() || pItem->IsNFO() || pItem->IsInternetStream()) return false; if (pItem->GetProperty("hasfullmusictag") == "true") return false; // already have the information std::string path(pItem->GetPath()); if (pItem->IsMusicDb()) { // set the artist / album properties XFILE::MUSICDATABASEDIRECTORY::CQueryParams param; XFILE::MUSICDATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(pItem->GetPath(),param); CArtist artist; CMusicDatabase database; database.Open(); if (database.GetArtist(param.GetArtistId(), artist, false)) CMusicDatabase::SetPropertiesFromArtist(*pItem,artist); CAlbum album; if (database.GetAlbum(param.GetAlbumId(), album, false)) CMusicDatabase::SetPropertiesFromAlbum(*pItem,album); path = pItem->GetMusicInfoTag()->GetURL(); } CLog::Log(LOGDEBUG, "Loading additional tag info for file %s", path.c_str()); // we load up the actual tag for this file in order to // fetch the lyrics and add it to the current music info tag CFileItem tempItem(path, false); std::unique_ptr<IMusicInfoTagLoader> pLoader (CMusicInfoTagLoaderFactory::CreateLoader(tempItem)); if (NULL != pLoader.get()) { CMusicInfoTag tag; pLoader->Load(path, tag); pItem->GetMusicInfoTag()->SetLyrics(tag.GetLyrics()); pItem->SetProperty("hasfullmusictag", "true"); return true; } return false; }
JSONRPC_STATUS CAudioLibrary::SetAlbumDetails(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { int id = (int)parameterObject["albumid"].asInteger(); CMusicDatabase musicdatabase; if (!musicdatabase.Open()) return InternalError; CAlbum album; if (!musicdatabase.GetAlbum(id, album) || album.idAlbum <= 0) return InvalidParams; if (ParameterNotNull(parameterObject, "title")) album.strAlbum = parameterObject["title"].asString(); if (ParameterNotNull(parameterObject, "artist")) CopyStringArray(parameterObject["artist"], album.artist); if (ParameterNotNull(parameterObject, "description")) album.strReview = parameterObject["description"].asString(); if (ParameterNotNull(parameterObject, "genre")) CopyStringArray(parameterObject["genre"], album.genre); if (ParameterNotNull(parameterObject, "theme")) CopyStringArray(parameterObject["theme"], album.themes); if (ParameterNotNull(parameterObject, "mood")) CopyStringArray(parameterObject["mood"], album.moods); if (ParameterNotNull(parameterObject, "style")) CopyStringArray(parameterObject["style"], album.styles); if (ParameterNotNull(parameterObject, "type")) album.strType = parameterObject["type"].asString(); if (ParameterNotNull(parameterObject, "albumlabel")) album.strLabel = parameterObject["albumlabel"].asString(); if (ParameterNotNull(parameterObject, "rating")) album.iRating = (int)parameterObject["rating"].asInteger(); if (ParameterNotNull(parameterObject, "year")) album.iYear = (int)parameterObject["year"].asInteger(); if (!musicdatabase.UpdateAlbum(album)) return InternalError; CJSONRPCUtils::NotifyItemUpdated(); return ACK; }
JSONRPC_STATUS CAudioLibrary::SetAlbumDetails(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { int id = (int)parameterObject["albumid"].asInteger(); CMusicDatabase musicdatabase; if (!musicdatabase.Open()) return InternalError; CAlbum album; // Get current album details, but not songs as we do not want to update them here if (!musicdatabase.GetAlbum(id, album, false) || album.idAlbum <= 0) return InvalidParams; if (ParameterNotNull(parameterObject, "title")) album.strAlbum = parameterObject["title"].asString(); if (ParameterNotNull(parameterObject, "displayartist")) album.strArtistDesc = parameterObject["displayartist"].asString(); // Set album sort string before processing artist credits if (ParameterNotNull(parameterObject, "sortartist")) album.strArtistSort = parameterObject["sortartist"].asString(); // Match up artist names and mbids to make new artist credits // Mbid values only apply if there are names if (ParameterNotNull(parameterObject, "artist")) { std::vector<std::string> artists; std::vector<std::string> mbids; CopyStringArray(parameterObject["artist"], artists); // Check for Musicbrainz ids if (ParameterNotNull(parameterObject, "musicbrainzalbumartistid")) CopyStringArray(parameterObject["musicbrainzalbumartistid"], mbids); // When display artist is not provided and yet artists is changing make by concatenation if (!ParameterNotNull(parameterObject, "displayartist")) album.strArtistDesc = StringUtils::Join(artists, g_advancedSettings.m_musicItemSeparator); album.SetArtistCredits(artists, std::vector<std::string>(), mbids); // On updatealbum artists will be changed album.bArtistSongMerge = true; } if (ParameterNotNull(parameterObject, "description")) album.strReview = parameterObject["description"].asString(); if (ParameterNotNull(parameterObject, "genre")) CopyStringArray(parameterObject["genre"], album.genre); if (ParameterNotNull(parameterObject, "theme")) CopyStringArray(parameterObject["theme"], album.themes); if (ParameterNotNull(parameterObject, "mood")) CopyStringArray(parameterObject["mood"], album.moods); if (ParameterNotNull(parameterObject, "style")) CopyStringArray(parameterObject["style"], album.styles); if (ParameterNotNull(parameterObject, "type")) album.strType = parameterObject["type"].asString(); if (ParameterNotNull(parameterObject, "albumlabel")) album.strLabel = parameterObject["albumlabel"].asString(); if (ParameterNotNull(parameterObject, "rating")) album.fRating = parameterObject["rating"].asFloat(); if (ParameterNotNull(parameterObject, "userrating")) album.iUserrating = parameterObject["userrating"].asInteger(); if (ParameterNotNull(parameterObject, "votes")) album.iVotes = parameterObject["votes"].asInteger(); if (ParameterNotNull(parameterObject, "year")) album.iYear = (int)parameterObject["year"].asInteger(); if (ParameterNotNull(parameterObject, "musicbrainzalbumid")) album.strMusicBrainzAlbumID = parameterObject["musicbrainzalbumid"].asString(); if (ParameterNotNull(parameterObject, "musicbrainzreleasegroupid")) album.strReleaseGroupMBID = parameterObject["musicbrainzreleasegroupid"].asString(); // Update existing art. Any existing artwork that isn't specified in this request stays as is. // If the value is null then the existing art with that type is removed. if (ParameterNotNull(parameterObject, "art")) { // Get current artwork musicdatabase.GetArtForItem(album.idAlbum, MediaTypeAlbum, album.art); std::set<std::string> removedArtwork; CVariant art = parameterObject["art"]; for (CVariant::const_iterator_map artIt = art.begin_map(); artIt != art.end_map(); artIt++) { if (artIt->second.isString() && !artIt->second.asString().empty()) album.art[artIt->first] = CTextureUtils::UnwrapImageURL(artIt->second.asString()); else if (artIt->second.isNull()) { album.art.erase(artIt->first); removedArtwork.insert(artIt->first); } } // Remove null art now, as not done by update if (!musicdatabase.RemoveArtForItem(album.idAlbum, MediaTypeAlbum, removedArtwork)) return InternalError; } // Update artist including adding or replacing (but not removing) art if (!musicdatabase.UpdateAlbum(album)) return InternalError; CJSONRPCUtils::NotifyItemUpdated(); return ACK; }
bool CMusicInfoLoader::LoadAdditionalTagInfo(CFileItem* pItem) { if (!pItem || (pItem->m_bIsFolder && !pItem->IsAudio()) || pItem->IsPlayList() || pItem->IsNFO() || pItem->IsInternetStream()) return false; if (pItem->GetProperty("hasfullmusictag") == "true") return false; // already have the information std::string path(pItem->GetPath()); // For songs in library set the (primary) song artist and album properties // Use song Id (not path) as called for items from either library or file view, // but could also be listitem with tag loaded by a script if (pItem->HasMusicInfoTag() && pItem->GetMusicInfoTag()->GetType() == MediaTypeSong && pItem->GetMusicInfoTag()->GetDatabaseId() > 0) { CMusicDatabase database; database.Open(); // May already have song artist ids as item property set when data read from // db, but check property is valid array (scripts could set item properties // incorrectly), otherwise fetch artist using song id. CArtist artist; bool artistfound = false; if (pItem->HasProperty("artistid") && pItem->GetProperty("artistid").isArray()) { CVariant::const_iterator_array varid = pItem->GetProperty("artistid").begin_array(); int idArtist = varid->asInteger(); artistfound = database.GetArtist(idArtist, artist, false); } else artistfound = database.GetArtistFromSong(pItem->GetMusicInfoTag()->GetDatabaseId(), artist); if (artistfound) CMusicDatabase::SetPropertiesFromArtist(*pItem, artist); // May already have album id, otherwise fetch album from song id CAlbum album; bool albumfound = false; int idAlbum = pItem->GetMusicInfoTag()->GetAlbumId(); if (idAlbum > 0) albumfound = database.GetAlbum(idAlbum, album, false); else albumfound = database.GetAlbumFromSong(pItem->GetMusicInfoTag()->GetDatabaseId(), album); if (albumfound) CMusicDatabase::SetPropertiesFromAlbum(*pItem, album); path = pItem->GetMusicInfoTag()->GetURL(); } CLog::Log(LOGDEBUG, "Loading additional tag info for file %s", path.c_str()); // we load up the actual tag for this file in order to // fetch the lyrics and add it to the current music info tag CFileItem tempItem(path, false); std::unique_ptr<IMusicInfoTagLoader> pLoader (CMusicInfoTagLoaderFactory::CreateLoader(tempItem)); if (NULL != pLoader.get()) { CMusicInfoTag tag; pLoader->Load(path, tag); pItem->GetMusicInfoTag()->SetLyrics(tag.GetLyrics()); pItem->SetProperty("hasfullmusictag", "true"); return true; } return false; }
// Fetch full album/artist information including art types list bool DoWork() override { CGUIDialogMusicInfo *dialog = CServiceBroker::GetGUI()->GetWindowManager(). GetWindow<CGUIDialogMusicInfo>(WINDOW_DIALOG_MUSIC_INFO); if (!dialog) return false; if (dialog->IsCancelled()) return false; CFileItemPtr m_item = dialog->GetCurrentListItem(); CMusicInfoTag& tag = *m_item->GetMusicInfoTag(); CMusicDatabase database; database.Open(); // May only have partially populated item, so fetch all artist or album data from db if (tag.GetType() == MediaTypeArtist) { int artistId = tag.GetDatabaseId(); CArtist artist; if (!database.GetArtist(artistId, artist)) return false; tag.SetArtist(artist); CMusicDatabase::SetPropertiesFromArtist(*m_item, artist); m_item->SetLabel(artist.strArtist); // Get artist folder where local art could be found // Get the *name* of the folder for this artist within the Artist Info folder (may not exist). // If there is no Artist Info folder specified in settings this will be blank database.GetArtistPath(artist, artist.strPath); // Get the old location for those album artists with a unique folder (local to music files) // If there is no folder for the artist and *only* the artist this will be blank std::string oldartistpath; bool oldpathfound = database.GetOldArtistPath(artist.idArtist, oldartistpath); // Set up path for *item folder when browsing for art, by default this is // in the Artist Info Folder (when it exists), but could end up blank std::string artistItemPath = artist.strPath; if (!CDirectory::Exists(artistItemPath)) { // Fall back local to music files (historic location for those album artists with a unique folder) // although there may not be such a unique folder for the arist if (oldpathfound) artistItemPath = oldartistpath; else // Fall back further to browse the Artist Info Folder itself artistItemPath = CServiceBroker::GetSettings().GetString(CSettings::SETTING_MUSICLIBRARY_ARTISTSFOLDER); } m_item->SetPath(artistItemPath); // Store info as CArtist as well as item properties dialog->SetArtist(artist, oldartistpath); // Fetch artist discography as scraped from online sources, but always // include all the albums in the music library dialog->SetDiscography(database); } else { // tag.GetType == MediaTypeAlbum int albumId = tag.GetDatabaseId(); CAlbum album; if (!database.GetAlbum(albumId, album)) return false; tag.SetAlbum(album); CMusicDatabase::SetPropertiesFromAlbum(*m_item, album); // Get album folder where local art could be found database.GetAlbumPath(albumId, album.strPath); // Set up path for *item folder when browsing for art m_item->SetPath(album.strPath); // Store info as CAlbum as well as item properties dialog->SetAlbum(album, album.strPath); // Set the list of songs and related art dialog->SetSongs(album.songs); } database.Close(); /* Load current art (to CGUIListItem.m_art) For albums this includes related artist(s) art and artist fanart set as fallback album fanart. Clear item art first to ensure fresh not cached/partial art */ m_item->ClearArt(); CMusicThumbLoader loader; loader.LoadItem(m_item.get()); // Fill vector of possible art types with current art, when it exists, // for display on the art type selection dialog CFileItemList artlist; MUSIC_UTILS::FillArtTypesList(*m_item, artlist); dialog->SetArtTypeList(artlist); if (dialog->IsCancelled()) return false; // Tell waiting MusicDialog that job is complete dialog->FetchComplete(); return true; }