summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/Screenshot.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/utils/Screenshot.cpp')
-rw-r--r--xbmc/utils/Screenshot.cpp117
1 files changed, 117 insertions, 0 deletions
diff --git a/xbmc/utils/Screenshot.cpp b/xbmc/utils/Screenshot.cpp
new file mode 100644
index 0000000..25ecbac
--- /dev/null
+++ b/xbmc/utils/Screenshot.cpp
@@ -0,0 +1,117 @@
+/*
+ * 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<std::function<std::unique_ptr<IScreenshotSurface>()>> CScreenShot::m_screenShotSurfaces;
+
+void CScreenShot::Register(const std::function<std::unique_ptr<IScreenshotSurface>()>& 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 {} failed", CURL::GetRedacted(filename));
+ return;
+ }
+
+ surface->CaptureVideo(true);
+
+ CLog::Log(LOGDEBUG, "Saving screenshot {}", CURL::GetRedacted(filename));
+
+ //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 {}", CURL::GetRedacted(filename));
+
+ 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 {}", CURL::GetRedacted(filename));
+
+ //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);
+ CServiceBroker::GetJobManager()->AddJob(thumbnailwriter, nullptr);
+ }
+}
+
+void CScreenShot::TakeScreenshot()
+{
+ std::shared_ptr<CSettingPath> screenshotSetting = std::static_pointer_cast<CSettingPath>(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{:05}.png"), 65535);
+
+ if (!file.empty())
+ {
+ TakeScreenshot(file, false);
+ }
+ else
+ {
+ CLog::Log(LOGWARNING, "Too many screen shots or invalid folder");
+ }
+ }
+}