<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">Index: mythplugins/mythmusic/mythmusic/playbackbox.h
===================================================================
--- mythplugins/mythmusic/mythmusic/playbackbox.h	(revision 10952)
+++ mythplugins/mythmusic/mythmusic/playbackbox.h	(working copy)
@@ -67,6 +67,7 @@
     void checkForPlaylists();
     void handleTreeListSignals(int, IntVector*);
     void visEnable();
+    void bannerDisable();
     void changeVolume(bool up_or_down);
     void toggleMute();
     void resetTimer();
@@ -109,6 +110,8 @@
     void openOutputDevice(void);
     void postUpdate();
     void playFirstTrack();
+    void bannerEnable(Metadata *mdata);
+    void bannerToggle(Metadata *mdata);
 
     QIODevice *input;
     AudioOutput *output;
@@ -159,6 +162,7 @@
     int visual_mode_delay;
     QTimer *visual_mode_timer;
     QTimer *lcd_update_timer;
+    QTimer *banner_timer;
     int visualizer_status;
 
     bool showrating;
Index: mythplugins/mythmusic/mythmusic/playbackbox.cpp
===================================================================
--- mythplugins/mythmusic/mythmusic/playbackbox.cpp	(revision 10952)
+++ mythplugins/mythmusic/mythmusic/playbackbox.cpp	(working copy)
@@ -42,6 +42,7 @@
     mainvisual = NULL;
     visual_mode_timer = NULL;
     lcd_update_timer = NULL;
+    banner_timer = NULL;
     waiting_for_playlists_timer = NULL;
     playlist_tree = NULL;
     playlist_popup = NULL;    
@@ -61,6 +62,9 @@
     curSmartPlaylistCategory = "";
     curSmartPlaylistName = "";
     
+    banner_timer = new QTimer(this);
+    connect(banner_timer, SIGNAL(timeout()), this, SLOT(bannerDisable()));
+
     menufilters = gContext-&gt;GetNumSetting("MusicMenuFilters", 0);
 
     cd_reader_thread = NULL;
@@ -367,7 +371,10 @@
             showMenu();
         }
         else if (action == "INFO")
-            showEditMetadataDialog();
+            if (visualizer_status == 2) 
+                bannerToggle(curMeta);
+            else
+                showEditMetadataDialog();
         else
             handled = false;
     }
@@ -401,6 +408,7 @@
                                             160, 160);
                 setUpdatesEnabled(true);
                 mainvisual-&gt;setVisual(visual_workaround);
+                bannerDisable();
 
                 if (!m_parent-&gt;IsExitingToMain())
                     handled = true;
@@ -1122,6 +1130,7 @@
 
         decoder-&gt;start();
 
+        bannerEnable(curMeta);
         isplaying = true;
         curMeta-&gt;setLastPlay();
         curMeta-&gt;incPlayCount();    
@@ -1135,9 +1144,37 @@
         setUpdatesEnabled(false);
         mainvisual-&gt;setGeometry(0, 0, screenwidth, screenheight);
         visualizer_status = 2;
+    } 
+    else 
+    {
+        bannerDisable();
     }
 }
 
