[Windows] Fix driver version detection of AMD RDNA+ GPU on Windows 10
[xbmc.git] / xbmc / music / windows / GUIWindowMusicNav.cpp
blobb54eb59e938819ab318157a6f02c383d18519c57
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "GUIWindowMusicNav.h"
11 #include "FileItem.h"
12 #include "FileItemList.h"
13 #include "GUIPassword.h"
14 #include "GUIUserMessages.h"
15 #include "PartyModeManager.h"
16 #include "ServiceBroker.h"
17 #include "URL.h"
18 #include "Util.h"
19 #include "addons/AddonSystemSettings.h"
20 #include "dialogs/GUIDialogYesNo.h"
21 #include "filesystem/MusicDatabaseDirectory.h"
22 #include "filesystem/VideoDatabaseDirectory.h"
23 #include "guilib/GUIComponent.h"
24 #include "guilib/GUIEditControl.h"
25 #include "guilib/GUIKeyboardFactory.h"
26 #include "guilib/GUIWindowManager.h"
27 #include "guilib/LocalizeStrings.h"
28 #include "input/actions/Action.h"
29 #include "input/actions/ActionIDs.h"
30 #include "messaging/ApplicationMessenger.h"
31 #include "messaging/helpers/DialogOKHelper.h"
32 #include "music/MusicFileItemClassify.h"
33 #include "music/MusicLibraryQueue.h"
34 #include "music/dialogs/GUIDialogInfoProviderSettings.h"
35 #include "music/tags/MusicInfoTag.h"
36 #include "network/NetworkFileItemClassify.h"
37 #include "playlists/PlayList.h"
38 #include "playlists/PlayListFactory.h"
39 #include "profiles/ProfileManager.h"
40 #include "settings/AdvancedSettings.h"
41 #include "settings/Settings.h"
42 #include "settings/SettingsComponent.h"
43 #include "storage/MediaManager.h"
44 #include "utils/FileUtils.h"
45 #include "utils/LegacyPathTranslation.h"
46 #include "utils/StringUtils.h"
47 #include "utils/URIUtils.h"
48 #include "utils/Variant.h"
49 #include "utils/log.h"
50 #include "video/VideoDatabase.h"
51 #include "video/VideoFileItemClassify.h"
52 #include "video/dialogs/GUIDialogVideoInfo.h"
53 #include "video/windows/GUIWindowVideoNav.h"
54 #include "view/GUIViewState.h"
56 using namespace XFILE;
57 using namespace MUSICDATABASEDIRECTORY;
58 using namespace KODI;
59 using namespace KODI::MESSAGING;
60 using namespace KODI::VIDEO;
62 #define CONTROL_BTNVIEWASICONS 2
63 #define CONTROL_BTNSORTBY 3
64 #define CONTROL_BTNSORTASC 4
65 #define CONTROL_BTNTYPE 5
66 #define CONTROL_LABELFILES 12
68 #define CONTROL_SEARCH 8
69 #define CONTROL_FILTER 15
70 #define CONTROL_BTNPARTYMODE 16
71 #define CONTROL_BTNMANUALINFO 17
72 #define CONTROL_BTN_FILTER 19
74 #define CONTROL_UPDATE_LIBRARY 20
76 CGUIWindowMusicNav::CGUIWindowMusicNav(void)
77 : CGUIWindowMusicBase(WINDOW_MUSIC_NAV, "MyMusicNav.xml")
79 m_vecItems->SetPath("?");
80 m_searchWithEdit = false;
83 CGUIWindowMusicNav::~CGUIWindowMusicNav(void) = default;
85 bool CGUIWindowMusicNav::OnMessage(CGUIMessage& message)
87 switch (message.GetMessage())
89 case GUI_MSG_WINDOW_RESET:
90 m_vecItems->SetPath("?");
91 break;
92 case GUI_MSG_WINDOW_INIT:
94 /* We don't want to show Autosourced items (ie removable pendrives, memorycards) in Library mode */
95 m_rootDir.AllowNonLocalSources(false);
97 // is this the first time the window is opened?
98 if (m_vecItems->GetPath() == "?" && message.GetStringParam().empty())
99 message.SetStringParam(CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_MYMUSIC_DEFAULTLIBVIEW));
101 if (!CGUIWindowMusicBase::OnMessage(message))
102 return false;
104 if (message.GetStringParam(0) != "")
106 CURL url(message.GetStringParam(0));
108 int i = 0;
109 for (; i < m_vecItems->Size(); i++)
111 CFileItemPtr pItem = m_vecItems->Get(i);
113 // skip ".."
114 if (pItem->IsParentFolder())
115 continue;
117 if (URIUtils::PathEquals(pItem->GetPath(), message.GetStringParam(0), true, true))
119 m_viewControl.SetSelectedItem(i);
120 i = -1;
121 if (url.GetOption("showinfo") == "true")
122 OnItemInfo(i);
123 break;
128 return true;
130 break;
132 case GUI_MSG_CLICKED:
134 int iControl = message.GetSenderId();
135 if (iControl == CONTROL_BTNPARTYMODE)
137 if (g_partyModeManager.IsEnabled())
138 g_partyModeManager.Disable();
139 else
141 if (!g_partyModeManager.Enable())
143 SET_CONTROL_SELECTED(GetID(),CONTROL_BTNPARTYMODE,false);
144 return false;
147 // Playlist directory is the root of the playlist window
148 if (m_guiState)
149 m_guiState->SetPlaylistDirectory("playlistmusic://");
151 return true;
153 UpdateButtons();
155 else if (iControl == CONTROL_SEARCH)
157 if (m_searchWithEdit)
159 // search updated - reset timer
160 m_searchTimer.StartZero();
161 // grab our search string
162 CGUIMessage selected(GUI_MSG_ITEM_SELECTED, GetID(), CONTROL_SEARCH);
163 OnMessage(selected);
164 SetProperty("search", selected.GetLabel());
165 return true;
167 std::string search(GetProperty("search").asString());
168 CGUIKeyboardFactory::ShowAndGetFilter(search, true);
169 SetProperty("search", search);
170 return true;
172 else if (iControl == CONTROL_UPDATE_LIBRARY)
174 if (!CMusicLibraryQueue::GetInstance().IsScanningLibrary())
175 CMusicLibraryQueue::GetInstance().ScanLibrary("");
176 else
177 CMusicLibraryQueue::GetInstance().StopLibraryScanning();
178 return true;
181 break;
182 case GUI_MSG_PLAYBACK_STOPPED:
183 case GUI_MSG_PLAYBACK_ENDED:
184 case GUI_MSG_PLAYLISTPLAYER_STOPPED:
185 case GUI_MSG_PLAYBACK_STARTED:
187 SET_CONTROL_SELECTED(GetID(),CONTROL_BTNPARTYMODE, g_partyModeManager.IsEnabled());
189 break;
190 case GUI_MSG_NOTIFY_ALL:
192 if (message.GetParam1() == GUI_MSG_SEARCH_UPDATE && IsActive())
194 // search updated - reset timer
195 m_searchTimer.StartZero();
196 SetProperty("search", message.GetStringParam());
200 return CGUIWindowMusicBase::OnMessage(message);
203 bool CGUIWindowMusicNav::OnAction(const CAction& action)
205 if (action.GetID() == ACTION_SCAN_ITEM)
207 int item = m_viewControl.GetSelectedItem();
208 CMusicDatabaseDirectory dir;
209 if (item > -1 && m_vecItems->Get(item)->m_bIsFolder
210 && (m_vecItems->Get(item)->IsAlbum()||
211 dir.IsArtistDir(m_vecItems->Get(item)->GetPath())))
213 OnContextButton(item,CONTEXT_BUTTON_INFO);
214 return true;
218 return CGUIWindowMusicBase::OnAction(action);
221 bool CGUIWindowMusicNav::ManageInfoProvider(const CFileItemPtr& item)
223 CQueryParams params;
224 CDirectoryNode::GetDatabaseInfo(item->GetPath(), params);
225 // Management of Info provider only valid for specific artist or album items
226 if (params.GetAlbumId() == -1 && params.GetArtistId() == -1)
227 return false;
229 // Set things up for processing artist or albums
230 CONTENT_TYPE content = CONTENT_ALBUMS;
231 int id = params.GetAlbumId();
232 if (id == -1)
234 content = CONTENT_ARTISTS;
235 id = params.GetArtistId();
238 ADDON::ScraperPtr scraper;
239 // Get specific scraper and settings for current item or use default
240 if (!m_musicdatabase.GetScraper(id, content, scraper))
242 ADDON::AddonPtr defaultScraper;
243 if (ADDON::CAddonSystemSettings::GetInstance().GetActive(
244 ADDON::ScraperTypeFromContent(content), defaultScraper))
246 scraper = std::dynamic_pointer_cast<ADDON::CScraper>(defaultScraper);
250 // Set Information provider and settings
251 int applyto = CGUIDialogInfoProviderSettings::Show(scraper);
252 if (applyto >= 0)
254 bool result = false;
255 CVariant msgctxt;
256 switch (applyto)
258 case INFOPROVIDERAPPLYOPTIONS::INFOPROVIDER_THISITEM: // Change information provider for specific item
259 result = m_musicdatabase.SetScraper(id, content, scraper);
260 break;
261 case INFOPROVIDERAPPLYOPTIONS::INFOPROVIDER_ALLVIEW: // Change information provider for the filtered items shown on this node
263 msgctxt = 38069;
264 if (content == CONTENT_ARTISTS)
265 msgctxt = 38068;
266 if (CGUIDialogYesNo::ShowAndGetInput(CVariant{ 20195 }, msgctxt)) // Change information provider, confirm for all shown
268 // Set scraper for all items on current view.
269 std::string strPath = "musicdb://";
270 if (content == CONTENT_ARTISTS)
271 strPath += "artists";
272 else
273 strPath += "albums";
274 URIUtils::AddSlashAtEnd(strPath);
275 // Items on view could be limited by navigation criteria, smart playlist rules or a filter.
276 // Get these options, except ID, from item path
277 CURL musicUrl(item->GetPath()); //Use CURL, as CMusicDbUrl removes "filter" option
278 if (content == CONTENT_ARTISTS)
279 musicUrl.RemoveOption("artistid");
280 else
281 musicUrl.RemoveOption("albumid");
282 strPath += musicUrl.GetOptions();
283 result = m_musicdatabase.SetScraperAll(strPath, scraper);
286 break;
287 case INFOPROVIDERAPPLYOPTIONS::INFOPROVIDER_DEFAULT: // Change information provider for all items
289 msgctxt = 38071;
290 if (content == CONTENT_ARTISTS)
291 msgctxt = 38070;
292 if (CGUIDialogYesNo::ShowAndGetInput(CVariant{20195}, msgctxt)) // Change information provider, confirm default and clear
294 // Save scraper addon default setting values
295 scraper->SaveSettings();
296 // Set default scraper
297 const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings();
298 if (content == CONTENT_ARTISTS)
299 settings->SetString(CSettings::SETTING_MUSICLIBRARY_ARTISTSSCRAPER, scraper->ID());
300 else
301 settings->SetString(CSettings::SETTING_MUSICLIBRARY_ALBUMSSCRAPER, scraper->ID());
302 settings->Save();
303 // Clear all item specific settings
304 if (content == CONTENT_ARTISTS)
305 result = m_musicdatabase.SetScraperAll("musicdb://artists/", nullptr);
306 else
307 result = m_musicdatabase.SetScraperAll("musicdb://albums/", nullptr);
310 default:
311 break;
313 if (!result)
314 return false;
316 // Refresh additional information using the new settings
317 if (applyto == INFOPROVIDERAPPLYOPTIONS::INFOPROVIDER_ALLVIEW || applyto == INFOPROVIDERAPPLYOPTIONS::INFOPROVIDER_DEFAULT)
319 // Change information provider, all artists or albums
320 if (CGUIDialogYesNo::ShowAndGetInput(CVariant{20195}, CVariant{38072}))
321 OnItemInfoAll(m_vecItems->GetPath(), true);
323 else
325 // Change information provider, selected artist or album
326 if (CGUIDialogYesNo::ShowAndGetInput(CVariant{20195}, CVariant{38073}))
328 std::string itempath = StringUtils::Format("musicdb://albums/{}/", id);
329 if (content == CONTENT_ARTISTS)
330 itempath = StringUtils::Format("musicdb://artists/{}/", id);
331 OnItemInfoAll(itempath, true);
335 return true;
338 bool CGUIWindowMusicNav::OnClick(int iItem, const std::string &player /* = "" */)
340 if (iItem < 0 || iItem >= m_vecItems->Size()) return false;
342 CFileItemPtr item = m_vecItems->Get(iItem);
343 if (StringUtils::StartsWith(item->GetPath(), "musicsearch://"))
345 if (m_searchWithEdit)
346 OnSearchUpdate();
347 else
349 std::string search(GetProperty("search").asString());
350 CGUIKeyboardFactory::ShowAndGetFilter(search, true);
351 SetProperty("search", search);
353 return true;
355 if (MUSIC::IsMusicDb(*item) && !item->m_bIsFolder)
356 m_musicdatabase.SetPropertiesForFileItem(*item);
358 if (item->IsPlayList() &&
359 !CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_playlistAsFolders)
361 PlayItem(iItem);
362 return true;
364 return CGUIWindowMusicBase::OnClick(iItem, player);
367 bool CGUIWindowMusicNav::Update(const std::string &strDirectory, bool updateFilterPath /* = true */)
369 if (m_thumbLoader.IsLoading())
370 m_thumbLoader.StopThread();
372 if (CGUIWindowMusicBase::Update(strDirectory, updateFilterPath))
374 m_thumbLoader.Load(*m_unfilteredItems);
375 return true;
378 return false;
381 bool CGUIWindowMusicNav::GetDirectory(const std::string &strDirectory, CFileItemList &items)
383 if (strDirectory.empty())
384 AddSearchFolder();
386 bool bResult = CGUIWindowMusicBase::GetDirectory(strDirectory, items);
387 if (bResult)
389 if (items.IsPlayList())
390 OnRetrieveMusicInfo(items);
393 // update our content in the info manager
394 if (StringUtils::StartsWithNoCase(strDirectory, "videodb://") || IsVideoDb(items))
396 CVideoDatabaseDirectory dir;
397 VIDEODATABASEDIRECTORY::NODE_TYPE node = dir.GetDirectoryChildType(items.GetPath());
398 switch (node)
400 case VIDEODATABASEDIRECTORY::NODE_TYPE_TITLE_MUSICVIDEOS:
401 case VIDEODATABASEDIRECTORY::NODE_TYPE_RECENTLY_ADDED_MUSICVIDEOS:
402 items.SetContent("musicvideos");
403 break;
404 case VIDEODATABASEDIRECTORY::NODE_TYPE_GENRE:
405 items.SetContent("genres");
406 break;
407 case VIDEODATABASEDIRECTORY::NODE_TYPE_COUNTRY:
408 items.SetContent("countries");
409 break;
410 case VIDEODATABASEDIRECTORY::NODE_TYPE_ACTOR:
411 items.SetContent("artists");
412 break;
413 case VIDEODATABASEDIRECTORY::NODE_TYPE_DIRECTOR:
414 items.SetContent("directors");
415 break;
416 case VIDEODATABASEDIRECTORY::NODE_TYPE_STUDIO:
417 items.SetContent("studios");
418 break;
419 case VIDEODATABASEDIRECTORY::NODE_TYPE_YEAR:
420 items.SetContent("years");
421 break;
422 case VIDEODATABASEDIRECTORY::NODE_TYPE_MUSICVIDEOS_ALBUM:
423 items.SetContent("albums");
424 break;
425 case VIDEODATABASEDIRECTORY::NODE_TYPE_TAGS:
426 items.SetContent("tags");
427 break;
428 default:
429 items.SetContent("");
430 break;
433 else if (StringUtils::StartsWithNoCase(strDirectory, "musicdb://") || MUSIC::IsMusicDb(items))
435 CMusicDatabaseDirectory dir;
436 NODE_TYPE node = dir.GetDirectoryChildType(items.GetPath());
437 switch (node)
439 case NODE_TYPE_ALBUM:
440 case NODE_TYPE_ALBUM_RECENTLY_ADDED:
441 case NODE_TYPE_ALBUM_RECENTLY_PLAYED:
442 case NODE_TYPE_ALBUM_TOP100:
443 case NODE_TYPE_DISC: // ! @todo: own content type "discs"??
444 items.SetContent("albums");
445 break;
446 case NODE_TYPE_ARTIST:
447 items.SetContent("artists");
448 break;
449 case NODE_TYPE_SONG:
450 case NODE_TYPE_SONG_TOP100:
451 case NODE_TYPE_SINGLES:
452 case NODE_TYPE_ALBUM_RECENTLY_ADDED_SONGS:
453 case NODE_TYPE_ALBUM_RECENTLY_PLAYED_SONGS:
454 case NODE_TYPE_ALBUM_TOP100_SONGS:
455 items.SetContent("songs");
456 break;
457 case NODE_TYPE_GENRE:
458 items.SetContent("genres");
459 break;
460 case NODE_TYPE_SOURCE:
461 items.SetContent("sources");
462 break;
463 case NODE_TYPE_ROLE:
464 items.SetContent("roles");
465 break;
466 case NODE_TYPE_YEAR:
467 items.SetContent("years");
468 break;
469 default:
470 items.SetContent("");
471 break;
474 else if (items.IsPlayList())
475 items.SetContent("songs");
476 else if (URIUtils::PathEquals(strDirectory, "special://musicplaylists/") ||
477 URIUtils::PathEquals(strDirectory, "library://music/playlists.xml/"))
478 items.SetContent("playlists");
479 else if (URIUtils::PathEquals(strDirectory, "plugin://music/"))
480 items.SetContent("plugins");
481 else if (items.IsAddonsPath())
482 items.SetContent("addons");
483 else if (!items.IsSourcesPath() && !items.IsVirtualDirectoryRoot() &&
484 !items.IsLibraryFolder() && !items.IsPlugin() && !items.IsSmartPlayList())
485 items.SetContent("files");
487 return bResult;
490 void CGUIWindowMusicNav::UpdateButtons()
492 CGUIWindowMusicBase::UpdateButtons();
494 // Update object count
495 int iItems = m_vecItems->Size();
496 if (iItems)
498 // check for parent dir and "all" items
499 // should always be the first two items
500 for (int i = 0; i <= (iItems>=2 ? 1 : 0); i++)
502 CFileItemPtr pItem = m_vecItems->Get(i);
503 if (pItem->IsParentFolder()) iItems--;
504 if (StringUtils::StartsWith(pItem->GetPath(), "/-1/")) iItems--;
506 // or the last item
507 if (m_vecItems->Size() > 2 &&
508 StringUtils::StartsWith(m_vecItems->Get(m_vecItems->Size()-1)->GetPath(), "/-1/"))
509 iItems--;
511 std::string items = StringUtils::Format("{} {}", iItems, g_localizeStrings.Get(127));
512 SET_CONTROL_LABEL(CONTROL_LABELFILES, items);
514 // set the filter label
515 std::string strLabel;
517 // "Playlists"
518 if (m_vecItems->IsPath("special://musicplaylists/"))
519 strLabel = g_localizeStrings.Get(136);
520 // "{Playlist Name}"
521 else if (m_vecItems->IsPlayList())
523 // get playlist name from path
524 std::string strDummy;
525 URIUtils::Split(m_vecItems->GetPath(), strDummy, strLabel);
527 // everything else is from a musicdb:// path
528 else
530 CMusicDatabaseDirectory dir;
531 dir.GetLabel(m_vecItems->GetPath(), strLabel);
534 SET_CONTROL_LABEL(CONTROL_FILTER, strLabel);
536 SET_CONTROL_SELECTED(GetID(),CONTROL_BTNPARTYMODE, g_partyModeManager.IsEnabled());
538 CONTROL_ENABLE_ON_CONDITION(CONTROL_UPDATE_LIBRARY, !m_vecItems->IsAddonsPath() && !m_vecItems->IsPlugin() && !m_vecItems->IsScript());
541 void CGUIWindowMusicNav::PlayItem(int iItem)
543 // unlike additemtoplaylist, we need to check the items here
544 // before calling it since the current playlist will be stopped
545 // and cleared!
547 // root is not allowed
548 if (m_vecItems->IsVirtualDirectoryRoot() && !m_vecItems->Get(iItem)->IsDVD())
549 return;
551 CGUIWindowMusicBase::PlayItem(iItem);
554 void CGUIWindowMusicNav::OnWindowLoaded()
556 const CGUIControl *control = GetControl(CONTROL_SEARCH);
557 m_searchWithEdit = (control && control->GetControlType() == CGUIControl::GUICONTROL_EDIT);
559 CGUIWindowMusicBase::OnWindowLoaded();
561 if (m_searchWithEdit)
563 SendMessage(GUI_MSG_SET_TYPE, CONTROL_SEARCH, CGUIEditControl::INPUT_TYPE_SEARCH);
564 SET_CONTROL_LABEL2(CONTROL_SEARCH, GetProperty("search").asString());
568 void CGUIWindowMusicNav::GetContextButtons(int itemNumber, CContextButtons &buttons)
570 CFileItemPtr item;
571 if (itemNumber >= 0 && itemNumber < m_vecItems->Size())
572 item = m_vecItems->Get(itemNumber);
573 if (item)
575 const std::shared_ptr<CProfileManager> profileManager = CServiceBroker::GetSettingsComponent()->GetProfileManager();
577 // are we in the playlists location?
578 bool inPlaylists = m_vecItems->IsPath(CUtil::MusicPlaylistsLocation()) ||
579 m_vecItems->IsPath("special://musicplaylists/");
581 if (m_vecItems->IsPath("sources://music/"))
583 // get the usual music shares, and anything for all media windows
584 CGUIDialogContextMenu::GetContextButtons("music", item, buttons);
585 #ifdef HAS_OPTICAL_DRIVE
586 // enable Rip CD an audio disc
587 if (CServiceBroker::GetMediaManager().IsDiscInDrive() && MUSIC::IsCDDA(*item))
589 // those cds can also include Audio Tracks: CDExtra and MixedMode!
590 MEDIA_DETECT::CCdInfo* pCdInfo = CServiceBroker::GetMediaManager().GetCdInfo();
591 if (pCdInfo->IsAudio(1) || pCdInfo->IsCDExtra(1) || pCdInfo->IsMixedMode(1))
593 if (CServiceBroker::GetJobManager()->IsProcessing("cdrip"))
594 buttons.Add(CONTEXT_BUTTON_CANCEL_RIP_CD, 14100);
595 else
596 buttons.Add(CONTEXT_BUTTON_RIP_CD, 600);
599 #endif
600 // Scan button for music sources except ".." and "Add music source" items
601 if (!item->IsPath("add") && !item->IsParentFolder() &&
602 (profileManager->GetCurrentProfile().canWriteDatabases() || g_passwordManager.bMasterUser))
604 buttons.Add(CONTEXT_BUTTON_SCAN, 13352);
606 CGUIMediaWindow::GetContextButtons(itemNumber, buttons);
608 else
610 CGUIWindowMusicBase::GetContextButtons(itemNumber, buttons);
612 // Scan button for real folders containing files when navigating within music sources.
613 // Blacklist the bespoke Kodi protocols as to many valid external protocols to whitelist
614 if (m_vecItems->GetContent() == "files" && // Other content not scanned to library
615 !inPlaylists &&
616 !NETWORK::IsInternetStream(*m_vecItems) && // Not playlists locations or streams
617 !item->IsPath("add") && !item->IsParentFolder() && // Not ".." and "Add items
618 item->m_bIsFolder && // Folders only, but playlists can be folders too
619 !URIUtils::IsLibraryContent(item->GetPath()) && // database folder or .xsp files
620 !URIUtils::IsSpecial(item->GetPath()) && !item->IsPlugin() && !item->IsScript() &&
621 !item->IsPlayList() && // .m3u etc. that as flagged as folders when playlistasfolders
622 !StringUtils::StartsWithNoCase(item->GetPath(), "addons://") &&
623 (profileManager->GetCurrentProfile().canWriteDatabases() ||
624 g_passwordManager.bMasterUser))
626 buttons.Add(CONTEXT_BUTTON_SCAN, 13352);
629 CMusicDatabaseDirectory dir;
631 if (!item->IsParentFolder() && !dir.IsAllItem(item->GetPath()))
633 if (item->m_bIsFolder && !IsVideoDb(*item) && !item->IsPlugin() &&
634 !StringUtils::StartsWithNoCase(item->GetPath(), "musicsearch://"))
636 if (item->IsAlbum())
637 // enable query all albums button only in album view
638 buttons.Add(CONTEXT_BUTTON_INFO_ALL, 20059);
639 else if (dir.IsArtistDir(item->GetPath()))
640 // enable query all artist button only in artist view
641 buttons.Add(CONTEXT_BUTTON_INFO_ALL, 21884);
643 //Set default or clear default
644 NODE_TYPE nodetype = dir.GetDirectoryType(item->GetPath());
645 if (!inPlaylists &&
646 (nodetype == NODE_TYPE_ROOT ||
647 nodetype == NODE_TYPE_OVERVIEW ||
648 nodetype == NODE_TYPE_TOP100))
650 const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings();
651 if (!item->IsPath(settings->GetString(CSettings::SETTING_MYMUSIC_DEFAULTLIBVIEW)))
652 buttons.Add(CONTEXT_BUTTON_SET_DEFAULT, 13335); // set default
653 if (!settings->GetString(CSettings::SETTING_MYMUSIC_DEFAULTLIBVIEW).empty())
654 buttons.Add(CONTEXT_BUTTON_CLEAR_DEFAULT, 13403); // clear default
657 //Change information provider
658 if (StringUtils::EqualsNoCase(m_vecItems->GetContent(), "albums") ||
659 StringUtils::EqualsNoCase(m_vecItems->GetContent(), "artists"))
661 // we allow the user to set information provider for albums and artists
662 buttons.Add(CONTEXT_BUTTON_SET_CONTENT, 20195);
665 if (item->HasMusicInfoTag() && !item->GetMusicInfoTag()->GetArtistString().empty())
667 CVideoDatabase database;
668 database.Open();
669 if (database.GetMatchingMusicVideo(item->GetMusicInfoTag()->GetArtistString()) > -1)
670 buttons.Add(CONTEXT_BUTTON_GO_TO_ARTIST, 20400);
672 if (item->HasMusicInfoTag() && !item->GetMusicInfoTag()->GetArtistString().empty() &&
673 !item->GetMusicInfoTag()->GetAlbum().empty() &&
674 !item->GetMusicInfoTag()->GetTitle().empty())
676 CVideoDatabase database;
677 database.Open();
678 if (database.GetMatchingMusicVideo(item->GetMusicInfoTag()->GetArtistString(), item->GetMusicInfoTag()->GetAlbum(), item->GetMusicInfoTag()->GetTitle()) > -1)
679 buttons.Add(CONTEXT_BUTTON_PLAY_OTHER, 20401);
681 if (item->HasVideoInfoTag() && !item->m_bIsFolder)
683 if ((profileManager->GetCurrentProfile().canWriteDatabases() || g_passwordManager.bMasterUser) && !item->IsPlugin())
685 buttons.Add(CONTEXT_BUTTON_RENAME, 16105);
686 buttons.Add(CONTEXT_BUTTON_DELETE, 646);
689 if (inPlaylists && URIUtils::GetFileName(item->GetPath()) != "PartyMode.xsp"
690 && (item->IsPlayList() || item->IsSmartPlayList()))
691 buttons.Add(CONTEXT_BUTTON_DELETE, 117);
693 if (!item->IsReadOnly() && CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool("filelists.allowfiledeletion"))
695 buttons.Add(CONTEXT_BUTTON_DELETE, 117);
696 buttons.Add(CONTEXT_BUTTON_RENAME, 118);
701 // noncontextual buttons
703 CGUIWindowMusicBase::GetNonContextButtons(buttons);
706 bool CGUIWindowMusicNav::OnPopupMenu(int iItem)
708 if (iItem >= 0 && iItem < m_vecItems->Size())
710 const auto item = m_vecItems->Get(iItem);
711 item->SetProperty("CheckAutoPlayNextItem", true);
714 return CGUIWindowMusicBase::OnPopupMenu(iItem);
717 bool CGUIWindowMusicNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
719 CFileItemPtr item;
720 if (itemNumber >= 0 && itemNumber < m_vecItems->Size())
721 item = m_vecItems->Get(itemNumber);
723 switch (button)
725 case CONTEXT_BUTTON_INFO:
727 if (!IsVideoDb(*item))
728 return CGUIWindowMusicBase::OnContextButton(itemNumber,button);
730 // music videos - artists
731 if (StringUtils::StartsWithNoCase(item->GetPath(), "videodb://musicvideos/artists/"))
733 int idArtist = m_musicdatabase.GetArtistByName(item->GetLabel());
734 if (idArtist == -1)
735 return false;
736 std::string path = StringUtils::Format("musicdb://artists/{}/", idArtist);
737 CArtist artist;
738 m_musicdatabase.GetArtist(idArtist, artist, false);
739 *item = CFileItem(artist);
740 item->SetPath(path);
741 CGUIWindowMusicBase::OnContextButton(itemNumber,button);
742 Refresh();
743 m_viewControl.SetSelectedItem(itemNumber);
744 return true;
747 // music videos - albums
748 if (StringUtils::StartsWithNoCase(item->GetPath(), "videodb://musicvideos/albums/"))
750 int idAlbum = m_musicdatabase.GetAlbumByName(item->GetLabel());
751 if (idAlbum == -1)
752 return false;
753 std::string path = StringUtils::Format("musicdb://albums/{}/", idAlbum);
754 CAlbum album;
755 m_musicdatabase.GetAlbum(idAlbum, album, false);
756 *item = CFileItem(path,album);
757 item->SetPath(path);
758 CGUIWindowMusicBase::OnContextButton(itemNumber,button);
759 Refresh();
760 m_viewControl.SetSelectedItem(itemNumber);
761 return true;
764 if (item->HasVideoInfoTag() && !item->GetVideoInfoTag()->m_strTitle.empty())
766 CGUIDialogVideoInfo::ShowFor(*item);
767 Refresh();
769 return true;
772 case CONTEXT_BUTTON_INFO_ALL:
773 OnItemInfoAll(m_vecItems->GetPath());
774 return true;
776 case CONTEXT_BUTTON_SET_DEFAULT:
778 const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings();
779 settings->SetString(CSettings::SETTING_MYMUSIC_DEFAULTLIBVIEW, item->GetPath());
780 settings->Save();
781 return true;
784 case CONTEXT_BUTTON_CLEAR_DEFAULT:
786 const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings();
787 settings->SetString(CSettings::SETTING_MYMUSIC_DEFAULTLIBVIEW, "");
788 settings->Save();
789 return true;
792 case CONTEXT_BUTTON_GO_TO_ARTIST:
794 std::string strPath;
795 CVideoDatabase database;
796 database.Open();
797 strPath = StringUtils::Format(
798 "videodb://musicvideos/artists/{}/",
799 database.GetMatchingMusicVideo(item->GetMusicInfoTag()->GetArtistString()));
800 CServiceBroker::GetGUI()->GetWindowManager().ActivateWindow(WINDOW_VIDEO_NAV,strPath);
801 return true;
804 case CONTEXT_BUTTON_PLAY_OTHER:
806 CVideoDatabase database;
807 database.Open();
808 CVideoInfoTag details;
809 database.GetMusicVideoInfo("", details, database.GetMatchingMusicVideo(item->GetMusicInfoTag()->GetArtistString(), item->GetMusicInfoTag()->GetAlbum(), item->GetMusicInfoTag()->GetTitle()));
810 CServiceBroker::GetAppMessenger()->PostMsg(TMSG_MEDIA_PLAY, 0, 0,
811 static_cast<void*>(new CFileItem(details)));
812 return true;
815 case CONTEXT_BUTTON_RENAME:
816 if (!IsVideoDb(*item) && !item->IsReadOnly())
817 OnRenameItem(itemNumber);
819 CGUIDialogVideoInfo::UpdateVideoItemTitle(item);
820 CUtil::DeleteVideoDatabaseDirectoryCache();
821 Refresh();
822 return true;
824 case CONTEXT_BUTTON_DELETE:
825 if (item->IsPlayList() || item->IsSmartPlayList())
827 item->m_bIsFolder = false;
828 CGUIComponent *gui = CServiceBroker::GetGUI();
829 if (gui && gui->ConfirmDelete(item->GetPath()))
830 CFileUtils::DeleteItem(item);
832 else if (!IsVideoDb(*item))
833 OnDeleteItem(itemNumber);
834 else
836 CGUIDialogVideoInfo::DeleteVideoItemFromDatabase(item);
837 CUtil::DeleteVideoDatabaseDirectoryCache();
839 Refresh();
840 return true;
842 case CONTEXT_BUTTON_SET_CONTENT:
843 return ManageInfoProvider(item);
845 default:
846 break;
849 return CGUIWindowMusicBase::OnContextButton(itemNumber, button);
852 bool CGUIWindowMusicNav::GetSongsFromPlayList(const std::string& strPlayList, CFileItemList &items)
854 std::string strParentPath=m_history.GetParentPath();
856 if (m_guiState.get() && !m_guiState->HideParentDirItems())
858 CFileItemPtr pItem(new CFileItem(".."));
859 pItem->SetPath(strParentPath);
860 items.Add(pItem);
863 items.SetPath(strPlayList);
864 CLog::Log(LOGDEBUG, "CGUIWindowMusicNav, opening playlist [{}]", strPlayList);
866 std::unique_ptr<PLAYLIST::CPlayList> pPlayList(PLAYLIST::CPlayListFactory::Create(strPlayList));
867 if (nullptr != pPlayList)
869 // load it
870 if (!pPlayList->Load(strPlayList))
872 HELPERS::ShowOKDialogText(CVariant{6}, CVariant{477});
873 return false; //hmmm unable to load playlist?
875 PLAYLIST::CPlayList playlist = *pPlayList;
876 // convert playlist items to songs
877 for (int i = 0; i < playlist.size(); ++i)
879 items.Add(playlist[i]);
883 return true;
886 void CGUIWindowMusicNav::OnSearchUpdate()
888 std::string search(CURL::Encode(GetProperty("search").asString()));
889 if (!search.empty())
891 std::string path = "musicsearch://" + search + "/";
892 m_history.ClearSearchHistory();
893 Update(path);
895 else if (m_vecItems->IsVirtualDirectoryRoot())
897 Update("");
901 void CGUIWindowMusicNav::FrameMove()
903 static const int search_timeout = 2000;
904 // update our searching
905 if (m_searchTimer.IsRunning() && m_searchTimer.GetElapsedMilliseconds() > search_timeout)
907 m_searchTimer.Stop();
908 OnSearchUpdate();
910 CGUIWindowMusicBase::FrameMove();
913 void CGUIWindowMusicNav::AddSearchFolder()
915 // we use a general viewstate (and not our member) here as our
916 // current viewstate may be specific to some other folder, and
917 // we know we're in the root here
918 CFileItemList items;
919 CGUIViewState* viewState = CGUIViewState::GetViewState(GetID(), items);
920 if (viewState)
922 // add our remove the musicsearch source
923 VECSOURCES &sources = viewState->GetSources();
924 bool haveSearchSource = false;
925 bool needSearchSource = !GetProperty("search").empty() || !m_searchWithEdit; // we always need it if we don't have the edit control
926 for (IVECSOURCES it = sources.begin(); it != sources.end(); ++it)
928 CMediaSource& share = *it;
929 if (share.strPath == "musicsearch://")
931 haveSearchSource = true;
932 if (!needSearchSource)
933 { // remove it
934 sources.erase(it);
935 break;
939 if (!haveSearchSource && needSearchSource)
941 // add search share
942 CMediaSource share;
943 share.strName=g_localizeStrings.Get(137); // Search
944 share.strPath = "musicsearch://";
945 share.m_iDriveType = CMediaSource::SOURCE_TYPE_LOCAL;
946 sources.push_back(share);
948 m_rootDir.SetSources(sources);
949 delete viewState;
953 std::string CGUIWindowMusicNav::GetStartFolder(const std::string &dir)
955 static const auto map = std::map<std::string, std::string>{
956 {"albums", "musicdb://albums/"},
957 {"artists", "musicdb://artists/"},
958 {"boxsets", "musicdb://boxsets/"},
959 {"compilations", "musicdb://compilations/"},
960 {"files", "sources://music/"},
961 {"genres", "musicdb://genres/"},
962 {"recentlyaddedalbums", "musicdb://recentlyaddedalbums/"},
963 {"recentlyplayedalbums", "musicdb://recentlyplayedalbums/"},
964 {"singles", "musicdb://singles/"},
965 {"songs", "musicdb://songs/"},
966 {"top100", "musicdb://top100/"},
967 {"top100albums", "musicdb://top100/albums/"},
968 {"top100songs", "musicdb://top100/songs/"},
969 {"years", "musicdb://years/"},
972 const auto it = map.find(StringUtils::ToLower(dir));
973 if (it == map.end())
974 return CGUIWindowMusicBase::GetStartFolder(dir);
975 else
976 return it->second;