rendered paste bodyIndex: libs/libmythui/mythimage.cpp
===================================================================
--- libs/libmythui/mythimage.cpp (revision 22250)
+++ libs/libmythui/mythimage.cpp (working copy)
@@ -56,6 +56,7 @@
void MythImage::UpRef(void)
{
+ QMutexLocker locker(&m_RefCountLock);
if (m_ui && m_cached && m_RefCount == 1)
m_ui->ExcludeFromCacheSize(this);
m_RefCount++;
@@ -63,6 +64,7 @@
bool MythImage::DownRef(void)
{
+ m_RefCountLock.lock();
m_RefCount--;
if (m_ui && m_cached)
{
@@ -74,19 +76,23 @@
if (m_RefCount <= 0)
{
+ m_RefCountLock.unlock();
delete this;
return true;
}
+ m_RefCountLock.unlock();
return false;
}
int MythImage::RefCount(void)
{
+ QMutexLocker locker(&m_RefCountLock);
return m_RefCount;
}
void MythImage::SetIsInCache(bool bCached)
{
+ QMutexLocker locker(&m_RefCountLock);
if (m_ui && m_RefCount == 1)
{
if (!m_cached && bCached)
@@ -99,6 +105,7 @@
void MythImage::Assign(const QImage &img)
{
+ QMutexLocker locker(&m_RefCountLock);
if (m_ui && m_RefCount == 1 && m_cached)
m_ui->ExcludeFromCacheSize(this);
*(static_cast<QImage *> (this)) = img;
Index: libs/libmythui/mythuiimage.cpp
===================================================================
--- libs/libmythui/mythuiimage.cpp (revision 22249)
+++ libs/libmythui/mythuiimage.cpp (working copy)
@@ -9,6 +9,7 @@
#include <QDir>
#include <QDomDocument>
#include <QImageReader>
+#include <QReadWriteLock>
#include <QRunnable>
#include <QEvent>
#include <QCoreApplication>
@@ -26,6 +27,10 @@
const int kImageLoadEventType = 35112;
+#define LOC QString("MythUIImage(%1): ").arg((long long)this)
+#define LOC_ERR QString("MythUIImage(%1) ERROR: ").arg((long long)this)
+#define LOC_WARN QString("MythUIImage(%1) WARNING: ").arg((long long)this)
+
/*!
* \class ImageLoadThread
*/
@@ -80,7 +85,21 @@
};
/////////////////////////////////////////////////////////////////
+class MythUIImagePrivate
+{
+ public:
+ MythUIImagePrivate(MythUIImage *p)
+ : m_parent(p), m_UpdateLock(QReadWriteLock::Recursive)
+ { };
+ ~MythUIImagePrivate() {};
+ MythUIImage *m_parent;
+
+ QReadWriteLock m_UpdateLock;
+};
+
+/////////////////////////////////////////////////////////////////
+
QHash<QString, MythUIImage*> MythUIImage::m_loadingImages;
QMutex MythUIImage::m_loadingImagesLock;
QWaitCondition MythUIImage::m_loadingImagesCond;
@@ -98,6 +117,8 @@
m_imageLoadThread = NULL;
+ d = new MythUIImagePrivate(this);
+
Init();
}
@@ -112,6 +133,8 @@
m_HighNum = 0;
m_Delay = -1;
+ d = new MythUIImagePrivate(this);
+
Init();
}
@@ -122,6 +145,8 @@
m_HighNum = 0;
m_Delay = -1;
+ d = new MythUIImagePrivate(this);
+
Init();
}
@@ -130,6 +155,9 @@
Clear();
if (m_maskImage)
m_maskImage->DownRef();
+
+ if (d)
+ delete d;
}
/**
@@ -151,11 +179,16 @@
*/
void MythUIImage::Reset(void)
{
+ d->m_UpdateLock.lockForWrite();
if (m_Filename != m_OrigFilename)
{
m_Filename = m_OrigFilename;
+ d->m_UpdateLock.unlock();
Load();
}
+ else
+ d->m_UpdateLock.unlock();
+
MythUIType::Reset();
}
@@ -197,6 +230,7 @@
*/
void MythUIImage::SetFilename(const QString &filename)
{
+ QWriteLocker updateLocker(&d->m_UpdateLock);
m_Filename = filename;
}
@@ -207,6 +241,7 @@
void MythUIImage::SetFilepattern(const QString &filepattern, int low,
int high)
{
+ QWriteLocker updateLocker(&d->m_UpdateLock);
m_Filename = filepattern;
m_LowNum = low;
m_HighNum = high;
@@ -217,6 +252,7 @@
*/
void MythUIImage::SetImageCount(int low, int high)
{
+ QWriteLocker updateLocker(&d->m_UpdateLock);
m_LowNum = low;
m_HighNum = high;
}
@@ -226,6 +262,7 @@
*/
void MythUIImage::SetDelay(int delayms)
{
+ QWriteLocker updateLocker(&d->m_UpdateLock);
m_Delay = delayms;
m_LastDisplay = QTime::currentTime();
m_CurPos = 0;
@@ -237,6 +274,7 @@
*/
void MythUIImage::SetImage(MythImage *img)
{
+ QWriteLocker updateLocker(&d->m_UpdateLock);
if (!img)
{
Reset();
@@ -285,12 +323,16 @@
// HACK: This is just a workaround for the buttonlist inheritance problem
// until the image cache is completed.
+ d->m_UpdateLock.lockForRead();
if (m_gradient)
{
+ d->m_UpdateLock.unlock();
Load();
return;
}
+ d->m_UpdateLock.unlock();
+ QWriteLocker updateLocker(&d->m_UpdateLock);
QSize aSize = m_Area.size();
QVector<MythImage *>::iterator it;
@@ -333,6 +375,7 @@
*/
void MythUIImage::ForceSize(const QSize &size)
{
+ QWriteLocker updateLocker(&d->m_UpdateLock);
if (m_ForceSize == size)
return;
@@ -341,22 +384,10 @@
if (size.isEmpty())
return;
- QSize aSize = m_Area.size();
- QMutexLocker locker(&m_ImagesLock);
+ SetSize(m_ForceSize);
- QHash<int, MythImage *>::iterator it;
- for (it = m_Images.begin(); it != m_Images.end(); ++it)
- {
- MythImage *im = (*it);
-
- int w = (m_ForceSize.width() <= 0) ? im->width() : m_ForceSize.width();
- int h = (m_ForceSize.height() <= 0) ? im->height() : m_ForceSize.height();
-
- im->Resize(QSize(w, h), m_preserveAspect);
- aSize = aSize.expandedTo(im->size());
- }
-
- SetSize(m_ForceSize);
+ SetRedraw();
+ return;
}
/**
@@ -372,6 +403,7 @@
*/
void MythUIImage::SetSize(const QSize &size)
{
+ QWriteLocker updateLocker(&d->m_UpdateLock);
MythUIType::SetSize(size);
m_NeedLoad = true;
}
@@ -391,6 +423,7 @@
*/
void MythUIImage::SetCropRect(const MythRect &rect)
{
+ QWriteLocker updateLocker(&d->m_UpdateLock);
m_cropRect = rect;
SetRedraw();
}
@@ -401,6 +434,7 @@
*/
QString MythUIImage::GenImageLabel(const QString &filename, int w, int h) const
{
+ QReadLocker updateLocker(&d->m_UpdateLock);
QString imagelabel;
QString s_Attrib;
@@ -429,6 +463,7 @@
*/
QString MythUIImage::GenImageLabel(int w, int h) const
{
+ QReadLocker updateLocker(&d->m_UpdateLock);
return GenImageLabel(m_Filename, w, h);
}
@@ -437,13 +472,17 @@
*/
bool MythUIImage::Load(bool allowLoadInBackground)
{
+ d->m_UpdateLock.lockForRead();
if (m_Filename.isEmpty() && (!m_gradient))
{
+ d->m_UpdateLock.unlock();
Clear();
+ QWriteLocker updateLocker(&d->m_UpdateLock);
SetRedraw();
return false;
}
+ d->m_UpdateLock.unlock();
Clear();
@@ -454,7 +493,9 @@
int w = -1;
int h = -1;
+ bool bForceResize = false;
+ d->m_UpdateLock.lockForWrite();
if (!m_ForceSize.isNull())
{
if (m_ForceSize.width() != -1)
@@ -462,11 +503,46 @@
if (m_ForceSize.height() != -1)
h = m_ForceSize.height();
+
+ bForceResize = true;
}
+ if (m_gradient)
+ {
+ int gradWidth = 10;
+ int gradHeight = 10;
+
+ if (!m_Area.isEmpty())
+ {
+ gradWidth = m_Area.size().width();
+ gradHeight = m_Area.size().height();
+ }
+ else if ((w > 0) && (h > 0))
+ {
+ gradWidth = w;
+ gradHeight = h;
+ }
+
+ int sr, sg, sb;
+ m_gradientStart.getRgb(&sr, &sg, &sb);
+
+ int er, eg, eb;
+ m_gradientEnd.getRgb(&er, &eg, &eb);
+
+ m_Filename =
+ QString("gradient-%1x%2-%3-%4-%5-%6-%7-%8-%9-%10")
+ .arg(gradWidth).arg(gradHeight)
+ .arg(sr).arg(sg).arg(sb).arg(er).arg(eg).arg(eb)
+ .arg(m_gradientAlpha).arg(m_gradientDirection);
+ VERBOSE(VB_FILE+VB_EXTRA, LOC + QString("Auto-generated gradient "
+ "filename of '%1'").arg(m_Filename));
+ }
+ d->m_UpdateLock.unlock();
+
QString imagelabel;
QString filename = m_Filename;
+ d->m_UpdateLock.lockForRead();
for (int i = m_LowNum; i <= m_HighNum; i++)
{
if (m_HighNum >= 1)
@@ -479,6 +555,8 @@
if ((allowLoadInBackground) &&
(!GetMythUI()->LoadCacheImage(filename, imagelabel, false)))
{
+ VERBOSE(VB_FILE+VB_EXTRA, LOC + QString("Load(), spawning "
+ "thread to load '%1'").arg(filename));
m_imageLoadThread =
new ImageLoadThread(this, m_Filename, filename, i);
GetMythUI()->GetImageThreadPool()->start(m_imageLoadThread);
@@ -486,9 +564,14 @@
else
{
// Perform a blocking load
+ VERBOSE(VB_FILE+VB_EXTRA, LOC + QString("Load(), loading "
+ "'%1' in foreground").arg(filename));
MythImage *image = LoadImage(filename, i);
if (image)
{
+ d->m_UpdateLock.unlock();
+ d->m_UpdateLock.lockForWrite();
+
if (m_ForceSize.isNull())
SetSize(image->size());
@@ -498,9 +581,12 @@
SetRedraw();
m_LastDisplay = QTime::currentTime();
+ d->m_UpdateLock.unlock();
+ d->m_UpdateLock.lockForRead();
}
}
}
+ d->m_UpdateLock.unlock();
return true;
}
@@ -510,6 +596,7 @@
*/
MythImage *MythUIImage::LoadImage(const QString &imFile, int imageNumber)
{
+ d->m_UpdateLock.lockForRead();
QString filename = imFile;
m_loadingImagesLock.lock();
@@ -522,6 +609,7 @@
"file is already being loaded by this same MythUIImage in "
"another thread.").arg(filename));
m_loadingImagesLock.unlock();
+ d->m_UpdateLock.unlock();
return NULL;
}
@@ -607,6 +695,7 @@
m_loadingImagesCond.wakeAll();
m_loadingImagesLock.unlock();
+ d->m_UpdateLock.unlock();
return NULL;
}
}
@@ -649,6 +738,7 @@
if (bNeedLoad)
GetMythUI()->CacheImage(imagelabel, image);
}
+ d->m_UpdateLock.unlock();
if (image->isNull())
{
@@ -680,6 +770,7 @@
*/
void MythUIImage::Pulse(void)
{
+ QWriteLocker updateLocker(&d->m_UpdateLock);
if (m_Delay > 0 &&
abs(m_LastDisplay.msecsTo(QTime::currentTime())) > m_Delay)
{
@@ -709,6 +800,7 @@
m_ImagesLock.lock();
if (m_Images.size() > 0)
{
+ d->m_UpdateLock.lockForWrite();
if (m_CurPos > (uint)m_Images.size())
m_CurPos = 0;
if (!m_Images.contains(m_CurPos))
@@ -729,7 +821,19 @@
int alpha = CalcAlpha(alphaMod);
MythImage *currentImage = m_Images[m_CurPos];
+ currentImage->UpRef();
m_ImagesLock.unlock();
+ d->m_UpdateLock.unlock();
+ d->m_UpdateLock.lockForRead();
+
+ if (!m_ForceSize.isNull() && m_ForceSize != currentImage->size())
+ {
+ int w = (m_ForceSize.width() <= 0) ? currentImage->width() : m_ForceSize.width();
+ int h = (m_ForceSize.height() <= 0) ? currentImage->height() : m_ForceSize.height();
+
+ currentImage->Resize(QSize(w, h), m_preserveAspect);
+ }
+
QRect currentImageArea = currentImage->rect();
if (!m_ForceSize.isNull())
@@ -754,6 +858,8 @@
srcRect = currentImageArea;
p->DrawImage(area, currentImage, srcRect, alpha);
+ currentImage->DownRef();
+ d->m_UpdateLock.unlock();
}
else
m_ImagesLock.unlock();
@@ -764,6 +870,7 @@
*/
bool MythUIImage::ParseElement(QDomElement &element)
{
+ QWriteLocker updateLocker(&d->m_UpdateLock);
if (element.tagName() == "filename")
{
m_OrigFilename = m_Filename = getFirstText(element);
@@ -891,10 +998,12 @@
*/
void MythUIImage::CopyFrom(MythUIType *base)
{
+ d->m_UpdateLock.lockForWrite();
MythUIImage *im = dynamic_cast<MythUIImage *>(base);
if (!im)
{
VERBOSE(VB_IMPORTANT, "ERROR, bad parsing");
+ d->m_UpdateLock.unlock();
return;
}
@@ -939,8 +1048,16 @@
m_NeedLoad = im->m_NeedLoad;
+ d->m_UpdateLock.unlock();
+
+ d->m_UpdateLock.lockForRead();
if (m_NeedLoad)
+ {
+ d->m_UpdateLock.unlock();
Load();
+ }
+ else
+ d->m_UpdateLock.unlock();
}
/**
@@ -948,6 +1065,7 @@
*/
void MythUIImage::CreateCopy(MythUIType *parent)
{
+ QReadLocker updateLocker(&d->m_UpdateLock);
MythUIImage *im = new MythUIImage(parent, objectName());
im->CopyFrom(this);
}
@@ -957,8 +1075,14 @@
*/
void MythUIImage::Finalize(void)
{
+ d->m_UpdateLock.lockForRead();
if (m_NeedLoad)
+ {
+ d->m_UpdateLock.unlock();
Load();
+ }
+ else
+ d->m_UpdateLock.unlock();
MythUIType::Finalize();
}
@@ -968,10 +1092,16 @@
*/
void MythUIImage::LoadNow(void)
{
+ d->m_UpdateLock.lockForWrite();
if (m_NeedLoad)
+ {
+ d->m_UpdateLock.unlock();
return;
+ }
m_NeedLoad = true;
+ d->m_UpdateLock.unlock();
+
Load(false);
MythUIType::LoadNow();
@@ -994,17 +1124,25 @@
if (!image)
return;
+ d->m_UpdateLock.lockForRead();
if (le->GetBasefile() != m_Filename)
{
+ //VERBOSE(VB_FILE+VB_EXTRA,QString("MythUIImage::customEvent(%1): "
+ // "Expecting '%2', got '%3'").arg((long long)this)
+ // .arg(m_Filename).arg(le->GetBasefile()));
+ d->m_UpdateLock.unlock();
image->DownRef();
return;
}
+ d->m_UpdateLock.unlock();
QString filename = le->GetFilename();
int number = le->GetNumber();
+ d->m_UpdateLock.lockForWrite();
if (m_ForceSize.isNull())
SetSize(image->size());
+ d->m_UpdateLock.unlock();
m_ImagesLock.lock();
if (m_Images.contains(number))
@@ -1017,7 +1155,9 @@
m_Images[number] = image;
m_ImagesLock.unlock();
+ d->m_UpdateLock.lockForWrite();
SetRedraw();
m_LastDisplay = QTime::currentTime();
+ d->m_UpdateLock.unlock();
}
}
Index: libs/libmythui/mythuihelper.cpp
===================================================================
--- libs/libmythui/mythuihelper.cpp (revision 22249)
+++ libs/libmythui/mythuihelper.cpp (working copy)
@@ -100,6 +100,7 @@
QMap<QString, uint> CacheTrack;
QMutex *m_cacheLock;
size_t m_cacheSize;
+ QMutex *m_cacheSizeLock;
uint maxImageCacheSize;
@@ -144,6 +145,7 @@
m_xbase(0), m_ybase(0), m_height(0), m_width(0),
m_baseWidth(800), m_baseHeight(600), m_isWide(false),
m_cacheLock(new QMutex(QMutex::Recursive)), m_cacheSize(0),
+ m_cacheSizeLock(new QMutex(QMutex::Recursive)),
m_screenxbase(0), m_screenybase(0), m_screenwidth(0), m_screenheight(0),
bigfontsize(0), mediumfontsize(0), smallfontsize(0),
screensaver(NULL), screensaverEnabled(false), display_res(NULL),
@@ -343,10 +345,10 @@
d->Init();
d->callbacks = cbs;
- d->m_cacheLock->lock();
+ d->m_cacheSizeLock->lock();
d->maxImageCacheSize = GetMythDB()->GetNumSetting("UIImageCacheSize", 20)
* 1024 * 1024;
- d->m_cacheLock->unlock();
+ d->m_cacheSizeLock->unlock();
VERBOSE(VB_GENERAL, QString("MythUI Image Cache size set to %1 bytes")
.arg(d->maxImageCacheSize));
@@ -445,7 +447,10 @@
}
d->CacheTrack.clear();
+
+ d->m_cacheSizeLock->lock();
d->m_cacheSize = 0;
+ d->m_cacheSizeLock->unlock();
ClearOldImageCache();
}
@@ -473,9 +478,9 @@
if (!im)
return;
- d->m_cacheLock->lock();
+ d->m_cacheSizeLock->lock();
d->m_cacheSize += im->numBytes();
- d->m_cacheLock->unlock();
+ d->m_cacheSizeLock->unlock();
}
void MythUIHelper::ExcludeFromCacheSize(MythImage *im)
@@ -483,9 +488,9 @@
if (!im)
return;
- d->m_cacheLock->lock();
+ d->m_cacheSizeLock->lock();
d->m_cacheSize -= im->numBytes();
- d->m_cacheLock->unlock();
+ d->m_cacheSizeLock->unlock();
}
MythImage *MythUIHelper::CacheImage(const QString &url, MythImage *im,
@@ -511,9 +516,11 @@
// delete the oldest cached images until we fall below threshold.
QMutexLocker locker(d->m_cacheLock);
+ d->m_cacheSizeLock->lock();
while (d->m_cacheSize + im->numBytes() >= d->maxImageCacheSize &&
d->imageCache.size())
{
+ d->m_cacheSizeLock->unlock();
QMap<QString, MythImage*>::iterator it = d->imageCache.begin();
uint oldestTime = QDateTime::currentDateTime().toTime_t();
QString oldestKey = it.key();
@@ -541,10 +548,16 @@
d->imageCache[oldestKey]->DownRef();
d->imageCache.remove(oldestKey);
d->CacheTrack.remove(oldestKey);
+
+ d->m_cacheSizeLock->lock();
}
else
+ {
+ d->m_cacheSizeLock->lock();
break;
+ }
}
+ d->m_cacheSizeLock->unlock();
QMap<QString, MythImage*>::iterator it = d->imageCache.find(url);
if (it == d->imageCache.end())
@@ -1241,7 +1254,10 @@
MythImage *MythUIHelper::LoadCacheImage(QString srcfile, QString label,
bool allowLoadFromDisk)
{
- //VERBOSE(VB_GENERAL, QString("LoadCacheImage %1:%2").arg(srcfile).arg(label));
+ //VERBOSE(VB_FILE+VB_EXTRA, QString("LoadCacheImage %1:%2").arg(srcfile).arg(label));
+
+ if (srcfile.isEmpty() || label.isEmpty())
+ return NULL;
QString cachefilepath = GetThemeCacheDir() + '/' + label;
QFileInfo fi(cachefilepath);
Index: libs/libmythui/mythuiimage.h
===================================================================
--- libs/libmythui/mythuiimage.h (revision 22249)
+++ libs/libmythui/mythuiimage.h (working copy)
@@ -9,6 +9,7 @@
#include "mythuitype.h"
#include "mythimage.h"
+class MythUIImagePrivate;
class MythScreenType;
class ImageLoadThread;
@@ -125,6 +126,8 @@
ImageLoadThread *m_imageLoadThread;
+ MythUIImagePrivate *d;
+
friend class MythThemeBase;
friend class MythUIButtonListItem;
friend class MythUIProgressBar;