Ticket #341: dbupdate5.patch

File dbupdate5.patch, 34.3 KB (added by myth@…, 15 years ago)

updated version of the patch

  • mythtv/libs/libmyth/lcddevice.cpp

     
    191191#endif
    192192        // Just stream the text out the socket
    193193
    194         os << someText << "\n";
     194        os << someText << "\n" << flush;
    195195    }
    196196    else
    197197    {
     
    376376    sendToServer("SET_CHANNEL_PROGRESS " + QString().setNum(value));   
    377377}
    378378
    379 void LCD::setGenericProgress(float value)
     379void LCD::setGenericProgress(bool busy, float value)
    380380{
    381381    if (!lcd_ready || !lcd_showgeneric)
    382382        return;
     
    386386    else if (value > 1.0)
    387387        value = 1.0;
    388388       
    389     sendToServer("SET_GENERIC_PROGRESS " + QString().setNum(value));   
     389    sendToServer("SET_GENERIC_PROGRESS " + QString().setNum (busy) +
     390                 " " + QString().setNum(value));   
    390391}
    391392
    392393void LCD::setMusicProgress(QString time, float value)
  • mythtv/libs/libmyth/mythdialogs.cpp

     
    15581558
    15591559void MythProgressDialog::setProgress(int curprogress)
    15601560{
    1561     progress->setProgress(curprogress);
    1562     if (curprogress % steps == 0)
    1563     {
    1564         qApp->processEvents();
     1561    if (m_totalSteps <= 0) {
     1562        progress->setProgress (progress->progress () + 1);
    15651563        if (LCD * lcddev = LCD::Get())
    15661564        {
    1567             float fProgress = (float)curprogress / m_totalSteps;
    1568             lcddev->setGenericProgress(fProgress);
     1565            lcddev->setGenericProgress(true, 0.0);
    15691566        }
     1567    } else {
     1568        progress->setProgress(curprogress);
     1569        if (curprogress % steps == 0)
     1570        {
     1571            qApp->processEvents();
     1572            if (LCD * lcddev = LCD::Get())
     1573            {
     1574                float fProgress = (float)curprogress / m_totalSteps;
     1575                lcddev->setGenericProgress(false, fProgress);
     1576            }
     1577        }
    15701578    }
    15711579}
    15721580
     
    15881596        MythDialog::keyPressEvent(e);
    15891597}
    15901598
     1599MythBusyIndicator::MythBusyIndicator (const QString &title, bool autonomous) {
     1600    done = false;       
     1601    progress = new MythProgressDialog (title);
     1602    if (autonomous) {
     1603        start ();
     1604    }
     1605}
     1606 
     1607MythBusyIndicator::~MythBusyIndicator () {
     1608    Close ();
     1609    delete progress;
     1610}
     1611
     1612void
     1613MythBusyIndicator::Close () {
     1614    if (!done) {
     1615        done = true;
     1616        wait ();
     1617    }
     1618}
     1619
     1620void
     1621MythBusyIndicator::run ()  {
     1622    sleep (1);
     1623    while (!done) {
     1624        progress->setProgress ();
     1625        msleep (300);
     1626    }
     1627    progress->Close ();
     1628}
     1629
    15911630MythThemedDialog::MythThemedDialog(MythMainWindow *parent, QString window_name,
    15921631                                   QString theme_filename, const char* name,
    15931632                                   bool setsize)
  • mythtv/libs/libmyth/lcddevice.h

     
    147147    // define the screen, row, and alignment of the text
    148148    void switchToGeneric(QPtrList<LCDTextItem> *textItems);
    149149
    150     // Do a progress bar with the generic level between 0 and 1.0
    151     void setGenericProgress(float generic_progress);
     150    /** Update the generic progress bar.
     151        @param busy if true, display a busy indicator instead of progress bar
     152        @param generic_progress a value between 0 and 1.0
     153    */
     154    void setGenericProgress(bool busy, float generic_progress);
    152155
    153156    // Do a music progress bar with the generic level between 0 and 1.0
    154157    void setMusicProgress(QString time, float generic_progress);
  • mythtv/libs/libmyth/mythdialogs.h

     
    1111#include <qevent.h>
    1212#include <qvaluevector.h>
    1313#include <qscrollview.h>
     14#include <qthread.h>
    1415
    1516#include <vector>
    1617using namespace std;
     
    229230    bool arrowAccel;
    230231};
    231232
     233/** The MythTV progress bar dialog.
     234
     235    This dialog is responsible for displaying a progress bar box on
     236    the screen. It can display either a progressive progress bar or a
     237    spinner busy indicator, depending on the totalSteps value passed
     238    to the constructor.
     239
     240    If created as a busy indicator, calls to setProgress ignore the
     241    value passed, and simply 'spin' the indicator.
     242
     243    The dialog widget also updates the LCD display if present.
     244
     245*/
    232246class MythProgressDialog: public MythDialog
    233247{
    234248  public:
    235     MythProgressDialog(const QString& message, int totalSteps);
     249    /** Create a progress bar dialog.
     250       
     251        @param message the title string to appear in the progress dialog.
     252        @param totalSteps the total number of steps, default value is -1 for busy indicator.
     253     */
     254    MythProgressDialog(const QString& message, int totalSteps = 0);
    236255
    237256    void Close(void);
    238     void setProgress(int curprogress);
     257    void setProgress(int curprogress = 0);
    239258    void keyPressEvent(QKeyEvent *);
    240259
    241260  private:
     
    247266    int m_totalSteps;
    248267};
    249268
     269/** The MythTV busy indicator
     270
     271    @note This is not a MythDialog widget, but a thread object that
     272    displays a @p MythProgressDialog until it's closed or destroyed.
     273
     274    This thread will wait for 1 second, and if it hasn't been asked to
     275    stop (or destroyed), it will start displaying a `busy spinner'
     276    style @p MythProgressDialog.
     277
     278    If  objects constructor/destroctor are responsible for
     279    starting/stopping the thread handling the spinner, a call to
     280    stop() can be called to end the spinner.
     281 */
     282class MythBusyIndicator : public QThread {
     283  public:
     284    /** Create the busy indicator.
     285        @param title the title to appear in the progress bar dialog.
     286        @param autonomous if true, whether a instance manages threads itself
     287    */
     288    MythBusyIndicator (const QString &title, bool autonomous=true);
     289    ~MythBusyIndicator ();
     290
     291    /** Close the dialog.
     292        This will also stop the thread and wait for it to finish.
     293     */
     294    void Close ();
     295    virtual void run ();
     296  private:
     297    bool done;
     298    MythProgressDialog *progress;
     299};
     300
    250301class MythThemedDialog : public MythDialog
    251302{
    252303    Q_OBJECT
  • mythtv/programs/mythlcdserver/lcdprocclient.cpp

     
    959959void LCDProcClient::startMusic(QString artist, QString album, QString track)
    960960{
    961961    QString aString;
     962    music_progress = 0.0;
    962963    if (lcd_showmusic)
    963964      setPriority("Music", HIGH);
    964965    aString = artist;
     
    10161017    QString aString;
    10171018
    10181019    if (lcd_showgeneric)
    1019       setPriority("Generic", HIGH);
     1020      setPriority("Generic", TOP);
    10201021
    10211022    // Clear out the LCD.  Do this before checking if its empty incase the user
    10221023    //  wants to just clear the lcd
     
    10291030        return;
    10301031
    10311032    activeScreen = "Generic";
     1033
     1034    busy_progress = false;
     1035    busy_pos = 1;
     1036    busy_direction = 1;
     1037    busy_indicator_size = 2.0;
    10321038    generic_progress = 0.0;
    10331039
    10341040    // Return if there are no more items
     
    15051511    outputChannel();   
    15061512}
    15071513
    1508 void LCDProcClient::setGenericProgress(float value)
     1514void LCDProcClient::setGenericProgress(bool b, float value)
    15091515{
    15101516    if (!lcd_ready)
    15111517        return;
     
    15171523    else if (generic_progress > 1.0)
    15181524        generic_progress = 1.0;
    15191525
     1526    // Note, this will let us switch to/from busy indicator by alternating between
     1527    // being passed true or false for b.
     1528    busy_progress = b;
     1529    if (busy_progress) {
     1530        // If we're at either end of the line, switch direction
     1531        if (busy_pos + busy_direction > (signed int)lcdWidth - busy_indicator_size ||
     1532            busy_pos + busy_direction < 1) {
     1533            busy_direction = -busy_direction;
     1534        }
     1535        busy_pos += busy_direction;
     1536        generic_progress = busy_indicator_size / (float)lcdWidth;
     1537    } else {
     1538        busy_pos = 1;
     1539    }
     1540
    15201541    outputGeneric();
    15211542}
    15221543
     
    17941815void LCDProcClient::outputGeneric()
    17951816{
    17961817    QString aString;
    1797     aString = "widget_set Generic progressBar 1 ";
     1818    aString = "widget_set Generic progressBar ";
     1819    aString += QString::number (busy_pos);
     1820    aString += " ";
    17981821    aString += QString::number(lcdHeight);
    17991822    aString += " ";
    18001823    aString += QString::number((int)rint(generic_progress * lcdWidth *
     
    20032026                                  "- is the master server running?\n\t\t\t"
    20042027                                  "Will retry in 30 seconds");
    20052028            QTimer::singleShot(30 * 1000, this, SLOT(updateRecordingList()));
    2006             switchToTime();
     2029
     2030            // If we can't get the recording status and we're showing
     2031            // it, switch back to time. Maybe it would be even better
     2032            // to show that the backend is unreachable ?
     2033            if  (activeScreen == "RecStatus")
     2034                switchToTime();
    20072035            return;
    20082036        }   
    20092037    }
  • mythtv/programs/mythlcdserver/lcdserver.cpp

     
    577577
    578578    QString flat = tokens.join(" ");
    579579   
    580     if (tokens.count() != 2)
     580    if (tokens.count() != 3)
    581581    {
    582582        VERBOSE(VB_IMPORTANT, "LCDServer: bad SET_GENERIC_PROGRESS command: "
    583583                << flat);
     
    586586    }
    587587     
    588588    bool bOK;
    589     float progress = tokens[1].toFloat(&bOK);
     589    bool busy = tokens[1].toInt (&bOK);
    590590    if (!bOK)
    591591    {
     592        VERBOSE(VB_IMPORTANT, "LCDServer: bad bool value in "
     593                "SET_GENERIC_PROGRESS command: %1 %2" << tokens[1] << tokens[2]);
     594        sendMessage(socket, "HUH?");
     595        return;
     596    }
     597    float progress = tokens[2].toFloat(&bOK);
     598    if (!bOK)
     599    {
    592600        VERBOSE(VB_IMPORTANT, "LCDServer: bad float value in "
    593601                "SET_GENERIC_PROGRESS command: %1" << tokens[1]);
    594602        sendMessage(socket, "HUH?");
     
    596604    }
    597605   
    598606    if (m_lcd)
    599         m_lcd->setGenericProgress(progress);
     607        m_lcd->setGenericProgress(busy, progress);
    600608       
    601609    sendMessage(socket, "OK");
    602610}
  • mythtv/programs/mythlcdserver/lcdprocclient.h

     
    4949                      bool popMenu = true);
    5050   
    5151    void switchToGeneric(QPtrList<LCDTextItem> *textItems);
    52     void setGenericProgress(float generic_progress);
     52    void setGenericProgress(bool busy, float generic_progress);
    5353
    5454    void switchToVolume(QString app_name);
    5555    void setVolumeLevel(float volume_level);
     
    162162       
    163163    float EQlevels[10];
    164164    float progress;
     165    /** TRUE if the generic progress indicator is a busy (ie. doesn't have a known total steps */
     166    bool busy_progress;
     167    /** Current position of the busy indicator, used if @p busy_progress is true. */
     168    int busy_pos;
     169    /** How many "blocks" the busy indicator must be, used if @p busy_progress is true. */
     170    float busy_indicator_size;
     171    /** Dicrection of the busy indicator on the, -1 or 1, used if @p busy_progress is true. */
     172    int busy_direction;
    165173    float generic_progress;
    166174    float volume_level;
    167175
  • mythplugins/mythmusic/mythmusic/decoder.h

     
    88#include <qptrlist.h>
    99
    1010class Metadata;
     11class MetaIO;
    1112class Decoder;
    1213class DecoderFactory;
    1314
     
    7980    static Decoder *create(const QString &, QIODevice *, AudioOutput *,
    8081                           bool = FALSE);
    8182
    82     virtual Metadata *getMetadata() = 0;
    83     virtual void commitMetadata(Metadata *mdata) = 0;
     83    /** Read the metadata from @p filename directly.
     84       
     85        Creates a @p MetaIO object using @p ::doCreateTagger and uses
     86        the MetaIO object to read the metadata.
     87       
     88        @returns an instance of @p Metadata owned by the caller
     89     */
     90    virtual Metadata *readMetadata();
    8491
     92    /** Get the metadata  for @p filename
     93       
     94        Tries first to read the metadata from the database. If there
     95        is no database entry, it'll call @p ::readMetadata
     96
     97                @returns an instance of @p Metadata owned by the caller
     98    */
     99    virtual Metadata *getMetadata();
     100
     101    /** Create a @p MetaIO object for the format.
     102
     103        This method should be overwritten by subclasses to return an
     104        instance of the appropriate MetaIO subtype. It is used by @p
     105        ::getMetadata, @p ::readMetadata and @p ::commitMetadata.
     106       
     107        The default implementation returns a NULL pointer, which
     108        essentially means, that if the decoder does not overrider this
     109        method or all of the users (see previous paragraph), files
     110        that the decoder supports cannot be indexed using metadata in
     111        the file.
     112
     113                Eg. the mp3 decoder (@p MadDecoder) implements this, whereas
     114                the audio CD decoder (@p CdDecoder) does not. 
     115
     116                @returns an instance of @p MetaIO owned by the caller
     117     */
     118    virtual MetaIO *doCreateTagger ();
     119
     120    /** Write the given metadata to the @p filename.
     121       
     122        Creates a @p MetaIO object using @p ::createTagger and asks
     123        the MetaIO object to write the contents of mdata to @p
     124        filename.
     125
     126        @params mdata the metadata to write to the disk
     127     */
     128    virtual void commitMetadata(Metadata *mdata);
     129
    85130    static void SetLocationFormatUseTags(void);
    86131
    87132    QString getFilename(void) { return filename; }
  • mythplugins/mythmusic/mythmusic/aacdecoder.cpp

     
    614614    deinit();
    615615}
    616616
    617 Metadata* aacDecoder::getMetadata()
     617MetaIO* aacDecoder::doCreateTagger()
    618618{
    619 
    620     Metadata *mdata = new Metadata(filename);
    621     if (mdata->isInDatabase(musiclocation))
    622     {
    623       return mdata;
    624     }
    625    
    626     delete mdata;
    627 
    628     MetaIOMP4* p_tagger = new MetaIOMP4;
    629     if (ignore_id3) {
    630         mdata = p_tagger->readFromFilename(filename);
    631     } else {
    632         mdata = p_tagger->read(filename);
    633     }
    634    
    635     delete p_tagger;
    636 
    637     if (mdata)
    638         mdata->dumpToDatabase(musiclocation);
    639     else
    640       error(QString("aacdecoder.o: Could not read metadata from \"%1\"").arg(filename.local8Bit()));
    641 
    642     return mdata;
    643 }   
    644 
    645 void aacDecoder::commitMetadata(Metadata *mdata)
    646 {
    647     MetaIOMP4* p_tagger = new MetaIOMP4;
    648     p_tagger->write(mdata);
    649     delete p_tagger;
     619    return new MetaIOMP4;
    650620}
    651621
    652622uint32_t aacDecoder::aacRead(char *buffer, uint32_t length)
  • mythplugins/mythmusic/mythmusic/metadata.cpp

     
    148148        playcount = query.value(10).toInt();
    149149        lastplay = query.value(11).toString();
    150150        compilation = (query.value(12).toInt() > 0);
    151        
     151
    152152        retval = true;
    153153    }
    154154
     
    194194        return;
    195195
    196196    query.prepare("INSERT INTO musicmetadata (artist,compilation_artist,album,title,"
    197                   "genre,year,tracknum,length,filename,compilation,date_added) VALUES "
     197                  "genre,year,tracknum,length,filename,compilation,date_added,"
     198                  "date_modified) VALUES "
    198199                  "(:ARTIST, :COMPILATION_ARTIST, :ALBUM, :TITLE, :GENRE, :YEAR, :TRACKNUM, "
    199                   ":LENGTH, :FILENAME, :COMPILATION, :DATE_ADDED );");
     200                  ":LENGTH, :FILENAME, :COMPILATION, :DATE_ADDED, :DATE_MODIFIED );");
    200201    query.bindValue(":ARTIST", artist.utf8());
    201202    query.bindValue(":COMPILATION_ARTIST", compilation_artist.utf8());
    202203    query.bindValue(":ALBUM", album.utf8());
     
    207208    query.bindValue(":LENGTH", length);
    208209    query.bindValue(":FILENAME", sqlfilename.utf8());
    209210    query.bindValue(":COMPILATION", compilation);
    210     query.bindValue(":DATE_ADDED", QDate::currentDate());
     211    query.bindValue(":DATE_ADDED", QDateTime::currentDateTime());
     212    query.bindValue(":DATE_MODIFIED", QDateTime::currentDateTime());
    211213   
    212214    query.exec();
    213215
     
    364366                  "compilation_artist = :COMPILATION_ARTIST, "
    365367                  "title = :TITLE, genre = :GENRE, year = :YEAR, "
    366368                  "tracknum = :TRACKNUM, rating = :RATING, "
    367                   "compilation = :COMPILATION "
     369                  "compilation = :COMPILATION, "
     370                  "date_modified= :DATE_MODIFIED "
    368371                  "WHERE intid = :ID;");
    369372    query.bindValue(":ARTIST", artist.utf8());
    370373    query.bindValue(":COMPILATION_ARTIST", compilation_artist.utf8());
     
    375378    query.bindValue(":TRACKNUM", tracknum);
    376379    query.bindValue(":RATING", rating);
    377380    query.bindValue(":COMPILATION", compilation);
     381    query.bindValue(":DATE_MODIFIED", QDateTime::currentDateTime());
    378382    query.bindValue(":ID", id);
    379383
    380384    if (!query.exec())
     
    11931197        if( *it != "genre"  &&
    11941198            *it != "artist" &&
    11951199            *it != "splitartist" &&
     1200            *it != "splitartist1" &&
    11961201            *it != "album"  &&
    11971202            *it != "title")
    11981203        {
  • mythplugins/mythmusic/mythmusic/cdrip.cpp

     
    862862            if (class LCD * lcd = LCD::Get())
    863863            {
    864864                float fProgress = (float)(totalSectorsDone + (curpos - start))/totalSectors;
    865                 lcd->setGenericProgress(fProgress);
     865                lcd->setGenericProgress(false, fProgress);
    866866            }
    867867            qApp->processEvents();
    868868        }
  • mythplugins/mythmusic/mythmusic/decoder.cpp

     
    66
    77#include "decoder.h"
    88#include "constants.h"
     9#include "metadata.h"
     10#include "metaio.h"
    911#include <mythtv/output.h>
    1012#include <mythtv/visual.h>
    1113
     
    8789    listeners.remove(object);
    8890}
    8991
     92Metadata *Decoder::readMetadata () {
     93    Metadata *mdata = NULL;
     94    MetaIO* p_tagger = doCreateTagger ();
    9095
     96    if (p_tagger) {
     97        if (ignore_id3)
     98            mdata = p_tagger->readFromFilename(filename);
     99        else
     100            mdata = p_tagger->read(filename);
     101       
     102        delete p_tagger;
     103    } else {
     104        if (!mdata)
     105            cerr << "maddecoder.o: Could not read metadata from " << filename.local8Bit() << endl;
     106    }
     107
     108    return mdata;   
     109}
     110
     111Metadata* Decoder::getMetadata()
     112{
     113
     114    Metadata *mdata = new Metadata(filename);
     115    if (mdata->isInDatabase(musiclocation))
     116    {
     117      return mdata;
     118    }
     119   
     120    delete mdata;
     121
     122    return readMetadata ();
     123}   
     124
     125void Decoder::commitMetadata(Metadata *mdata)
     126{
     127    MetaIO* p_tagger = doCreateTagger ();
     128    if (p_tagger) {
     129        p_tagger->write(mdata);
     130        delete p_tagger;
     131    }
     132}
     133
     134MetaIO *Decoder::doCreateTagger () {
     135    return NULL;
     136}
     137
    91138// static methods
    92139
    93140int Decoder::ignore_id3 = 0;
  • mythplugins/mythmusic/mythmusic/aacdecoder.h

     
    2929    void seek(double);
    3030    void stop();
    3131
    32     Metadata *getMetadata();
    33     void commitMetadata(Metadata *mdata);
     32    MetaIO *doCreateTagger();
    3433
    3534    bool     initializeMP4();
    3635    int      getAACTrack(mp4ff_t *infile);
  • mythplugins/mythmusic/mythmusic/vorbisdecoder.cpp

     
    293293    deinit();
    294294}
    295295
    296 Metadata *VorbisDecoder::getMetadata()
     296MetaIO *VorbisDecoder::doCreateTagger()
    297297{
    298     Metadata *mdata = new Metadata(filename);
    299     if (mdata->isInDatabase(musiclocation))
    300     {
    301         return mdata;
    302     }
    303 
    304     delete mdata;
    305 
    306 
    307     MetaIOOggVorbisComment* p_tagger = new MetaIOOggVorbisComment;
    308     if (ignore_id3)
    309         mdata = p_tagger->readFromFilename(filename);
    310     else
    311         mdata = p_tagger->read(filename);
    312 
    313     delete p_tagger;
    314 
    315     if (mdata)
    316         mdata->dumpToDatabase(musiclocation);
    317     else
    318         cerr << "vorbisdecoder.o: Could not read metadata from " << filename.local8Bit() << endl;   
    319 
    320     return mdata;
    321 }   
    322 
    323 void VorbisDecoder::commitMetadata(Metadata *mdata)
    324 {
    325     MetaIOOggVorbisComment* p_tagger = new MetaIOOggVorbisComment;
    326     p_tagger->write(mdata);
    327     delete p_tagger;
     298    return new MetaIOOggVorbisComment;
    328299}
    329300
    330301
  • mythplugins/mythmusic/mythmusic/flacdecoder.h

     
    2222    void doWrite(const FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
    2323    void setFlacMetadata(const FLAC__StreamMetadata *metadata);
    2424
    25     Metadata *getMetadata();
    26     void commitMetadata(Metadata *mdata);
     25    MetaIO *doCreateTagger();
    2726
    2827  private:
    2928    void run();
  • mythplugins/mythmusic/mythmusic/avfdecoder.cpp

     
    357357    deinit();
    358358}
    359359
    360 Metadata* avfDecoder::getMetadata()
     360MetaIO* avfDecoder::doCreateTagger()
    361361{
    362     Metadata *mdata = new Metadata(filename);
    363     if (mdata->isInDatabase(musiclocation))
    364     {
    365         return mdata;
    366     }
    367 
    368     delete mdata;
    369 
    370 
    371     MetaIOAVFComment* p_tagger = new MetaIOAVFComment;
    372     if (ignore_id3)
    373         mdata = p_tagger->readFromFilename(filename);
    374     else
    375         mdata = p_tagger->read(filename);
    376    
    377     delete p_tagger;
    378 
    379     if (mdata)
    380         mdata->dumpToDatabase(musiclocation);
    381     else
    382         cerr << "avfdecoder.o: Could not read metadata from " << filename << endl;
    383 
    384     return mdata;
     362    return new MetaIOAVFComment;
    385363}   
    386364
    387 void avfDecoder::commitMetadata(Metadata *mdata)
    388 {
    389     MetaIOAVFComment* p_tagger = new MetaIOAVFComment;
    390     p_tagger->write(mdata);
    391     delete p_tagger;
    392 }
    393 
    394365bool avfDecoderFactory::supports(const QString &source) const
    395366{
    396367    return (source.right(extension().length()).lower() == extension());
  • mythplugins/mythmusic/mythmusic/main.cpp

     
    66#include <qapplication.h>
    77#include <qsqldatabase.h>
    88#include <qregexp.h>
     9#include <sys/types.h>
     10#include <sys/stat.h>
    911#include <unistd.h>
    1012
    1113#include <cdaudio.h>
     
    6567    return decoder;
    6668}
    6769
    68 void CheckFile(const QString &filename)
     70// Add a file to the database
     71void CheckFile(const QString &directory, const QString &filename)
    6972{
    7073    Decoder *decoder = getDecoder(filename);
    7174
    7275    if (decoder)
    7376    {
    7477        Metadata *data = decoder->getMetadata();
    75         if (data)
     78        if (data)
     79        {
     80            data->dumpToDatabase(directory);
    7681            delete data;
     82        }
     83        delete decoder;
     84    }
     85}
    7786
     87// Remove a file from the database
     88void RemoveFile (const QString &directory, const QString &filename)
     89{
     90    QString name(filename);
     91    name.remove(0, directory.length());
     92    MSqlQuery query(MSqlQuery::InitCon());
     93    query.prepare("DELETE FROM musicmetadata WHERE "
     94                  "filename = :NAME ;");
     95    query.bindValue(":NAME", name.utf8());
     96    query.exec();
     97}
     98
     99// Update a file's metadata in the database, preserving it's id
     100void UpdateFile (const QString &directory, const QString &filename)
     101{
     102    Decoder *decoder = getDecoder (filename);
     103
     104    if (decoder)
     105    {
     106        Metadata *db_meta = decoder->getMetadata ();
     107        Metadata *disk_meta = decoder->readMetadata ();
     108
     109        if (db_meta && disk_meta)
     110        {
     111            disk_meta->setID (db_meta->ID ());
     112            disk_meta->updateDatabase (directory);
     113        }
     114
     115        if (disk_meta)
     116            delete disk_meta;
     117
     118        if (db_meta)
     119            delete db_meta;
     120
    78121        delete decoder;
    79122    }
    80123}
     
    83126{
    84127    kFileSystem,
    85128    kDatabase,
    86     kBoth
     129    kNeedUpdate,
    87130};
    88131
    89132typedef QMap <QString, MusicFileLocation> MusicLoadedMap;
     
    102145    QFileInfoListIterator it(*list);
    103146    QFileInfo *fi;
    104147
     148    /* Recursively traverse directory */
    105149    while ((fi = it.current()) != 0)
    106150    {
    107151        ++it;
     
    111155        if (fi->isDir())
    112156            BuildFileList(filename, music_files);
    113157        else
    114             music_files[filename] = kFileSystem;
     158            music_files[filename] = kFileSystem;           
    115159    }
    116160}
    117161
     162/* Check if the file's mdate is after the date_modified */
     163bool HasFileChanged (const QString &filename, const QString &date_modified)
     164{
     165    struct stat sbuf;
     166    if (stat (filename.ascii (), &sbuf) == 0) {
     167        if (sbuf.st_mtime > (time_t)QDateTime::fromString (date_modified, Qt::ISODate).toTime_t ()) {
     168            return true;
     169        }
     170    }
     171    return false;
     172}
     173
    118174void SavePending(int pending)
    119175{
    120176    //  Temporary Hack until mythmusic
     
    176232{
    177233    MusicLoadedMap music_files;
    178234    MusicLoadedMap::Iterator iter;
     235   
     236    {
     237        /* Let the user know we're doing something, since ie. building
     238           the filelist over NFS can take quite a while, so progress
     239           bar now...
     240        */
     241        MythBusyIndicator busy (QObject::tr("Searching for music files"));
     242        BuildFileList(directory, music_files);
     243    }
    179244
    180     BuildFileList(directory, music_files);
    181 
    182245    MSqlQuery query(MSqlQuery::InitCon());
    183     query.exec("SELECT filename FROM musicmetadata "
     246    query.exec("SELECT filename, date_modified FROM musicmetadata "
    184247                    "WHERE filename NOT LIKE ('%://%');");
    185248
     249    MythProgressDialog *progress;
     250    progress = new MythProgressDialog(QObject::tr("Scanning music files"),
     251                                      query.numRowsAffected());
     252
    186253    int counter = 0;
    187254
    188     MythProgressDialog *file_checking;
    189     file_checking = new MythProgressDialog(QObject::tr("Searching for music files"),
    190                                            query.numRowsAffected());
    191 
    192255    if (query.isActive() && query.size() > 0)
    193256    {
    194257        while (query.next())
     
    196259            QString name = directory + QString::fromUtf8(query.value(0).toString());
    197260            if (name != QString::null)
    198261            {
    199                 if ((iter = music_files.find(name)) != music_files.end())
    200                     music_files.remove(iter);
    201                 else
     262                if ((iter = music_files.find(name)) != music_files.end()) {
     263                    if (HasFileChanged (name, query.value (1).toString ())) {
     264                        music_files[name] = kNeedUpdate;
     265                    } else {
     266                        music_files.remove(iter);
     267                    }
     268                } else {
    202269                    music_files[name] = kDatabase;
     270                }
    203271            }
    204             file_checking->setProgress(++counter);
     272            progress->setProgress(++counter);
    205273        }
    206274    }
    207275
    208     file_checking->Close();
    209     delete file_checking;
     276    progress->Close();
     277    delete progress;
    210278
    211     file_checking = new MythProgressDialog(QObject::tr("Updating music database"),
     279    counter = 0;
     280    progress = new MythProgressDialog(QObject::tr("Updating music database"),
    212281                                           music_files.size());
    213282
    214283    QRegExp quote_regex("\"");
    215284    for (iter = music_files.begin(); iter != music_files.end(); iter++)
    216285    {
    217         if (*iter == kFileSystem)
    218         {
    219             CheckFile(iter.key());
     286        switch (*iter) {
     287        case kFileSystem:
     288            CheckFile(directory, iter.key());
     289            break;
     290        case kDatabase:
     291            RemoveFile (directory, iter.key());
     292            break;
     293        case kNeedUpdate:
     294            UpdateFile (directory, iter.key ());
     295            break;
    220296        }
    221         else if (*iter == kDatabase)
    222         {
    223             QString name(iter.key());
    224             name.remove(0, directory.length());
    225 
    226             query.prepare("DELETE FROM musicmetadata WHERE "
    227                           "filename = :NAME ;");
    228             query.bindValue(":NAME", name.utf8());
    229             query.exec();
    230         }
    231 
    232         file_checking->setProgress(++counter);
     297        progress->setProgress(++counter);
    233298    }
    234     file_checking->Close();
    235     delete file_checking;
     299    progress->Close();
     300    delete progress;
    236301}
    237302
    238303void startPlayback(PlaylistsContainer *all_playlists, AllMusic *all_music)
     
    302367            //  Reconcile with the database
    303368            SearchDir(mdata->startdir);
    304369            //  Tell the metadata to reset itself
     370            MythBusyIndicator busy (QObject::tr("Rebuilding music tree"));
    305371            mdata->all_music->resync();
    306372            mdata->all_playlists->postLoad();
    307373        }
     
    311377        if ("" != mdata->startdir)
    312378        {
    313379            SearchDir(mdata->startdir);
     380            MythBusyIndicator busy (QObject::tr("Rebuilding music tree"));
    314381            mdata->all_music->resync();
    315382            mdata->all_playlists->postLoad();
    316383        }
     
    554621        // if startRipper returns true, then new files should be present
    555622        // so we should look for them.
    556623        SearchDir(mdata.startdir);
     624        MythBusyIndicator busy (QObject::tr("Rebuilding music tree"));
    557625        mdata.all_music->resync();
    558626        mdata.all_playlists->postLoad();
    559627    }
  • mythplugins/mythmusic/mythmusic/flacdecoder.cpp

     
    385385        char *field_value;
    386386} Argument_VcField;
    387387
    388 Metadata *FlacDecoder::getMetadata()
     388MetaIO *FlacDecoder::doCreateTagger()
    389389{
    390     Metadata *mdata = new Metadata(filename);
    391     if (mdata->isInDatabase(musiclocation))
    392     {
    393         return mdata;
    394     }
     390    return new MetaIOFLACVorbisComment;
     391}
    395392
    396     delete mdata;
    397393
    398     MetaIOFLACVorbisComment* p_tagger = new MetaIOFLACVorbisComment;
    399     if (ignore_id3)
    400         mdata = p_tagger->readFromFilename(filename);
    401     else
    402         mdata = p_tagger->read(filename);
    403 
    404     delete p_tagger;
    405 
    406     if (mdata)
    407         mdata->dumpToDatabase(musiclocation);
    408     else
    409         cerr << "flacdecoder.o: Could not read metadata from " << filename.local8Bit() << endl;
    410 
    411     return mdata;
    412 }   
    413 
    414 void FlacDecoder::commitMetadata(Metadata *mdata)
    415 {
    416     MetaIOFLACVorbisComment* p_tagger = new MetaIOFLACVorbisComment;
    417     p_tagger->write(mdata);
    418     delete p_tagger;
    419     }
    420 
    421 
    422394bool FlacDecoderFactory::supports(const QString &source) const
    423395{
    424396    return (source.right(extension().length()).lower() == extension());
  • mythplugins/mythmusic/mythmusic/maddecoder.h

     
    2424    static const int maxFrameCheck;
    2525    static const int initialFrameSize;
    2626
    27     Metadata *getMetadata();
    28     void commitMetadata(Metadata *mdata);
     27    MetaIO *doCreateTagger();
    2928
    3029private:
    3130    void run();
  • mythplugins/mythmusic/mythmusic/vorbisdecoder.h

     
    1818    void seek(double);
    1919    void stop();
    2020
    21     Metadata *getMetadata();
    22     void commitMetadata(Metadata *mdata);
     21    MetaIO *doCreateTagger();
    2322
    2423  private:
    2524    void run();
  • mythplugins/mythmusic/mythmusic/avfdecoder.h

     
    1818    void seek(double);
    1919    void stop();
    2020
    21     Metadata *getMetadata();
    22     void commitMetadata(Metadata *mdata);
     21    MetaIO *doCreateTagger();
    2322
    2423  private:
    2524    void run();
  • mythplugins/mythmusic/mythmusic/maddecoder.cpp

     
    512512    return MAD_FLOW_STOP;
    513513}
    514514
    515 Metadata *MadDecoder::getMetadata()
     515MetaIO *MadDecoder::doCreateTagger()
    516516{
    517     Metadata *mdata = new Metadata(filename);
    518     if (mdata->isInDatabase(musiclocation))
    519     {
    520         return mdata;
    521     }
    522 
    523     delete mdata;
    524 
    525 
    526     MetaIOID3v2* p_tagger = new MetaIOID3v2;
    527     if (ignore_id3)
    528         mdata = p_tagger->readFromFilename(filename);
    529     else
    530         mdata = p_tagger->read(filename);
    531 
    532     delete p_tagger;
    533 
    534     if (mdata)
    535         mdata->dumpToDatabase(musiclocation);
    536     else
    537         cerr << "maddecoder.o: Could not read metadata from " << filename.local8Bit() << endl;
    538 
    539     return mdata;
     517    return new MetaIOID3v2;
    540518}
    541519
    542 void MadDecoder::commitMetadata(Metadata *mdata)
    543 {
    544     MetaIOID3v2* p_tagger = new MetaIOID3v2;
    545     p_tagger->write(mdata);
    546     delete p_tagger;
    547 }
    548 
    549520bool MadDecoderFactory::supports(const QString &source) const
    550521{
    551522    bool res = false;