2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "GUIMultiImage.h"
22 #include "TextureManager.h"
23 #include "filesystem/Directory.h"
24 #include "utils/URIUtils.h"
25 #include "utils/JobManager.h"
27 #include "settings/AdvancedSettings.h"
29 #include "TextureCache.h"
30 #include "WindowIDs.h"
31 #include "utils/StringUtils.h"
34 using namespace XFILE;
36 CGUIMultiImage::CGUIMultiImage(int parentID, int controlID, float posX, float posY, float width, float height, const CTextureInfo& texture, unsigned int timePerImage, unsigned int fadeTime, bool randomized, bool loop, unsigned int timeToPauseAtEnd)
37 : CGUIControl(parentID, controlID, posX, posY, width, height),
38 m_image(0, 0, posX, posY, width, height, texture)
41 m_timePerImage = timePerImage + fadeTime;
42 m_timeToPauseAtEnd = timeToPauseAtEnd;
43 m_image.SetCrossFade(fadeTime);
44 m_randomized = randomized;
46 ControlType = GUICONTROL_MULTI_IMAGE;
47 m_bDynamicResourceAlloc=false;
48 m_directoryStatus = UNLOADED;
52 CGUIMultiImage::CGUIMultiImage(const CGUIMultiImage &from)
53 : CGUIControl(from), m_texturePath(), m_imageTimer(), m_files(), m_image(from.m_image)
55 m_timePerImage = from.m_timePerImage;
56 m_timeToPauseAtEnd = from.m_timeToPauseAtEnd;
57 m_randomized = from.m_randomized;
59 m_bDynamicResourceAlloc=false;
60 m_directoryStatus = UNLOADED;
61 if (m_texturePath.IsConstant())
62 m_currentPath = m_texturePath.GetLabel(WINDOW_INVALID);
64 ControlType = GUICONTROL_MULTI_IMAGE;
68 CGUIMultiImage::~CGUIMultiImage(void)
73 void CGUIMultiImage::UpdateVisibility(const CGUIListItem *item)
75 CGUIControl::UpdateVisibility(item);
77 // check if we're hidden, and deallocate if so
78 if (!IsVisible() && m_visible != DELAYED)
80 if (m_bDynamicResourceAlloc && m_bAllocated)
85 // we are either delayed or visible, so we can allocate our resources
86 if (m_directoryStatus == UNLOADED)
92 if (m_directoryStatus == LOADED)
96 void CGUIMultiImage::UpdateInfo(const CGUIListItem *item)
98 // check for conditional information before we
99 // alloc as this can free our resources
100 if (!m_texturePath.IsConstant())
102 CStdString texturePath;
104 texturePath = m_texturePath.GetItemLabel(item, true);
106 texturePath = m_texturePath.GetLabel(m_parentID);
107 if (texturePath != m_currentPath && !texturePath.empty())
109 // a new path - set our current path and tell ourselves to load our directory
110 m_currentPath = texturePath;
116 void CGUIMultiImage::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions)
118 // Set a viewport so that we don't render outside the defined area
119 if (m_directoryStatus == READY && !m_files.empty())
121 unsigned int nextImage = m_currentImage + 1;
122 if (nextImage >= m_files.size())
123 nextImage = m_loop ? 0 : m_currentImage; // stay on the last image if <loop>no</loop>
125 if (nextImage != m_currentImage)
127 // check if we should be loading a new image yet
128 unsigned int timeToShow = m_timePerImage;
129 if (0 == nextImage) // last image should be paused for a bit longer if that's what the skinner wishes.
130 timeToShow += m_timeToPauseAtEnd;
131 if (m_imageTimer.IsRunning() && m_imageTimer.GetElapsedMilliseconds() > timeToShow)
134 m_currentImage = nextImage;
135 m_image.SetFileName(m_files[m_currentImage]);
138 m_imageTimer.StartZero();
143 if (g_graphicsContext.SetClipRegion(m_posX, m_posY, m_width, m_height))
145 if (m_image.SetColorDiffuse(m_diffuseColor))
148 m_image.DoProcess(currentTime, dirtyregions);
150 g_graphicsContext.RestoreClipRegion();
153 CGUIControl::Process(currentTime, dirtyregions);
156 void CGUIMultiImage::Render()
159 CGUIControl::Render();
162 bool CGUIMultiImage::OnAction(const CAction &action)
167 bool CGUIMultiImage::OnMessage(CGUIMessage &message)
169 if (message.GetMessage() == GUI_MSG_REFRESH_THUMBS)
171 if (!m_texturePath.IsConstant())
175 return CGUIControl::OnMessage(message);
178 void CGUIMultiImage::AllocResources()
181 CGUIControl::AllocResources();
183 if (m_directoryStatus == UNLOADED)
187 void CGUIMultiImage::FreeResources(bool immediately)
189 m_image.FreeResources(immediately);
193 CGUIControl::FreeResources(immediately);
196 void CGUIMultiImage::DynamicResourceAlloc(bool bOnOff)
198 CGUIControl::DynamicResourceAlloc(bOnOff);
199 m_bDynamicResourceAlloc=bOnOff;
202 void CGUIMultiImage::SetInvalid()
204 m_image.SetInvalid();
205 CGUIControl::SetInvalid();
208 bool CGUIMultiImage::CanFocus() const
213 void CGUIMultiImage::SetAspectRatio(const CAspectRatio &ratio)
215 m_image.SetAspectRatio(ratio);
218 void CGUIMultiImage::LoadDirectory()
220 // clear current stuff out
223 // don't load any images if our path is empty
224 if (m_currentPath.empty()) return;
226 /* Check the fast cases:
228 2. Cached picture (in case an extension is not present)
231 CFileItem item(m_currentPath, false);
232 if (item.IsPicture() || CTextureCache::Get().HasCachedImage(m_currentPath))
233 m_files.push_back(m_currentPath);
234 else // bundled folder?
235 g_TextureManager.GetBundledTexturesFromPath(m_currentPath, m_files);
236 if (!m_files.empty())
237 { // found - nothing more to do
241 // slow(er) checks necessary - do them in the background
242 CSingleLock lock(m_section);
243 m_directoryStatus = LOADING;
244 m_jobID = CJobManager::GetInstance().AddJob(new CMultiImageJob(m_currentPath), this, CJob::PRIORITY_NORMAL);
247 void CGUIMultiImage::OnDirectoryLoaded()
249 // Randomize or sort our images if necessary
251 random_shuffle(m_files.begin(), m_files.end());
253 sort(m_files.begin(), m_files.end());
255 // flag as loaded - no point in constantly reloading them
256 m_directoryStatus = READY;
257 m_imageTimer.StartZero();
259 m_image.SetFileName(m_files.empty() ? "" : m_files[0]);
262 void CGUIMultiImage::CancelLoading()
264 CSingleLock lock(m_section);
265 if (m_directoryStatus == LOADING)
266 CJobManager::GetInstance().CancelJob(m_jobID);
267 m_directoryStatus = UNLOADED;
270 void CGUIMultiImage::OnJobComplete(unsigned int jobID, bool success, CJob *job)
272 CSingleLock lock(m_section);
273 if (m_directoryStatus == LOADING && strncmp(job->GetType(), "multiimage", 10) == 0)
275 m_files = ((CMultiImageJob *)job)->m_files;
276 m_directoryStatus = LOADED;
280 void CGUIMultiImage::SetInfo(const CGUIInfoLabel &info)
282 m_texturePath = info;
283 if (m_texturePath.IsConstant())
284 m_currentPath = m_texturePath.GetLabel(WINDOW_INVALID);
287 CStdString CGUIMultiImage::GetDescription() const
289 return m_image.GetDescription();
292 CGUIMultiImage::CMultiImageJob::CMultiImageJob(const CStdString &path)
297 bool CGUIMultiImage::CMultiImageJob::DoWork()
299 // check to see if we have a single image or a folder of images
300 CFileItem item(m_path, false);
301 item.FillInMimeType();
302 if (item.IsPicture() || StringUtils::StartsWithNoCase(item.GetMimeType(), "image/"))
304 m_files.push_back(m_path);
308 // Load in images from the directory specified
309 // m_path is relative (as are all skin paths)
310 CStdString realPath = g_TextureManager.GetTexturePath(m_path, true);
311 if (realPath.empty())
314 URIUtils::AddSlashAtEnd(realPath);
316 CDirectory::GetDirectory(realPath, items, g_advancedSettings.m_pictureExtensions + "|.tbn|.dds", DIR_FLAG_NO_FILE_DIRS | DIR_FLAG_NO_FILE_INFO);
317 for (int i=0; i < items.Size(); i++)
319 CFileItem* pItem = items[i].get();
320 if (pItem && (pItem->IsPicture() || StringUtils::StartsWithNoCase(pItem->GetMimeType(), "image/")))
321 m_files.push_back(pItem->GetPath());