+void PlaybackBoxMusic::bannerEnable(Metadata *mdata)
+{
+    if (visualizer_status != 2) 
+        return;
+    
+    banner_timer-&gt;start(8000);
+    mainvisual-&gt;addInformation("\"" + mdata-&gt;Title() + "\"\n" + 
+                               mdata-&gt;Artist() + " - " + mdata-&gt;Album());
+}
+
+void PlaybackBoxMusic::bannerToggle(Metadata *mdata) 
+{
+    if (banner_timer-&gt;isActive())
+        bannerDisable();
+    else
+        bannerEnable(mdata);
+}
+
+void PlaybackBoxMusic::bannerDisable()
+{
+    banner_timer-&gt;stop();
+    mainvisual-&gt;addInformation("");
+}
+
 void PlaybackBoxMusic::CycleVisualizer()
 {
     QString new_visualizer;
@@ -1905,6 +1942,7 @@
             mainvisual-&gt;setGeometry(screenwidth + 10, screenheight + 10, 
                                     160, 160);
         mainvisual-&gt;setVisual(visual_mode);
+        bannerDisable();
         visualizer_status = 1;
         if(visual_mode_delay &gt; 0)
         {
Index: mythplugins/mythmusic/mythmusic/visualize.h
===================================================================
--- mythplugins/mythmusic/mythmusic/visualize.h	(revision 10952)
+++ mythplugins/mythmusic/mythmusic/visualize.h	(working copy)
@@ -51,11 +51,11 @@
     Spectrum();
     virtual ~Spectrum();
 
-    void resize(const QSize &amp;size);
+    virtual void resize(const QSize &amp;size);
     bool process(VisualNode *node);
-    bool draw(QPainter *p, const QColor &amp;back = Qt::black);
+    virtual bool draw(QPainter *p, const QColor &amp;back = Qt::black);
 
-  private:
+  protected:
     inline double clamp(double cur, double max, double min);
 
     QColor startColor, targetColor;
@@ -93,12 +93,15 @@
     void resize(const QSize &amp;size);
     bool process(VisualNode *node = 0);
     bool draw(QPainter *p, const QColor &amp;back = Qt::black);
+    bool needsUpdate();
+    QString getImageFilename();
 
   private:
     QSize size, cursize;
     QString filename;
     QString directory;
     MainVisual *pParent;
+    QImage image;
 };
 
 class AlbumArtFactory : public VisFactory
@@ -132,6 +135,31 @@
     VisualBase *create(MainVisual *parent, long int winid);
 };
 
+class Squares : public Spectrum
+{
+  public:
+    Squares();
+    virtual ~Squares();
+    
+    void resize (const QSize &amp;newsize);
+    bool draw(QPainter *p, const QColor &amp;back = Qt::black);
+
+  private:
+    void drawRect(QPainter *p, QRect *rect, int i, int c, int w, int h);
+    QSize size;
+    MainVisual *pParent;
+    int fake_height;
+    int number_of_squares;
+};
+
+class SquaresFactory : public VisFactory
+{
+  public:
+    const QString &amp;name(void) const;
+    const QString &amp;description(void) const;
+    VisualBase *create(MainVisual *parent, long int winid);
+};
+
 #ifdef OPENGL_SUPPORT
 
 class Gears : public QGLWidget, public VisualBase
Index: mythplugins/mythmusic/mythmusic/visualize.cpp
===================================================================
--- mythplugins/mythmusic/mythmusic/visualize.cpp	(revision 10952)
+++ mythplugins/mythmusic/mythmusic/visualize.cpp	(working copy)
@@ -19,6 +19,7 @@
 #include &lt;qpixmap.h&gt;
 #include &lt;qimage.h&gt;
 #include &lt;qdir.h&gt;
+#include &lt;qurl.h&gt;
 
 #include &lt;iostream&gt;
 using namespace std;
@@ -266,13 +267,9 @@
 
 #else
     // Oops ... user doesn't have a Fast Fourier Library
-    p-&gt;fillRect(0, 0, size.width(), size.height(), back);
-    p-&gt;setPen(Qt::white);
-    p-&gt;setFont(gContext-&gt;GetMediumFont());
-    p-&gt;drawText(size.width() / 2 - 200, size.height() / 2 - 20, 400, 20, 
-                Qt::AlignCenter, QObject::tr("Visualization requires FFT library"));
-    p-&gt;drawText(size.width() / 2 - 200, size.height() / 2, 400, 20, 
-                Qt::AlignCenter, QObject::tr("Did you run configure?"));
+    drawWarning(p, back, size,
+                QObject::tr("Visualization requires FFT library") + "\n" + 
+                QObject::tr("Did you run configure?"));
 #endif
     
     return true;
