CFileItem* CSavestateDatabase::CreateFileItem(const CVariant& object) const { using namespace ADDON; CSavestate save; save.Deserialize(object); CFileItem* item = new CFileItem(save.Label()); item->SetPath(save.Path()); if (!save.Thumbnail().empty()) item->SetArt("thumb", save.Thumbnail()); else { AddonPtr addon; if (CAddonMgr::GetInstance().GetAddon(save.GameClient(), addon, ADDON_GAMEDLL)) item->SetArt("thumb", addon->Icon()); } // Use the slot number as the second label if (save.Type() == SAVETYPE::SLOT) item->SetLabel2(StringUtils::Format("%u", save.Slot())); item->m_dateTime = save.Timestamp(); item->SetProperty(FILEITEM_PROPERTY_SAVESTATE_DURATION, static_cast<uint64_t>(save.PlaytimeWallClock())); item->GetGameInfoTag()->SetGameClient(save.GameClient()); item->m_dwSize = save.Size(); item->m_bIsFolder = false; return item; }
bool CRetroPlayer::OpenFile(const CFileItem& file, const CPlayerOptions& options) { CFileItem fileCopy(file); // When playing a game, set the game client that we'll use to open the game // Currently this may prompt the user, the goal is to figure this out silently if (!GAME::CGameUtils::FillInGameClient(fileCopy, true)) { CLog::Log(LOGINFO, "RetroPlayer: No compatible game client selected, aborting playback"); return false; } // Check if we should open in standalone mode const bool bStandalone = fileCopy.GetPath().empty(); m_processInfo.reset(CRPProcessInfo::CreateInstance()); if (!m_processInfo) { CLog::Log(LOGERROR, "Failed to create RetroPlayer - no process info registered"); return false; } m_processInfo->SetDataCache(&CServiceBroker::GetDataCacheCore()); m_processInfo->ResetInfo(); m_renderManager.reset(new CRPRenderManager(*m_processInfo)); CSingleLock lock(m_mutex); if (IsPlaying()) CloseFile(); PrintGameInfo(fileCopy); bool bSuccess = false; std::string gameClientId = fileCopy.GetGameInfoTag()->GetGameClient(); ADDON::AddonPtr addon; if (gameClientId.empty()) { CLog::Log(LOGERROR, "Can't play game, no game client was passed to RetroPlayer!"); } else if (!CServiceBroker::GetAddonMgr().GetAddon(gameClientId, addon, ADDON::ADDON_GAMEDLL)) { CLog::Log(LOGERROR, "Can't find add-on %s for game file!", gameClientId.c_str()); } else { m_gameClient = std::static_pointer_cast<CGameClient>(addon); if (m_gameClient->Initialize()) { m_audio.reset(new CRetroPlayerAudio(*m_processInfo)); m_video.reset(new CRetroPlayerVideo(*m_renderManager, *m_processInfo)); m_input.reset(new CRetroPlayerInput(CServiceBroker::GetPeripherals())); if (!bStandalone) { std::string redactedPath = CURL::GetRedacted(fileCopy.GetPath()); CLog::Log(LOGINFO, "RetroPlayer: Opening: %s", redactedPath.c_str()); bSuccess = m_gameClient->OpenFile(fileCopy, m_audio.get(), m_video.get(), m_input.get()); } else { CLog::Log(LOGINFO, "RetroPlayer: Opening standalone"); bSuccess = m_gameClient->OpenStandalone(m_audio.get(), m_video.get(), m_input.get()); } if (bSuccess) CLog::Log(LOGDEBUG, "RetroPlayer: Using game client %s", gameClientId.c_str()); else CLog::Log(LOGERROR, "RetroPlayer: Failed to open file using %s", gameClientId.c_str()); } else CLog::Log(LOGERROR, "RetroPlayer: Failed to initialize %s", gameClientId.c_str()); } if (bSuccess && !bStandalone) { std::string savestatePath = CSavestateUtils::MakeMetadataPath(fileCopy.GetPath()); CSavestate save; if (save.Deserialize(savestatePath)) { // Check if game client is the same if (save.GameClient() != m_gameClient->ID()) { ADDON::AddonPtr addon; if (CServiceBroker::GetAddonMgr().GetAddon(save.GameClient(), addon)) { // Warn the user that continuing with a different game client will // overwrite the save bool dummy; if (!CGUIDialogYesNo::ShowAndGetInput(438, StringUtils::Format(g_localizeStrings.Get(35217), addon->Name()), dummy, 222, 35218, 0)) bSuccess = false; } } } if (bSuccess) { std::string redactedSavestatePath = CURL::GetRedacted(savestatePath); CLog::Log(LOGDEBUG, "RetroPlayer: Loading savestate %s", redactedSavestatePath.c_str()); if (!SetPlayerState(savestatePath)) CLog::Log(LOGERROR, "RetroPlayer: Failed to load savestate"); } } if (bSuccess) { RegisterWindowCallbacks(); SetSpeedInternal(1.0); m_callback.OnPlayBackStarted(fileCopy); if (!bStandalone) m_autoSave.reset(new CRetroPlayerAutoSave(*m_gameClient)); m_processInfo->SetVideoFps(static_cast<float>(m_gameClient->Timing().GetFrameRate())); } else { m_gameClient.reset(); m_audio.reset(); m_video.reset(); } return bSuccess; }
bool CSavestateDatabase::GetSavestate(const std::string& path, CSavestate& save) { return save.Deserialize(path); }