Index: mythtv/libs/libmyth/lcddevice.cpp
===================================================================
--- mythtv/libs/libmyth/lcddevice.cpp	(revision 7455)
+++ mythtv/libs/libmyth/lcddevice.cpp	(working copy)
@@ -191,7 +191,7 @@
 #endif
         // Just stream the text out the socket
 
-        os << someText << "\n";
+        os << someText << "\n" << flush;
     }
     else
     {
@@ -376,7 +376,7 @@
     sendToServer("SET_CHANNEL_PROGRESS " + QString().setNum(value));    
 }
 
-void LCD::setGenericProgress(float value)
+void LCD::setGenericProgress(bool busy, float value)
 {
     if (!lcd_ready || !lcd_showgeneric)
         return;
@@ -386,7 +386,8 @@
     else if (value > 1.0)
         value = 1.0;
         
-    sendToServer("SET_GENERIC_PROGRESS " + QString().setNum(value));    
+    sendToServer("SET_GENERIC_PROGRESS " + QString().setNum (busy) + 
+                 " " + QString().setNum(value));    
 }
 
 void LCD::setMusicProgress(QString time, float value)
Index: mythtv/libs/libmyth/mythdialogs.cpp
===================================================================
--- mythtv/libs/libmyth/mythdialogs.cpp	(revision 7455)
+++ mythtv/libs/libmyth/mythdialogs.cpp	(working copy)
@@ -1558,15 +1558,23 @@
 
 void MythProgressDialog::setProgress(int curprogress)
 {
-    progress->setProgress(curprogress);
-    if (curprogress % steps == 0)
-    {
-        qApp->processEvents();
+    if (m_totalSteps <= 0) {
+        progress->setProgress (progress->progress () + 1);
         if (LCD * lcddev = LCD::Get())
         {
-            float fProgress = (float)curprogress / m_totalSteps;
-            lcddev->setGenericProgress(fProgress);
+            lcddev->setGenericProgress(true, 0.0);
         }
+    } else {
+        progress->setProgress(curprogress);
+        if (curprogress % steps == 0)
+        {
+            qApp->processEvents();
+            if (LCD * lcddev = LCD::Get())
+            {
+                float fProgress = (float)curprogress / m_totalSteps;
+                lcddev->setGenericProgress(false, fProgress);
+            }
+        }
     }
 }
 
@@ -1588,6 +1596,37 @@
         MythDialog::keyPressEvent(e);
 }
 
+MythBusyIndicator::MythBusyIndicator (const QString &title, bool autonomous) {
+    done = false;        
+    progress = new MythProgressDialog (title);
+    if (autonomous) {
+        start ();
+    }
+}
+ 
+MythBusyIndicator::~MythBusyIndicator () {
+    Close ();
+    delete progress;
+}
+
+void 
+MythBusyIndicator::Close () {
+    if (!done) {
+        done = true;
+        wait ();
+    }
+}
+
+void
+MythBusyIndicator::run ()  {
+    sleep (1);
+    while (!done) {
+        progress->setProgress ();
+        msleep (300);
+    }
+    progress->Close ();
+}
+
 MythThemedDialog::MythThemedDialog(MythMainWindow *parent, QString window_name,
                                    QString theme_filename, const char* name,
                                    bool setsize)
Index: mythtv/libs/libmyth/lcddevice.h
===================================================================
--- mythtv/libs/libmyth/lcddevice.h	(revision 7455)
+++ mythtv/libs/libmyth/lcddevice.h	(working copy)
@@ -147,8 +147,11 @@
     // define the screen, row, and alignment of the text
     void switchToGeneric(QPtrList<LCDTextItem> *textItems);
 
-    // Do a progress bar with the generic level between 0 and 1.0
-    void setGenericProgress(float generic_progress);
+    /** Update the generic progress bar.
+        @param busy if true, display a busy indicator instead of progress bar
+        @param generic_progress a value between 0 and 1.0
+    */
+    void setGenericProgress(bool busy, float generic_progress);
 
     // Do a music progress bar with the generic level between 0 and 1.0
     void setMusicProgress(QString time, float generic_progress);
Index: mythtv/libs/libmyth/mythdialogs.h
===================================================================
--- mythtv/libs/libmyth/mythdialogs.h	(revision 7455)
+++ mythtv/libs/libmyth/mythdialogs.h	(working copy)
@@ -11,6 +11,7 @@
 #include <qevent.h>
 #include <qvaluevector.h>
 #include <qscrollview.h>
+#include <qthread.h>
 
 #include <vector>
 using namespace std;
@@ -229,13 +230,31 @@
     bool arrowAccel;
 };
 