@@ -304,10 +301,10 @@
     if (dec)
     {
         filename = dec-&gt;getFilename();
-        directory = filename.left(filename.findRev("/"));
+        directory = QUrl(filename).dirPath();
     }
 
-    fps = 20;
+    fps = 1;
 }
 
 AlbumArt::~AlbumArt()
@@ -325,57 +322,66 @@
     return true;
 }
 
+bool AlbumArt::needsUpdate() {
+    if (cursize != size)
+        return true;
+
+    if (filename != pParent-&gt;decoder()-&gt;getFilename()) {
+        QString curdir = QUrl(pParent-&gt;decoder()-&gt;getFilename()).dirPath();
+        if (directory != curdir)
+            return true;
+    }
+
+    return false;
+}
+
+QString AlbumArt::getImageFilename() 
+{
+    QString result;
+    QString curfile = pParent-&gt;decoder()-&gt;getFilename();
+    QString curdir = QUrl(curfile).dirPath();
+    QString namefilter = gContext-&gt;GetSetting("AlbumArtFilter",
+                                              "*.png;*.jpg;*.jpeg;*.gif;*.bmp");
+    // Get directory contents based on filter
+    QDir folder(curdir, namefilter, QDir::Name | QDir::IgnoreCase, 
+                QDir::Files | QDir::Hidden);
+    
+    if (folder.count())
+        result = folder[rand() % folder.count()];
+
+    result.prepend("/");
+    result.prepend(curdir);
+    
+    return result;
+}
+
 bool AlbumArt::draw(QPainter *p, const QColor &amp;back)
 {
     if (!pParent-&gt;decoder())
         return false;
 
-    QString curfile = pParent-&gt;decoder()-&gt;getFilename();
-    QString curdir = curfile.left(curfile.findRev("/"));
-    QImage art;
- 
     // If the directory has changed (new album) or the size, reload
-    if ((directory.compare(curdir) != 0) || (cursize != size))
+    if (needsUpdate())
     {
-        // Directory has changed
-        directory = curdir;
-        // Get filter
-        QString namefilter = gContext-&gt;GetSetting("AlbumArtFilter",
-                                              "*.png;*.jpg;*.jpeg;*.gif;*.bmp");
-        // Get directory contents based on filter
-        QDir folder(curdir, namefilter, QDir::Name | QDir::IgnoreCase, 
-                    QDir::Files | QDir::Hidden);
-
-        QString fileart = "";
-
-        if (folder.count())
-            fileart = folder[rand() % folder.count()];
-
-        curdir.append("/");
-        curdir.append(fileart);
-        art.load(curdir);
+        QImage art(getImageFilename());
         if (art.isNull())
         {
-            p-&gt;fillRect(0, 0, size.width(), size.height(), back);
-            p-&gt;setPen(Qt::white);
-            p-&gt;setFont(gContext-&gt;GetMediumFont());
-            p-&gt;drawText(size.width() / 2 - 200, size.height() / 2 - 10, 400, 20, 
-                        Qt::AlignCenter, QObject::tr("?"));
+            drawWarning(p, back, size, QObject::tr("?"));
+            cursize = size;
             return true;
         }
+        image = art.smoothScale(size, QImage::ScaleMin);
+    }
 
-        QSize artsize = art.scale(size, QImage::ScaleMin).size();
+    // Paint the image
+    p-&gt;fillRect(0, 0, size.width(), size.height(), back);
+    p-&gt;drawPixmap((size.width() - image.width()) / 2,
+                  (size.height() - image.height()) / 2,
+                  image);
+    
+    // Store our new size
+    cursize = size;
 
-        // Paint the image
-        p-&gt;fillRect(0, 0, size.width(), size.height(), back);
-        p-&gt;drawPixmap((size.width() - artsize.width()) / 2,
-                      (size.height() - artsize.height()) / 2,
-                      art.smoothScale(size, QImage::ScaleMin));
-        // Store our new size
-        cursize = size;
-        return true;
-    }
-    art.reset();
     return true;
 }
 
