diff options
Diffstat (limited to 'xbmc/guilib/guiinfo/MusicGUIInfo.cpp')
-rw-r--r-- | xbmc/guilib/guiinfo/MusicGUIInfo.cpp | 713 |
1 files changed, 713 insertions, 0 deletions
diff --git a/xbmc/guilib/guiinfo/MusicGUIInfo.cpp b/xbmc/guilib/guiinfo/MusicGUIInfo.cpp new file mode 100644 index 0000000..f58a9ae --- /dev/null +++ b/xbmc/guilib/guiinfo/MusicGUIInfo.cpp @@ -0,0 +1,713 @@ +/* + * Copyright (C) 2012-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "guilib/guiinfo/MusicGUIInfo.h" + +#include "FileItem.h" +#include "PartyModeManager.h" +#include "PlayListPlayer.h" +#include "ServiceBroker.h" +#include "URL.h" +#include "Util.h" +#include "application/Application.h" +#include "application/ApplicationComponents.h" +#include "application/ApplicationPlayer.h" +#include "guilib/LocalizeStrings.h" +#include "guilib/guiinfo/GUIInfo.h" +#include "guilib/guiinfo/GUIInfoHelper.h" +#include "guilib/guiinfo/GUIInfoLabels.h" +#include "music/MusicInfoLoader.h" +#include "music/MusicThumbLoader.h" +#include "music/tags/MusicInfoTag.h" +#include "playlists/PlayList.h" +#include "settings/AdvancedSettings.h" +#include "settings/SettingsComponent.h" +#include "utils/URIUtils.h" +#include "utils/log.h" + +using namespace KODI::GUILIB; +using namespace KODI::GUILIB::GUIINFO; +using namespace MUSIC_INFO; + +bool CMusicGUIInfo::InitCurrentItem(CFileItem *item) +{ + const auto& components = CServiceBroker::GetAppComponents(); + const auto appPlayer = components.GetComponent<CApplicationPlayer>(); + if (item && (item->IsAudio() || (item->IsInternetStream() && appPlayer->IsPlayingAudio()))) + { + CLog::Log(LOGDEBUG, "CMusicGUIInfo::InitCurrentItem({})", item->GetPath()); + + item->LoadMusicTag(); + + CMusicInfoTag* tag = item->GetMusicInfoTag(); // creates item if not yet set, so no nullptr checks needed + tag->SetLoaded(true); + + // find a thumb for this file. + if (item->IsInternetStream() && !item->IsMusicDb()) + { + if (!g_application.m_strPlayListFile.empty()) + { + CLog::Log(LOGDEBUG, "Streaming media detected... using {} to find a thumb", + g_application.m_strPlayListFile); + CFileItem streamingItem(g_application.m_strPlayListFile,false); + + CMusicThumbLoader loader; + loader.FillThumb(streamingItem); + if (streamingItem.HasArt("thumb")) + item->SetArt("thumb", streamingItem.GetArt("thumb")); + } + } + else + { + CMusicThumbLoader loader; + loader.LoadItem(item); + } + + CMusicInfoLoader::LoadAdditionalTagInfo(item); + return true; + } + return false; +} + +bool CMusicGUIInfo::GetLabel(std::string& value, const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback) const +{ + // For musicplayer "offset" and "position" info labels check playlist + if (info.GetData1() && ((info.m_info >= MUSICPLAYER_OFFSET_POSITION_FIRST && + info.m_info <= MUSICPLAYER_OFFSET_POSITION_LAST) || + (info.m_info >= PLAYER_OFFSET_POSITION_FIRST && info.m_info <= PLAYER_OFFSET_POSITION_LAST))) + return GetPlaylistInfo(value, info); + + const CMusicInfoTag* tag = item->GetMusicInfoTag(); + if (tag) + { + switch (info.m_info) + { + ///////////////////////////////////////////////////////////////////////////////////////////// + // PLAYER_* / MUSICPLAYER_* / LISTITEM_* + ///////////////////////////////////////////////////////////////////////////////////////////// + case PLAYER_PATH: + case PLAYER_FILENAME: + case PLAYER_FILEPATH: + value = tag->GetURL(); + if (value.empty()) + value = item->GetPath(); + value = GUIINFO::GetFileInfoLabelValueFromPath(info.m_info, value); + return true; + case PLAYER_TITLE: + value = tag->GetTitle(); + return !value.empty(); + case MUSICPLAYER_TITLE: + value = tag->GetTitle(); + return !value.empty(); + case LISTITEM_TITLE: + value = tag->GetTitle(); + return true; + case MUSICPLAYER_PLAYCOUNT: + case LISTITEM_PLAYCOUNT: + if (tag->GetPlayCount() > 0) + { + value = std::to_string(tag->GetPlayCount()); + return true; + } + break; + case MUSICPLAYER_LASTPLAYED: + case LISTITEM_LASTPLAYED: + { + const CDateTime& dateTime = tag->GetLastPlayed(); + if (dateTime.IsValid()) + { + value = dateTime.GetAsLocalizedDate(); + return true; + } + break; + } + case MUSICPLAYER_TRACK_NUMBER: + case LISTITEM_TRACKNUMBER: + if (tag->Loaded() && tag->GetTrackNumber() > 0) + { + value = StringUtils::Format("{:02}", tag->GetTrackNumber()); + return true; + } + break; + case MUSICPLAYER_DISC_NUMBER: + case LISTITEM_DISC_NUMBER: + if (tag->GetDiscNumber() > 0) + { + value = std::to_string(tag->GetDiscNumber()); + return true; + } + break; + case MUSICPLAYER_TOTALDISCS: + case LISTITEM_TOTALDISCS: + value = std::to_string(tag->GetTotalDiscs()); + return true; + case MUSICPLAYER_DISC_TITLE: + case LISTITEM_DISC_TITLE: + value = tag->GetDiscSubtitle(); + return true; + case MUSICPLAYER_ARTIST: + case LISTITEM_ARTIST: + value = tag->GetArtistString(); + return true; + case MUSICPLAYER_ALBUM_ARTIST: + case LISTITEM_ALBUM_ARTIST: + value = tag->GetAlbumArtistString(); + return true; + case MUSICPLAYER_CONTRIBUTORS: + case LISTITEM_CONTRIBUTORS: + if (tag->HasContributors()) + { + value = tag->GetContributorsText(); + return true; + } + break; + case MUSICPLAYER_CONTRIBUTOR_AND_ROLE: + case LISTITEM_CONTRIBUTOR_AND_ROLE: + if (tag->HasContributors()) + { + value = tag->GetContributorsAndRolesText(); + return true; + } + break; + case MUSICPLAYER_ALBUM: + case LISTITEM_ALBUM: + value = tag->GetAlbum(); + return true; + case MUSICPLAYER_YEAR: + case LISTITEM_YEAR: + value = tag->GetYearString(); + return true; + case MUSICPLAYER_GENRE: + case LISTITEM_GENRE: + value = StringUtils::Join(tag->GetGenre(), CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_musicItemSeparator); + return true; + case MUSICPLAYER_LYRICS: + value = tag->GetLyrics(); + return true; + case MUSICPLAYER_RATING: + case LISTITEM_RATING: + { + float rating = tag->GetRating(); + if (rating > 0.f) + { + value = StringUtils::FormatNumber(rating); + return true; + } + break; + } + case MUSICPLAYER_RATING_AND_VOTES: + case LISTITEM_RATING_AND_VOTES: + { + float rating = tag->GetRating(); + if (rating > 0.f) + { + int votes = tag->GetVotes(); + if (votes <= 0) + value = StringUtils::FormatNumber(rating); + else + value = + StringUtils::Format(g_localizeStrings.Get(20350), StringUtils::FormatNumber(rating), + StringUtils::FormatNumber(votes)); + return true; + } + break; + } + case MUSICPLAYER_USER_RATING: + case LISTITEM_USER_RATING: + if (tag->GetUserrating() > 0) + { + value = std::to_string(tag->GetUserrating()); + return true; + } + break; + case MUSICPLAYER_COMMENT: + case LISTITEM_COMMENT: + value = tag->GetComment(); + return true; + case MUSICPLAYER_MOOD: + case LISTITEM_MOOD: + value = tag->GetMood(); + return true; + case LISTITEM_DBTYPE: + value = tag->GetType(); + return true; + case MUSICPLAYER_DBID: + case LISTITEM_DBID: + { + int dbId = tag->GetDatabaseId(); + if (dbId > -1) + { + value = std::to_string(dbId); + return true; + } + break; + } + case PLAYER_DURATION: + { + const auto& components = CServiceBroker::GetAppComponents(); + const auto appPlayer = components.GetComponent<CApplicationPlayer>(); + if (!appPlayer->IsPlayingAudio()) + break; + } + [[fallthrough]]; + case MUSICPLAYER_DURATION: + case LISTITEM_DURATION: + { + int iDuration = tag->GetDuration(); + if (iDuration > 0) + { + value = StringUtils::SecondsToTimeString(iDuration, + static_cast<TIME_FORMAT>(info.m_info == LISTITEM_DURATION + ? info.GetData4() + : info.GetData1())); + return true; + } + break; + } + case MUSICPLAYER_BPM: + case LISTITEM_BPM: + if (tag->GetBPM() > 0) + { + value = std::to_string(tag->GetBPM()); + return true; + } + break; + case MUSICPLAYER_STATIONNAME: + // This property can be used for example by addons to enforce/override the station name. + value = item->GetProperty("StationName").asString(); + if (value.empty()) + value = tag->GetStationName(); + return true; + + ///////////////////////////////////////////////////////////////////////////////////////////// + // LISTITEM_* + ///////////////////////////////////////////////////////////////////////////////////////////// + case LISTITEM_PROPERTY: + if (StringUtils::StartsWithNoCase(info.GetData3(), "Role.")) + { + // "Role.xxxx" properties are held in music tag + std::string property = info.GetData3(); + property.erase(0, 5); //Remove Role. + value = tag->GetArtistStringForRole(property); + return true; + } + break; + case LISTITEM_VOTES: + value = StringUtils::FormatNumber(tag->GetVotes()); + return true; + case MUSICPLAYER_ORIGINALDATE: + case LISTITEM_ORIGINALDATE: + { + value = tag->GetOriginalDate(); + if (!CServiceBroker::GetSettingsComponent() + ->GetAdvancedSettings() + ->m_bMusicLibraryUseISODates) + value = StringUtils::ISODateToLocalizedDate(value); + return true; + } + case MUSICPLAYER_RELEASEDATE: + case LISTITEM_RELEASEDATE: + { + value = tag->GetReleaseDate(); + if (!CServiceBroker::GetSettingsComponent() + ->GetAdvancedSettings() + ->m_bMusicLibraryUseISODates) + value = StringUtils::ISODateToLocalizedDate(value); + return true; + } + break; + case LISTITEM_BITRATE: + { + int BitRate = tag->GetBitRate(); + if (BitRate > 0) + { + value = std::to_string(BitRate); + return true; + } + break; + } + case LISTITEM_SAMPLERATE: + { + int sampleRate = tag->GetSampleRate(); + if (sampleRate > 0) + { + value = StringUtils::Format("{:.5}", static_cast<double>(sampleRate) / 1000.0); + return true; + } + break; + } + case LISTITEM_MUSICCHANNELS: + { + int channels = tag->GetNoOfChannels(); + if (channels > 0) + { + value = std::to_string(channels); + return true; + } + break; + } + case LISTITEM_ALBUMSTATUS: + value = tag->GetAlbumReleaseStatus(); + return true; + case LISTITEM_FILENAME: + case LISTITEM_FILE_EXTENSION: + if (item->IsMusicDb()) + value = URIUtils::GetFileName(tag->GetURL()); + else if (item->HasVideoInfoTag()) // special handling for music videos, which have both a videotag and a musictag + break; + else + value = URIUtils::GetFileName(item->GetPath()); + + if (info.m_info == LISTITEM_FILE_EXTENSION) + { + std::string strExtension = URIUtils::GetExtension(value); + value = StringUtils::TrimLeft(strExtension, "."); + } + return true; + case LISTITEM_FOLDERNAME: + case LISTITEM_PATH: + if (item->IsMusicDb()) + value = URIUtils::GetDirectory(tag->GetURL()); + else if (item->HasVideoInfoTag()) // special handling for music videos, which have both a videotag and a musictag + break; + else + URIUtils::GetParentPath(item->GetPath(), value); + + value = CURL(value).GetWithoutUserDetails(); + + if (info.m_info == LISTITEM_FOLDERNAME) + { + URIUtils::RemoveSlashAtEnd(value); + value = URIUtils::GetFileName(value); + } + return true; + case LISTITEM_FILENAME_AND_PATH: + if (item->IsMusicDb()) + value = tag->GetURL(); + else if (item->HasVideoInfoTag()) // special handling for music videos, which have both a videotag and a musictag + break; + else + value = item->GetPath(); + + value = CURL(value).GetWithoutUserDetails(); + return true; + case LISTITEM_DATE_ADDED: + if (tag->GetDateAdded().IsValid()) + { + value = tag->GetDateAdded().GetAsLocalizedDate(); + return true; + } + break; + } + } + + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // MUSICPLAYER_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case MUSICPLAYER_PROPERTY: + if (StringUtils::StartsWithNoCase(info.GetData3(), "Role.") && item->HasMusicInfoTag()) + { + // "Role.xxxx" properties are held in music tag + std::string property = info.GetData3(); + property.erase(0, 5); //Remove Role. + value = item->GetMusicInfoTag()->GetArtistStringForRole(property); + return true; + } + value = item->GetProperty(info.GetData3()).asString(); + return true; + case MUSICPLAYER_PLAYLISTLEN: + if (CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() == PLAYLIST::TYPE_MUSIC) + { + value = GUIINFO::GetPlaylistLabel(PLAYLIST_LENGTH); + return true; + } + break; + case MUSICPLAYER_PLAYLISTPOS: + if (CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() == PLAYLIST::TYPE_MUSIC) + { + value = GUIINFO::GetPlaylistLabel(PLAYLIST_POSITION); + return true; + } + break; + case MUSICPLAYER_COVER: + { + const auto& components = CServiceBroker::GetAppComponents(); + const auto appPlayer = components.GetComponent<CApplicationPlayer>(); + if (appPlayer->IsPlayingAudio()) + { + if (fallback) + *fallback = "DefaultAlbumCover.png"; + value = item->HasArt("thumb") ? item->GetArt("thumb") : "DefaultAlbumCover.png"; + return true; + } + break; + } + case MUSICPLAYER_BITRATE: + { + int iBitrate = m_audioInfo.bitrate; + if (iBitrate > 0) + { + value = std::to_string(std::lrint(static_cast<double>(iBitrate) / 1000.0)); + return true; + } + break; + } + case MUSICPLAYER_CHANNELS: + { + int iChannels = m_audioInfo.channels; + if (iChannels > 0) + { + value = std::to_string(iChannels); + return true; + } + break; + } + case MUSICPLAYER_BITSPERSAMPLE: + { + int iBPS = m_audioInfo.bitspersample; + if (iBPS > 0) + { + value = std::to_string(iBPS); + return true; + } + break; + } + case MUSICPLAYER_SAMPLERATE: + { + int iSamplerate = m_audioInfo.samplerate; + if (iSamplerate > 0) + { + value = StringUtils::Format("{:.5}", static_cast<double>(iSamplerate) / 1000.0); + return true; + } + break; + } + case MUSICPLAYER_CODEC: + value = m_audioInfo.codecName; + return true; + } + + /////////////////////////////////////////////////////////////////////////////////////////////// + // MUSICPM_* + /////////////////////////////////////////////////////////////////////////////////////////////// + if (GetPartyModeLabel(value, info)) + return true; + + return false; +} + +bool CMusicGUIInfo::GetPartyModeLabel(std::string& value, const CGUIInfo &info) const +{ + int iSongs = -1; + + switch (info.m_info) + { + case MUSICPM_SONGSPLAYED: + iSongs = g_partyModeManager.GetSongsPlayed(); + break; + case MUSICPM_MATCHINGSONGS: + iSongs = g_partyModeManager.GetMatchingSongs(); + break; + case MUSICPM_MATCHINGSONGSPICKED: + iSongs = g_partyModeManager.GetMatchingSongsPicked(); + break; + case MUSICPM_MATCHINGSONGSLEFT: + iSongs = g_partyModeManager.GetMatchingSongsLeft(); + break; + case MUSICPM_RELAXEDSONGSPICKED: + iSongs = g_partyModeManager.GetRelaxedSongs(); + break; + case MUSICPM_RANDOMSONGSPICKED: + iSongs = g_partyModeManager.GetRandomSongs(); + break; + } + + if (iSongs >= 0) + { + value = std::to_string(iSongs); + return true; + } + + return false; +} + +bool CMusicGUIInfo::GetPlaylistInfo(std::string& value, const CGUIInfo &info) const +{ + const PLAYLIST::CPlayList& playlist = + CServiceBroker::GetPlaylistPlayer().GetPlaylist(PLAYLIST::TYPE_MUSIC); + if (playlist.size() < 1) + return false; + + int index = info.GetData2(); + if (info.GetData1() == 1) + { // relative index (requires current playlist is TYPE_MUSIC) + if (CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() != PLAYLIST::TYPE_MUSIC) + return false; + + index = CServiceBroker::GetPlaylistPlayer().GetNextSong(index); + } + + if (index < 0 || index >= playlist.size()) + return false; + + const CFileItemPtr playlistItem = playlist[index]; + if (playlistItem->HasMusicInfoTag() && !playlistItem->GetMusicInfoTag()->Loaded()) + { + playlistItem->LoadMusicTag(); + playlistItem->GetMusicInfoTag()->SetLoaded(); + } + // try to set a thumbnail + if (!playlistItem->HasArt("thumb")) + { + CMusicThumbLoader loader; + loader.LoadItem(playlistItem.get()); + // still no thumb? then just the set the default cover + if (!playlistItem->HasArt("thumb")) + playlistItem->SetArt("thumb", "DefaultAlbumCover.png"); + } + if (info.m_info == MUSICPLAYER_PLAYLISTPOS) + { + value = std::to_string(index + 1); + return true; + } + else if (info.m_info == MUSICPLAYER_COVER) + { + value = playlistItem->GetArt("thumb"); + return true; + } + + return GetLabel(value, playlistItem.get(), 0, CGUIInfo(info.m_info), nullptr); +} + +bool CMusicGUIInfo::GetFallbackLabel(std::string& value, + const CFileItem* item, + int contextWindow, + const CGUIInfo& info, + std::string* fallback) +{ + // No fallback for musicplayer "offset" and "position" info labels + if (info.GetData1() && ((info.m_info >= MUSICPLAYER_OFFSET_POSITION_FIRST && + info.m_info <= MUSICPLAYER_OFFSET_POSITION_LAST) || + (info.m_info >= PLAYER_OFFSET_POSITION_FIRST && info.m_info <= PLAYER_OFFSET_POSITION_LAST))) + return false; + + const CMusicInfoTag* tag = item->GetMusicInfoTag(); + if (tag) + { + switch (info.m_info) + { + ///////////////////////////////////////////////////////////////////////////////////////////// + // MUSICPLAYER_* + ///////////////////////////////////////////////////////////////////////////////////////////// + case MUSICPLAYER_TITLE: + value = item->GetLabel(); + if (value.empty()) + value = CUtil::GetTitleFromPath(item->GetPath()); + return true; + default: + break; + } + } + return false; +} + +bool CMusicGUIInfo::GetInt(int& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + return false; +} + +bool CMusicGUIInfo::GetBool(bool& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const +{ + const CFileItem* item = static_cast<const CFileItem*>(gitem); + const CMusicInfoTag* tag = item->GetMusicInfoTag(); + + switch (info.m_info) + { + /////////////////////////////////////////////////////////////////////////////////////////////// + // MUSICPLAYER_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case MUSICPLAYER_CONTENT: + value = StringUtils::EqualsNoCase(info.GetData3(), "files"); + return value; // if no match for this provider, other providers shall be asked. + case MUSICPLAYER_HASPREVIOUS: + // requires current playlist be TYPE_MUSIC + if (CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() == PLAYLIST::TYPE_MUSIC) + { + value = (CServiceBroker::GetPlaylistPlayer().GetCurrentSong() > 0); // not first song + return true; + } + break; + case MUSICPLAYER_HASNEXT: + // requires current playlist be TYPE_MUSIC + if (CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() == PLAYLIST::TYPE_MUSIC) + { + value = (CServiceBroker::GetPlaylistPlayer().GetCurrentSong() < + (CServiceBroker::GetPlaylistPlayer().GetPlaylist(PLAYLIST::TYPE_MUSIC).size() - + 1)); // not last song + return true; + } + break; + case MUSICPLAYER_PLAYLISTPLAYING: + { + const auto& components = CServiceBroker::GetAppComponents(); + const auto appPlayer = components.GetComponent<CApplicationPlayer>(); + if (appPlayer->IsPlayingAudio() && + CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() == PLAYLIST::TYPE_MUSIC) + { + value = true; + return true; + } + break; + } + case MUSICPLAYER_EXISTS: + { + int index = info.GetData2(); + if (info.GetData1() == 1) + { // relative index + if (CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist() != PLAYLIST::TYPE_MUSIC) + { + value = false; + return true; + } + index += CServiceBroker::GetPlaylistPlayer().GetCurrentSong(); + } + value = + (index >= 0 && + index < CServiceBroker::GetPlaylistPlayer().GetPlaylist(PLAYLIST::TYPE_MUSIC).size()); + return true; + } + case MUSICPLAYER_ISMULTIDISC: + if (tag) + { + value = (item->GetMusicInfoTag()->GetTotalDiscs() > 1); + return true; + } + break; + /////////////////////////////////////////////////////////////////////////////////////////////// + // MUSICPM_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case MUSICPM_ENABLED: + value = g_partyModeManager.IsEnabled(); + return true; + + /////////////////////////////////////////////////////////////////////////////////////////////// + // LISTITEM_* + /////////////////////////////////////////////////////////////////////////////////////////////// + case LISTITEM_IS_BOXSET: + if (tag) + { + value = tag->GetBoxset() == true; + return true; + } + break; + } + + return false; +} |