+/** The MythTV progress bar dialog.
+
+    This dialog is responsible for displaying a progress bar box on
+    the screen. It can display either a progressive progress bar or a
+    spinner busy indicator, depending on the totalSteps value passed
+    to the constructor.
+
+    If created as a busy indicator, calls to setProgress ignore the
+    value passed, and simply 'spin' the indicator.
+
+    The dialog widget also updates the LCD display if present.
+
+*/
 class MythProgressDialog: public MythDialog
 {
   public:
-    MythProgressDialog(const QString& message, int totalSteps);
+    /** Create a progress bar dialog.
+        
+        @param message the title string to appear in the progress dialog.
+        @param totalSteps the total number of steps, default value is -1 for busy indicator.
+     */
+    MythProgressDialog(const QString& message, int totalSteps = 0);
 
     void Close(void);
-    void setProgress(int curprogress);
+    void setProgress(int curprogress = 0);
     void keyPressEvent(QKeyEvent *);
 
   private:
@@ -247,6 +266,38 @@
     int m_totalSteps;
 };
 
+/** The MythTV busy indicator
+
+    @note This is not a MythDialog widget, but a thread object that
+    displays a @p MythProgressDialog until it's closed or destroyed.
+
+    This thread will wait for 1 second, and if it hasn't been asked to
+    stop (or destroyed), it will start displaying a `busy spinner'
+    style @p MythProgressDialog.
+
+    If  objects constructor/destroctor are responsible for
+    starting/stopping the thread handling the spinner, a call to
+    stop() can be called to end the spinner.
+ */
+class MythBusyIndicator : public QThread {
+  public:
+    /** Create the busy indicator.
+        @param title the title to appear in the progress bar dialog.
+        @param autonomous if true, whether a instance manages threads itself
+    */
+    MythBusyIndicator (const QString &title, bool autonomous=true);
+    ~MythBusyIndicator ();
+
+    /** Close the dialog.
+        This will also stop the thread and wait for it to finish.
+     */
+    void Close ();
+    virtual void run ();
+  private:
+    bool done;
+    MythProgressDialog *progress;
+};
+
 class MythThemedDialog : public MythDialog
 {
     Q_OBJECT
Index: mythtv/programs/mythlcdserver/lcdprocclient.cpp
===================================================================
--- mythtv/programs/mythlcdserver/lcdprocclient.cpp	(revision 7455)
+++ mythtv/programs/mythlcdserver/lcdprocclient.cpp	(working copy)
@@ -959,6 +959,7 @@
 void LCDProcClient::startMusic(QString artist, QString album, QString track)
 {
     QString aString;
+    music_progress = 0.0;
     if (lcd_showmusic)
       setPriority("Music", HIGH);
     aString = artist;
@@ -1016,7 +1017,7 @@
     QString aString;
 
     if (lcd_showgeneric)
-      setPriority("Generic", HIGH);
+      setPriority("Generic", TOP);
 
     // Clear out the LCD.  Do this before checking if its empty incase the user
     //  wants to just clear the lcd
@@ -1029,6 +1030,11 @@
         return;
 
     activeScreen = "Generic";
+
+    busy_progress = false;
+    busy_pos = 1;
+    busy_direction = 1;
+    busy_indicator_size = 2.0;
     generic_progress = 0.0;
 
     // Return if there are no more items
@@ -1505,7 +1511,7 @@
     outputChannel();    
 }
 
-void LCDProcClient::setGenericProgress(float value)
+void LCDProcClient::setGenericProgress(bool b, float value)
 {
     if (!lcd_ready)
         return;
@@ -1517,6 +1523,21 @@
     else if (generic_progress > 1.0)
         generic_progress = 1.0;
 
+    // Note, this will let us switch to/from busy indicator by alternating between
+    // being passed true or false for b.
+    busy_progress = b;
+    if (busy_progress) {
+        // If we're at either end of the line, switch direction
+        if (busy_pos + busy_direction > (signed int)lcdWidth - busy_indicator_size || 
+            busy_pos + busy_direction < 1) {
+            busy_direction = -busy_direction;
+        }
+        busy_pos += busy_direction;
+        generic_progress = busy_indicator_size / (float)lcdWidth;
+    } else {
+        busy_pos = 1;
+    }
+
     outputGeneric();
 }
 
@@ -1794,7 +1815,9 @@
 void LCDProcClient::outputGeneric()
 {
     QString aString;
-    aString = "widget_set Generic progressBar 1 ";
+    aString = "widget_set Generic progressBar ";
+    aString += QString::number (busy_pos);
+    aString += " ";
     aString += QString::number(lcdHeight);
     aString += " ";
     aString += QString::number((int)rint(generic_progress * lcdWidth * 
@@ -2003,7 +2026,12 @@
                                   "- is the master server running?\n\t\t\t"
                                   "Will retry in 30 seconds");
             QTimer::singleShot(30 * 1000, this, SLOT(updateRecordingList()));
-            switchToTime();
+
+            // If we can't get the recording status and we're showing
+            // it, switch back to time. Maybe it would be even better
+            // to show that the backend is unreachable ?
+            if  (activeScreen == "RecStatus")
+                switchToTime();
             return;
         }    
     }
Index: mythtv/programs/mythlcdserver/lcdserver.cpp
===================================================================
--- mythtv/programs/mythlcdserver/lcdserver.cpp	(revision 7455)
+++ mythtv/programs/mythlcdserver/lcdserver.cpp	(working copy)
@@ -577,7 +577,7 @@
 
     QString flat = tokens.join(" ");
    
-    if (tokens.count() != 2)
+    if (tokens.count() != 3)
     {
         VERBOSE(VB_IMPORTANT, "LCDServer: bad SET_GENERIC_PROGRESS command: "
                 << flat);
@@ -586,9 +586,17 @@
     }
      
     bool bOK;
-    float progress = tokens[1].toFloat(&bOK);
+    bool busy = tokens[1].toInt (&bOK);
     if (!bOK)
     {
+        VERBOSE(VB_IMPORTANT, "LCDServer: bad bool value in "
+                "SET_GENERIC_PROGRESS command: %1 %2" << tokens[1] << tokens[2]);
+        sendMessage(socket, "HUH?");
+        return;
+    }
+    float progress = tokens[2].toFloat(&bOK);
+    if (!bOK)
+    {
         VERBOSE(VB_IMPORTANT, "LCDServer: bad float value in "
                 "SET_GENERIC_PROGRESS command: %1" << tokens[1]);
         sendMessage(socket, "HUH?");
@@ -596,7 +604,7 @@
     }
     
     if (m_lcd)
-        m_lcd->setGenericProgress(progress);
+        m_lcd->setGenericProgress(busy, progress);
         
     sendMessage(socket, "OK");
 }
