Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

1004 lines (881 sloc) 30.781 kb
/*
* Copyright (C) 2005-2008 Team XBMC
* http://www.xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "threads/SystemClock.h"
#include "system.h"
#include "GUIWindowSlideShow.h"
#include "Application.h"
#include "ApplicationMessenger.h"
#include "utils/URIUtils.h"
#include "URL.h"
#include "guilib/TextureManager.h"
#include "guilib/GUILabelControl.h"
#include "GUIInfoManager.h"
#include "filesystem/Directory.h"
#include "GUIDialogPictureInfo.h"
#include "GUIUserMessages.h"
#include "guilib/GUIWindowManager.h"
#include "settings/Settings.h"
#include "settings/GUISettings.h"
#include "FileItem.h"
#include "guilib/Texture.h"
#include "windowing/WindowingFactory.h"
#include "guilib/Texture.h"
#include "guilib/LocalizeStrings.h"
#include "threads/SingleLock.h"
#include "utils/log.h"
#include "utils/TimeUtils.h"
using namespace XFILE;
#define MAX_ZOOM_FACTOR 10
#define MAX_PICTURE_SIZE 2048*2048
#define IMMEDIATE_TRANSISTION_TIME 20
#define PICTURE_MOVE_AMOUNT 0.02f
#define PICTURE_MOVE_AMOUNT_ANALOG 0.01f
#define PICTURE_MOVE_AMOUNT_TOUCH 0.002f
#define PICTURE_VIEW_BOX_COLOR 0xffffff00 // YELLOW
#define PICTURE_VIEW_BOX_BACKGROUND 0xff000000 // BLACK
#define FPS 25
#define BAR_IMAGE 1
#define LABEL_ROW1 10
#define LABEL_ROW2 11
#define LABEL_ROW2_EXTRA 12
#define CONTROL_PAUSE 13
static float zoomamount[10] = { 1.0f, 1.2f, 1.5f, 2.0f, 2.8f, 4.0f, 6.0f, 9.0f, 13.5f, 20.0f };
CBackgroundPicLoader::CBackgroundPicLoader() : CThread("CBackgroundPicLoader")
{
m_pCallback = NULL;
m_isLoading = false;
}
CBackgroundPicLoader::~CBackgroundPicLoader()
{
StopThread();
}
void CBackgroundPicLoader::Create(CGUIWindowSlideShow *pCallback)
{
m_pCallback = pCallback;
m_isLoading = false;
CThread::Create(false);
}
void CBackgroundPicLoader::Process()
{
unsigned int totalTime = 0;
unsigned int count = 0;
while (!m_bStop)
{ // loop around forever, waiting for the app to call LoadPic
if (AbortableWait(m_loadPic,10) == WAIT_SIGNALED)
{
if (m_pCallback)
{
unsigned int start = XbmcThreads::SystemClockMillis();
CBaseTexture* texture = new CTexture();
unsigned int originalWidth = 0;
unsigned int originalHeight = 0;
texture->LoadFromFile(m_strFileName, m_maxWidth, m_maxHeight, g_guiSettings.GetBool("pictures.useexifrotation"), &originalWidth, &originalHeight);
totalTime += XbmcThreads::SystemClockMillis() - start;
count++;
// tell our parent
bool bFullSize = ((int)texture->GetWidth() < m_maxWidth) && ((int)texture->GetHeight() < m_maxHeight);
if (!bFullSize)
{
int iSize = texture->GetWidth() * texture->GetHeight() - MAX_PICTURE_SIZE;
if ((iSize + (int)texture->GetWidth() > 0) || (iSize + (int)texture->GetHeight() > 0))
bFullSize = true;
if (!bFullSize && texture->GetWidth() == g_Windowing.GetMaxTextureSize())
bFullSize = true;
if (!bFullSize && texture->GetHeight() == g_Windowing.GetMaxTextureSize())
bFullSize = true;
}
m_pCallback->OnLoadPic(m_iPic, m_iSlideNumber, texture, originalWidth, originalHeight, bFullSize);
m_isLoading = false;
}
}
}
if (count > 0)
CLog::Log(LOGDEBUG, "Time for loading %u images: %u ms, average %u ms",
count, totalTime, totalTime / count);
}
void CBackgroundPicLoader::LoadPic(int iPic, int iSlideNumber, const CStdString &strFileName, const int maxWidth, const int maxHeight)
{
m_iPic = iPic;
m_iSlideNumber = iSlideNumber;
m_strFileName = strFileName;
m_maxWidth = maxWidth;
m_maxHeight = maxHeight;
m_isLoading = true;
m_loadPic.Set();
}
CGUIWindowSlideShow::CGUIWindowSlideShow(void)
: CGUIWindow(WINDOW_SLIDESHOW, "SlideShow.xml")
{
m_pBackgroundLoader = NULL;
m_slides = new CFileItemList;
m_Resolution = RES_INVALID;
Reset();
}
CGUIWindowSlideShow::~CGUIWindowSlideShow(void)
{
Reset();
delete m_slides;
}
bool CGUIWindowSlideShow::IsPlaying() const
{
return m_Image[m_iCurrentPic].IsLoaded();
}
void CGUIWindowSlideShow::Reset()
{
g_infoManager.SetShowCodec(false);
m_bSlideShow = false;
m_bShuffled = false;
m_bPause = false;
m_bPlayingVideo = false;
m_bErrorMessage = false;
m_bReloadImage = false;
m_bScreensaver = false;
m_Image[0].UnLoad();
m_Image[0].Close();
m_iRotate = 0;
m_iZoomFactor = 1;
m_iCurrentSlide = 0;
m_iNextSlide = 1;
m_iCurrentPic = 0;
m_iDirection = 1;
CSingleLock lock(m_slideSection);
m_slides->Clear();
m_Resolution = g_graphicsContext.GetVideoResolution();
}
void CGUIWindowSlideShow::FreeResources()
{ // wait for any outstanding picture loads
if (m_pBackgroundLoader)
{
// sleep until the loader finishes loading the current pic
CLog::Log(LOGDEBUG,"Waiting for BackgroundLoader thread to close");
while (m_pBackgroundLoader->IsLoading())
Sleep(10);
// stop the thread
CLog::Log(LOGDEBUG,"Stopping BackgroundLoader thread");
m_pBackgroundLoader->StopThread();
delete m_pBackgroundLoader;
m_pBackgroundLoader = NULL;
}
// and close the images.
m_Image[0].Close();
m_Image[1].Close();
g_infoManager.ResetCurrentSlide();
}
void CGUIWindowSlideShow::Add(const CFileItem *picture)
{
CFileItemPtr item(new CFileItem(*picture));
m_slides->Add(item);
}
void CGUIWindowSlideShow::ShowNext()
{
if (m_slides->Size() == 1)
return;
m_iNextSlide = m_iCurrentSlide + 1;
if (m_iNextSlide >= m_slides->Size())
m_iNextSlide = 0;
m_iDirection = 1;
m_bLoadNextPic = true;
}
void CGUIWindowSlideShow::ShowPrevious()
{
if (m_slides->Size() == 1)
return;
m_iNextSlide = m_iCurrentSlide - 1;
if (m_iNextSlide < 0)
m_iNextSlide = m_slides->Size() - 1;
m_iDirection = -1;
m_bLoadNextPic = true;
}
void CGUIWindowSlideShow::Select(const CStdString& strPicture)
{
for (int i = 0; i < m_slides->Size(); ++i)
{
const CFileItemPtr item = m_slides->Get(i);
if (item->GetPath() == strPicture)
{
m_iDirection = 1;
if (IsActive())
m_iNextSlide = i;
else
{
m_iCurrentSlide = i;
m_iNextSlide = GetNextSlide();
}
m_bLoadNextPic = true;
return ;
}
}
}
const CFileItemList &CGUIWindowSlideShow::GetSlideShowContents()
{
return *m_slides;
}
void CGUIWindowSlideShow::GetSlideShowContents(CFileItemList &list)
{
for (int index = 0; index < m_slides->Size(); index++)
list.Add(CFileItemPtr(new CFileItem(*m_slides->Get(index))));
}
const CFileItemPtr CGUIWindowSlideShow::GetCurrentSlide()
{
if (m_iCurrentSlide >= 0 && m_iCurrentSlide < m_slides->Size())
return m_slides->Get(m_iCurrentSlide);
return CFileItemPtr();
}
bool CGUIWindowSlideShow::InSlideShow() const
{
return m_bSlideShow;
}
void CGUIWindowSlideShow::StartSlideShow(bool screensaver)
{
m_bSlideShow = true;
m_iDirection = 1;
m_bScreensaver = screensaver;
}
void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &regions)
{
// reset the screensaver if we're in a slideshow
// (unless we are the screensaver!)
if (m_bSlideShow && !g_application.IsInScreenSaver())
g_application.ResetScreenSaver();
int iSlides = m_slides->Size();
if (!iSlides) return ;
// if we haven't rendered yet, we should mark the whole screen
if (!m_hasRendered)
regions.push_back(CRect(0.0f, 0.0f, (float)g_graphicsContext.GetWidth(), (float)g_graphicsContext.GetHeight()));
if (m_iNextSlide < 0 || m_iNextSlide >= m_slides->Size())
m_iNextSlide = 0;
if (m_iCurrentSlide < 0 || m_iCurrentSlide >= m_slides->Size())
m_iCurrentSlide = 0;
// Create our background loader if necessary
if (!m_pBackgroundLoader)
{
m_pBackgroundLoader = new CBackgroundPicLoader();
if (!m_pBackgroundLoader)
{
throw 1;
}
m_pBackgroundLoader->Create(this);
}
bool bSlideShow = m_bSlideShow && !m_bPause && !m_bPlayingVideo;
if (m_bErrorMessage)
{ // we have an error when loading either the current or next picture
// check to see if we have a picture loaded
CLog::Log(LOGDEBUG, "We have an error loading a picture!");
if (m_Image[m_iCurrentPic].IsLoaded())
{ // Yes. Let's let it transistion out, wait for it to be released, then try loading again.
CLog::Log(LOGERROR, "Error loading the next image %s", m_slides->Get(m_iNextSlide)->GetPath().c_str());
if (!bSlideShow)
{ // tell the pic to start transistioning out now
m_Image[m_iCurrentPic].StartTransistion();
m_Image[m_iCurrentPic].SetTransistionTime(1, IMMEDIATE_TRANSISTION_TIME); // only 20 frames for the transistion
}
m_bWaitForNextPic = true;
m_bErrorMessage = false;
}
else
{ // No. Not much we can do here. If we're in a slideshow, we mayaswell move on to the next picture
// change to next image
if (bSlideShow)
{
CLog::Log(LOGERROR, "Error loading the current image %s", m_slides->Get(m_iCurrentSlide)->GetPath().c_str());
m_iCurrentSlide = m_iNextSlide;
m_iNextSlide = GetNextSlide();
ShowNext();
m_bErrorMessage = false;
}
else if (m_bLoadNextPic)
{
m_iCurrentSlide = m_iNextSlide;
m_iNextSlide = GetNextSlide();
m_bErrorMessage = false;
}
// else just drop through - there's nothing we can do (error message will be displayed)
}
}
if (m_bErrorMessage)
{ // hack, just mark it all
regions.push_back(CRect(0.0f, 0.0f, (float)g_graphicsContext.GetWidth(), (float)g_graphicsContext.GetHeight()));
return;
}
if (!m_Image[m_iCurrentPic].IsLoaded() && !m_pBackgroundLoader->IsLoading())
{ // load first image
CLog::Log(LOGDEBUG, "Loading the current image %s", m_slides->Get(m_iCurrentSlide)->GetPath().c_str());
m_bWaitForNextPic = false;
m_bLoadNextPic = false;
// load using the background loader
int maxWidth, maxHeight;
GetCheckedSize((float)g_settings.m_ResInfo[m_Resolution].iWidth * zoomamount[m_iZoomFactor - 1],
(float)g_settings.m_ResInfo[m_Resolution].iHeight * zoomamount[m_iZoomFactor - 1],
maxWidth, maxHeight);
if (!m_slides->Get(m_iCurrentSlide)->IsVideo())
m_pBackgroundLoader->LoadPic(m_iCurrentPic, m_iCurrentSlide, m_slides->Get(m_iCurrentSlide)->GetPath(), maxWidth, maxHeight);
}
// check if we should discard an already loaded next slide
if (m_bLoadNextPic && m_Image[1 - m_iCurrentPic].IsLoaded() && m_Image[1 - m_iCurrentPic].SlideNumber() != m_iNextSlide)
m_Image[1 - m_iCurrentPic].Close();
// if we're reloading an image (for better res on zooming we need to close any open ones as well)
if (m_bReloadImage && m_Image[1 - m_iCurrentPic].IsLoaded() && m_Image[1 - m_iCurrentPic].SlideNumber() != m_iCurrentSlide)
m_Image[1 - m_iCurrentPic].Close();
if (m_bReloadImage)
{
if (m_Image[m_iCurrentPic].IsLoaded() && !m_Image[1 - m_iCurrentPic].IsLoaded() && !m_pBackgroundLoader->IsLoading() && !m_bWaitForNextPic)
{ // reload the image if we need to
CLog::Log(LOGDEBUG, "Reloading the current image %s at zoom level %i", m_slides->Get(m_iCurrentSlide)->GetPath().c_str(), m_iZoomFactor);
// first, our maximal size for this zoom level
int maxWidth = (int)((float)g_settings.m_ResInfo[m_Resolution].iWidth * zoomamount[m_iZoomFactor - 1]);
int maxHeight = (int)((float)g_settings.m_ResInfo[m_Resolution].iWidth * zoomamount[m_iZoomFactor - 1]);
// the actual maximal size of the image to optimize the sizing based on the known sizing (aspect ratio)
int width, height;
GetCheckedSize((float)m_Image[m_iCurrentPic].GetOriginalWidth(), (float)m_Image[m_iCurrentPic].GetOriginalHeight(), width, height);
// use the smaller of the two (no point zooming in more than we have to)
if (maxWidth < width)
width = maxWidth;
if (maxHeight < height)
height = maxHeight;
m_pBackgroundLoader->LoadPic(m_iCurrentPic, m_iCurrentSlide, m_slides->Get(m_iCurrentSlide)->GetPath(), width, height);
}
}
else
{
if (m_iNextSlide != m_iCurrentSlide && m_Image[m_iCurrentPic].IsLoaded() && !m_Image[1 - m_iCurrentPic].IsLoaded() && !m_pBackgroundLoader->IsLoading() && !m_bWaitForNextPic)
{ // load the next image
CLog::Log(LOGDEBUG, "Loading the next image %s", m_slides->Get(m_iNextSlide)->GetPath().c_str());
int maxWidth, maxHeight;
GetCheckedSize((float)g_settings.m_ResInfo[m_Resolution].iWidth * zoomamount[m_iZoomFactor - 1],
(float)g_settings.m_ResInfo[m_Resolution].iHeight * zoomamount[m_iZoomFactor - 1],
maxWidth, maxHeight);
if (!m_slides->Get(m_iNextSlide)->IsVideo())
m_pBackgroundLoader->LoadPic(1 - m_iCurrentPic, m_iNextSlide, m_slides->Get(m_iNextSlide)->GetPath(), maxWidth, maxHeight);
}
}
// render the current image
if (m_Image[m_iCurrentPic].IsLoaded())
{
m_Image[m_iCurrentPic].SetInSlideshow(m_bSlideShow);
m_Image[m_iCurrentPic].Pause(m_bPause);
m_Image[m_iCurrentPic].Process(currentTime, regions);
}
if (m_slides->Get(m_iCurrentSlide)->IsVideo() && bSlideShow)
{
CLog::Log(LOGDEBUG, "Playing slide %s as video", m_slides->Get(m_iCurrentSlide)->GetPath().c_str());
m_bPlayingVideo = true;
CApplicationMessenger::Get().PlayFile(*m_slides->Get(m_iCurrentSlide));
m_iCurrentSlide = m_iNextSlide;
m_iNextSlide = GetNextSlide();
}
// Check if we should be transistioning immediately
if (m_bLoadNextPic)
{
CLog::Log(LOGDEBUG, "Starting immediate transistion due to user wanting slide %s", m_slides->Get(m_iNextSlide)->GetPath().c_str());
if (m_Image[m_iCurrentPic].StartTransistion())
{
m_Image[m_iCurrentPic].SetTransistionTime(1, IMMEDIATE_TRANSISTION_TIME); // only 20 frames for the transistion
m_bLoadNextPic = false;
}
}
// render the next image
if (m_Image[m_iCurrentPic].DrawNextImage())
{
if (m_Image[1 - m_iCurrentPic].IsLoaded())
{
// set the appropriate transistion time
m_Image[1 - m_iCurrentPic].SetTransistionTime(0, m_Image[m_iCurrentPic].GetTransistionTime(1));
m_Image[1 - m_iCurrentPic].Pause(m_bPause);
m_Image[1 - m_iCurrentPic].Process(currentTime, regions);
}
else // next pic isn't loaded. We should hang around if it is in progress
{
if (m_pBackgroundLoader->IsLoading())
{
// CLog::Log(LOGDEBUG, "Having to hold the current image (%s) while we load %s", m_vecSlides[m_iCurrentSlide].c_str(), m_vecSlides[m_iNextSlide].c_str());
m_Image[m_iCurrentPic].Keep();
}
}
}
// check if we should swap images now
if (m_Image[m_iCurrentPic].IsFinished())
{
CLog::Log(LOGDEBUG, "Image %s is finished rendering, switching to %s", m_slides->Get(m_iCurrentSlide)->GetPath().c_str(), m_slides->Get(m_iNextSlide)->GetPath().c_str());
m_Image[m_iCurrentPic].Close();
if (m_Image[1 - m_iCurrentPic].IsLoaded())
m_iCurrentPic = 1 - m_iCurrentPic;
m_iCurrentSlide = m_iNextSlide;
m_iNextSlide = GetNextSlide();
// m_iZoomFactor = 1;
m_iRotate = 0;
}
if (m_Image[m_iCurrentPic].IsLoaded())
g_infoManager.SetCurrentSlide(*m_slides->Get(m_iCurrentSlide));
RenderPause();
CGUIWindow::Process(currentTime, regions);
}
void CGUIWindowSlideShow::Render()
{
if (m_Image[m_iCurrentPic].IsLoaded())
m_Image[m_iCurrentPic].Render();
if (m_Image[m_iCurrentPic].DrawNextImage() && m_Image[1 - m_iCurrentPic].IsLoaded())
m_Image[1 - m_iCurrentPic].Render();
RenderErrorMessage();
CGUIWindow::Render();
}
int CGUIWindowSlideShow::GetNextSlide()
{
if (m_slides->Size() <= 1)
return m_iCurrentSlide;
if (m_bSlideShow || m_iDirection >= 0)
return (m_iCurrentSlide + 1) % m_slides->Size();
return (m_iCurrentSlide - 1 + m_slides->Size()) % m_slides->Size();
}
EVENT_RESULT CGUIWindowSlideShow::OnMouseEvent(const CPoint &point, const CMouseEvent &event)
{
if (event.m_id == ACTION_GESTURE_NOTIFY)
{
if (m_iZoomFactor == 1) //zoomed out - no inertial scrolling
return EVENT_RESULT_PAN_HORIZONTAL_WITHOUT_INERTIA;
return EVENT_RESULT_PAN_HORIZONTAL;
}
else if (event.m_id == ACTION_GESTURE_BEGIN)
{
m_firstGesturePoint = point;
return EVENT_RESULT_HANDLED;
}
else if (event.m_id == ACTION_GESTURE_PAN)
{ // on zoomlevel 1 just detect swipe left and right
if (m_iZoomFactor == 1)
{
if (m_firstGesturePoint.x > 0 && fabs(point.x - m_firstGesturePoint.x) > 100)
{
if (point.x < m_firstGesturePoint.x)
OnAction(CAction(ACTION_NEXT_PICTURE));
else
OnAction(CAction(ACTION_PREV_PICTURE));
m_firstGesturePoint.x = 0;
}
}
else //zoomed in - free move mode
{
Move(PICTURE_MOVE_AMOUNT_TOUCH / m_iZoomFactor * (m_firstGesturePoint.x - point.x), PICTURE_MOVE_AMOUNT_TOUCH / m_iZoomFactor * (m_firstGesturePoint.y - point.y));
m_firstGesturePoint = point;
}
return EVENT_RESULT_HANDLED;
}
else if (event.m_id == ACTION_GESTURE_END)
return EVENT_RESULT_HANDLED;
else if (event.m_id == ACTION_GESTURE_ZOOM)
{
if (event.m_offsetX > 1)
Zoom((int)event.m_offsetX);
else
Zoom((int)(m_iZoomFactor - event.m_offsetX));
return EVENT_RESULT_HANDLED;
}
return EVENT_RESULT_UNHANDLED;
}
bool CGUIWindowSlideShow::OnAction(const CAction &action)
{
if (m_bScreensaver)
{
g_windowManager.PreviousWindow();
return true;
}
switch (action.GetID())
{
case ACTION_SHOW_CODEC:
{
CGUIDialogPictureInfo *pictureInfo = (CGUIDialogPictureInfo *)g_windowManager.GetWindow(WINDOW_DIALOG_PICTURE_INFO);
if (pictureInfo)
{
// no need to set the picture here, it's done in Render()
pictureInfo->DoModal();
}
}
break;
case ACTION_PREVIOUS_MENU:
case ACTION_NAV_BACK:
case ACTION_STOP:
g_windowManager.PreviousWindow();
break;
case ACTION_NEXT_PICTURE:
ShowNext();
break;
case ACTION_PREV_PICTURE:
ShowPrevious();
break;
case ACTION_MOVE_RIGHT:
if (m_iZoomFactor == 1)
ShowNext();
else
Move(PICTURE_MOVE_AMOUNT, 0);
break;
case ACTION_MOVE_LEFT:
if (m_iZoomFactor == 1)
ShowPrevious();
else
Move( -PICTURE_MOVE_AMOUNT, 0);
break;
case ACTION_MOVE_DOWN:
Move(0, PICTURE_MOVE_AMOUNT);
break;
case ACTION_MOVE_UP:
Move(0, -PICTURE_MOVE_AMOUNT);
break;
case ACTION_PAUSE:
if (m_bSlideShow)
m_bPause = !m_bPause;
break;
case ACTION_PLAYER_PLAY:
if (!m_bSlideShow)
{
m_bSlideShow = true;
m_bPause = false;
}
else if (m_bPause)
m_bPause = false;
break;
case ACTION_ZOOM_OUT:
Zoom(m_iZoomFactor - 1);
break;
case ACTION_ZOOM_IN:
Zoom(m_iZoomFactor + 1);
break;
case ACTION_ROTATE_PICTURE:
Rotate();
break;
case ACTION_ZOOM_LEVEL_NORMAL:
case ACTION_ZOOM_LEVEL_1:
case ACTION_ZOOM_LEVEL_2:
case ACTION_ZOOM_LEVEL_3:
case ACTION_ZOOM_LEVEL_4:
case ACTION_ZOOM_LEVEL_5:
case ACTION_ZOOM_LEVEL_6:
case ACTION_ZOOM_LEVEL_7:
case ACTION_ZOOM_LEVEL_8:
case ACTION_ZOOM_LEVEL_9:
Zoom((action.GetID() - ACTION_ZOOM_LEVEL_NORMAL) + 1);
break;
case ACTION_ANALOG_MOVE:
Move(action.GetAmount()*PICTURE_MOVE_AMOUNT_ANALOG, -action.GetAmount(1)*PICTURE_MOVE_AMOUNT_ANALOG);
break;
default:
return CGUIWindow::OnAction(action);
}
return true;
}
void CGUIWindowSlideShow::RenderErrorMessage()
{
if (!m_bErrorMessage)
return ;
const CGUIControl *control = GetControl(LABEL_ROW1);
if (NULL == control || control->GetControlType() != CGUIControl::GUICONTROL_LABEL)
{
CLog::Log(LOGERROR,"CGUIWindowSlideShow::RenderErrorMessage - cant get label control!");
return;
}
CGUIFont *pFont = ((CGUILabelControl *)control)->GetLabelInfo().font;
CGUITextLayout::DrawText(pFont, 0.5f*g_graphicsContext.GetWidth(), 0.5f*g_graphicsContext.GetHeight(), 0xffffffff, 0, g_localizeStrings.Get(747), XBFONT_CENTER_X | XBFONT_CENTER_Y);
}
bool CGUIWindowSlideShow::OnMessage(CGUIMessage& message)
{
switch ( message.GetMessage() )
{
case GUI_MSG_WINDOW_DEINIT:
{
if (m_Resolution != g_guiSettings.m_LookAndFeelResolution)
{
//FIXME: Use GUI resolution for now
//g_graphicsContext.SetVideoResolution(g_guiSettings.m_LookAndFeelResolution, TRUE);
}
// Reset();
if (message.GetParam1() != WINDOW_PICTURES)
m_ImageLib.Unload();
g_windowManager.ShowOverlay(OVERLAY_STATE_SHOWN);
FreeResources();
}
break;
case GUI_MSG_WINDOW_INIT:
{
m_Resolution = (RESOLUTION) g_guiSettings.GetInt("pictures.displayresolution");
//FIXME: Use GUI resolution for now
if (0 /*m_Resolution != g_guiSettings.m_LookAndFeelResolution && m_Resolution != INVALID && m_Resolution!=AUTORES*/)
g_graphicsContext.SetVideoResolution(m_Resolution);
else
m_Resolution = g_graphicsContext.GetVideoResolution();
CGUIWindow::OnMessage(message);
if (message.GetParam1() != WINDOW_PICTURES)
m_ImageLib.Load();
g_windowManager.ShowOverlay(OVERLAY_STATE_HIDDEN);
// turn off slideshow if we only have 1 image
if (m_slides->Size() <= 1)
m_bSlideShow = false;
return true;
}
break;
case GUI_MSG_START_SLIDESHOW:
{
CStdString strFolder = message.GetStringParam();
unsigned int iParams = message.GetParam1();
//decode params
bool bRecursive = false;
bool bRandom = false;
bool bNotRandom = false;
if (iParams > 0)
{
if ((iParams & 1) == 1)
bRecursive = true;
if ((iParams & 2) == 2)
bRandom = true;
if ((iParams & 4) == 4)
bNotRandom = true;
}
RunSlideShow(strFolder, bRecursive, bRandom, bNotRandom);
}
break;
case GUI_MSG_PLAYLISTPLAYER_STOPPED:
{
m_bPlayingVideo = false;
if (m_bSlideShow)
g_windowManager.ActivateWindow(WINDOW_SLIDESHOW);
}
break;
case GUI_MSG_PLAYBACK_STARTED:
{
if (m_bSlideShow && m_bPlayingVideo)
g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
}
break;
case GUI_MSG_PLAYBACK_STOPPED:
{
if (m_bSlideShow && m_bPlayingVideo)
{
m_bSlideShow = false;
g_windowManager.PreviousWindow();
}
}
break;
}
return CGUIWindow::OnMessage(message);
}
void CGUIWindowSlideShow::RenderPause()
{ // display the pause icon
if (m_bPause)
{
SET_CONTROL_VISIBLE(CONTROL_PAUSE);
}
else
{
SET_CONTROL_HIDDEN(CONTROL_PAUSE);
}
/*
static DWORD dwCounter=0;
dwCounter++;
if (dwCounter > 25)
{
dwCounter=0;
}
if (!m_bPause) return;
if (dwCounter <13) return;*/
}
void CGUIWindowSlideShow::Rotate()
{
if (!m_Image[m_iCurrentPic].DrawNextImage() && m_iZoomFactor == 1)
m_Image[m_iCurrentPic].Rotate(++m_iRotate);
}
void CGUIWindowSlideShow::Zoom(int iZoom)
{
if (iZoom > MAX_ZOOM_FACTOR || iZoom < 1)
return;
// set the zoom amount and then set so that the image is reloaded at the higher (or lower)
// resolution as necessary
if (!m_Image[m_iCurrentPic].DrawNextImage())
{
m_Image[m_iCurrentPic].Zoom(iZoom);
// check if we need to reload the image for better resolution
#ifdef RELOAD_ON_ZOOM
if (iZoom > m_iZoomFactor && !m_Image[m_iCurrentPic].FullSize())
m_bReloadImage = true;
if (iZoom == 1)
m_bReloadImage = true;
#endif
m_iZoomFactor = iZoom;
}
}
void CGUIWindowSlideShow::Move(float fX, float fY)
{
if (m_Image[m_iCurrentPic].IsLoaded() && m_Image[m_iCurrentPic].GetZoom() > 1)
{ // we move in the opposite direction, due to the fact we are moving
// the viewing window, not the picture.
m_Image[m_iCurrentPic].Move( -fX, -fY);
}
}
void CGUIWindowSlideShow::OnLoadPic(int iPic, int iSlideNumber, CBaseTexture* pTexture, int iOriginalWidth, int iOriginalHeight, bool bFullSize)
{
if (pTexture)
{
// set the pic's texture + size etc.
CSingleLock lock(m_slideSection);
if (iSlideNumber >= m_slides->Size())
{ // throw this away - we must have cleared the slideshow while we were still loading
delete pTexture;
return;
}
CLog::Log(LOGDEBUG, "Finished background loading %s", m_slides->Get(iSlideNumber)->GetPath().c_str());
if (m_bReloadImage)
{
if (m_Image[m_iCurrentPic].IsLoaded() && m_Image[m_iCurrentPic].SlideNumber() != iSlideNumber)
{ // wrong image (ie we finished loading the next image, not the current image)
delete pTexture;
return;
}
m_Image[m_iCurrentPic].UpdateTexture(pTexture);
m_Image[m_iCurrentPic].SetOriginalSize(iOriginalWidth, iOriginalHeight, bFullSize);
m_bReloadImage = false;
}
else
{
if (m_bSlideShow)
m_Image[iPic].SetTexture(iSlideNumber, pTexture, g_guiSettings.GetBool("slideshow.displayeffects") ? CSlideShowPic::EFFECT_RANDOM : CSlideShowPic::EFFECT_NONE);
else
m_Image[iPic].SetTexture(iSlideNumber, pTexture, CSlideShowPic::EFFECT_NO_TIMEOUT);
m_Image[iPic].SetOriginalSize(iOriginalWidth, iOriginalHeight, bFullSize);
m_Image[iPic].Zoom(m_iZoomFactor, true);
m_Image[iPic].m_bIsComic = false;
if (URIUtils::IsInRAR(m_slides->Get(m_iCurrentSlide)->GetPath()) || URIUtils::IsInZIP(m_slides->Get(m_iCurrentSlide)->GetPath())) // move to top for cbr/cbz
{
CURL url(m_slides->Get(m_iCurrentSlide)->GetPath());
CStdString strHostName = url.GetHostName();
if (URIUtils::GetExtension(strHostName).Equals(".cbr", false) || URIUtils::GetExtension(strHostName).Equals(".cbz", false))
{
m_Image[iPic].m_bIsComic = true;
m_Image[iPic].Move((float)m_Image[iPic].GetOriginalWidth(),(float)m_Image[iPic].GetOriginalHeight());
}
}
}
}
else
{ // Failed to load image. What should be done??
// We should wait for the current pic to finish rendering, then transistion it out,
// release the texture, and try and reload this pic from scratch
m_bErrorMessage = true;
}
}
void CGUIWindowSlideShow::Shuffle()
{
m_slides->Randomize();
m_iCurrentSlide = 0;
m_iNextSlide = 1;
m_bShuffled = true;
}
int CGUIWindowSlideShow::NumSlides() const
{
return m_slides->Size();
}
int CGUIWindowSlideShow::CurrentSlide() const
{
return m_iCurrentSlide + 1;
}
void CGUIWindowSlideShow::AddFromPath(const CStdString &strPath,
bool bRecursive,
SORT_METHOD method, SortOrder order, const CStdString &strExtensions)
{
if (strPath!="")
{
// reset the slideshow
Reset();
m_strExtensions = strExtensions;
if (bRecursive)
{
path_set recursivePaths;
AddItems(strPath, &recursivePaths, method, order);
}
else
AddItems(strPath, NULL, method, order);
}
}
void CGUIWindowSlideShow::RunSlideShow(const CStdString &strPath,
bool bRecursive /* = false */, bool bRandom /* = false */,
bool bNotRandom /* = false */, SORT_METHOD method /* = SORT_METHOD_LABEL */,
SortOrder order /* = SortOrderAscending */, const CStdString &strExtensions)
{
// stop any video
if (g_application.IsPlayingVideo())
g_application.StopPlaying();
AddFromPath(strPath, bRecursive, method, order, strExtensions);
// mutually exclusive options
// if both are set, clear both and use the gui setting
if (bRandom && bNotRandom)
bRandom = bNotRandom = false;
// NotRandom overrides the window setting
if ((!bNotRandom && g_guiSettings.GetBool("slideshow.shuffle")) || bRandom)
Shuffle();
StartSlideShow();
if (NumSlides())
g_windowManager.ActivateWindow(WINDOW_SLIDESHOW);
}
void CGUIWindowSlideShow::AddItems(const CStdString &strPath, path_set *recursivePaths, SORT_METHOD method, SortOrder order)
{
// check whether we've already added this path
if (recursivePaths)
{
CStdString path(strPath);
URIUtils::RemoveSlashAtEnd(path);
if (recursivePaths->find(path) != recursivePaths->end())
return;
recursivePaths->insert(path);
}
// fetch directory and sort accordingly
CFileItemList items;
if (!CDirectory::GetDirectory(strPath, items, m_strExtensions.IsEmpty()?g_settings.m_pictureExtensions:m_strExtensions,DIR_FLAG_NO_FILE_DIRS,true))
return;
items.Sort(method, order);
// need to go into all subdirs
for (int i = 0; i < items.Size(); i++)
{
CFileItemPtr item = items[i];
if (item->m_bIsFolder && recursivePaths)
{
AddItems(item->GetPath(), recursivePaths);
}
else if (!item->m_bIsFolder && !URIUtils::IsRAR(item->GetPath()) && !URIUtils::IsZIP(item->GetPath()))
{ // add to the slideshow
Add(item.get());
}
}
}
void CGUIWindowSlideShow::GetCheckedSize(float width, float height, int &maxWidth, int &maxHeight)
{
#ifdef RELOAD_ON_ZOOM
if (width * height > MAX_PICTURE_SIZE)
{
float fScale = sqrt((float)MAX_PICTURE_SIZE / (width * height));
width = fScale * width;
height = fScale * height;
}
maxWidth = (int)width;
maxHeight = (int)height;
if (maxWidth > (int)g_Windowing.GetMaxTextureSize())
maxWidth = g_Windowing.GetMaxTextureSize();
if (maxHeight > (int)g_Windowing.GetMaxTextureSize())
maxHeight = g_Windowing.GetMaxTextureSize();
#else
maxWidth = g_Windowing.GetMaxTextureSize();
maxHeight = g_Windowing.GetMaxTextureSize();
#endif
}
Jump to Line
Something went wrong with that request. Please try again.