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.
9 #include "Screenshot.h"
11 #include "ServiceBroker.h"
14 #include "filesystem/File.h"
15 #include "guilib/LocalizeStrings.h"
16 #include "pictures/Picture.h"
17 #include "settings/SettingPath.h"
18 #include "settings/Settings.h"
19 #include "settings/SettingsComponent.h"
20 #include "settings/windows/GUIControlSettings.h"
21 #include "utils/JobManager.h"
22 #include "utils/URIUtils.h"
23 #include "utils/log.h"
25 using namespace XFILE
;
27 std::vector
<std::function
<std::unique_ptr
<IScreenshotSurface
>()>> CScreenShot::m_screenShotSurfaces
;
29 void CScreenShot::Register(const std::function
<std::unique_ptr
<IScreenshotSurface
>()>& createFunc
)
31 m_screenShotSurfaces
.emplace_back(createFunc
);
34 void CScreenShot::TakeScreenshot(const std::string
& filename
, bool sync
)
36 auto surface
= m_screenShotSurfaces
.back()();
40 CLog::Log(LOGERROR
, "failed to create screenshot surface");
44 if (!surface
->Capture())
46 CLog::Log(LOGERROR
, "Screenshot {} failed", CURL::GetRedacted(filename
));
50 surface
->CaptureVideo(true);
52 CLog::Log(LOGDEBUG
, "Saving screenshot {}", CURL::GetRedacted(filename
));
54 //set alpha byte to 0xFF
55 for (int y
= 0; y
< surface
->GetHeight(); y
++)
57 unsigned char* alphaptr
= surface
->GetBuffer() - 1 + y
* surface
->GetStride();
58 for (int x
= 0; x
< surface
->GetWidth(); x
++)
59 *(alphaptr
+= 4) = 0xFF;
62 //if sync is true, the png file needs to be completely written when this function returns
65 if (!CPicture::CreateThumbnailFromSurface(surface
->GetBuffer(), surface
->GetWidth(), surface
->GetHeight(), surface
->GetStride(), filename
))
66 CLog::Log(LOGERROR
, "Unable to write screenshot {}", CURL::GetRedacted(filename
));
68 surface
->ReleaseBuffer();
72 //make sure the file exists to avoid concurrency issues
74 if (file
.OpenForWrite(filename
))
77 CLog::Log(LOGERROR
, "Unable to create file {}", CURL::GetRedacted(filename
));
79 //write .png file asynchronous with CThumbnailWriter, prevents stalling of the render thread
80 //buffer is deleted from CThumbnailWriter
81 CThumbnailWriter
* thumbnailwriter
= new CThumbnailWriter(surface
->GetBuffer(), surface
->GetWidth(), surface
->GetHeight(), surface
->GetStride(), filename
);
82 CServiceBroker::GetJobManager()->AddJob(thumbnailwriter
, nullptr);
86 void CScreenShot::TakeScreenshot()
88 std::shared_ptr
<CSettingPath
> screenshotSetting
= std::static_pointer_cast
<CSettingPath
>(CServiceBroker::GetSettingsComponent()->GetSettings()->GetSetting(CSettings::SETTING_DEBUG_SCREENSHOTPATH
));
89 if (!screenshotSetting
)
92 std::string strDir
= screenshotSetting
->GetValue();
95 if (!CGUIControlButtonSetting::GetPath(screenshotSetting
, &g_localizeStrings
))
98 strDir
= screenshotSetting
->GetValue();
101 URIUtils::RemoveSlashAtEnd(strDir
);
106 CUtil::GetNextFilename(URIUtils::AddFileToFolder(strDir
, "screenshot{:05}.png"), 65535);
110 TakeScreenshot(file
, false);
114 CLog::Log(LOGWARNING
, "Too many screen shots or invalid folder");