Index: mythmusic/mythmusic/mainvisual.cpp
===================================================================
--- mythmusic/mythmusic/mainvisual.cpp	(revision 9914)
+++ mythmusic/mythmusic/mainvisual.cpp	(working copy)
@@ -50,6 +50,7 @@
         MainVisual::registerVisFactory(new SynaesthesiaFactory);
         MainVisual::registerVisFactory(new SpectrumFactory);
         MainVisual::registerVisFactory(new AlbumArtFactory);
+        MainVisual::registerVisFactory(new SlideShowFactory);
 #ifdef OPENGL_SUPPORT
         MainVisual::registerVisFactory(new GearsFactory);
 #endif
Index: mythmusic/mythmusic/visualize.cpp
===================================================================
--- mythmusic/mythmusic/visualize.cpp	(revision 9914)
+++ mythmusic/mythmusic/visualize.cpp	(working copy)
@@ -398,6 +398,249 @@
 }
 
 
+SlideShow::SlideShow(MainVisual *parent)
+{
+    pParent = parent;
+    m_curImg.reset();
+    
+    // get GalleryDir from settings.  if it doesn't exist, set
+    // the m_msg to an error, and never start the thread to load
+    // m_files
+    QString rootDir = gContext->GetSetting("GalleryDir");
+    QDir dir(rootDir);
+    if (!dir.exists() || !dir.isReadable())
+    {
+        m_msg = "MythGallery misconfigured";
+        m_bNeedToDraw = true;
+    }
+    else
+    {
+        fps = 2;
+        m_nSlideDelay = gContext->GetNumSetting("SlideshowDelay", 5);
+        m_nCurrentFrame = m_nSlideDelay * fps;
+        m_bNeedToDraw = false;
+        m_imageFinder.m_baseDir = dir.path();
+
+        // create and start the thread that fills m_files
+        m_imageFinder.start(QThread::LowestPriority);
+    }
+}
+
+SlideShow::ImageFinder::ImageFinder(void)
+{
+    m_abort = false;
+}
+
+unsigned SlideShow::ImageFinder::GetCount(void)
+{
+    m_filesMux.lock();
+    unsigned cnt = m_files.count();
+    m_filesMux.unlock();
+    return cnt;
+}
+
+bool SlideShow::ImageFinder::GetRandImage(QImage *pImage)
+{
+    bool ret = false;
+
+    if (m_filesMux.tryLock())
+    {
+        if (m_files.count())
+        {
+            int nFile = rand() % m_files.count();
+            QImage tmpImage(m_files[nFile]);
+            // only modify pImage if there's a valid replacement
+            if (!tmpImage.isNull())
+            {
+                pImage->reset();
+                *pImage = tmpImage;
+                ret = true;
+            }
+        }
+        m_filesMux.unlock();
+    }
+    return ret;
+}
+
+void SlideShow::ImageFinder::abort(void)
+{
+    // if the thread isn't finished, tell it to abort and then
+    // wait for it.
+    if (!this->finished())
+    {
+        m_filesMux.lock();
+        m_abort = true;
+        m_filesMux.unlock();
+        this->wait();
+    }
+}
+
+void SlideShow::ImageFinder::run()
+{
+    bool abort = false;
+  
+    // gather a list of all directories under m_baseDir (including m_baseDir)
+    // to unlimited depth.  Store them as absolute paths and check for dupes
+    // to prevent recursive symbolic links.
+    QStringList dirList;
+    dirList.append(m_baseDir);
+
+    QStringList::Iterator it = dirList.begin();
+    while (!abort && (it != dirList.end()))
+    {
+        QDir dir(*it, QString::null, QDir::Unsorted,
+                 QDir::Dirs | QDir::Readable | QDir::Executable);
+        for (unsigned i = 0; !abort && (i < dir.count()); i++)
+        {
+            // completely skip ANY directory that starts with a period.
+            // this will eliminate hidden stuff as well as stuff like
+            // "." and ".." (and gallery's .thumbnails)
+            if (dir[i][0] != '.')
+            {
+                QString path = *it + QDir::separator() + dir[i];
+                path = QDir(path).canonicalPath();
+                // if path isn't in dirList, append it
+                if (dirList.find(path) == dirList.end())
+                {
+                    dirList.append(path);
+                }
+            }
+        }
+        it++;
+    }
+
+    // now loop the directories, and find images within
+    for (unsigned i = 0; !abort && (i < dirList.count()); i++)
+    {
+      // Get directory contents based on filter
+        QDir folder(dirList[i], "*.png;*.jpg;*.jpeg;*.gif;*.bmp",
+                    QDir::Name | QDir::IgnoreCase, 
+                    QDir::Files | QDir::Readable);
+        QString dirname = dirList[i] + QDir::separator();
+    
+        for (unsigned j = 0; !abort && (j < folder.count()); j++)
+        {
+            // for each file that looks like an image, validate that
+            // Qt can load it before adding it to The List
+            QString fname = dirname + folder[j];
+            QImage img(fname);
+            if (!img.isNull())
+            {
+                m_filesMux.lock();
+                abort = m_abort;
+                m_files.append(fname);
+                m_filesMux.unlock();
+            }
+            img.reset();
+        }
+    }
+}
+
+SlideShow::~SlideShow()
+{
+    // if the finder is running, tell it to abort
+    if (m_imageFinder.running())
+    {
+        m_imageFinder.abort();
+    }
+}
+
+void SlideShow::resize(const QSize &newsize)
+{
+    m_size = newsize;
+    m_bNeedToDraw = true;
+}
+
+bool SlideShow::process(VisualNode *)
+{  
+    if (m_nCurrentFrame >= (m_nSlideDelay * fps))
+    {
+        // is anything available to load? if so, set redraw
+        if (m_imageFinder.GetRandImage(&m_curImg))
+        {
+          // random image retrieved - set redraw
+            m_msg = "";
+            m_bNeedToDraw = true;
+            m_nCurrentFrame = 0;
+        }
+        else if (m_imageFinder.finished())
+        {
+            // no image?  is the image finder done?  if so,
+            // must not be any images to load
+            m_msg = "No Images Found";
+            m_bNeedToDraw = true;
+        }
+        else if (m_curImg.isNull())
+        {
+            // no image, but the finder isn't done.  Display
+            // some text to prevent black screens
+            m_msg = "Loading Images...";
+            m_bNeedToDraw = true;
+        }
+    }
+    else
+    {
+        m_nCurrentFrame++;
+    }
+    return true;
+}
+
+bool SlideShow::draw(QPainter *p, const QColor &back)
+{
+    bool ret = true;
+    
+    if (!pParent->decoder())
+    {
+        ret = false;
+    }
+    else if (m_bNeedToDraw)
+    {
+        if (!m_msg.isEmpty())
+        {
+            p->fillRect(0, 0, m_size.width(), m_size.height(), back);
+            p->setPen(Qt::white);
+            p->setFont(gContext->GetMediumFont());
+            p->drawText(m_size.width() / 2 - 200,
+                        m_size.height() / 2 - 10, 400, 20, 
+                        Qt::AlignCenter, QObject::tr(m_msg));
+            m_bNeedToDraw = false;
+        }
+        else if (!m_curImg.isNull())
+        {
+            QSize artsize = m_curImg.scale(m_size, QImage::ScaleMin).size();
+        
+            // Paint the image
+            p->fillRect(0, 0, m_size.width(), m_size.height(), back);
+            p->drawPixmap((m_size.width() - artsize.width()) / 2,
+                          (m_size.height() - artsize.height()) / 2,
+                          m_curImg.smoothScale(m_size, QImage::ScaleMin));
+            // Store our new size
+            m_bNeedToDraw = false;
+        }
+    } // if need redraw
+    return ret;
+}
+
+const QString &SlideShowFactory::name(void) const
+{
+    static QString name("SlideShow");
+    return name;
+}
+
+const QString &SlideShowFactory::description(void) const
+{
+    static QString name("Displays a mythgallery based slideshow");
+    return name;
+}
+
+VisualBase *SlideShowFactory::create(MainVisual *parent, long int winid)
+{
+    (void)winid;
+    return new SlideShow(parent);
+}
+
+
+
 Blank::Blank()
     : VisualBase(true)
 {
Index: mythmusic/mythmusic/visualize.h
===================================================================
--- mythmusic/mythmusic/visualize.h	(revision 9914)
+++ mythmusic/mythmusic/visualize.h	(working copy)
@@ -13,6 +13,9 @@
 #define VISUALIZE_H
 
 #include <mythtv/visual.h>
+#include <qvaluevector.h>
+#include <qthread.h>
+#include <qimage.h>
 #include "mainvisual.h"
 #include "constants.h"
 #include "config.h"
@@ -109,6 +112,57 @@
     VisualBase *create(MainVisual *parent, long int winid);
 };
 
