All pastes #1596978 Raw Edit

Someone

public text v1 · immutable
#1596978 ·published 2009-10-06 06:19 UTC
rendered paste body
Index: 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;