@@ -446,7 +452,104 @@
     return new Blank();
 }
 
+Squares::Squares()
+{
+    number_of_squares = 16;
+    fake_height = number_of_squares * analyzerBarWidth;
+}
 
+Squares::~Squares()
+{
+}
+
+void Squares::resize (const QSize &amp;newsize) {
+    // Trick the spectrum analyzer into calculating 16 rectangles
+    Spectrum::resize (QSize (fake_height, fake_height));
+    // We have our own copy, Spectrum has it's own...
+    size = newsize;
+}
+
+void Squares::drawRect(QPainter *p, QRect *rect, int i, int c, int w, int h) 
+{
+    double r, g, b, per;
+    int correction = (size.width() % rects.size ()) / 2;
+    int x = ((i / 2) * w) + correction;
+    int y;
+
+    if (i % 2 == 0) 
+    {
+        y = c - h;
+        per = double(fake_height - rect-&gt;top()) / double(fake_height);
+    }
+    else
+    {
+        y = c;
+        per = double(rect-&gt;bottom()) / double(fake_height);
+    }
+
+    per = clamp(per, 1.0, 0.0);        
+    
+    r = startColor.red() + 
+        (targetColor.red() - startColor.red()) * (per * per);
+    g = startColor.green() + 
+        (targetColor.green() - startColor.green()) * (per * per);
+    b = startColor.blue() + 
+        (targetColor.blue() - startColor.blue()) * (per * per);
+    
+    r = clamp(r, 255.0, 0.0);
+    g = clamp(g, 255.0, 0.0);
+    b = clamp(b, 255.0, 0.0);
+
+    p-&gt;fillRect (x, y, w, h, QColor (int(r), int(g), int(b)));
+}
+
+bool Squares::draw(QPainter *p, const QColor &amp;back)
+{
+    p-&gt;fillRect (0, 0, size.width (), size.height (), back);
+    int w = size.width () / (rects.size () / 2);
+    int h = w;
+    int center = size.height () / 2;
+
+#if defined(FFTW3_SUPPORT) || defined(FFTW2_SUPPORT)
+    QRect *rectsp = rects.data();
+    for (uint i = 0; i &lt; rects.count(); i++)
+        drawRect(p, &amp;(rectsp[i]), i, center, w, h);
+
+#else
+    // Oops ... user doesn't have a Fast Fourier Library
+    drawWarning(p, back, size,
+                QObject::tr("Visualization requires FFT library") + "\n" + 
+                QObject::tr("Did you run configure?"));
+#endif
+    
+    return true;
+
+    for (int x = 0; x &lt; size.width (); x += w) {
+        p-&gt;fillRect (x, center - h / 2, w, h, QColor ("red"));
+        p-&gt;fillRect (x, center + h / 2, w, h, QColor ("blue"));
+    }
+    return true;
+}
+
+const QString &amp;SquaresFactory::name(void) const
+{
+    static QString name("Squares");
+    return name;
+}
+
+const QString &amp;SquaresFactory::description(void) const
+{
+    static QString name("Square visualizer");
+    return name;
+}
+
+VisualBase *SquaresFactory::create(MainVisual *parent, long int winid)
+{
+    (void)winid;
+    (void)parent;
+    return new Squares();
+}
+
 #ifdef OPENGL_SUPPORT
 
 //        Need this for the Gears Object (below)
Index: mythplugins/mythmusic/mythmusic/mainvisual.h
===================================================================
--- mythplugins/mythmusic/mythmusic/mainvisual.h	(revision 10952)
+++ mythplugins/mythmusic/mythmusic/mainvisual.h	(working copy)
@@ -15,6 +15,7 @@
 #include &lt;qdialog.h&gt;
 #include &lt;qmemarray.h&gt;
 #include &lt;qpixmap.h&gt;
