From be933ef2241d79558f91796cc5b3a161f72ebf9c Mon Sep 17 00:00:00 2001 From: manuel Date: Mon, 19 Oct 2020 00:52:24 +0200 Subject: sync with upstream --- xbmc/utils/Screenshot.cpp | 116 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 xbmc/utils/Screenshot.cpp (limited to 'xbmc/utils/Screenshot.cpp') diff --git a/xbmc/utils/Screenshot.cpp b/xbmc/utils/Screenshot.cpp new file mode 100644 index 0000000..638ea64 --- /dev/null +++ b/xbmc/utils/Screenshot.cpp @@ -0,0 +1,116 @@ +/* + * 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 "Screenshot.h" + +#include "ServiceBroker.h" +#include "URL.h" +#include "Util.h" +#include "filesystem/File.h" +#include "guilib/LocalizeStrings.h" +#include "pictures/Picture.h" +#include "settings/SettingPath.h" +#include "settings/Settings.h" +#include "settings/SettingsComponent.h" +#include "settings/windows/GUIControlSettings.h" +#include "utils/JobManager.h" +#include "utils/URIUtils.h" +#include "utils/log.h" + +using namespace XFILE; + +std::vector()>> CScreenShot::m_screenShotSurfaces; + +void CScreenShot::Register(std::function()> createFunc) +{ + m_screenShotSurfaces.emplace_back(createFunc); +} + +void CScreenShot::TakeScreenshot(const std::string& filename, bool sync) +{ + auto surface = m_screenShotSurfaces.back()(); + + if (!surface) + { + CLog::Log(LOGERROR, "failed to create screenshot surface"); + return; + } + + if (!surface->Capture()) + { + CLog::Log(LOGERROR, "Screenshot %s failed", CURL::GetRedacted(filename).c_str()); + return; + } + + surface->CaptureVideo(true); + + CLog::Log(LOGDEBUG, "Saving screenshot %s", CURL::GetRedacted(filename).c_str()); + + //set alpha byte to 0xFF + for (int y = 0; y < surface->GetHeight(); y++) + { + unsigned char* alphaptr = surface->GetBuffer() - 1 + y * surface->GetStride(); + for (int x = 0; x < surface->GetWidth(); x++) + *(alphaptr += 4) = 0xFF; + } + + //if sync is true, the png file needs to be completely written when this function returns + if (sync) + { + if (!CPicture::CreateThumbnailFromSurface(surface->GetBuffer(), surface->GetWidth(), surface->GetHeight(), surface->GetStride(), filename)) + CLog::Log(LOGERROR, "Unable to write screenshot %s", CURL::GetRedacted(filename).c_str()); + + surface->ReleaseBuffer(); + } + else + { + //make sure the file exists to avoid concurrency issues + XFILE::CFile file; + if (file.OpenForWrite(filename)) + file.Close(); + else + CLog::Log(LOGERROR, "Unable to create file %s", CURL::GetRedacted(filename).c_str()); + + //write .png file asynchronous with CThumbnailWriter, prevents stalling of the render thread + //buffer is deleted from CThumbnailWriter + CThumbnailWriter* thumbnailwriter = new CThumbnailWriter(surface->GetBuffer(), surface->GetWidth(), surface->GetHeight(), surface->GetStride(), filename); + CJobManager::GetInstance().AddJob(thumbnailwriter, NULL); + } +} + +void CScreenShot::TakeScreenshot() +{ + std::shared_ptr screenshotSetting = std::static_pointer_cast(CServiceBroker::GetSettingsComponent()->GetSettings()->GetSetting(CSettings::SETTING_DEBUG_SCREENSHOTPATH)); + if (!screenshotSetting) + return; + + std::string strDir = screenshotSetting->GetValue(); + if (strDir.empty()) + { + if (!CGUIControlButtonSetting::GetPath(screenshotSetting, &g_localizeStrings)) + return; + + strDir = screenshotSetting->GetValue(); + } + + URIUtils::RemoveSlashAtEnd(strDir); + + if (!strDir.empty()) + { + std::string file = CUtil::GetNextFilename(URIUtils::AddFileToFolder(strDir, "screenshot%03d.png"), 999); + + if (!file.empty()) + { + TakeScreenshot(file, false); + } + else + { + CLog::Log(LOGWARNING, "Too many screen shots or invalid folder"); + } + } +} -- cgit v1.2.3