Index: mythtv/programs/mythlcdserver/lcdprocclient.h
===================================================================
--- mythtv/programs/mythlcdserver/lcdprocclient.h	(revision 7455)
+++ mythtv/programs/mythlcdserver/lcdprocclient.h	(working copy)
@@ -49,7 +49,7 @@
                       bool popMenu = true);
     
     void switchToGeneric(QPtrList<LCDTextItem> *textItems);
-    void setGenericProgress(float generic_progress);
+    void setGenericProgress(bool busy, float generic_progress);
 
     void switchToVolume(QString app_name);
     void setVolumeLevel(float volume_level);
@@ -162,6 +162,14 @@
         
     float EQlevels[10];
     float progress;
+    /** TRUE if the generic progress indicator is a busy (ie. doesn't have a known total steps */
+    bool busy_progress;
+    /** Current position of the busy indicator, used if @p busy_progress is true. */
+    int busy_pos;
+    /** How many "blocks" the busy indicator must be, used if @p busy_progress is true. */
+    float busy_indicator_size;
+    /** Dicrection of the busy indicator on the, -1 or 1, used if @p busy_progress is true. */
+    int busy_direction;
     float generic_progress;
     float volume_level;
 
Index: mythplugins/mythmusic/mythmusic/decoder.h
===================================================================
--- mythplugins/mythmusic/mythmusic/decoder.h	(revision 7455)
+++ mythplugins/mythmusic/mythmusic/decoder.h	(working copy)
@@ -8,6 +8,7 @@
 #include <qptrlist.h>
 
 class Metadata;
+class MetaIO;
 class Decoder;
 class DecoderFactory;
 
@@ -79,9 +80,53 @@
     static Decoder *create(const QString &, QIODevice *, AudioOutput *, 
                            bool = FALSE);
 
-    virtual Metadata *getMetadata() = 0;
-    virtual void commitMetadata(Metadata *mdata) = 0;
+    /** Read the metadata from @p filename directly.
+	
+        Creates a @p MetaIO object using @p ::doCreateTagger and uses
+        the MetaIO object to read the metadata.
+        
+        @returns an instance of @p Metadata owned by the caller
+     */
+    virtual Metadata *readMetadata();
 
+    /** Get the metadata  for @p filename 
+	
+        Tries first to read the metadata from the database. If there
+        is no database entry, it'll call @p ::readMetadata
+
+		@returns an instance of @p Metadata owned by the caller
+    */
+    virtual Metadata *getMetadata();
+
+    /** Create a @p MetaIO object for the format.
+
+        This method should be overwritten by subclasses to return an
+        instance of the appropriate MetaIO subtype. It is used by @p
+        ::getMetadata, @p ::readMetadata and @p ::commitMetadata.
+        
+        The default implementation returns a NULL pointer, which
+        essentially means, that if the decoder does not overrider this
+        method or all of the users (see previous paragraph), files
+        that the decoder supports cannot be indexed using metadata in
+        the file.
+
+		Eg. the mp3 decoder (@p MadDecoder) implements this, whereas
+		the audio CD decoder (@p CdDecoder) does not.  
+
+		@returns an instance of @p MetaIO owned by the caller
+     */
+    virtual MetaIO *doCreateTagger ();
+
+    /** Write the given metadata to the @p filename.
+	
+        Creates a @p MetaIO object using @p ::createTagger and asks
+        the MetaIO object to write the contents of mdata to @p
+        filename.
+
+        @params mdata the metadata to write to the disk
+     */
+    virtual void commitMetadata(Metadata *mdata);
+
     static void SetLocationFormatUseTags(void);
 
     QString getFilename(void) { return filename; }