+#include &lt;qimage.h&gt;
 #include &lt;qptrlist.h&gt;
 #include &lt;qstringlist.h&gt;
 
@@ -37,8 +38,8 @@
 
     ~VisualNode()
     {
-	delete [] left;
-	delete [] right;
+        delete [] left;
+        delete [] right;
     }
 
     short *left, *right;
@@ -57,6 +58,7 @@
     virtual bool draw( QPainter *, const QColor &amp; ) = 0;
     virtual void resize( const QSize &amp;size ) = 0;
     virtual int getDesiredFPS(void) { return fps; }
+    void drawWarning(QPainter *, const QColor &amp;, const QSize &amp;, QString);
 
   protected:
     int fps;
@@ -94,6 +96,8 @@
     void setFrameRate( int newfps );
     int frameRate() const { return fps; }
 
+    void addInformation(const QString &amp;);
+
     static void registerVisFactory(VisFactory *);
     static VisualBase *createVis(const QString &amp;name,
                                  MainVisual *parent, long int winid);
@@ -106,6 +110,8 @@
 
 private:
     VisualBase *vis;
+    QString info;
+    QPixmap info_pixmap;
     QPixmap pixmap;
     QPtrList&lt;VisualNode&gt; nodes;
     QTimer *timer;
Index: mythplugins/mythmusic/mythmusic/mainvisual.cpp
===================================================================
--- mythplugins/mythmusic/mythmusic/mainvisual.cpp	(revision 10952)
+++ mythplugins/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 SquaresFactory);
 #ifdef OPENGL_SUPPORT
         MainVisual::registerVisFactory(new GearsFactory);
 #endif
@@ -70,6 +71,36 @@
         gContext-&gt;DoDisableScreensaver();
 }
 
+VisualBase::~VisualBase()
+{
+    //
+    //	This is only here so 
+    //	that derived classes
+    //	can destruct properly
+    //
+    if (!xscreensaverenable)
+        gContext-&gt;DoRestoreScreensaver();
+}
+
+void VisualBase::drawWarning(QPainter *p, const QColor &amp;back, const QSize &amp;size, QString warning)
+{
+    p-&gt;fillRect(0, 0, size.width(), size.height(), back);
+    p-&gt;setPen(Qt::white);
+    p-&gt;setFont(gContext-&gt;GetMediumFont());
+
+    QFontMetrics fm(p-&gt;font());
+    int width = fm.width(warning);
+    int height = fm.height() * (warning.contains("\n") + 1);
+    int x = size.width() / 2 - width / 2;
+    int y = size.height() / 2 - height / 2;
+
+    for (int offset = 0; offset &lt; height; offset += fm.height()) {
+        QString l = warning.left(warning.find("\n"));
+        p-&gt;drawText(x, y + offset, width, height, Qt::AlignCenter, l);
+        warning.remove(0, l.length () + 1);
+    }
+}
+
 MainVisual::MainVisual(QWidget *parent, const char *name)
     : QWidget( parent, name ), vis( 0 ), playing( FALSE ), fps( 20 )
 {
@@ -243,26 +274,26 @@
     }
 
     VisualNode *node = 0;
-
+    
     if (playing &amp;&amp; output()) {
         long synctime = output()-&gt;GetAudiotime();
-	mutex()-&gt;lock();
-	VisualNode *prev = 0;
-	while ((node = nodes.first())) {
-	    if (node-&gt;offset &gt; synctime)
-		break;
-
-	    delete prev;
-	    nodes.removeFirst();
-	    prev = node;
-	}
-	mutex()-&gt;unlock();
-	node = prev; 
+        mutex()-&gt;lock();
+        VisualNode *prev = 0;
+        while ((node = nodes.first())) {
+            if (node-&gt;offset &gt; synctime)
+                break;
+            
+            delete prev;
+            nodes.removeFirst();
+            prev = node;
+        }
+        mutex()-&gt;unlock();
+        node = prev; 
     }
 
     bool stop = TRUE;
     if (vis &amp;&amp; process)
