Merge pull request #25808 from CastagnaIT/fix_url_parse
[xbmc.git] / xbmc / profiles / ProfileManager.cpp
blob8b181dd9ddde927297be0300650aa9f0b4c652f0
1 /*
2 * Copyright (C) 2013-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 "ProfileManager.h"
11 #include "ContextMenuManager.h" //! @todo Remove me
12 #include "DatabaseManager.h"
13 #include "FileItem.h"
14 #include "GUIInfoManager.h"
15 #include "GUIPassword.h"
16 #include "PasswordManager.h"
17 #include "PlayListPlayer.h" //! @todo Remove me
18 #include "ServiceBroker.h"
19 #include "Util.h"
20 #include "addons/AddonManager.h" //! @todo Remove me
21 #include "addons/Service.h" //! @todo Remove me
22 #include "addons/Skin.h"
23 #include "application/Application.h" //! @todo Remove me
24 #include "application/ApplicationComponents.h"
25 #include "application/ApplicationPowerHandling.h"
26 #include "dialogs/GUIDialogKaiToast.h"
27 #include "dialogs/GUIDialogYesNo.h"
28 #include "events/EventLog.h"
29 #include "events/EventLogManager.h"
30 #include "favourites/FavouritesService.h" //! @todo Remove me
31 #include "filesystem/Directory.h"
32 #include "filesystem/DirectoryCache.h"
33 #include "filesystem/File.h"
34 #include "filesystem/SpecialProtocol.h"
35 #include "guilib/GUIComponent.h"
36 #include "guilib/GUIWindowManager.h"
37 #include "guilib/LocalizeStrings.h"
38 #include "guilib/StereoscopicsManager.h" //! @todo Remove me
39 #include "input/InputManager.h"
40 #include "interfaces/json-rpc/JSONRPC.h" //! @todo Remove me
41 #include "music/MusicLibraryQueue.h"
42 #include "network/Network.h" //! @todo Remove me
43 #include "network/NetworkServices.h" //! @todo Remove me
44 #include "pvr/PVRManager.h" //! @todo Remove me
45 #include "settings/Settings.h"
46 #include "settings/SettingsComponent.h"
47 #include "settings/lib/SettingsManager.h"
48 #if !defined(TARGET_WINDOWS) && defined(HAS_OPTICAL_DRIVE)
49 #include "storage/DetectDVDType.h"
50 #endif
51 #include "threads/SingleLock.h"
52 #include "utils/FileUtils.h"
53 #include "utils/StringUtils.h"
54 #include "utils/URIUtils.h"
55 #include "utils/Variant.h"
56 #include "utils/XMLUtils.h"
57 #include "utils/log.h"
58 #include "video/VideoLibraryQueue.h" //! @todo Remove me
59 #include "weather/WeatherManager.h" //! @todo Remove me
61 #include <algorithm>
62 #include <memory>
63 #include <mutex>
64 #include <string>
65 #include <vector>
67 //! @todo
68 //! eventually the profile should dictate where special://masterprofile/ is
69 //! but for now it makes sense to leave all the profile settings in a user
70 //! writeable location like special://masterprofile/
71 #define PROFILES_FILE "special://masterprofile/profiles.xml"
73 #define XML_PROFILES "profiles"
74 #define XML_AUTO_LOGIN "autologin"
75 #define XML_LAST_LOADED "lastloaded"
76 #define XML_LOGIN_SCREEN "useloginscreen"
77 #define XML_NEXTID "nextIdProfile"
78 #define XML_PROFILE "profile"
80 using namespace KODI;
81 using namespace XFILE;
83 static CProfile EmptyProfile;
85 CProfileManager::CProfileManager() : m_eventLogs(new CEventLogManager)
89 CProfileManager::~CProfileManager() = default;
91 void CProfileManager::Initialize(const std::shared_ptr<CSettings>& settings)
93 m_settings = settings;
95 if (m_settings->IsLoaded())
96 OnSettingsLoaded();
98 m_settings->GetSettingsManager()->RegisterSettingsHandler(this);
100 std::set<std::string> settingSet = {
101 CSettings::SETTING_EVENTLOG_SHOW
104 m_settings->GetSettingsManager()->RegisterCallback(this, settingSet);
107 void CProfileManager::Uninitialize()
109 m_settings->GetSettingsManager()->UnregisterCallback(this);
110 m_settings->GetSettingsManager()->UnregisterSettingsHandler(this);
113 void CProfileManager::OnSettingsLoaded()
115 // check them all
116 std::string strDir = m_settings->GetString(CSettings::SETTING_SYSTEM_PLAYLISTSPATH);
117 if (strDir == "set default" || strDir.empty())
119 strDir = "special://profile/playlists/";
120 m_settings->SetString(CSettings::SETTING_SYSTEM_PLAYLISTSPATH, strDir);
123 CDirectory::Create(strDir);
124 CDirectory::Create(URIUtils::AddFileToFolder(strDir,"music"));
125 CDirectory::Create(URIUtils::AddFileToFolder(strDir,"video"));
126 CDirectory::Create(URIUtils::AddFileToFolder(strDir,"mixed"));
129 void CProfileManager::OnSettingsSaved() const
131 // save mastercode
132 Save();
135 void CProfileManager::OnSettingsCleared()
137 Clear();
140 bool CProfileManager::Load()
142 bool ret = true;
143 const std::string file = PROFILES_FILE;
145 std::unique_lock<CCriticalSection> lock(m_critical);
147 // clear out our profiles
148 m_profiles.clear();
150 if (CFile::Exists(file))
152 CXBMCTinyXML profilesDoc;
153 if (profilesDoc.LoadFile(file))
155 const TiXmlElement *rootElement = profilesDoc.RootElement();
156 if (rootElement && StringUtils::EqualsNoCase(rootElement->Value(), XML_PROFILES))
158 XMLUtils::GetUInt(rootElement, XML_LAST_LOADED, m_lastUsedProfile);
159 XMLUtils::GetBoolean(rootElement, XML_LOGIN_SCREEN, m_usingLoginScreen);
160 XMLUtils::GetInt(rootElement, XML_AUTO_LOGIN, m_autoLoginProfile);
161 XMLUtils::GetInt(rootElement, XML_NEXTID, m_nextProfileId);
163 std::string defaultDir("special://home/userdata");
164 if (!CDirectory::Exists(defaultDir))
165 defaultDir = "special://xbmc/userdata";
167 const TiXmlElement* pProfile = rootElement->FirstChildElement(XML_PROFILE);
168 while (pProfile)
170 CProfile profile(defaultDir);
171 profile.Load(pProfile, GetNextProfileId());
172 AddProfile(profile);
174 pProfile = pProfile->NextSiblingElement(XML_PROFILE);
177 else
179 CLog::Log(LOGERROR, "CProfileManager: error loading {}, no <profiles> node", file);
180 ret = false;
183 else
185 CLog::Log(LOGERROR, "CProfileManager: error loading {}, Line {}\n{}", file,
186 profilesDoc.ErrorRow(), profilesDoc.ErrorDesc());
187 ret = false;
190 if (!ret)
192 CLog::Log(LOGERROR,
193 "Failed to load profile - might be corrupted - falling back to master profile");
194 m_profiles.clear();
195 CFile::Delete(file);
197 ret = true;
200 if (m_profiles.empty())
201 { // add the master user
202 CProfile profile("special://masterprofile/", "Master user", 0);
203 AddProfile(profile);
206 // check the validity of the previous profile index
207 if (m_lastUsedProfile >= m_profiles.size())
208 m_lastUsedProfile = 0;
210 SetCurrentProfileId(m_lastUsedProfile);
212 // check the validity of the auto login profile index
213 if (m_autoLoginProfile < -1 || m_autoLoginProfile >= (int)m_profiles.size())
214 m_autoLoginProfile = -1;
215 else if (m_autoLoginProfile >= 0)
216 SetCurrentProfileId(m_autoLoginProfile);
218 // the login screen runs as the master profile, so if we're using this, we need to ensure
219 // we switch to the master profile
220 if (m_usingLoginScreen)
221 SetCurrentProfileId(0);
223 return ret;
226 bool CProfileManager::Save() const
228 const std::string file = PROFILES_FILE;
230 std::unique_lock<CCriticalSection> lock(m_critical);
232 CXBMCTinyXML xmlDoc;
233 TiXmlElement xmlRootElement(XML_PROFILES);
234 TiXmlNode *pRoot = xmlDoc.InsertEndChild(xmlRootElement);
235 if (pRoot == nullptr)
236 return false;
238 XMLUtils::SetInt(pRoot, XML_LAST_LOADED, m_currentProfile);
239 XMLUtils::SetBoolean(pRoot, XML_LOGIN_SCREEN, m_usingLoginScreen);
240 XMLUtils::SetInt(pRoot, XML_AUTO_LOGIN, m_autoLoginProfile);
241 XMLUtils::SetInt(pRoot, XML_NEXTID, m_nextProfileId);
243 for (const auto& profile : m_profiles)
244 profile.Save(pRoot);
246 // save the file
247 return xmlDoc.SaveFile(file);
250 void CProfileManager::Clear()
252 std::unique_lock<CCriticalSection> lock(m_critical);
253 m_usingLoginScreen = false;
254 m_profileLoadedForLogin = false;
255 m_previousProfileLoadedForLogin = false;
256 m_lastUsedProfile = 0;
257 m_nextProfileId = 0;
258 SetCurrentProfileId(0);
259 m_profiles.clear();
262 void CProfileManager::PrepareLoadProfile(unsigned int profileIndex)
264 CContextMenuManager &contextMenuManager = CServiceBroker::GetContextMenuManager();
265 ADDON::CServiceAddonManager &serviceAddons = CServiceBroker::GetServiceAddons();
266 PVR::CPVRManager &pvrManager = CServiceBroker::GetPVRManager();
267 CNetworkBase &networkManager = CServiceBroker::GetNetwork();
269 contextMenuManager.Deinit();
271 serviceAddons.Stop();
273 // stop PVR related services
274 pvrManager.Stop();
276 if (profileIndex != 0 || !IsMasterProfile())
277 networkManager.NetworkMessage(CNetworkBase::SERVICES_DOWN, 1);
280 bool CProfileManager::LoadProfile(unsigned int index)
282 PrepareLoadProfile(index);
284 if (index == 0 && IsMasterProfile())
286 CGUIWindow* pWindow = CServiceBroker::GetGUI()->GetWindowManager().GetWindow(WINDOW_HOME);
287 if (pWindow)
288 pWindow->ResetControlStates();
290 UpdateCurrentProfileDate();
291 FinalizeLoadProfile();
293 return true;
296 std::unique_lock<CCriticalSection> lock(m_critical);
297 // check if the index is valid or not
298 if (index >= m_profiles.size())
299 return false;
301 // check if the profile is already active
302 if (m_currentProfile == index)
303 return true;
305 // save any settings of the currently used skin but only if the (master)
306 // profile hasn't just been loaded as a temporary profile for login
307 if (g_SkinInfo != nullptr && !m_previousProfileLoadedForLogin)
308 g_SkinInfo->SaveSettings();
310 // @todo: why is m_settings not used here?
311 const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings();
313 // unload any old settings
314 settings->Unload();
316 SetCurrentProfileId(index);
317 m_previousProfileLoadedForLogin = false;
319 // load the new settings
320 if (!settings->Load())
322 CLog::Log(LOGFATAL, "CProfileManager: unable to load settings for profile \"{}\"",
323 m_profiles.at(index).getName());
324 return false;
326 settings->SetLoaded();
328 CreateProfileFolders();
330 CServiceBroker::GetDatabaseManager().Initialize();
331 CServiceBroker::GetInputManager().LoadKeymaps();
333 CServiceBroker::GetInputManager().SetMouseEnabled(settings->GetBool(CSettings::SETTING_INPUT_ENABLEMOUSE));
335 CGUIComponent* gui = CServiceBroker::GetGUI();
336 if (gui)
338 CGUIInfoManager& infoMgr = gui->GetInfoManager();
339 infoMgr.ResetCache();
340 infoMgr.GetInfoProviders().GetGUIControlsInfoProvider().ResetContainerMovingCache();
341 infoMgr.GetInfoProviders().GetLibraryInfoProvider().ResetLibraryBools();
344 if (m_currentProfile != 0)
346 CXBMCTinyXML doc;
347 if (doc.LoadFile(URIUtils::AddFileToFolder(GetUserDataFolder(), "guisettings.xml")))
349 settings->LoadSetting(doc.RootElement(), CSettings::SETTING_MASTERLOCK_MAXRETRIES);
350 settings->LoadSetting(doc.RootElement(), CSettings::SETTING_MASTERLOCK_STARTUPLOCK);
354 CPasswordManager::GetInstance().Clear();
356 // to set labels - shares are reloaded
357 #if !defined(TARGET_WINDOWS) && defined(HAS_OPTICAL_DRIVE)
358 MEDIA_DETECT::CDetectDVDMedia::UpdateState();
359 #endif
361 // init windows
362 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_WINDOW_RESET);
363 CServiceBroker::GetGUI()->GetWindowManager().SendMessage(msg);
365 CUtil::DeleteDirectoryCache();
366 g_directoryCache.Clear();
368 lock.unlock();
370 UpdateCurrentProfileDate();
371 FinalizeLoadProfile();
373 m_profileLoadedForLogin = false;
375 return true;
378 void CProfileManager::FinalizeLoadProfile()
380 CContextMenuManager &contextMenuManager = CServiceBroker::GetContextMenuManager();
381 ADDON::CServiceAddonManager &serviceAddons = CServiceBroker::GetServiceAddons();
382 PVR::CPVRManager &pvrManager = CServiceBroker::GetPVRManager();
383 CNetworkBase &networkManager = CServiceBroker::GetNetwork();
384 ADDON::CAddonMgr &addonManager = CServiceBroker::GetAddonMgr();
385 CWeatherManager &weatherManager = CServiceBroker::GetWeatherManager();
386 CFavouritesService &favouritesManager = CServiceBroker::GetFavouritesService();
387 PLAYLIST::CPlayListPlayer &playlistManager = CServiceBroker::GetPlaylistPlayer();
388 CStereoscopicsManager &stereoscopicsManager = CServiceBroker::GetGUI()->GetStereoscopicsManager();
390 if (m_lastUsedProfile != m_currentProfile)
392 playlistManager.ClearPlaylist(PLAYLIST::Id::TYPE_VIDEO);
393 playlistManager.ClearPlaylist(PLAYLIST::Id::TYPE_MUSIC);
394 playlistManager.SetCurrentPlaylist(PLAYLIST::Id::TYPE_NONE);
397 networkManager.NetworkMessage(CNetworkBase::SERVICES_UP, 1);
399 // reload the add-ons, or we will first load all add-ons from the master account without checking disabled status
400 addonManager.ReInit();
402 // let CApplication know that we are logging into a new profile
403 g_application.SetLoggingIn(true);
405 if (!g_application.LoadLanguage(true))
407 CLog::Log(LOGFATAL, "Unable to load language for profile \"{}\"",
408 GetCurrentProfile().getName());
409 return;
412 weatherManager.Refresh();
414 JSONRPC::CJSONRPC::Initialize();
416 // Restart context menu manager
417 contextMenuManager.Init();
419 // Restart PVR services if we are not just loading the master profile for the login screen
420 if (m_previousProfileLoadedForLogin || m_currentProfile != 0 || m_lastUsedProfile == 0)
421 pvrManager.Init();
423 favouritesManager.ReInit(GetProfileUserDataFolder());
425 // Start these operations only when a profile is loaded, not on the login screen
426 if (!m_profileLoadedForLogin || (m_profileLoadedForLogin && m_lastUsedProfile == 0))
428 serviceAddons.Start();
429 g_application.UpdateLibraries();
432 stereoscopicsManager.Initialize();
434 // Load initial window
435 int firstWindow = g_SkinInfo->GetFirstWindow();
437 CServiceBroker::GetGUI()->GetWindowManager().ChangeActiveWindow(firstWindow);
439 //the user interfaces has been fully initialized, let everyone know
440 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, WINDOW_SETTINGS_PROFILES, 0, GUI_MSG_UI_READY);
441 CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg);
444 void CProfileManager::LogOff()
446 CNetworkBase &networkManager = CServiceBroker::GetNetwork();
448 g_application.StopPlaying();
450 if (CMusicLibraryQueue::GetInstance().IsScanningLibrary())
451 CMusicLibraryQueue::GetInstance().StopLibraryScanning();
453 if (CVideoLibraryQueue::GetInstance().IsRunning())
454 CVideoLibraryQueue::GetInstance().CancelAllJobs();
456 // Stop PVR services
457 CServiceBroker::GetPVRManager().Stop();
459 networkManager.NetworkMessage(CNetworkBase::SERVICES_DOWN, 1);
461 LoadMasterProfileForLogin();
463 g_passwordManager.bMasterUser = false;
465 auto& components = CServiceBroker::GetAppComponents();
466 const auto appPower = components.GetComponent<CApplicationPowerHandling>();
467 appPower->WakeUpScreenSaverAndDPMS();
468 CServiceBroker::GetGUI()->GetWindowManager().ActivateWindow(WINDOW_LOGIN_SCREEN, {}, false);
470 if (!CServiceBroker::GetNetwork().GetServices().StartEventServer()) // event server could be needed in some situations
471 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, g_localizeStrings.Get(33102), g_localizeStrings.Get(33100));
474 bool CProfileManager::DeleteProfile(unsigned int index)
476 std::unique_lock<CCriticalSection> lock(m_critical);
477 const CProfile *profile = GetProfile(index);
478 if (profile == NULL)
479 return false;
481 CGUIDialogYesNo* dlgYesNo = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogYesNo>(WINDOW_DIALOG_YES_NO);
482 if (dlgYesNo == NULL)
483 return false;
485 const std::string& str = g_localizeStrings.Get(13201);
486 dlgYesNo->SetHeading(CVariant{13200});
487 dlgYesNo->SetLine(0, CVariant{StringUtils::Format(str, profile->getName())});
488 dlgYesNo->SetLine(1, CVariant{""});
489 dlgYesNo->SetLine(2, CVariant{""});
490 dlgYesNo->Open();
492 if (!dlgYesNo->IsConfirmed())
493 return false;
495 // fall back to master profile if necessary
496 if ((int)index == m_autoLoginProfile)
497 m_autoLoginProfile = 0;
499 // delete profile
500 std::string strDirectory = profile->getDirectory();
501 m_profiles.erase(m_profiles.begin() + index);
503 // fall back to master profile if necessary
504 if (index == m_currentProfile)
506 LoadProfile(0);
507 m_settings->Save();
510 CFileItemPtr item =
511 std::make_shared<CFileItem>(URIUtils::AddFileToFolder(GetUserDataFolder(), strDirectory));
512 item->SetPath(URIUtils::AddFileToFolder(GetUserDataFolder(), strDirectory + "/"));
513 item->m_bIsFolder = true;
514 item->Select(true);
516 CGUIComponent *gui = CServiceBroker::GetGUI();
517 if (gui && gui->ConfirmDelete(item->GetPath()))
518 CFileUtils::DeleteItem(item);
520 return Save();
523 void CProfileManager::CreateProfileFolders()
525 CDirectory::Create(GetDatabaseFolder());
526 CDirectory::Create(GetCDDBFolder());
527 CDirectory::Create(GetLibraryFolder());
529 // create Thumbnails/*
530 CDirectory::Create(GetThumbnailsFolder());
531 CDirectory::Create(GetVideoThumbFolder());
532 CDirectory::Create(GetBookmarksThumbFolder());
533 CDirectory::Create(GetSavestatesFolder());
534 for (size_t hex = 0; hex < 16; hex++)
535 CDirectory::Create(
536 URIUtils::AddFileToFolder(GetThumbnailsFolder(), StringUtils::Format("{:x}", hex)));
538 CDirectory::Create("special://profile/addon_data");
539 CDirectory::Create("special://profile/keymaps");
542 const CProfile& CProfileManager::GetMasterProfile() const
544 std::unique_lock<CCriticalSection> lock(m_critical);
545 if (!m_profiles.empty())
546 return m_profiles[0];
548 CLog::Log(LOGERROR, "{}: master profile doesn't exist", __FUNCTION__);
549 return EmptyProfile;
552 const CProfile& CProfileManager::GetCurrentProfile() const
554 std::unique_lock<CCriticalSection> lock(m_critical);
555 if (m_currentProfile < m_profiles.size())
556 return m_profiles[m_currentProfile];
558 CLog::Log(LOGERROR, "CProfileManager: current profile index ({0}) is outside of the valid range ({1})", m_currentProfile, m_profiles.size());
559 return EmptyProfile;
562 const CProfile* CProfileManager::GetProfile(unsigned int index) const
564 std::unique_lock<CCriticalSection> lock(m_critical);
565 if (index < m_profiles.size())
566 return &m_profiles[index];
568 return NULL;
571 CProfile* CProfileManager::GetProfile(unsigned int index)
573 std::unique_lock<CCriticalSection> lock(m_critical);
574 if (index < m_profiles.size())
575 return &m_profiles[index];
577 return NULL;
580 int CProfileManager::GetProfileIndex(const std::string &name) const
582 std::unique_lock<CCriticalSection> lock(m_critical);
583 for (int i = 0; i < static_cast<int>(m_profiles.size()); i++)
585 if (StringUtils::EqualsNoCase(m_profiles[i].getName(), name))
586 return i;
589 return -1;
592 void CProfileManager::AddProfile(const CProfile &profile)
595 std::unique_lock<CCriticalSection> lock(m_critical);
596 // data integrity check - covers off migration from old profiles.xml,
597 // incrementing of the m_nextIdProfile,and bad data coming in
598 m_nextProfileId = std::max(m_nextProfileId, profile.getId() + 1);
600 m_profiles.push_back(profile);
602 Save();
605 void CProfileManager::UpdateCurrentProfileDate()
607 std::unique_lock<CCriticalSection> lock(m_critical);
608 if (m_currentProfile < m_profiles.size())
610 m_profiles[m_currentProfile].setDate();
611 CSingleExit exit(m_critical);
612 Save();
616 void CProfileManager::LoadMasterProfileForLogin()
618 std::unique_lock<CCriticalSection> lock(m_critical);
619 // save the previous user
620 m_lastUsedProfile = m_currentProfile;
621 if (m_currentProfile != 0)
623 // determines that the (master) profile has only been loaded for login
624 m_profileLoadedForLogin = true;
626 LoadProfile(0);
628 // remember that the (master) profile has only been loaded for login
629 m_previousProfileLoadedForLogin = true;
633 bool CProfileManager::GetProfileName(const unsigned int profileId, std::string& name) const
635 std::unique_lock<CCriticalSection> lock(m_critical);
636 const CProfile *profile = GetProfile(profileId);
637 if (!profile)
638 return false;
640 name = profile->getName();
641 return true;
644 std::string CProfileManager::GetUserDataFolder() const
646 return GetMasterProfile().getDirectory();
649 std::string CProfileManager::GetProfileUserDataFolder() const
651 if (m_currentProfile == 0)
652 return GetUserDataFolder();
654 return URIUtils::AddFileToFolder(GetUserDataFolder(), GetCurrentProfile().getDirectory());
657 std::string CProfileManager::GetDatabaseFolder() const
659 if (GetCurrentProfile().hasDatabases())
660 return URIUtils::AddFileToFolder(GetProfileUserDataFolder(), "Database");
662 return URIUtils::AddFileToFolder(GetUserDataFolder(), "Database");
665 std::string CProfileManager::GetCDDBFolder() const
667 return URIUtils::AddFileToFolder(GetDatabaseFolder(), "CDDB");
670 std::string CProfileManager::GetThumbnailsFolder() const
672 if (GetCurrentProfile().hasDatabases())
673 return URIUtils::AddFileToFolder(GetProfileUserDataFolder(), "Thumbnails");
675 return URIUtils::AddFileToFolder(GetUserDataFolder(), "Thumbnails");
678 std::string CProfileManager::GetVideoThumbFolder() const
680 return URIUtils::AddFileToFolder(GetThumbnailsFolder(), "Video");
683 std::string CProfileManager::GetBookmarksThumbFolder() const
685 return URIUtils::AddFileToFolder(GetVideoThumbFolder(), "Bookmarks");
688 std::string CProfileManager::GetLibraryFolder() const
690 if (GetCurrentProfile().hasDatabases())
691 return URIUtils::AddFileToFolder(GetProfileUserDataFolder(), "library");
693 return URIUtils::AddFileToFolder(GetUserDataFolder(), "library");
696 std::string CProfileManager::GetSavestatesFolder() const
698 if (GetCurrentProfile().hasDatabases())
699 return URIUtils::AddFileToFolder(GetProfileUserDataFolder(), "Savestates");
701 return URIUtils::AddFileToFolder(GetUserDataFolder(), "Savestates");
704 std::string CProfileManager::GetSettingsFile() const
706 if (m_currentProfile == 0)
707 return "special://masterprofile/guisettings.xml";
709 return "special://profile/guisettings.xml";
712 std::string CProfileManager::GetUserDataItem(const std::string& strFile) const
714 std::string path;
715 path = "special://profile/" + strFile;
717 // check if item exists in the profile (either for folder or
718 // for a file (depending on slashAtEnd of strFile) otherwise
719 // return path to masterprofile
720 if ((URIUtils::HasSlashAtEnd(path) && !CDirectory::Exists(path)) || !CFile::Exists(path))
721 path = "special://masterprofile/" + strFile;
723 return path;
726 CEventLog& CProfileManager::GetEventLog()
728 return m_eventLogs->GetEventLog(GetCurrentProfileId());
731 void CProfileManager::OnSettingAction(const std::shared_ptr<const CSetting>& setting)
733 if (setting == nullptr)
734 return;
736 const std::string& settingId = setting->GetId();
737 if (settingId == CSettings::SETTING_EVENTLOG_SHOW)
738 GetEventLog().ShowFullEventLog();
741 void CProfileManager::SetCurrentProfileId(unsigned int profileId)
744 std::unique_lock<CCriticalSection> lock(m_critical);
745 m_currentProfile = profileId;
746 CSpecialProtocol::SetProfilePath(GetProfileUserDataFolder());
748 Save();