+
+class SlideShow : public VisualBase
+{
+  public:
+    SlideShow(MainVisual *parent);
+    virtual ~SlideShow();
+
+    void resize(const QSize &size);
+    bool process(VisualNode *node = 0);
+    bool draw(QPainter *p, const QColor &back = Qt::black);
+
+  private:
+    QImage m_curImg;
+    QSize m_size;
+    QString m_msg;
+    int m_nSlideDelay;
+    int m_nCurrentFrame;
+    bool m_bNeedToDraw;
+    MainVisual *pParent;
+
+    class ImageFinder : public QThread
+    {
+      public:
+        ImageFinder(void);
+        virtual void run();
+        
+        bool GetRandImage(QImage *pImage);
+        unsigned GetCount(void);
+        void abort(void);
+        
+        QMutex m_filesMux;
+        QString m_baseDir;
+      private:
+        bool m_abort;
+        QValueVector <QString> m_files;
+    };
+
+    ImageFinder m_imageFinder;
+    
+};
+
+class SlideShowFactory : public VisFactory
+{
+  public:
+    const QString &name(void) const;
+    const QString &description(void) const;
+    VisualBase *create(MainVisual *parent, long int winid);
+};
+
+
+
 class Blank : public VisualBase
 {
     // This draws ... well ... nothing	