Index: mythplugins/mythmusic/mythmusic/aacdecoder.cpp
===================================================================
--- mythplugins/mythmusic/mythmusic/aacdecoder.cpp	(revision 7455)
+++ mythplugins/mythmusic/mythmusic/aacdecoder.cpp	(working copy)
@@ -614,39 +614,9 @@
     deinit();
 }
 
-Metadata* aacDecoder::getMetadata()
+MetaIO* aacDecoder::doCreateTagger()
 {
-
-    Metadata *mdata = new Metadata(filename);
-    if (mdata->isInDatabase(musiclocation))
-    {
-      return mdata;
-    }
-    
-    delete mdata;
-
-    MetaIOMP4* p_tagger = new MetaIOMP4;
-    if (ignore_id3) {
-        mdata = p_tagger->readFromFilename(filename);
-    } else {
-        mdata = p_tagger->read(filename);
-    }
-    
-    delete p_tagger;
-
-    if (mdata)
-        mdata->dumpToDatabase(musiclocation);
-    else
-      error(QString("aacdecoder.o: Could not read metadata from \"%1\"").arg(filename.local8Bit()));
-
-    return mdata;
-}    
-
-void aacDecoder::commitMetadata(Metadata *mdata)
-{
-    MetaIOMP4* p_tagger = new MetaIOMP4;
-    p_tagger->write(mdata);
-    delete p_tagger;
+    return new MetaIOMP4;
 }
 
 uint32_t aacDecoder::aacRead(char *buffer, uint32_t length)
Index: mythplugins/mythmusic/mythmusic/metadata.cpp
===================================================================
--- mythplugins/mythmusic/mythmusic/metadata.cpp	(revision 7455)
+++ mythplugins/mythmusic/mythmusic/metadata.cpp	(working copy)
@@ -148,7 +148,7 @@
         playcount = query.value(10).toInt();
         lastplay = query.value(11).toString();
         compilation = (query.value(12).toInt() > 0);
-        
+
         retval = true;
     }
 
@@ -194,9 +194,10 @@
         return;
 
     query.prepare("INSERT INTO musicmetadata (artist,compilation_artist,album,title,"
-                  "genre,year,tracknum,length,filename,compilation,date_added) VALUES "
+                  "genre,year,tracknum,length,filename,compilation,date_added,"
+                  "date_modified) VALUES "
                   "(:ARTIST, :COMPILATION_ARTIST, :ALBUM, :TITLE, :GENRE, :YEAR, :TRACKNUM, "
-                  ":LENGTH, :FILENAME, :COMPILATION, :DATE_ADDED );");
+                  ":LENGTH, :FILENAME, :COMPILATION, :DATE_ADDED, :DATE_MODIFIED );");
     query.bindValue(":ARTIST", artist.utf8());
     query.bindValue(":COMPILATION_ARTIST", compilation_artist.utf8());
     query.bindValue(":ALBUM", album.utf8());
@@ -207,7 +208,8 @@
     query.bindValue(":LENGTH", length);
     query.bindValue(":FILENAME", sqlfilename.utf8());
     query.bindValue(":COMPILATION", compilation);
-    query.bindValue(":DATE_ADDED", QDate::currentDate());
+    query.bindValue(":DATE_ADDED", QDateTime::currentDateTime());
+    query.bindValue(":DATE_MODIFIED", QDateTime::currentDateTime());
     
     query.exec();
 
@@ -364,7 +366,8 @@
                   "compilation_artist = :COMPILATION_ARTIST, "
                   "title = :TITLE, genre = :GENRE, year = :YEAR, "
                   "tracknum = :TRACKNUM, rating = :RATING, " 
-                  "compilation = :COMPILATION "
+                  "compilation = :COMPILATION, "
+                  "date_modified= :DATE_MODIFIED "
                   "WHERE intid = :ID;");
     query.bindValue(":ARTIST", artist.utf8());
     query.bindValue(":COMPILATION_ARTIST", compilation_artist.utf8());
@@ -375,6 +378,7 @@
     query.bindValue(":TRACKNUM", tracknum);
     query.bindValue(":RATING", rating);
     query.bindValue(":COMPILATION", compilation);
