Ticket #8595: mythmusic_popm.diff
| File mythmusic_popm.diff, 17.9 KB (added by , 15 years ago) |
|---|
-
mythplugins/mythmusic/mythmusic/decoder.h
93 93 virtual Metadata *getMetadata(void); 94 94 virtual MetaIO *doCreateTagger (void); 95 95 virtual void commitMetadata(Metadata *mdata); 96 virtual void commitPlayCount(const Metadata *mdata); 97 virtual void commitRating(const Metadata *mdata); 96 98 97 99 // static methods 98 100 static QStringList all(); -
mythplugins/mythmusic/mythmusic/metaio.h
16 16 virtual ~MetaIO(void); 17 17 18 18 /*! 19 * \brief Writes metadata back to a file19 * \brief Writes all metadata back to a file 20 20 * 21 21 * \param mdata A pointer to a Metadata object 22 22 * \returns Boolean to indicate success/failure. … … 24 24 virtual bool write(Metadata* mdata) = 0; 25 25 26 26 /*! 27 * \brief Writes playcount (only) back to a file 28 * 29 * \param playcount Integer representing the number of times this file has 30 * been played 31 * \returns Boolean to indicate success/failure. 32 */ 33 virtual bool writePlayCount(const Metadata* mdata) 34 { 35 (void)mdata; 36 return false; 37 } 38 39 /*! 40 * \brief Writes rating (only) back to a file 41 * 42 * \param rating Integer between 0 and 10 representing the rating given to 43 * this file by the user 44 * \returns Boolean to indicate success/failure. 45 */ 46 virtual bool writeRating(const Metadata* mdata) 47 { 48 (void)mdata; 49 return false; 50 } 51 52 /*! 27 53 * \brief Reads Metadata from a file. 28 54 * 29 55 * \param filename The filename to read metadata from. … … 31 57 */ 32 58 virtual Metadata* read(QString filename) = 0; 33 59 34 void readFromFilename(QString filename, QString &artist, QString &album, 60 void readFromFilename(QString filename, QString &artist, QString &album, 35 61 QString &title, QString &genre, int &tracknum); 36 62 37 63 Metadata* readFromFilename(QString filename, bool blnLength = false); 38 64 39 65 void readFromFilename(Metadata *metadata); 40 66 41 67 protected: 42 68 43 69 private: -
mythplugins/mythmusic/mythmusic/decoder.cpp
156 156 } 157 157 } 158 158 159 /** 160 * \brief Write the playcount to the \p filename if the tag format supports it. 161 * 162 * Creates a \p MetaIO object using \p Decoder::doCreateTagger and 163 * asks the MetaIO object to write the playcount to \p 164 * filename. 165 * 166 * \params mdata the metadata to write to the disk 167 */ 168 void Decoder::commitPlayCount(const Metadata *mdata) 169 { 170 MetaIO* p_tagger = doCreateTagger(); 171 if (p_tagger) 172 { 173 p_tagger->writePlayCount(mdata); 174 delete p_tagger; 175 } 176 } 177 178 /** 179 * \brief Write the rating to the \p filename if the tag format supports it. 180 * 181 * Creates a \p MetaIO object using \p Decoder::doCreateTagger and 182 * asks the MetaIO object to write the rating to \p 183 * filename. 184 * 185 * \params mdata the metadata to write to the disk 186 */ 187 void Decoder::commitRating(const Metadata *mdata) 188 { 189 MetaIO* p_tagger = doCreateTagger(); 190 if (p_tagger) 191 { 192 p_tagger->writeRating(mdata); 193 delete p_tagger; 194 } 195 } 196 159 197 // static methods 160 198 161 199 int Decoder::ignore_id3 = 0; -
mythplugins/mythmusic/mythmusic/editmetadata.cpp
660 660 661 661 m_metadata->dumpToDatabase(); 662 662 *m_sourceMetadata = m_metadata; 663 664 if (m_metadata->hasChanged()) 665 { 666 // Only save rating, this is safe for ID3 since mythtv uses it's own 667 // labelled field and won't overwrite existing ratings 668 Decoder *decoder = Decoder::create(m_metadata->Filename(), NULL, NULL, true); 669 if (decoder) 670 { 671 decoder->commitRating(m_metadata); 672 delete decoder; 673 } 674 } 675 663 676 accept(); 664 677 } 665 678 -
mythplugins/mythmusic/mythmusic/metaiotaglib.h
26 26 27 27 virtual bool write(Metadata* mdata) = 0; 28 28 virtual Metadata* read(QString filename) = 0; 29 29 30 30 protected: 31 31 int getTrackLength(TagLib::FileRef *file); 32 32 int getTrackLength(QString filename); -
mythplugins/mythmusic/mythmusic/metaioid3.cpp
4 4 5 5 // Libmyth 6 6 #include <mythverbose.h> 7 #include <set> 7 8 9 const String email = "music@mythtv.org"; // TODO username/ip/hostname? 10 8 11 MetaIOID3::MetaIOID3(void) 9 12 : MetaIOTagLib() 10 13 { … … 24 27 { 25 28 QByteArray fname = filename.toLocal8Bit(); 26 29 TagLib::MPEG::File *mpegfile = new TagLib::MPEG::File(fname.constData()); 27 30 28 31 if (!mpegfile->isOpen()) 29 32 { 30 33 delete mpegfile; … … 43 46 44 47 if (!mpegfile) 45 48 return false; 46 49 47 50 TagLib::ID3v2::Tag *tag = mpegfile->ID3v2Tag(); 48 51 49 52 if (!tag) … … 51 54 delete mpegfile; 52 55 return false; 53 56 } 54 57 55 58 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 63 64 // MusicBrainz ID 64 65 UserTextIdentificationFrame *musicbrainz = NULL; 65 66 musicbrainz = find(tag, "MusicBrainz Album Artist Id"); 66 67 67 68 if (mdata->Compilation()) 68 69 { 69 70 70 71 if (!musicbrainz) 71 72 { 72 73 musicbrainz = new UserTextIdentificationFrame(TagLib::String::UTF8); 73 74 tag->addFrame(musicbrainz); 74 75 musicbrainz->setDescription("MusicBrainz Album Artist Id"); 75 76 } 76 77 77 78 musicbrainz->setText(MYTH_MUSICBRAINZ_ALBUMARTIST_UUID); 78 79 } 79 80 else if (musicbrainz) … … 86 87 TagLib::ID3v2::FrameList tpelist = tag->frameListMap()["TPE4"]; 87 88 if (!tpelist.isEmpty()) 88 89 tpe4frame = (TextIdentificationFrame *)tpelist.front(); 89 90 90 91 if (!tpe4frame) 91 92 { 92 93 tpe4frame = new TextIdentificationFrame(TagLib::ByteVector("TPE4"), … … 95 96 } 96 97 tpe4frame->setText(QStringToTString(mdata->CompilationArtist())); 97 98 98 99 99 100 TextIdentificationFrame *tpe2frame = NULL; 100 101 tpelist = tag->frameListMap()["TPE2"]; 101 102 if (!tpelist.isEmpty()) … … 109 110 } 110 111 tpe2frame->setText(QStringToTString(mdata->CompilationArtist())); 111 112 } 112 113 113 114 bool result = mpegfile->save(); 114 115 115 116 delete mpegfile; 116 117 117 118 return result; 118 119 } 119 120 … … 123 124 Metadata *MetaIOID3::read(QString filename) 124 125 { 125 126 TagLib::MPEG::File *mpegfile = OpenFile(filename); 126 127 127 128 if (!mpegfile) 128 129 return NULL; 129 130 … … 134 135 delete mpegfile; 135 136 return NULL; 136 137 } 137 138 138 139 Metadata *metadata = new Metadata(filename); 139 140 140 141 ReadGenericMetadata(tag, metadata); 141 142 142 143 bool compilation = false; … … 151 152 tpelist = tag->frameListMap()["TPE2"]; 152 153 if (!tpelist.isEmpty()) 153 154 tpeframe = (TextIdentificationFrame *)tpelist.front(); 154 155 155 156 if (tpeframe && !tpeframe->toString().isEmpty()) 156 157 { 157 158 QString compilation_artist = TStringToQString(tpeframe->toString()) … … 159 160 metadata->setCompilationArtist(compilation_artist); 160 161 } 161 162 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 162 182 // Look for MusicBrainz Album+Artist ID in TXXX Frame 163 183 UserTextIdentificationFrame *musicbrainz = find(tag, 164 184 "MusicBrainz Album Artist Id"); … … 173 193 } 174 194 175 195 // Length 176 if (! mpegfile->ID3v2Tag()->frameListMap()["TLEN"].isEmpty())196 if (!tag->frameListMap()["TLEN"].isEmpty()) 177 197 { 178 198 int length = tag->frameListMap()["TLEN"].front()->toString().toInt(); 179 199 metadata->setLength(length); … … 199 219 } 200 220 else 201 221 delete mpegfile; 202 222 203 223 return metadata; 204 224 } 205 225 … … 237 257 default: 238 258 return picture; 239 259 } 240 260 241 261 QByteArray fname = filename.toLocal8Bit(); 242 262 TagLib::MPEG::File *mpegfile = new TagLib::MPEG::File(fname.constData()); 243 263 … … 364 384 if (f && f->description() == description) 365 385 return f; 366 386 } 367 return 0;387 return NULL; 368 388 } 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 */ 400 PopularimeterFrame* 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 413 bool MetaIOID3::writePlayCount(const Metadata* mdata) 414 { 415 QString filename = mdata->Filename(); 416 int playcount = mdata->PlayCount(); 417 TagLib::MPEG::File *mpegfile = OpenFile(filename); 418 419 if (!mpegfile) 420 return false; 421 422 TagLib::ID3v2::Tag *tag = mpegfile->ID3v2Tag(); 423 424 if (!tag) 425 { 426 delete mpegfile; 427 return false; 428 } 429 430 bool result = writePlayCount(tag, playcount); 431 432 mpegfile->save(); 433 delete mpegfile; 434 435 return result; 436 } 437 438 bool MetaIOID3::writePlayCount(TagLib::ID3v2::Tag *tag, int playcount) 439 { 440 if (!tag) 441 return false; 442 443 PopularimeterFrame *popm = findPOPM(tag, email); 444 445 if (!popm) 446 { 447 popm = new PopularimeterFrame(); 448 tag->addFrame(popm); 449 popm->setEmail(email); 450 } 451 452 popm->setCounter(playcount); 453 454 return true; 455 } 456 457 bool MetaIOID3::writeRating(const Metadata* mdata) 458 { 459 QString filename = mdata->Filename(); 460 int rating = mdata->Rating(); 461 TagLib::MPEG::File *mpegfile = OpenFile(filename); 462 463 if (!mpegfile) 464 return false; 465 466 TagLib::ID3v2::Tag *tag = mpegfile->ID3v2Tag(); 467 468 if (!tag) 469 { 470 delete mpegfile; 471 return false; 472 } 473 474 bool result = writeRating(tag, rating); 475 476 mpegfile->save(); 477 delete mpegfile; 478 479 return result; 480 } 481 482 bool MetaIOID3::writeRating(TagLib::ID3v2::Tag *tag, int rating) 483 { 484 if (!tag) 485 return false; 486 487 PopularimeterFrame *popm = findPOPM(tag, email); 488 489 if (!popm) 490 { 491 popm = new PopularimeterFrame(); 492 tag->addFrame(popm); 493 popm->setEmail(email); 494 } 495 int popmrating = static_cast<int>(((static_cast<float>(rating) / 10.0) 496 * 255.0) + 0.5); 497 popm->setRating(popmrating); 498 499 return true; 500 } -
mythplugins/mythmusic/mythmusic/musicplayer.cpp
166 166 m_output->addListener(visual); 167 167 m_output->addVisual(visual); 168 168 } 169 169 170 170 m_visualisers.insert(visual); 171 171 } 172 172 } … … 355 355 if (m_currentMetadata) 356 356 { 357 357 if (m_currentMetadata->hasChanged()) 358 { 358 359 m_currentMetadata->persist(); 360 m_decoder->commitPlayCount(m_currentMetadata); 361 } 359 362 delete m_currentMetadata; 360 363 } 361 364 m_currentMetadata = NULL; … … 768 771 { 769 772 m_currentTrack = position; 770 773 } 771 774 772 775 m_currentFile.clear(); 773 776 Track *track = m_currentPlaylist->getSongAt(m_currentTrack); 774 777 if (track) 775 778 m_currentFile = getFilenameFromID(track->getValue()); 776 779 777 780 if (!m_currentFile.isEmpty()) 778 781 play(); 779 782 } … … 989 992 990 993 void MusicPlayer::toMap(QHash<QString, QString> &map) 991 994 { 992 map["volumemute"] = QString("%1%").arg(getVolume()) + 995 map["volumemute"] = QString("%1%").arg(getVolume()) + 993 996 (isMuted() ? " (" + tr("Muted") + ")" : ""); 994 997 map["volume"] = QString("%1").arg(getVolume()); 995 998 map["volumepercent"] = QString("%1%").arg(getVolume()); -
mythplugins/mythmusic/mythmusic/metaioavfcomment.h
21 21 public: 22 22 MetaIOAVFComment(void); 23 23 virtual ~MetaIOAVFComment(void); 24 24 25 25 bool write(Metadata* mdata); 26 26 Metadata* read(QString filename); 27 27 28 28 private: 29 29 int getTrackLength(QString filename); 30 30 int getTrackLength(AVFormatContext* p_context); -
mythplugins/mythmusic/mythmusic/metaioid3.h
9 9 #include <id3v2tag.h> 10 10 #include <textidentificationframe.h> 11 11 #include <attachedpictureframe.h> 12 #include <popularimeterframe.h> 12 13 #include <mpegproperties.h> 13 14 #include <mpegfile.h> 14 15 #include <tfile.h> … … 18 19 19 20 using TagLib::ID3v2::UserTextIdentificationFrame; 20 21 using TagLib::ID3v2::TextIdentificationFrame; 22 using TagLib::ID3v2::PopularimeterFrame; 21 23 using TagLib::ID3v2::AttachedPictureFrame; 22 24 using TagLib::MPEG::Properties; 23 25 … … 37 39 public: 38 40 MetaIOID3(void); 39 41 virtual ~MetaIOID3(void); 40 42 41 43 bool write(Metadata* mdata); 44 45 bool writePlayCount(const Metadata* mdata); 46 bool writePlayCount(TagLib::ID3v2::Tag *tag, int playcount); 47 bool writeRating(const Metadata* mdata); 48 bool writeRating(TagLib::ID3v2::Tag *tag, int rating); 49 42 50 Metadata* read(QString filename); 43 51 static QImage getAlbumArt(QString filename, ImageType type); 44 52 … … 47 55 48 56 AlbumArtList readAlbumArt(TagLib::ID3v2::Tag *tag); 49 57 UserTextIdentificationFrame* find(TagLib::ID3v2::Tag *tag, const String &description); 58 PopularimeterFrame* findPOPM(TagLib::ID3v2::Tag *tag, const String &email); 50 59 }; 51 60 52 61 #endif -
mythplugins/mythmusic/mythmusic/musiccommon.cpp
191 191 192 192 if (m_currentPlaylist) 193 193 { 194 connect(m_currentPlaylist, SIGNAL(itemClicked(MythUIButtonListItem*)), 194 connect(m_currentPlaylist, SIGNAL(itemClicked(MythUIButtonListItem*)), 195 195 this, SLOT(playlistItemClicked(MythUIButtonListItem*))); 196 connect(m_currentPlaylist, SIGNAL(itemSelected(MythUIButtonListItem*)), 196 connect(m_currentPlaylist, SIGNAL(itemSelected(MythUIButtonListItem*)), 197 197 this, SLOT(playlistItemSelected(MythUIButtonListItem*))); 198 198 199 199 updateUIPlaylist(); … … 836 836 { 837 837 curMeta->incRating(); 838 838 curMeta->persist(); 839 if (gPlayer->getDecoder()) 840 gPlayer->getDecoder()->commitRating(curMeta); 839 841 m_ratingState->DisplayState(QString("%1").arg(curMeta->Rating())); 840 842 841 843 // if all_music is still in scope we need to keep that in sync … … 843 845 { 844 846 Metadata *mdata = gMusicData->all_music->getMetadata(curMeta->ID()); 845 847 if (mdata) 848 { 846 849 mdata->incRating(); 850 } 847 851 } 848 852 } 849 853 } … … 859 863 { 860 864 curMeta->decRating(); 861 865 curMeta->persist(); 866 if (gPlayer->getDecoder()) 867 gPlayer->getDecoder()->commitRating(curMeta); 862 868 m_ratingState->DisplayState(QString("%1").arg(curMeta->Rating())); 863 869 864 870 // if all_music is still in scope we need to keep that in sync … … 1256 1262 MetadataMap metadataMap; 1257 1263 mdata->toMap(metadataMap); 1258 1264 SetTextFromMap(metadataMap); 1259 1265 1260 1266 m_maxTime = mdata->Length() / 1000; 1261 1267 if (m_coverartImage) 1262 1268 { … … 1383 1389 Metadata *mdata = gMusicData->all_music->getMetadata(trackid); 1384 1390 if (mdata) 1385 1391 { 1386 MythUIButtonListItem *item = 1392 MythUIButtonListItem *item = 1387 1393 new MythUIButtonListItem(m_currentPlaylist, "", qVariantFromValue(mdata)); 1388 1394 1389 1395 MetadataMap metadataMap;
