summaryrefslogtreecommitdiffstats
path: root/xbmc/music/windows/GUIWindowMusicNav.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 18:07:22 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 18:07:22 +0000
commitc04dcc2e7d834218ef2d4194331e383402495ae1 (patch)
tree7333e38d10d75386e60f336b80c2443c1166031d /xbmc/music/windows/GUIWindowMusicNav.cpp
parentInitial commit. (diff)
downloadkodi-c04dcc2e7d834218ef2d4194331e383402495ae1.tar.xz
kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.zip
Adding upstream version 2:20.4+dfsg.upstream/2%20.4+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xbmc/music/windows/GUIWindowMusicNav.cpp')
-rw-r--r--xbmc/music/windows/GUIWindowMusicNav.cpp944
1 files changed, 944 insertions, 0 deletions
diff --git a/xbmc/music/windows/GUIWindowMusicNav.cpp b/xbmc/music/windows/GUIWindowMusicNav.cpp
new file mode 100644
index 0000000..f8ba5a4
--- /dev/null
+++ b/xbmc/music/windows/GUIWindowMusicNav.cpp
@@ -0,0 +1,944 @@
+/*
+ * Copyright (C) 2005-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 "GUIWindowMusicNav.h"
+
+#include "FileItem.h"
+#include "GUIPassword.h"
+#include "GUIUserMessages.h"
+#include "PartyModeManager.h"
+#include "ServiceBroker.h"
+#include "URL.h"
+#include "Util.h"
+#include "addons/AddonSystemSettings.h"
+#include "dialogs/GUIDialogYesNo.h"
+#include "filesystem/MusicDatabaseDirectory.h"
+#include "filesystem/VideoDatabaseDirectory.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUIEditControl.h"
+#include "guilib/GUIKeyboardFactory.h"
+#include "guilib/GUIWindowManager.h"
+#include "guilib/LocalizeStrings.h"
+#include "input/Key.h"
+#include "messaging/ApplicationMessenger.h"
+#include "messaging/helpers/DialogOKHelper.h"
+#include "music/MusicLibraryQueue.h"
+#include "music/dialogs/GUIDialogInfoProviderSettings.h"
+#include "music/tags/MusicInfoTag.h"
+#include "playlists/PlayList.h"
+#include "playlists/PlayListFactory.h"
+#include "profiles/ProfileManager.h"
+#include "settings/AdvancedSettings.h"
+#include "settings/Settings.h"
+#include "settings/SettingsComponent.h"
+#include "storage/MediaManager.h"
+#include "utils/FileUtils.h"
+#include "utils/LegacyPathTranslation.h"
+#include "utils/StringUtils.h"
+#include "utils/URIUtils.h"
+#include "utils/Variant.h"
+#include "utils/log.h"
+#include "video/VideoDatabase.h"
+#include "video/dialogs/GUIDialogVideoInfo.h"
+#include "video/windows/GUIWindowVideoNav.h"
+#include "view/GUIViewState.h"
+
+using namespace XFILE;
+using namespace PLAYLIST;
+using namespace MUSICDATABASEDIRECTORY;
+using namespace KODI::MESSAGING;
+
+#define CONTROL_BTNVIEWASICONS 2
+#define CONTROL_BTNSORTBY 3
+#define CONTROL_BTNSORTASC 4
+#define CONTROL_BTNTYPE 5
+#define CONTROL_LABELFILES 12
+
+#define CONTROL_SEARCH 8
+#define CONTROL_FILTER 15
+#define CONTROL_BTNPARTYMODE 16
+#define CONTROL_BTNMANUALINFO 17
+#define CONTROL_BTN_FILTER 19
+
+#define CONTROL_UPDATE_LIBRARY 20
+
+CGUIWindowMusicNav::CGUIWindowMusicNav(void)
+ : CGUIWindowMusicBase(WINDOW_MUSIC_NAV, "MyMusicNav.xml")
+{
+ m_vecItems->SetPath("?");
+ m_searchWithEdit = false;
+}
+
+CGUIWindowMusicNav::~CGUIWindowMusicNav(void) = default;
+
+bool CGUIWindowMusicNav::OnMessage(CGUIMessage& message)
+{
+ switch (message.GetMessage())
+ {
+ case GUI_MSG_WINDOW_RESET:
+ m_vecItems->SetPath("?");
+ break;
+ case GUI_MSG_WINDOW_INIT:
+ {
+ /* We don't want to show Autosourced items (ie removable pendrives, memorycards) in Library mode */
+ m_rootDir.AllowNonLocalSources(false);
+
+ // is this the first time the window is opened?
+ if (m_vecItems->GetPath() == "?" && message.GetStringParam().empty())
+ message.SetStringParam(CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_MYMUSIC_DEFAULTLIBVIEW));
+
+ if (!CGUIWindowMusicBase::OnMessage(message))
+ return false;
+
+ if (message.GetStringParam(0) != "")
+ {
+ CURL url(message.GetStringParam(0));
+
+ int i = 0;
+ for (; i < m_vecItems->Size(); i++)
+ {
+ CFileItemPtr pItem = m_vecItems->Get(i);
+
+ // skip ".."
+ if (pItem->IsParentFolder())
+ continue;
+
+ if (URIUtils::PathEquals(pItem->GetPath(), message.GetStringParam(0), true, true))
+ {
+ m_viewControl.SetSelectedItem(i);
+ i = -1;
+ if (url.GetOption("showinfo") == "true")
+ OnItemInfo(i);
+ break;
+ }
+ }
+ }
+
+ return true;
+ }
+ break;
+
+ case GUI_MSG_CLICKED:
+ {
+ int iControl = message.GetSenderId();
+ if (iControl == CONTROL_BTNPARTYMODE)
+ {
+ if (g_partyModeManager.IsEnabled())
+ g_partyModeManager.Disable();
+ else
+ {
+ if (!g_partyModeManager.Enable())
+ {
+ SET_CONTROL_SELECTED(GetID(),CONTROL_BTNPARTYMODE,false);
+ return false;
+ }
+
+ // Playlist directory is the root of the playlist window
+ if (m_guiState)
+ m_guiState->SetPlaylistDirectory("playlistmusic://");
+
+ return true;
+ }
+ UpdateButtons();
+ }
+ else if (iControl == CONTROL_SEARCH)
+ {
+ if (m_searchWithEdit)
+ {
+ // search updated - reset timer
+ m_searchTimer.StartZero();
+ // grab our search string
+ CGUIMessage selected(GUI_MSG_ITEM_SELECTED, GetID(), CONTROL_SEARCH);
+ OnMessage(selected);
+ SetProperty("search", selected.GetLabel());
+ return true;
+ }
+ std::string search(GetProperty("search").asString());
+ CGUIKeyboardFactory::ShowAndGetFilter(search, true);
+ SetProperty("search", search);
+ return true;
+ }
+ else if (iControl == CONTROL_UPDATE_LIBRARY)
+ {
+ if (!CMusicLibraryQueue::GetInstance().IsScanningLibrary())
+ CMusicLibraryQueue::GetInstance().ScanLibrary("");
+ else
+ CMusicLibraryQueue::GetInstance().StopLibraryScanning();
+ return true;
+ }
+ }
+ break;
+ case GUI_MSG_PLAYBACK_STOPPED:
+ case GUI_MSG_PLAYBACK_ENDED:
+ case GUI_MSG_PLAYLISTPLAYER_STOPPED:
+ case GUI_MSG_PLAYBACK_STARTED:
+ {
+ SET_CONTROL_SELECTED(GetID(),CONTROL_BTNPARTYMODE, g_partyModeManager.IsEnabled());
+ }
+ break;
+ case GUI_MSG_NOTIFY_ALL:
+ {
+ if (message.GetParam1() == GUI_MSG_SEARCH_UPDATE && IsActive())
+ {
+ // search updated - reset timer
+ m_searchTimer.StartZero();
+ SetProperty("search", message.GetStringParam());
+ }
+ }
+ }
+ return CGUIWindowMusicBase::OnMessage(message);
+}
+
+bool CGUIWindowMusicNav::OnAction(const CAction& action)
+{
+ if (action.GetID() == ACTION_SCAN_ITEM)
+ {
+ int item = m_viewControl.GetSelectedItem();
+ CMusicDatabaseDirectory dir;
+ if (item > -1 && m_vecItems->Get(item)->m_bIsFolder
+ && (m_vecItems->Get(item)->IsAlbum()||
+ dir.IsArtistDir(m_vecItems->Get(item)->GetPath())))
+ {
+ OnContextButton(item,CONTEXT_BUTTON_INFO);
+ return true;
+ }
+ }
+
+ return CGUIWindowMusicBase::OnAction(action);
+}
+
+bool CGUIWindowMusicNav::ManageInfoProvider(const CFileItemPtr& item)
+{
+ CQueryParams params;
+ CDirectoryNode::GetDatabaseInfo(item->GetPath(), params);
+ // Management of Info provider only valid for specific artist or album items
+ if (params.GetAlbumId() == -1 && params.GetArtistId() == -1)
+ return false;
+
+ // Set things up for processing artist or albums
+ CONTENT_TYPE content = CONTENT_ALBUMS;
+ int id = params.GetAlbumId();
+ if (id == -1)
+ {
+ content = CONTENT_ARTISTS;
+ id = params.GetArtistId();
+ }
+
+ ADDON::ScraperPtr scraper;
+ // Get specific scraper and settings for current item or use default
+ if (!m_musicdatabase.GetScraper(id, content, scraper))
+ {
+ ADDON::AddonPtr defaultScraper;
+ if (ADDON::CAddonSystemSettings::GetInstance().GetActive(
+ ADDON::ScraperTypeFromContent(content), defaultScraper))
+ {
+ scraper = std::dynamic_pointer_cast<ADDON::CScraper>(defaultScraper);
+ }
+ }
+
+ // Set Information provider and settings
+ int applyto = CGUIDialogInfoProviderSettings::Show(scraper);
+ if (applyto >= 0)
+ {
+ bool result = false;
+ CVariant msgctxt;
+ switch (applyto)
+ {
+ case INFOPROVIDERAPPLYOPTIONS::INFOPROVIDER_THISITEM: // Change information provider for specific item
+ result = m_musicdatabase.SetScraper(id, content, scraper);
+ break;
+ case INFOPROVIDERAPPLYOPTIONS::INFOPROVIDER_ALLVIEW: // Change information provider for the filtered items shown on this node
+ {
+ msgctxt = 38069;
+ if (content == CONTENT_ARTISTS)
+ msgctxt = 38068;
+ if (CGUIDialogYesNo::ShowAndGetInput(CVariant{ 20195 }, msgctxt)) // Change information provider, confirm for all shown
+ {
+ // Set scraper for all items on current view.
+ std::string strPath = "musicdb://";
+ if (content == CONTENT_ARTISTS)
+ strPath += "artists";
+ else
+ strPath += "albums";
+ URIUtils::AddSlashAtEnd(strPath);
+ // Items on view could be limited by navigation criteria, smart playlist rules or a filter.
+ // Get these options, except ID, from item path
+ CURL musicUrl(item->GetPath()); //Use CURL, as CMusicDbUrl removes "filter" option
+ if (content == CONTENT_ARTISTS)
+ musicUrl.RemoveOption("artistid");
+ else
+ musicUrl.RemoveOption("albumid");
+ strPath += musicUrl.GetOptions();
+ result = m_musicdatabase.SetScraperAll(strPath, scraper);
+ }
+ }
+ break;
+ case INFOPROVIDERAPPLYOPTIONS::INFOPROVIDER_DEFAULT: // Change information provider for all items
+ {
+ msgctxt = 38071;
+ if (content == CONTENT_ARTISTS)
+ msgctxt = 38070;
+ if (CGUIDialogYesNo::ShowAndGetInput(CVariant{20195}, msgctxt)) // Change information provider, confirm default and clear
+ {
+ // Save scraper addon default setting values
+ scraper->SaveSettings();
+ // Set default scraper
+ const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings();
+ if (content == CONTENT_ARTISTS)
+ settings->SetString(CSettings::SETTING_MUSICLIBRARY_ARTISTSSCRAPER, scraper->ID());
+ else
+ settings->SetString(CSettings::SETTING_MUSICLIBRARY_ALBUMSSCRAPER, scraper->ID());
+ settings->Save();
+ // Clear all item specific settings
+ if (content == CONTENT_ARTISTS)
+ result = m_musicdatabase.SetScraperAll("musicdb://artists/", nullptr);
+ else
+ result = m_musicdatabase.SetScraperAll("musicdb://albums/", nullptr);
+ }
+ }
+ default:
+ break;
+ }
+ if (!result)
+ return false;
+
+ // Refresh additional information using the new settings
+ if (applyto == INFOPROVIDERAPPLYOPTIONS::INFOPROVIDER_ALLVIEW || applyto == INFOPROVIDERAPPLYOPTIONS::INFOPROVIDER_DEFAULT)
+ {
+ // Change information provider, all artists or albums
+ if (CGUIDialogYesNo::ShowAndGetInput(CVariant{20195}, CVariant{38072}))
+ OnItemInfoAll(m_vecItems->GetPath(), true);
+ }
+ else
+ {
+ // Change information provider, selected artist or album
+ if (CGUIDialogYesNo::ShowAndGetInput(CVariant{20195}, CVariant{38073}))
+ {
+ std::string itempath = StringUtils::Format("musicdb://albums/{}/", id);
+ if (content == CONTENT_ARTISTS)
+ itempath = StringUtils::Format("musicdb://artists/{}/", id);
+ OnItemInfoAll(itempath, true);
+ }
+ }
+ }
+ return true;
+}
+
+bool CGUIWindowMusicNav::OnClick(int iItem, const std::string &player /* = "" */)
+{
+ if (iItem < 0 || iItem >= m_vecItems->Size()) return false;
+
+ CFileItemPtr item = m_vecItems->Get(iItem);
+ if (StringUtils::StartsWith(item->GetPath(), "musicsearch://"))
+ {
+ if (m_searchWithEdit)
+ OnSearchUpdate();
+ else
+ {
+ std::string search(GetProperty("search").asString());
+ CGUIKeyboardFactory::ShowAndGetFilter(search, true);
+ SetProperty("search", search);
+ }
+ return true;
+ }
+ if (item->IsMusicDb() && !item->m_bIsFolder)
+ m_musicdatabase.SetPropertiesForFileItem(*item);
+
+ if (item->IsPlayList() &&
+ !CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_playlistAsFolders)
+ {
+ PlayItem(iItem);
+ return true;
+ }
+ return CGUIWindowMusicBase::OnClick(iItem, player);
+}
+
+bool CGUIWindowMusicNav::Update(const std::string &strDirectory, bool updateFilterPath /* = true */)
+{
+ if (m_thumbLoader.IsLoading())
+ m_thumbLoader.StopThread();
+
+ if (CGUIWindowMusicBase::Update(strDirectory, updateFilterPath))
+ {
+ m_thumbLoader.Load(*m_unfilteredItems);
+ return true;
+ }
+
+ return false;
+}
+
+bool CGUIWindowMusicNav::GetDirectory(const std::string &strDirectory, CFileItemList &items)
+{
+ if (strDirectory.empty())
+ AddSearchFolder();
+
+ bool bResult = CGUIWindowMusicBase::GetDirectory(strDirectory, items);
+ if (bResult)
+ {
+ if (items.IsPlayList())
+ OnRetrieveMusicInfo(items);
+ }
+
+ // update our content in the info manager
+ if (StringUtils::StartsWithNoCase(strDirectory, "videodb://") || items.IsVideoDb())
+ {
+ CVideoDatabaseDirectory dir;
+ VIDEODATABASEDIRECTORY::NODE_TYPE node = dir.GetDirectoryChildType(items.GetPath());
+ if (node == VIDEODATABASEDIRECTORY::NODE_TYPE_TITLE_MUSICVIDEOS ||
+ node == VIDEODATABASEDIRECTORY::NODE_TYPE_RECENTLY_ADDED_MUSICVIDEOS)
+ items.SetContent("musicvideos");
+ else if (node == VIDEODATABASEDIRECTORY::NODE_TYPE_GENRE)
+ items.SetContent("genres");
+ else if (node == VIDEODATABASEDIRECTORY::NODE_TYPE_COUNTRY)
+ items.SetContent("countries");
+ else if (node == VIDEODATABASEDIRECTORY::NODE_TYPE_ACTOR)
+ items.SetContent("artists");
+ else if (node == VIDEODATABASEDIRECTORY::NODE_TYPE_DIRECTOR)
+ items.SetContent("directors");
+ else if (node == VIDEODATABASEDIRECTORY::NODE_TYPE_STUDIO)
+ items.SetContent("studios");
+ else if (node == VIDEODATABASEDIRECTORY::NODE_TYPE_YEAR)
+ items.SetContent("years");
+ else if (node == VIDEODATABASEDIRECTORY::NODE_TYPE_MUSICVIDEOS_ALBUM)
+ items.SetContent("albums");
+ else if (node == VIDEODATABASEDIRECTORY::NODE_TYPE_TAGS)
+ items.SetContent("tags");
+ else
+ items.SetContent("");
+ }
+ else if (StringUtils::StartsWithNoCase(strDirectory, "musicdb://") || items.IsMusicDb())
+ {
+ CMusicDatabaseDirectory dir;
+ NODE_TYPE node = dir.GetDirectoryChildType(items.GetPath());
+ if (node == NODE_TYPE_ALBUM ||
+ node == NODE_TYPE_ALBUM_RECENTLY_ADDED ||
+ node == NODE_TYPE_ALBUM_RECENTLY_PLAYED ||
+ node == NODE_TYPE_ALBUM_TOP100 ||
+ node == NODE_TYPE_DISC) // ! @todo: own content type "discs"??
+ items.SetContent("albums");
+ else if (node == NODE_TYPE_ARTIST)
+ items.SetContent("artists");
+ else if (node == NODE_TYPE_SONG ||
+ node == NODE_TYPE_SONG_TOP100 ||
+ node == NODE_TYPE_SINGLES ||
+ node == NODE_TYPE_ALBUM_RECENTLY_ADDED_SONGS ||
+ node == NODE_TYPE_ALBUM_RECENTLY_PLAYED_SONGS ||
+ node == NODE_TYPE_ALBUM_TOP100_SONGS)
+ items.SetContent("songs");
+ else if (node == NODE_TYPE_GENRE)
+ items.SetContent("genres");
+ else if (node == NODE_TYPE_SOURCE)
+ items.SetContent("sources");
+ else if (node == NODE_TYPE_ROLE)
+ items.SetContent("roles");
+ else if (node == NODE_TYPE_YEAR)
+ items.SetContent("years");
+ else
+ items.SetContent("");
+ }
+ else if (items.IsPlayList())
+ items.SetContent("songs");
+ else if (URIUtils::PathEquals(strDirectory, "special://musicplaylists/") ||
+ URIUtils::PathEquals(strDirectory, "library://music/playlists.xml/"))
+ items.SetContent("playlists");
+ else if (URIUtils::PathEquals(strDirectory, "plugin://music/"))
+ items.SetContent("plugins");
+ else if (items.IsAddonsPath())
+ items.SetContent("addons");
+ else if (!items.IsSourcesPath() && !items.IsVirtualDirectoryRoot() &&
+ !items.IsLibraryFolder() && !items.IsPlugin() && !items.IsSmartPlayList())
+ items.SetContent("files");
+
+ return bResult;
+}
+
+void CGUIWindowMusicNav::UpdateButtons()
+{
+ CGUIWindowMusicBase::UpdateButtons();
+
+ // Update object count
+ int iItems = m_vecItems->Size();
+ if (iItems)
+ {
+ // check for parent dir and "all" items
+ // should always be the first two items
+ for (int i = 0; i <= (iItems>=2 ? 1 : 0); i++)
+ {
+ CFileItemPtr pItem = m_vecItems->Get(i);
+ if (pItem->IsParentFolder()) iItems--;
+ if (StringUtils::StartsWith(pItem->GetPath(), "/-1/")) iItems--;
+ }
+ // or the last item
+ if (m_vecItems->Size() > 2 &&
+ StringUtils::StartsWith(m_vecItems->Get(m_vecItems->Size()-1)->GetPath(), "/-1/"))
+ iItems--;
+ }
+ std::string items = StringUtils::Format("{} {}", iItems, g_localizeStrings.Get(127));
+ SET_CONTROL_LABEL(CONTROL_LABELFILES, items);
+
+ // set the filter label
+ std::string strLabel;
+
+ // "Playlists"
+ if (m_vecItems->IsPath("special://musicplaylists/"))
+ strLabel = g_localizeStrings.Get(136);
+ // "{Playlist Name}"
+ else if (m_vecItems->IsPlayList())
+ {
+ // get playlist name from path
+ std::string strDummy;
+ URIUtils::Split(m_vecItems->GetPath(), strDummy, strLabel);
+ }
+ // everything else is from a musicdb:// path
+ else
+ {
+ CMusicDatabaseDirectory dir;
+ dir.GetLabel(m_vecItems->GetPath(), strLabel);
+ }
+
+ SET_CONTROL_LABEL(CONTROL_FILTER, strLabel);
+
+ SET_CONTROL_SELECTED(GetID(),CONTROL_BTNPARTYMODE, g_partyModeManager.IsEnabled());
+
+ CONTROL_ENABLE_ON_CONDITION(CONTROL_UPDATE_LIBRARY, !m_vecItems->IsAddonsPath() && !m_vecItems->IsPlugin() && !m_vecItems->IsScript());
+}
+
+void CGUIWindowMusicNav::PlayItem(int iItem)
+{
+ // unlike additemtoplaylist, we need to check the items here
+ // before calling it since the current playlist will be stopped
+ // and cleared!
+
+ // root is not allowed
+ if (m_vecItems->IsVirtualDirectoryRoot() && !m_vecItems->Get(iItem)->IsDVD())
+ return;
+
+ CGUIWindowMusicBase::PlayItem(iItem);
+}
+
+void CGUIWindowMusicNav::OnWindowLoaded()
+{
+ const CGUIControl *control = GetControl(CONTROL_SEARCH);
+ m_searchWithEdit = (control && control->GetControlType() == CGUIControl::GUICONTROL_EDIT);
+
+ CGUIWindowMusicBase::OnWindowLoaded();
+
+ if (m_searchWithEdit)
+ {
+ SendMessage(GUI_MSG_SET_TYPE, CONTROL_SEARCH, CGUIEditControl::INPUT_TYPE_SEARCH);
+ SET_CONTROL_LABEL2(CONTROL_SEARCH, GetProperty("search").asString());
+ }
+}
+
+void CGUIWindowMusicNav::GetContextButtons(int itemNumber, CContextButtons &buttons)
+{
+ CFileItemPtr item;
+ if (itemNumber >= 0 && itemNumber < m_vecItems->Size())
+ item = m_vecItems->Get(itemNumber);
+ if (item)
+ {
+ const std::shared_ptr<CProfileManager> profileManager = CServiceBroker::GetSettingsComponent()->GetProfileManager();
+
+ // are we in the playlists location?
+ bool inPlaylists = m_vecItems->IsPath(CUtil::MusicPlaylistsLocation()) ||
+ m_vecItems->IsPath("special://musicplaylists/");
+
+ if (m_vecItems->IsPath("sources://music/"))
+ {
+ // get the usual music shares, and anything for all media windows
+ CGUIDialogContextMenu::GetContextButtons("music", item, buttons);
+#ifdef HAS_DVD_DRIVE
+ // enable Rip CD an audio disc
+ if (CServiceBroker::GetMediaManager().IsDiscInDrive() && item->IsCDDA())
+ {
+ // those cds can also include Audio Tracks: CDExtra and MixedMode!
+ MEDIA_DETECT::CCdInfo* pCdInfo = CServiceBroker::GetMediaManager().GetCdInfo();
+ if (pCdInfo->IsAudio(1) || pCdInfo->IsCDExtra(1) || pCdInfo->IsMixedMode(1))
+ {
+ if (CServiceBroker::GetJobManager()->IsProcessing("cdrip"))
+ buttons.Add(CONTEXT_BUTTON_CANCEL_RIP_CD, 14100);
+ else
+ buttons.Add(CONTEXT_BUTTON_RIP_CD, 600);
+ }
+ }
+#endif
+ // Scan button for music sources except ".." and "Add music source" items
+ if (!item->IsPath("add") && !item->IsParentFolder() &&
+ (profileManager->GetCurrentProfile().canWriteDatabases() || g_passwordManager.bMasterUser))
+ {
+ buttons.Add(CONTEXT_BUTTON_SCAN, 13352);
+ }
+ CGUIMediaWindow::GetContextButtons(itemNumber, buttons);
+ }
+ else
+ {
+ CGUIWindowMusicBase::GetContextButtons(itemNumber, buttons);
+
+ // Scan button for real folders containing files when navigating within music sources.
+ // Blacklist the bespoke Kodi protocols as to many valid external protocols to whitelist
+ if (m_vecItems->GetContent() == "files" && // Other content not scanned to library
+ !inPlaylists && !m_vecItems->IsInternetStream() && // Not playlists locations or streams
+ !item->IsPath("add") && !item->IsParentFolder() && // Not ".." and "Add items
+ item->m_bIsFolder && // Folders only, but playlists can be folders too
+ !URIUtils::IsLibraryContent(item->GetPath()) && // database folder or .xsp files
+ !URIUtils::IsSpecial(item->GetPath()) && !item->IsPlugin() && !item->IsScript() &&
+ !item->IsPlayList() && // .m3u etc. that as flagged as folders when playlistasfolders
+ !StringUtils::StartsWithNoCase(item->GetPath(), "addons://") &&
+ (profileManager->GetCurrentProfile().canWriteDatabases() ||
+ g_passwordManager.bMasterUser))
+ {
+ buttons.Add(CONTEXT_BUTTON_SCAN, 13352);
+ }
+
+ CMusicDatabaseDirectory dir;
+
+ if (!item->IsParentFolder() && !dir.IsAllItem(item->GetPath()))
+ {
+ if (item->m_bIsFolder && !item->IsVideoDb() &&
+ !item->IsPlugin() && !StringUtils::StartsWithNoCase(item->GetPath(), "musicsearch://"))
+ {
+ if (item->IsAlbum())
+ // enable query all albums button only in album view
+ buttons.Add(CONTEXT_BUTTON_INFO_ALL, 20059);
+ else if (dir.IsArtistDir(item->GetPath()))
+ // enable query all artist button only in artist view
+ buttons.Add(CONTEXT_BUTTON_INFO_ALL, 21884);
+
+ //Set default or clear default
+ NODE_TYPE nodetype = dir.GetDirectoryType(item->GetPath());
+ if (!inPlaylists &&
+ (nodetype == NODE_TYPE_ROOT ||
+ nodetype == NODE_TYPE_OVERVIEW ||
+ nodetype == NODE_TYPE_TOP100))
+ {
+ const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings();
+ if (!item->IsPath(settings->GetString(CSettings::SETTING_MYMUSIC_DEFAULTLIBVIEW)))
+ buttons.Add(CONTEXT_BUTTON_SET_DEFAULT, 13335); // set default
+ if (!settings->GetString(CSettings::SETTING_MYMUSIC_DEFAULTLIBVIEW).empty())
+ buttons.Add(CONTEXT_BUTTON_CLEAR_DEFAULT, 13403); // clear default
+ }
+
+ //Change information provider
+ if (StringUtils::EqualsNoCase(m_vecItems->GetContent(), "albums") ||
+ StringUtils::EqualsNoCase(m_vecItems->GetContent(), "artists"))
+ {
+ // we allow the user to set information provider for albums and artists
+ buttons.Add(CONTEXT_BUTTON_SET_CONTENT, 20195);
+ }
+ }
+ if (item->HasMusicInfoTag() && !item->GetMusicInfoTag()->GetArtistString().empty())
+ {
+ CVideoDatabase database;
+ database.Open();
+ if (database.GetMatchingMusicVideo(item->GetMusicInfoTag()->GetArtistString()) > -1)
+ buttons.Add(CONTEXT_BUTTON_GO_TO_ARTIST, 20400);
+ }
+ if (item->HasMusicInfoTag() && !item->GetMusicInfoTag()->GetArtistString().empty() &&
+ !item->GetMusicInfoTag()->GetAlbum().empty() &&
+ !item->GetMusicInfoTag()->GetTitle().empty())
+ {
+ CVideoDatabase database;
+ database.Open();
+ if (database.GetMatchingMusicVideo(item->GetMusicInfoTag()->GetArtistString(), item->GetMusicInfoTag()->GetAlbum(), item->GetMusicInfoTag()->GetTitle()) > -1)
+ buttons.Add(CONTEXT_BUTTON_PLAY_OTHER, 20401);
+ }
+ if (item->HasVideoInfoTag() && !item->m_bIsFolder)
+ {
+ if ((profileManager->GetCurrentProfile().canWriteDatabases() || g_passwordManager.bMasterUser) && !item->IsPlugin())
+ {
+ buttons.Add(CONTEXT_BUTTON_RENAME, 16105);
+ buttons.Add(CONTEXT_BUTTON_DELETE, 646);
+ }
+ }
+ if (inPlaylists && URIUtils::GetFileName(item->GetPath()) != "PartyMode.xsp"
+ && (item->IsPlayList() || item->IsSmartPlayList()))
+ buttons.Add(CONTEXT_BUTTON_DELETE, 117);
+
+ if (!item->IsReadOnly() && CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool("filelists.allowfiledeletion"))
+ {
+ buttons.Add(CONTEXT_BUTTON_DELETE, 117);
+ buttons.Add(CONTEXT_BUTTON_RENAME, 118);
+ }
+ }
+ }
+ }
+ // noncontextual buttons
+
+ CGUIWindowMusicBase::GetNonContextButtons(buttons);
+}
+
+bool CGUIWindowMusicNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
+{
+ CFileItemPtr item;
+ if (itemNumber >= 0 && itemNumber < m_vecItems->Size())
+ item = m_vecItems->Get(itemNumber);
+
+ switch (button)
+ {
+ case CONTEXT_BUTTON_INFO:
+ {
+ if (!item->IsVideoDb())
+ return CGUIWindowMusicBase::OnContextButton(itemNumber,button);
+
+ // music videos - artists
+ if (StringUtils::StartsWithNoCase(item->GetPath(), "videodb://musicvideos/artists/"))
+ {
+ int idArtist = m_musicdatabase.GetArtistByName(item->GetLabel());
+ if (idArtist == -1)
+ return false;
+ std::string path = StringUtils::Format("musicdb://artists/{}/", idArtist);
+ CArtist artist;
+ m_musicdatabase.GetArtist(idArtist, artist, false);
+ *item = CFileItem(artist);
+ item->SetPath(path);
+ CGUIWindowMusicBase::OnContextButton(itemNumber,button);
+ Refresh();
+ m_viewControl.SetSelectedItem(itemNumber);
+ return true;
+ }
+
+ // music videos - albums
+ if (StringUtils::StartsWithNoCase(item->GetPath(), "videodb://musicvideos/albums/"))
+ {
+ int idAlbum = m_musicdatabase.GetAlbumByName(item->GetLabel());
+ if (idAlbum == -1)
+ return false;
+ std::string path = StringUtils::Format("musicdb://albums/{}/", idAlbum);
+ CAlbum album;
+ m_musicdatabase.GetAlbum(idAlbum, album, false);
+ *item = CFileItem(path,album);
+ item->SetPath(path);
+ CGUIWindowMusicBase::OnContextButton(itemNumber,button);
+ Refresh();
+ m_viewControl.SetSelectedItem(itemNumber);
+ return true;
+ }
+
+ if (item->HasVideoInfoTag() && !item->GetVideoInfoTag()->m_strTitle.empty())
+ {
+ CGUIDialogVideoInfo::ShowFor(*item);
+ Refresh();
+ }
+ return true;
+ }
+
+ case CONTEXT_BUTTON_INFO_ALL:
+ OnItemInfoAll(m_vecItems->GetPath());
+ return true;
+
+ case CONTEXT_BUTTON_SET_DEFAULT:
+ {
+ const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings();
+ settings->SetString(CSettings::SETTING_MYMUSIC_DEFAULTLIBVIEW, item->GetPath());
+ settings->Save();
+ return true;
+ }
+
+ case CONTEXT_BUTTON_CLEAR_DEFAULT:
+ {
+ const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings();
+ settings->SetString(CSettings::SETTING_MYMUSIC_DEFAULTLIBVIEW, "");
+ settings->Save();
+ return true;
+ }
+
+ case CONTEXT_BUTTON_GO_TO_ARTIST:
+ {
+ std::string strPath;
+ CVideoDatabase database;
+ database.Open();
+ strPath = StringUtils::Format(
+ "videodb://musicvideos/artists/{}/",
+ database.GetMatchingMusicVideo(item->GetMusicInfoTag()->GetArtistString()));
+ CServiceBroker::GetGUI()->GetWindowManager().ActivateWindow(WINDOW_VIDEO_NAV,strPath);
+ return true;
+ }
+
+ case CONTEXT_BUTTON_PLAY_OTHER:
+ {
+ CVideoDatabase database;
+ database.Open();
+ CVideoInfoTag details;
+ database.GetMusicVideoInfo("", details, database.GetMatchingMusicVideo(item->GetMusicInfoTag()->GetArtistString(), item->GetMusicInfoTag()->GetAlbum(), item->GetMusicInfoTag()->GetTitle()));
+ CServiceBroker::GetAppMessenger()->PostMsg(TMSG_MEDIA_PLAY, 0, 0,
+ static_cast<void*>(new CFileItem(details)));
+ return true;
+ }
+
+ case CONTEXT_BUTTON_RENAME:
+ if (!item->IsVideoDb() && !item->IsReadOnly())
+ OnRenameItem(itemNumber);
+
+ CGUIDialogVideoInfo::UpdateVideoItemTitle(item);
+ CUtil::DeleteVideoDatabaseDirectoryCache();
+ Refresh();
+ return true;
+
+ case CONTEXT_BUTTON_DELETE:
+ if (item->IsPlayList() || item->IsSmartPlayList())
+ {
+ item->m_bIsFolder = false;
+ CGUIComponent *gui = CServiceBroker::GetGUI();
+ if (gui && gui->ConfirmDelete(item->GetPath()))
+ CFileUtils::DeleteItem(item);
+ }
+ else if (!item->IsVideoDb())
+ OnDeleteItem(itemNumber);
+ else
+ {
+ CGUIDialogVideoInfo::DeleteVideoItemFromDatabase(item);
+ CUtil::DeleteVideoDatabaseDirectoryCache();
+ }
+ Refresh();
+ return true;
+
+ case CONTEXT_BUTTON_SET_CONTENT:
+ return ManageInfoProvider(item);
+
+ default:
+ break;
+ }
+
+ return CGUIWindowMusicBase::OnContextButton(itemNumber, button);
+}
+
+bool CGUIWindowMusicNav::GetSongsFromPlayList(const std::string& strPlayList, CFileItemList &items)
+{
+ std::string strParentPath=m_history.GetParentPath();
+
+ if (m_guiState.get() && !m_guiState->HideParentDirItems())
+ {
+ CFileItemPtr pItem(new CFileItem(".."));
+ pItem->SetPath(strParentPath);
+ items.Add(pItem);
+ }
+
+ items.SetPath(strPlayList);
+ CLog::Log(LOGDEBUG, "CGUIWindowMusicNav, opening playlist [{}]", strPlayList);
+
+ std::unique_ptr<CPlayList> pPlayList (CPlayListFactory::Create(strPlayList));
+ if (nullptr != pPlayList)
+ {
+ // load it
+ if (!pPlayList->Load(strPlayList))
+ {
+ HELPERS::ShowOKDialogText(CVariant{6}, CVariant{477});
+ return false; //hmmm unable to load playlist?
+ }
+ CPlayList playlist = *pPlayList;
+ // convert playlist items to songs
+ for (int i = 0; i < playlist.size(); ++i)
+ {
+ items.Add(playlist[i]);
+ }
+ }
+
+ return true;
+}
+
+void CGUIWindowMusicNav::OnSearchUpdate()
+{
+ std::string search(CURL::Encode(GetProperty("search").asString()));
+ if (!search.empty())
+ {
+ std::string path = "musicsearch://" + search + "/";
+ m_history.ClearSearchHistory();
+ Update(path);
+ }
+ else if (m_vecItems->IsVirtualDirectoryRoot())
+ {
+ Update("");
+ }
+}
+
+void CGUIWindowMusicNav::FrameMove()
+{
+ static const int search_timeout = 2000;
+ // update our searching
+ if (m_searchTimer.IsRunning() && m_searchTimer.GetElapsedMilliseconds() > search_timeout)
+ {
+ m_searchTimer.Stop();
+ OnSearchUpdate();
+ }
+ CGUIWindowMusicBase::FrameMove();
+}
+
+void CGUIWindowMusicNav::AddSearchFolder()
+{
+ // we use a general viewstate (and not our member) here as our
+ // current viewstate may be specific to some other folder, and
+ // we know we're in the root here
+ CFileItemList items;
+ CGUIViewState* viewState = CGUIViewState::GetViewState(GetID(), items);
+ if (viewState)
+ {
+ // add our remove the musicsearch source
+ VECSOURCES &sources = viewState->GetSources();
+ bool haveSearchSource = false;
+ bool needSearchSource = !GetProperty("search").empty() || !m_searchWithEdit; // we always need it if we don't have the edit control
+ for (IVECSOURCES it = sources.begin(); it != sources.end(); ++it)
+ {
+ CMediaSource& share = *it;
+ if (share.strPath == "musicsearch://")
+ {
+ haveSearchSource = true;
+ if (!needSearchSource)
+ { // remove it
+ sources.erase(it);
+ break;
+ }
+ }
+ }
+ if (!haveSearchSource && needSearchSource)
+ {
+ // add search share
+ CMediaSource share;
+ share.strName=g_localizeStrings.Get(137); // Search
+ share.strPath = "musicsearch://";
+ share.m_iDriveType = CMediaSource::SOURCE_TYPE_LOCAL;
+ sources.push_back(share);
+ }
+ m_rootDir.SetSources(sources);
+ delete viewState;
+ }
+}
+
+std::string CGUIWindowMusicNav::GetStartFolder(const std::string &dir)
+{
+ std::string lower(dir); StringUtils::ToLower(lower);
+ if (lower == "genres")
+ return "musicdb://genres/";
+ else if (lower == "artists")
+ return "musicdb://artists/";
+ else if (lower == "albums")
+ return "musicdb://albums/";
+ else if (lower == "singles")
+ return "musicdb://singles/";
+ else if (lower == "songs")
+ return "musicdb://songs/";
+ else if (lower == "top100")
+ return "musicdb://top100/";
+ else if (lower == "top100songs")
+ return "musicdb://top100/songs/";
+ else if (lower == "top100albums")
+ return "musicdb://top100/albums/";
+ else if (lower == "recentlyaddedalbums")
+ return "musicdb://recentlyaddedalbums/";
+ else if (lower == "recentlyplayedalbums")
+ return "musicdb://recentlyplayedalbums/";
+ else if (lower == "compilations")
+ return "musicdb://compilations/";
+ else if (lower == "years")
+ return "musicdb://years/";
+ else if (lower == "files")
+ return "sources://music/";
+ else if (lower == "boxsets")
+ return "musicdb://boxsets/";
+
+ return CGUIWindowMusicBase::GetStartFolder(dir);
+}