+    query.bindValue(":DATE_MODIFIED", QDateTime::currentDateTime());
     query.bindValue(":ID", id);
 
     if (!query.exec())
@@ -1193,6 +1197,7 @@
         if( *it != "genre"  &&
             *it != "artist" &&
             *it != "splitartist" && 
+            *it != "splitartist1" && 
             *it != "album"  &&
             *it != "title")
         {
Index: mythplugins/mythmusic/mythmusic/cdrip.cpp
===================================================================
--- mythplugins/mythmusic/mythmusic/cdrip.cpp	(revision 7455)
+++ mythplugins/mythmusic/mythmusic/cdrip.cpp	(working copy)
@@ -862,7 +862,7 @@
             if (class LCD * lcd = LCD::Get()) 
             {
                 float fProgress = (float)(totalSectorsDone + (curpos - start))/totalSectors;
-                lcd->setGenericProgress(fProgress);
+                lcd->setGenericProgress(false, fProgress);
             }
             qApp->processEvents();
         }
Index: mythplugins/mythmusic/mythmusic/decoder.cpp
===================================================================
--- mythplugins/mythmusic/mythmusic/decoder.cpp	(revision 7455)
+++ mythplugins/mythmusic/mythmusic/decoder.cpp	(working copy)
@@ -6,6 +6,8 @@
 
 #include "decoder.h"
 #include "constants.h"
+#include "metadata.h"
+#include "metaio.h"
 #include <mythtv/output.h>
 #include <mythtv/visual.h>
 
@@ -87,7 +89,52 @@
     listeners.remove(object);
 }
 
+Metadata *Decoder::readMetadata () {
+    Metadata *mdata = NULL;
+    MetaIO* p_tagger = doCreateTagger ();
 
+    if (p_tagger) {
+        if (ignore_id3)
+            mdata = p_tagger->readFromFilename(filename);
+        else
+            mdata = p_tagger->read(filename);
+        
+        delete p_tagger;
+    } else {
+        if (!mdata)
+            cerr << "maddecoder.o: Could not read metadata from " << filename.local8Bit() << endl;
+    }
+
+    return mdata;    
+}
+
+Metadata* Decoder::getMetadata()
+{
+
+    Metadata *mdata = new Metadata(filename);
+    if (mdata->isInDatabase(musiclocation))
+    {
+      return mdata;
+    }
+    
+    delete mdata;
+
+    return readMetadata ();
+}    
+
+void Decoder::commitMetadata(Metadata *mdata)
+{
+    MetaIO* p_tagger = doCreateTagger ();
+    if (p_tagger) {
+        p_tagger->write(mdata);
+        delete p_tagger;
+    }
+}
+
+MetaIO *Decoder::doCreateTagger () {
+    return NULL;
+}
+
 // static methods
 
 int Decoder::ignore_id3 = 0;
Index: mythplugins/mythmusic/mythmusic/aacdecoder.h
===================================================================
--- mythplugins/mythmusic/mythmusic/aacdecoder.h	(revision 7455)
+++ mythplugins/mythmusic/mythmusic/aacdecoder.h	(working copy)
@@ -29,8 +29,7 @@
     void seek(double);
     void stop();
 
-    Metadata *getMetadata();
-    void commitMetadata(Metadata *mdata);
+    MetaIO *doCreateTagger();
 
     bool     initializeMP4();
     int      getAACTrack(mp4ff_t *infile);
Index: mythplugins/mythmusic/mythmusic/vorbisdecoder.cpp
===================================================================
--- mythplugins/mythmusic/mythmusic/vorbisdecoder.cpp	(revision 7455)
+++ mythplugins/mythmusic/mythmusic/vorbisdecoder.cpp	(working copy)
@@ -293,38 +293,9 @@
     deinit();
 }
 
-Metadata *VorbisDecoder::getMetadata()
+MetaIO *VorbisDecoder::doCreateTagger()
 {
-    Metadata *mdata = new Metadata(filename);
-    if (mdata->isInDatabase(musiclocation))
-    {
-        return mdata;
-    }
-
-    delete mdata;
-
-
-    MetaIOOggVorbisComment* p_tagger = new MetaIOOggVorbisComment;
-    if (ignore_id3)
-        mdata = p_tagger->readFromFilename(filename);
-    else
-        mdata = p_tagger->read(filename);
-
-    delete p_tagger;
-
-    if (mdata)
-        mdata->dumpToDatabase(musiclocation);
-    else
-        cerr << "vorbisdecoder.o: Could not read metadata from " << filename.local8Bit() << endl;    
-
-    return mdata;
-}    
-
-void VorbisDecoder::commitMetadata(Metadata *mdata)
-{
-    MetaIOOggVorbisComment* p_tagger = new MetaIOOggVorbisComment;
-    p_tagger->write(mdata);
-    delete p_tagger;
+    return new MetaIOOggVorbisComment;
 }
 
 
