Ticket #8595: mythmusic_popm.2.diff

File mythmusic_popm.2.diff, 21.5 KB (added by stuartm, 11 years ago)

Updated patch with a few changes, including modtime update

  • mythplugins/mythmusic/mythmusic/playbackbox.cpp

     
    12141214    gPlayer->getOutput()->ToggleUpmix();
    12151215    gPlayer->getOutput()->SetTimecode(currentTime * 1000);
    12161216}
    1217    
    12181217
     1218
    12191219void PlaybackBoxMusic::showProgressBar()
    12201220{
    12211221    if (progress_bar && visualizer_status != 2)
    1222     {       
     1222    {
    12231223        int percentplayed = 1;
    12241224        if (maxTime)
    12251225            percentplayed = (int)(((double)currentTime / (double)maxTime)*100);
     
    15621562            }
    15631563
    15641564        }
    1565        
     1565
    15661566        gPlayer->getOutput()->SetTimecode(pos*1000);
    15671567
    15681568        if (!gPlayer->isPlaying())
     
    17741774            // sanity check - if we are not in 'show whole tree' mode we
    17751775            // should only restore the position if it points to a track
    17761776            // in the active play queue
    1777             if (branches_to_current_node.size() >= 3 && 
     1777            if (branches_to_current_node.size() >= 3 &&
    17781778                branches_to_current_node[0] == 0 &&
    17791779                branches_to_current_node[1] == 1 &&
    17801780                branches_to_current_node[2] == 0)
     
    19461946        {
    19471947            if (class LCD *lcd = LCD::Get())
    19481948            {
    1949                 float percent_heard = (maxTime<=0) ? 
     1949                float percent_heard = (maxTime<=0) ?
    19501950                    0.0:((float)rs / (float)curMeta->Length()) * 1000.0;
    19511951
    19521952                QString lcd_time_string = time_string;
  • mythplugins/mythmusic/mythmusic/decoder.h

     
    9393    virtual Metadata *getMetadata(void);
    9494    virtual MetaIO *doCreateTagger (void);
    9595    virtual void commitMetadata(Metadata *mdata);
     96    virtual void commitVolatileMetadata(const Metadata *mdata);
    9697
    9798    // static methods
    9899    static QStringList all();
  • mythplugins/mythmusic/mythmusic/metadata.cpp

     
    8787    Metadata::m_startdir = dir;
    8888}
    8989
    90 void Metadata::persist()
     90void Metadata::persist() const
    9191{
     92    if (m_id < 1)
     93        return;
     94
    9295    MSqlQuery query(MSqlQuery::InitCon());
    9396    query.prepare("UPDATE music_songs set rating = :RATING , "
    9497                  "numplays = :PLAYCOUNT , lastplay = :LASTPLAY "
     
    102105        MythDB::DBError("music persist", query);
    103106}
    104107
     108
     109void Metadata::UpdateModTime() const
     110{
     111    if (m_id < 1)
     112        return;
     113
     114    MSqlQuery query(MSqlQuery::InitCon());
     115
     116    query.prepare("UPDATE music_songs SET date_modified = :DATE_MOD "
     117                  "WHERE song_id= :ID ;");
     118
     119    query.bindValue(":DATE_MOD", QDateTime::currentDateTime());
     120    query.bindValue(":ID", m_id);
     121
     122    if (!query.exec())
     123        MythDB::DBError("Metadata::UpdateModTime",
     124                        query);
     125}
     126
    105127int Metadata::compare(const Metadata *other) const
    106128{
    107129    if (m_format == "cast")
  • mythplugins/mythmusic/mythmusic/metaio.h

     
    1616    virtual ~MetaIO(void);
    1717
    1818    /*!
    19     * \brief Writes metadata back to a file
     19    * \brief Writes all metadata back to a file
    2020    *
    2121    * \param mdata A pointer to a Metadata object
    2222    * \returns Boolean to indicate success/failure.
     
    2424    virtual bool write(Metadata* mdata) = 0;
    2525
    2626    /*!
     27    * \brief Writes rating and playcount back to a file
     28    *
     29    * \param rating Integer between 0 and 10 representing the rating given to
     30    *               this file by the user
     31    * \returns Boolean to indicate success/failure.
     32    */
     33    virtual bool writeVolatileMetadata(const Metadata* mdata)
     34    {
     35        (void)mdata;
     36        return false;
     37    }
     38
     39    /*!
    2740    * \brief Reads Metadata from a file.
    2841    *
    2942    * \param filename The filename to read metadata from.
     
    3144    */
    3245    virtual Metadata* read(QString filename) = 0;
    3346
    34     void readFromFilename(QString filename, QString &artist, QString &album, 
     47    void readFromFilename(QString filename, QString &artist, QString &album,
    3548                          QString &title, QString &genre, int &tracknum);
    3649
    3750    Metadata* readFromFilename(QString filename, bool blnLength = false);
    3851
    3952    void readFromFilename(Metadata *metadata);
    40    
     53
    4154  protected:
    4255
    4356  private:
  • mythplugins/mythmusic/mythmusic/decoder.cpp

     
    156156    }
    157157}
    158158
     159/**
     160 *  \brief Write the changable metadata, e.g. ratings, playcounts; to the
     161 *         \p filename if the tag format supports it.
     162 *
     163 *  Creates a \p MetaIO object using \p Decoder::doCreateTagger and
     164 *  asks the MetaIO object to write changes to a specific subset of metadata
     165 *  to \p filename.
     166 *
     167 *  \params mdata the metadata to write to the disk
     168 */
     169void Decoder::commitVolatileMetadata(const Metadata *mdata)
     170{
     171    if (!mdata)
     172        return;
     173
     174    MetaIO* p_tagger = doCreateTagger();
     175    if (p_tagger)
     176    {
     177        p_tagger->writeVolatileMetadata(mdata);
     178        delete p_tagger;
     179    }
     180
     181    mdata->UpdateModTime();
     182}
     183
    159184// static methods
    160185
    161186int Decoder::ignore_id3 = 0;
  • mythplugins/mythmusic/mythmusic/metadata.h

     
    181181    void getField(const QString& field, QString *data);
    182182    void toMap(MetadataMap &metadataMap);
    183183
    184     void persist();
     184    void persist(void) const;
     185    void UpdateModTime(void) const;
    185186    bool hasChanged() {return m_changed;}
    186187    int compare(const Metadata *other) const;
    187188    static void setArtistAndTrackFormats();
  • mythplugins/mythmusic/mythmusic/editmetadata.cpp

     
    660660
    661661    m_metadata->dumpToDatabase();
    662662    *m_sourceMetadata = m_metadata;
     663
    663664    accept();
    664665}
    665666
  • mythplugins/mythmusic/mythmusic/metaiotaglib.h

     
    2626
    2727    virtual bool write(Metadata* mdata) = 0;
    2828    virtual Metadata* read(QString filename) = 0;
    29    
     29
    3030  protected:
    3131    int getTrackLength(TagLib::FileRef *file);
    3232    int getTrackLength(QString filename);
  • mythplugins/mythmusic/mythmusic/metaioid3.cpp

     
    44
    55// Libmyth
    66#include <mythverbose.h>
     7#include <set>
    78
     9const String email = "music@mythtv.org";  // TODO username/ip/hostname?
     10
    811MetaIOID3::MetaIOID3(void)
    912    : MetaIOTagLib()
    1013{
     
    2427{
    2528    QByteArray fname = filename.toLocal8Bit();
    2629    TagLib::MPEG::File *mpegfile = new TagLib::MPEG::File(fname.constData());
    27    
     30
    2831    if (!mpegfile->isOpen())
    2932    {
    3033        delete mpegfile;
     
    4346
    4447    if (!mpegfile)
    4548        return false;
    46    
     49
    4750    TagLib::ID3v2::Tag *tag = mpegfile->ID3v2Tag();
    4851
    4952    if (!tag)
     
    5154        delete mpegfile;
    5255        return false;
    5356    }
    54    
     57
    5558    WriteGenericMetadata(tag, mdata);
    56    
    57     if (mdata->Rating() > 0 || mdata->PlayCount() > 0)
    58     {
    59         // Needs to be implemented for taglib by subclassing ID3v2::Frames
    60         // with one to handle POPM frames
    61     }
    62    
     59
     60    // MythTV rating and playcount, stored in POPM frame
     61    writeRating(tag, mdata->Rating());
     62    writePlayCount(tag, mdata->PlayCount());
     63
    6364    // MusicBrainz ID
    6465    UserTextIdentificationFrame *musicbrainz = NULL;
    6566    musicbrainz = find(tag, "MusicBrainz Album Artist Id");
    6667
    6768    if (mdata->Compilation())
    6869    {
    69        
     70
    7071        if (!musicbrainz)
    7172        {
    7273            musicbrainz = new UserTextIdentificationFrame(TagLib::String::UTF8);
    7374            tag->addFrame(musicbrainz);
    7475            musicbrainz->setDescription("MusicBrainz Album Artist Id");
    7576        }
    76        
     77
    7778        musicbrainz->setText(MYTH_MUSICBRAINZ_ALBUMARTIST_UUID);
    7879    }
    7980    else if (musicbrainz)
     
    8687        TagLib::ID3v2::FrameList tpelist = tag->frameListMap()["TPE4"];
    8788        if (!tpelist.isEmpty())
    8889            tpe4frame = (TextIdentificationFrame *)tpelist.front();
    89        
     90
    9091        if (!tpe4frame)
    9192        {
    9293            tpe4frame = new TextIdentificationFrame(TagLib::ByteVector("TPE4"),
     
    9596        }
    9697        tpe4frame->setText(QStringToTString(mdata->CompilationArtist()));
    9798
    98        
     99
    99100        TextIdentificationFrame *tpe2frame = NULL;
    100101        tpelist = tag->frameListMap()["TPE2"];
    101102        if (!tpelist.isEmpty())
     
    109110        }
    110111        tpe2frame->setText(QStringToTString(mdata->CompilationArtist()));
    111112    }
    112    
     113
    113114    bool result = mpegfile->save();
    114115
    115116    delete mpegfile;
    116    
     117
    117118    return result;
    118119}
    119120
     
    123124Metadata *MetaIOID3::read(QString filename)
    124125{
    125126    TagLib::MPEG::File *mpegfile = OpenFile(filename);
    126    
     127
    127128    if (!mpegfile)
    128129        return NULL;
    129130
     
    134135        delete mpegfile;
    135136        return NULL;
    136137    }
    137    
     138
    138139    Metadata *metadata = new Metadata(filename);
    139    
     140
    140141    ReadGenericMetadata(tag, metadata);
    141142
    142143    bool compilation = false;
     
    151152        tpelist = tag->frameListMap()["TPE2"];
    152153    if (!tpelist.isEmpty())
    153154        tpeframe = (TextIdentificationFrame *)tpelist.front();
    154    
     155
    155156    if (tpeframe && !tpeframe->toString().isEmpty())
    156157    {
    157158        QString compilation_artist = TStringToQString(tpeframe->toString())
     
    159160        metadata->setCompilationArtist(compilation_artist);
    160161    }
    161162
     163    // MythTV rating and playcount, stored in POPM frame
     164    PopularimeterFrame *popm = findPOPM(tag, email);
     165
     166    if (!popm)
     167    {
     168        if (!tag->frameListMap()["POPM"].isEmpty())
     169            popm = dynamic_cast<PopularimeterFrame *>
     170                                        (tag->frameListMap()["POPM"].front());
     171    }
     172
     173    if (popm)
     174    {
     175        int rating = popm->rating();
     176        rating = static_cast<int>(((static_cast<float>(rating)/255.0)
     177                                                                * 10.0) + 0.5);
     178        metadata->setRating(rating);
     179        metadata->setPlaycount(popm->counter());
     180    }
     181
    162182    // Look for MusicBrainz Album+Artist ID in TXXX Frame
    163183    UserTextIdentificationFrame *musicbrainz = find(tag,
    164184                                            "MusicBrainz Album Artist Id");
     
    173193    }
    174194
    175195    // Length
    176     if (!mpegfile->ID3v2Tag()->frameListMap()["TLEN"].isEmpty())
     196    if (!tag->frameListMap()["TLEN"].isEmpty())
    177197    {
    178198        int length = tag->frameListMap()["TLEN"].front()->toString().toInt();
    179199        metadata->setLength(length);
     
    199219    }
    200220    else
    201221        delete mpegfile;
    202    
     222
    203223    return metadata;
    204224}
    205225
     
    237257        default:
    238258            return picture;
    239259    }
    240    
     260
    241261    QByteArray fname = filename.toLocal8Bit();
    242262    TagLib::MPEG::File *mpegfile = new TagLib::MPEG::File(fname.constData());
    243263
     
    364384    if (f && f->description() == description)
    365385      return f;
    366386  }
    367   return 0;
     387  return NULL;
    368388}
     389
     390/*!
     391 * \brief Find the POPM tag associated with MythTV
     392 *        This is a copy of the same function in the
     393 *        TagLib::ID3v2::UserTextIdentificationFrame Class with a static
     394 *        instead of dynamic cast.
     395 *
     396 * \param tag Pointer to TagLib::ID3v2::Tag object
     397 * \param email Email address associated with this POPM frame
     398 * \returns Pointer to frame
     399 */
     400PopularimeterFrame* MetaIOID3::findPOPM(TagLib::ID3v2::Tag *tag,
     401                                        const String &email)
     402{
     403  TagLib::ID3v2::FrameList l = tag->frameList("POPM");
     404  for(TagLib::ID3v2::FrameList::Iterator it = l.begin(); it != l.end(); ++it)
     405  {
     406    PopularimeterFrame *f = static_cast<PopularimeterFrame *>(*it);
     407    if (f && f->email() == email)
     408      return f;
     409  }
     410  return NULL;
     411}
     412
     413bool MetaIOID3::writePlayCount(TagLib::ID3v2::Tag *tag, int playcount)
     414{
     415    if (!tag)
     416        return false;
     417
     418    PopularimeterFrame *popm = findPOPM(tag, email);
     419
     420    if (!popm)
     421    {
     422        popm = new PopularimeterFrame();
     423        tag->addFrame(popm);
     424        popm->setEmail(email);
     425    }
     426
     427    popm->setCounter(playcount);
     428
     429    return true;
     430}
     431
     432bool MetaIOID3::writeVolatileMetadata(const Metadata* mdata)
     433{
     434    QString filename = mdata->Filename();
     435    int rating = mdata->Rating();
     436    int playcount = mdata->PlayCount();
     437    TagLib::MPEG::File *mpegfile = OpenFile(filename);
     438
     439    if (!mpegfile)
     440        return false;
     441
     442    TagLib::ID3v2::Tag *tag = mpegfile->ID3v2Tag();
     443
     444    if (!tag)
     445    {
     446        delete mpegfile;
     447        return false;
     448    }
     449
     450    bool result = (writeRating(tag, rating) && writePlayCount(tag, playcount));
     451
     452    mpegfile->save();
     453    delete mpegfile;
     454
     455    return result;
     456}
     457
     458bool MetaIOID3::writeRating(TagLib::ID3v2::Tag *tag, int rating)
     459{
     460    if (!tag)
     461        return false;
     462
     463    PopularimeterFrame *popm = findPOPM(tag, email);
     464
     465    if (!popm)
     466    {
     467        popm = new PopularimeterFrame();
     468        tag->addFrame(popm);
     469        popm->setEmail(email);
     470    }
     471    int popmrating = static_cast<int>(((static_cast<float>(rating) / 10.0)
     472                                                               * 255.0) + 0.5);
     473    popm->setRating(popmrating);
     474
     475    return true;
     476}
  • mythplugins/mythmusic/mythmusic/musicplayer.cpp

     
    166166            m_output->addListener(visual);
    167167            m_output->addVisual(visual);
    168168        }
    169  
     169
    170170        m_visualisers.insert(visual);
    171171    }
    172172}
     
    355355    if (m_currentMetadata)
    356356    {
    357357        if (m_currentMetadata->hasChanged())
     358        {
    358359            m_currentMetadata->persist();
     360            m_decoder->commitVolatileMetadata(m_currentMetadata);
     361        }
    359362        delete m_currentMetadata;
    360363    }
    361364    m_currentMetadata = NULL;
     
    768771    {
    769772        m_currentTrack = position;
    770773    }
    771    
     774
    772775    m_currentFile.clear();
    773776    Track *track = m_currentPlaylist->getSongAt(m_currentTrack);
    774777    if (track)
    775778        m_currentFile = getFilenameFromID(track->getValue());
    776    
     779
    777780    if (!m_currentFile.isEmpty())
    778781        play();
    779782}
     
    989992
    990993void MusicPlayer::toMap(QHash<QString, QString> &map)
    991994{
    992     map["volumemute"] = QString("%1%").arg(getVolume()) + 
     995    map["volumemute"] = QString("%1%").arg(getVolume()) +
    993996                        (isMuted() ? " (" + tr("Muted") + ")" : "");
    994997    map["volume"] = QString("%1").arg(getVolume());
    995998    map["volumepercent"] = QString("%1%").arg(getVolume());
  • mythplugins/mythmusic/mythmusic/musiccommon.h

     
    5151    void seekback(void);
    5252    void seek(int);
    5353    void stopAll(void);
    54     void increaseRating(void);
    55     void decreaseRating(void);
     54    void changeRating(bool increase);
    5655
    5756    void showViewMenu(void);
    5857    void showPlaylistMenu(void);
  • mythplugins/mythmusic/mythmusic/metaioavfcomment.h

     
    2121public:
    2222    MetaIOAVFComment(void);
    2323    virtual ~MetaIOAVFComment(void);
    24    
     24
    2525    bool write(Metadata* mdata);
    2626    Metadata* read(QString filename);
    27    
     27
    2828private:
    2929    int getTrackLength(QString filename);
    3030    int getTrackLength(AVFormatContext* p_context);
  • mythplugins/mythmusic/mythmusic/metaioid3.h

     
    99#include <id3v2tag.h>
    1010#include <textidentificationframe.h>
    1111#include <attachedpictureframe.h>
     12#include <popularimeterframe.h>
    1213#include <mpegproperties.h>
    1314#include <mpegfile.h>
    1415#include <tfile.h>
     
    1819
    1920using TagLib::ID3v2::UserTextIdentificationFrame;
    2021using TagLib::ID3v2::TextIdentificationFrame;
     22using TagLib::ID3v2::PopularimeterFrame;
    2123using TagLib::ID3v2::AttachedPictureFrame;
    2224using TagLib::MPEG::Properties;
    2325
     
    3739  public:
    3840    MetaIOID3(void);
    3941    virtual ~MetaIOID3(void);
    40    
     42
    4143    bool write(Metadata* mdata);
     44    bool writeVolatileMetadata(const Metadata* mdata);
     45
     46    bool writePlayCount(TagLib::ID3v2::Tag *tag, int playcount);
     47    bool writeRating(TagLib::ID3v2::Tag *tag, int rating);
     48
    4249    Metadata* read(QString filename);
    4350    static QImage getAlbumArt(QString filename, ImageType type);
    4451
     
    4754
    4855    AlbumArtList readAlbumArt(TagLib::ID3v2::Tag *tag);
    4956    UserTextIdentificationFrame* find(TagLib::ID3v2::Tag *tag, const String &description);
     57    PopularimeterFrame* findPOPM(TagLib::ID3v2::Tag *tag, const String &email);
    5058};
    5159
    5260#endif
  • mythplugins/mythmusic/mythmusic/musiccommon.cpp

     
    191191
    192192    if (m_currentPlaylist)
    193193    {
    194         connect(m_currentPlaylist, SIGNAL(itemClicked(MythUIButtonListItem*)), 
     194        connect(m_currentPlaylist, SIGNAL(itemClicked(MythUIButtonListItem*)),
    195195                this, SLOT(playlistItemClicked(MythUIButtonListItem*)));
    196         connect(m_currentPlaylist, SIGNAL(itemSelected(MythUIButtonListItem*)), 
     196        connect(m_currentPlaylist, SIGNAL(itemSelected(MythUIButtonListItem*)),
    197197                this, SLOT(playlistItemSelected(MythUIButtonListItem*)));
    198198
    199199        updateUIPlaylist();
     
    413413            }
    414414        }
    415415        else if (action == "THMBUP")
    416             increaseRating();
     416            changeRating(true);
    417417        else if (action == "THMBDOWN")
    418             decreaseRating();
     418            changeRating(false);
    419419        else if (action == "NEXTTRACK")
    420420        {
    421421            if (m_nextButton)
     
    825825    }
    826826}
    827827
    828 void MusicCommon::increaseRating(void)
     828void MusicCommon::changeRating(bool increase)
    829829{
    830     Metadata *curMeta = gPlayer->getCurrentMetadata();
    831 
    832     if (!curMeta)
     830    // Rationale here is that if you can't get visual feedback on ratings
     831    // adjustments, you probably should not be changing them
     832    if (!m_ratingState)
    833833        return;
    834834
    835     if (m_ratingState)
    836     {
    837         curMeta->incRating();
    838         curMeta->persist();
    839         m_ratingState->DisplayState(QString("%1").arg(curMeta->Rating()));
    840 
    841         // if all_music is still in scope we need to keep that in sync
    842         if (gMusicData->all_music)
    843         {
    844             Metadata *mdata = gMusicData->all_music->getMetadata(curMeta->ID());
    845             if (mdata)
    846                 mdata->incRating();
    847         }
    848     }
    849 }
    850 
    851 void MusicCommon::decreaseRating(void)
    852 {
    853835    Metadata *curMeta = gPlayer->getCurrentMetadata();
    854836
    855837    if (!curMeta)
    856838        return;
    857839
    858     if (m_ratingState)
    859     {
     840    if (increase)
     841        curMeta->incRating();
     842    else
    860843        curMeta->decRating();
    861         curMeta->persist();
    862         m_ratingState->DisplayState(QString("%1").arg(curMeta->Rating()));
    863844
    864         // if all_music is still in scope we need to keep that in sync
    865         if (gMusicData->all_music)
     845    curMeta->persist(); // incRating() already triggers a persist on track changes - redundant?
     846    m_ratingState->DisplayState(QString("%1").arg(curMeta->Rating()));
     847
     848    // if all_music is still in scope we need to keep that in sync
     849    if (gMusicData->all_music)
     850    {
     851        Metadata *mdata = gMusicData->all_music->getMetadata(curMeta->ID());
     852        if (mdata)
    866853        {
    867             Metadata *mdata = gMusicData->all_music->getMetadata(curMeta->ID());
    868             if (mdata)
    869                 mdata->decRating();
     854            mdata->setRating(curMeta->Rating());
    870855        }
    871856    }
    872857}
     
    12561241    MetadataMap metadataMap;
    12571242    mdata->toMap(metadataMap);
    12581243    SetTextFromMap(metadataMap);
    1259    
     1244
    12601245    m_maxTime = mdata->Length() / 1000;
    12611246    if (m_coverartImage)
    12621247    {
     
    13831368        Metadata *mdata = gMusicData->all_music->getMetadata(trackid);
    13841369        if (mdata)
    13851370        {
    1386             MythUIButtonListItem *item = 
     1371            MythUIButtonListItem *item =
    13871372                new MythUIButtonListItem(m_currentPlaylist, "", qVariantFromValue(mdata));
    13881373
    13891374            MetadataMap metadataMap;