-	stop = vis-&gt;process(node);
+        stop = vis-&gt;process(node);
     if (node)
         delete node;
 
@@ -270,15 +301,20 @@
     {
         QPainter p(&amp;pixmap);
         if (vis-&gt;draw(&amp;p, Qt::black))
+        {
+            p.drawPixmap((int)(pixmap.width() * 0.1), (int)(pixmap.height() * 0.8), info_pixmap);
             bitBlt(this, 0, 0, &amp;pixmap);
+        }
     } 
 
     if (!playing &amp;&amp; stop)
-	timer-&gt;stop();
+        timer-&gt;stop();
 }
 
 void MainVisual::paintEvent(QPaintEvent *)
 {
+    QPainter p(&amp;pixmap);
+    p.drawPixmap((int)(pixmap.width() * 0.1), (int)(pixmap.height() * 0.8), info_pixmap);
     bitBlt(this, 0, 0, &amp;pixmap);
 }
 
@@ -323,6 +359,48 @@
     QWidget::hideEvent(e);
 }
 
+void MainVisual::addInformation(const QString &amp;new_info) {
+    if (new_info == info)
+        return;
+    
+    info = new_info;
+    if (info.isEmpty())
+    {        
+        info_pixmap.resize(0, 0);
+        return;
+    }
+
+    info_pixmap = QPixmap((int)(pixmap.width() * 0.8), 
+                          (int)(pixmap.height() * 0.15), 
+                          pixmap.depth ());
+    QPainter p(&amp;info_pixmap);
+
+    int indent = int(info_pixmap.width() * 0.02);
+
+    p.fillRect(0, 0,
+               info_pixmap.width(), info_pixmap.height(),
+               QColor ("darkblue"));
+
+
+    p.setFont(gContext-&gt;GetMediumFont());
+
+    QFontMetrics fm(p.font());
+    int width = fm.width(info);
+    int height = fm.height() * (info.contains("\n") + 1);
+    int x = indent;
+    int y = indent;
+
+    QString info_copy = info;
+    for (int offset = 0; offset &lt; height; offset += fm.height()) {
+        QString l = info_copy.left(info_copy.find("\n"));
+        p.setPen(Qt::black);
+        p.drawText(x + 2, y + offset + 2, width, height, Qt::AlignLeft, l);
+        p.setPen(Qt::white);
+        p.drawText(x, y + offset, width, height, Qt::AlignLeft, l);
+        info_copy.remove(0, l.length () + 1);
+    }
+}
+
 void MainVisual::registerVisFactory(VisFactory *vis)
 {
     visfactories-&gt;append(vis);
@@ -837,13 +915,3 @@
     return indices[index];
 }
 
-VisualBase::~VisualBase()
-{
-    //
-    //	This is only here so 
-    //	that derived classes
-    //	can destruct properly
-    //
-    if (!xscreensaverenable)
-        gContext-&gt;DoRestoreScreensaver();
-}
Index: mythplugins/mythmusic/mythmusic/globalsettings.cpp
===================================================================
--- mythplugins/mythmusic/mythmusic/globalsettings.cpp	(revision 10952)
+++ mythplugins/mythmusic/mythmusic/globalsettings.cpp	(working copy)
@@ -384,7 +384,7 @@
     gc-&gt;setHelpText(QObject::tr("List of visualizations to use during playback. "
                     "Possible values are space-separated list of ") + "Random, "
                     "MonoScope, StereoScope, Spectrum, BumpScope, Goom, "
-                    "Synaesthesia, AlbumArt, Gears, " + QObject::tr("and") +
+                    "Synaesthesia, AlbumArt, Gears, Squares" + QObject::tr("and") +
                     " Blank");
     return gc;
 };
</pre></body></html>