Index: mythplugins/mythmusic/mythmusic/flacdecoder.h
===================================================================
--- mythplugins/mythmusic/mythmusic/flacdecoder.h	(revision 7455)
+++ mythplugins/mythmusic/mythmusic/flacdecoder.h	(working copy)
@@ -22,8 +22,7 @@
     void doWrite(const FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
     void setFlacMetadata(const FLAC__StreamMetadata *metadata);
 
-    Metadata *getMetadata();
-    void commitMetadata(Metadata *mdata);
+    MetaIO *doCreateTagger();
 
   private:
     void run();
Index: mythplugins/mythmusic/mythmusic/avfdecoder.cpp
===================================================================
--- mythplugins/mythmusic/mythmusic/avfdecoder.cpp	(revision 7455)
+++ mythplugins/mythmusic/mythmusic/avfdecoder.cpp	(working copy)
@@ -357,40 +357,11 @@
     deinit();
 }
 
-Metadata* avfDecoder::getMetadata()
+MetaIO* avfDecoder::doCreateTagger()
 {
-    Metadata *mdata = new Metadata(filename);
-    if (mdata->isInDatabase(musiclocation))
-    {
-        return mdata;
-    }
-
-    delete mdata;
-
-
-    MetaIOAVFComment* p_tagger = new MetaIOAVFComment;
-    if (ignore_id3)
-        mdata = p_tagger->readFromFilename(filename);
-    else
-        mdata = p_tagger->read(filename);
-    
-    delete p_tagger;
-
-    if (mdata)
-        mdata->dumpToDatabase(musiclocation);
-    else
-        cerr << "avfdecoder.o: Could not read metadata from " << filename << endl;
-
-    return mdata;
+    return new MetaIOAVFComment;
 }    
 
-void avfDecoder::commitMetadata(Metadata *mdata)
-{
-    MetaIOAVFComment* p_tagger = new MetaIOAVFComment;
-    p_tagger->write(mdata);
-    delete p_tagger;
-}
-
 bool avfDecoderFactory::supports(const QString &source) const
 {
     return (source.right(extension().length()).lower() == extension());
Index: mythplugins/mythmusic/mythmusic/main.cpp
===================================================================
--- mythplugins/mythmusic/mythmusic/main.cpp	(revision 7455)
+++ mythplugins/mythmusic/mythmusic/main.cpp	(working copy)
@@ -6,6 +6,8 @@
 #include <qapplication.h>
 #include <qsqldatabase.h>
 #include <qregexp.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <unistd.h>
 
 #include <cdaudio.h>
@@ -65,16 +67,57 @@
     return decoder;
 }
 
-void CheckFile(const QString &filename)
+// Add a file to the database
+void CheckFile(const QString &directory, const QString &filename)
 {
     Decoder *decoder = getDecoder(filename);
 
     if (decoder)
     {
         Metadata *data = decoder->getMetadata();
-        if (data)
+        if (data) 
+        {
+            data->dumpToDatabase(directory);
             delete data;
+        }
+        delete decoder;
+    }
+}
 
+// Remove a file from the database
+void RemoveFile (const QString &directory, const QString &filename)
+{
+    QString name(filename);
+    name.remove(0, directory.length());
+    MSqlQuery query(MSqlQuery::InitCon());
+    query.prepare("DELETE FROM musicmetadata WHERE "
+                  "filename = :NAME ;");
+    query.bindValue(":NAME", name.utf8());
+    query.exec();
+}
+
+// Update a file's metadata in the database, preserving it's id
+void UpdateFile (const QString &directory, const QString &filename)
+{
+    Decoder *decoder = getDecoder (filename);
+
+    if (decoder)
+    {
+        Metadata *db_meta = decoder->getMetadata ();
+        Metadata *disk_meta = decoder->readMetadata ();
+
+        if (db_meta && disk_meta)
+        {
+            disk_meta->setID (db_meta->ID ());
+            disk_meta->updateDatabase (directory);
+        }
+
+        if (disk_meta)
+            delete disk_meta;
+
+        if (db_meta)
+            delete db_meta;
+
         delete decoder;
     }
 }
@@ -83,7 +126,7 @@
 {
     kFileSystem,
     kDatabase,
-    kBoth
+    kNeedUpdate,
 };
 
 typedef QMap <QString, MusicFileLocation> MusicLoadedMap;
@@ -102,6 +145,7 @@
     QFileInfoListIterator it(*list);
     QFileInfo *fi;
 
+    /* Recursively traverse directory */
     while ((fi = it.current()) != 0)
     {
         ++it;
@@ -111,10 +155,22 @@
         if (fi->isDir())
             BuildFileList(filename, music_files);
         else
-            music_files[filename] = kFileSystem;
+            music_files[filename] = kFileSystem;            
     }
 }
 
+/* Check if the file's mdate is after the date_modified */
+bool HasFileChanged (const QString &filename, const QString &date_modified) 
+{
+    struct stat sbuf;
+    if (stat (filename.ascii (), &sbuf) == 0) {
+        if (sbuf.st_mtime > (time_t)QDateTime::fromString (date_modified, Qt::ISODate).toTime_t ()) {
+            return true;
+        }
+    }
+    return false;
+}
+
 void SavePending(int pending)
 {
     //  Temporary Hack until mythmusic
@@ -176,19 +232,26 @@
 {
     MusicLoadedMap music_files;
     MusicLoadedMap::Iterator iter;
+    
+    {
+        /* Let the user know we're doing something, since ie. building
+           the filelist over NFS can take quite a while, so progress
+           bar now...
+        */
+        MythBusyIndicator busy (QObject::tr("Searching for music files"));
+        BuildFileList(directory, music_files);
+    }
 
-    BuildFileList(directory, music_files);
-
     MSqlQuery query(MSqlQuery::InitCon());
-    query.exec("SELECT filename FROM musicmetadata "
+    query.exec("SELECT filename, date_modified FROM musicmetadata "
                     "WHERE filename NOT LIKE ('%://%');");
 
+    MythProgressDialog *progress;
+    progress = new MythProgressDialog(QObject::tr("Scanning music files"),
+                                      query.numRowsAffected());
+
     int counter = 0;
 
-    MythProgressDialog *file_checking;
-    file_checking = new MythProgressDialog(QObject::tr("Searching for music files"),
-                                           query.numRowsAffected());
-
     if (query.isActive() && query.size() > 0)
     {
         while (query.next())
@@ -196,43 +259,45 @@
             QString name = directory + QString::fromUtf8(query.value(0).toString());
             if (name != QString::null)
             {
-                if ((iter = music_files.find(name)) != music_files.end())
-                    music_files.remove(iter);
-                else
+                if ((iter = music_files.find(name)) != music_files.end()) {
+                    if (HasFileChanged (name, query.value (1).toString ())) {
+                        music_files[name] = kNeedUpdate;
+                    } else {
+                        music_files.remove(iter);
+                    }
+                } else {
                     music_files[name] = kDatabase;
+                }
             }
-            file_checking->setProgress(++counter);
+            progress->setProgress(++counter);
         }
     }
 
-    file_checking->Close();
-    delete file_checking;
+    progress->Close();
+    delete progress;
 
-    file_checking = new MythProgressDialog(QObject::tr("Updating music database"), 
+    counter = 0;
+    progress = new MythProgressDialog(QObject::tr("Updating music database"), 
                                            music_files.size());
 
     QRegExp quote_regex("\"");
     for (iter = music_files.begin(); iter != music_files.end(); iter++)
     {
-        if (*iter == kFileSystem)
-        {
-            CheckFile(iter.key());
+        switch (*iter) {
+        case kFileSystem:
+            CheckFile(directory, iter.key());
+            break;
+        case kDatabase:
+            RemoveFile (directory, iter.key());
+            break;
+        case kNeedUpdate:
+            UpdateFile (directory, iter.key ());
+            break;
         }
-        else if (*iter == kDatabase)
-        {
-            QString name(iter.key());
-            name.remove(0, directory.length());
-
-            query.prepare("DELETE FROM musicmetadata WHERE "
-                          "filename = :NAME ;");
-            query.bindValue(":NAME", name.utf8());
-            query.exec();
-        }
-
-        file_checking->setProgress(++counter);
+        progress->setProgress(++counter);
     }
-    file_checking->Close();
-    delete file_checking;
+    progress->Close();
+    delete progress;
 }
 
 void startPlayback(PlaylistsContainer *all_playlists, AllMusic *all_music)
@@ -302,6 +367,7 @@
             //  Reconcile with the database
             SearchDir(mdata->startdir);
             //  Tell the metadata to reset itself
+            MythBusyIndicator busy (QObject::tr("Rebuilding music tree"));
             mdata->all_music->resync();
             mdata->all_playlists->postLoad();
         }
@@ -311,6 +377,7 @@
         if ("" != mdata->startdir)
         {
             SearchDir(mdata->startdir);
+            MythBusyIndicator busy (QObject::tr("Rebuilding music tree"));
             mdata->all_music->resync();
             mdata->all_playlists->postLoad();
         }
@@ -554,6 +621,7 @@
         // if startRipper returns true, then new files should be present
         // so we should look for them.
         SearchDir(mdata.startdir);
+        MythBusyIndicator busy (QObject::tr("Rebuilding music tree"));
         mdata.all_music->resync();
         mdata.all_playlists->postLoad();
     }
Index: mythplugins/mythmusic/mythmusic/flacdecoder.cpp
===================================================================
--- mythplugins/mythmusic/mythmusic/flacdecoder.cpp	(revision 7455)
+++ mythplugins/mythmusic/mythmusic/flacdecoder.cpp	(working copy)
@@ -385,40 +385,12 @@
         char *field_value;
 } Argument_VcField;
 
-Metadata *FlacDecoder::getMetadata()
+MetaIO *FlacDecoder::doCreateTagger()
 {
-    Metadata *mdata = new Metadata(filename);
-    if (mdata->isInDatabase(musiclocation))
-    {
-        return mdata;
-    }
+    return new MetaIOFLACVorbisComment;
+}
 
-    delete mdata;
 
-    MetaIOFLACVorbisComment* p_tagger = new MetaIOFLACVorbisComment;
-    if (ignore_id3)
-        mdata = p_tagger->readFromFilename(filename);
-    else
-        mdata = p_tagger->read(filename);
-
-    delete p_tagger;
-
-    if (mdata)
-        mdata->dumpToDatabase(musiclocation);
-    else
-        cerr << "flacdecoder.o: Could not read metadata from " << filename.local8Bit() << endl;
-
-    return mdata;
-}    
-
-void FlacDecoder::commitMetadata(Metadata *mdata)
-{
-    MetaIOFLACVorbisComment* p_tagger = new MetaIOFLACVorbisComment;
-    p_tagger->write(mdata);
-    delete p_tagger;
-    }
-
-
 bool FlacDecoderFactory::supports(const QString &source) const
 {
     return (source.right(extension().length()).lower() == extension());
Index: mythplugins/mythmusic/mythmusic/maddecoder.h
===================================================================
--- mythplugins/mythmusic/mythmusic/maddecoder.h	(revision 7455)
+++ mythplugins/mythmusic/mythmusic/maddecoder.h	(working copy)
@@ -24,8 +24,7 @@
     static const int maxFrameCheck;
     static const int initialFrameSize;
 
-    Metadata *getMetadata();
-    void commitMetadata(Metadata *mdata);
+    MetaIO *doCreateTagger();
 
 private:
     void run();
Index: mythplugins/mythmusic/mythmusic/vorbisdecoder.h
===================================================================
--- mythplugins/mythmusic/mythmusic/vorbisdecoder.h	(revision 7455)
+++ mythplugins/mythmusic/mythmusic/vorbisdecoder.h	(working copy)
@@ -18,8 +18,7 @@
     void seek(double);
     void stop();
 
-    Metadata *getMetadata();
-    void commitMetadata(Metadata *mdata);
+    MetaIO *doCreateTagger();
 
   private:
     void run();
Index: mythplugins/mythmusic/mythmusic/avfdecoder.h
===================================================================
--- mythplugins/mythmusic/mythmusic/avfdecoder.h	(revision 7455)
+++ mythplugins/mythmusic/mythmusic/avfdecoder.h	(working copy)
@@ -18,8 +18,7 @@
     void seek(double);
     void stop();
 
-    Metadata *getMetadata();
-    void commitMetadata(Metadata *mdata);
+    MetaIO *doCreateTagger();
 
   private:
     void run();
Index: mythplugins/mythmusic/mythmusic/maddecoder.cpp
===================================================================
--- mythplugins/mythmusic/mythmusic/maddecoder.cpp	(revision 7455)
+++ mythplugins/mythmusic/mythmusic/maddecoder.cpp	(working copy)
@@ -512,40 +512,11 @@
     return MAD_FLOW_STOP;
 }
 
-Metadata *MadDecoder::getMetadata()
+MetaIO *MadDecoder::doCreateTagger()
 {
-    Metadata *mdata = new Metadata(filename);
-    if (mdata->isInDatabase(musiclocation))
-    {
-        return mdata;
-    }
-
-    delete mdata;
-
-
-    MetaIOID3v2* p_tagger = new MetaIOID3v2;
-    if (ignore_id3)
-        mdata = p_tagger->readFromFilename(filename);
-    else
-        mdata = p_tagger->read(filename);
-
-    delete p_tagger;
-
-    if (mdata)
-        mdata->dumpToDatabase(musiclocation);
-    else
-        cerr << "maddecoder.o: Could not read metadata from " << filename.local8Bit() << endl;
-
-    return mdata;
+    return new MetaIOID3v2;
 }
 
-void MadDecoder::commitMetadata(Metadata *mdata)
-{
-    MetaIOID3v2* p_tagger = new MetaIOID3v2;
-    p_tagger->write(mdata);
-    delete p_tagger;
-}
-
 bool MadDecoderFactory::supports(const QString &source) const
 {
     bool res = false;
