Ticket #8595: mythmusic_popm.2.diff
File mythmusic_popm.2.diff, 21.5 KB (added by , 14 years ago) |
---|
-
mythplugins/mythmusic/mythmusic/playbackbox.cpp
1214 1214 gPlayer->getOutput()->ToggleUpmix(); 1215 1215 gPlayer->getOutput()->SetTimecode(currentTime * 1000); 1216 1216 } 1217 1218 1217 1218 1219 1219 void PlaybackBoxMusic::showProgressBar() 1220 1220 { 1221 1221 if (progress_bar && visualizer_status != 2) 1222 { 1222 { 1223 1223 int percentplayed = 1; 1224 1224 if (maxTime) 1225 1225 percentplayed = (int)(((double)currentTime / (double)maxTime)*100); … … 1562 1562 } 1563 1563 1564 1564 } 1565 1565 1566 1566 gPlayer->getOutput()->SetTimecode(pos*1000); 1567 1567 1568 1568 if (!gPlayer->isPlaying()) … … 1774 1774 // sanity check - if we are not in 'show whole tree' mode we 1775 1775 // should only restore the position if it points to a track 1776 1776 // in the active play queue 1777 if (branches_to_current_node.size() >= 3 && 1777 if (branches_to_current_node.size() >= 3 && 1778 1778 branches_to_current_node[0] == 0 && 1779 1779 branches_to_current_node[1] == 1 && 1780 1780 branches_to_current_node[2] == 0) … … 1946 1946 { 1947 1947 if (class LCD *lcd = LCD::Get()) 1948 1948 { 1949 float percent_heard = (maxTime<=0) ? 1949 float percent_heard = (maxTime<=0) ? 1950 1950 0.0:((float)rs / (float)curMeta->Length()) * 1000.0; 1951 1951 1952 1952 QString lcd_time_string = time_string; -
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 commitVolatileMetadata(const Metadata *mdata); 96 97 97 98 // static methods 98 99 static QStringList all(); -
mythplugins/mythmusic/mythmusic/metadata.cpp
87 87 Metadata::m_startdir = dir; 88 88 } 89 89 90 void Metadata::persist() 90 void Metadata::persist() const 91 91 { 92 if (m_id < 1) 93 return; 94 92 95 MSqlQuery query(MSqlQuery::InitCon()); 93 96 query.prepare("UPDATE music_songs set rating = :RATING , " 94 97 "numplays = :PLAYCOUNT , lastplay = :LASTPLAY " … … 102 105 MythDB::DBError("music persist", query); 103 106 } 104 107 108 109 void 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 105 127 int Metadata::compare(const Metadata *other) const 106 128 { 107 129 if (m_format == "cast") -
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 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 /*! 27 40 * \brief Reads Metadata from a file. 28 41 * 29 42 * \param filename The filename to read metadata from. … … 31 44 */ 32 45 virtual Metadata* read(QString filename) = 0; 33 46 34 void readFromFilename(QString filename, QString &artist, QString &album, 47 void readFromFilename(QString filename, QString &artist, QString &album, 35 48 QString &title, QString &genre, int &tracknum); 36 49 37 50 Metadata* readFromFilename(QString filename, bool blnLength = false); 38 51 39 52 void readFromFilename(Metadata *metadata); 40 53 41 54 protected: 42 55 43 56 private: -
mythplugins/mythmusic/mythmusic/decoder.cpp
156 156 } 157 157 } 158 158 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 */ 169 void 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 159 184 // static methods 160 185 161 186 int Decoder::ignore_id3 = 0; -
mythplugins/mythmusic/mythmusic/metadata.h
181 181 void getField(const QString& field, QString *data); 182 182 void toMap(MetadataMap &metadataMap); 183 183 184 void persist(); 184 void persist(void) const; 185 void UpdateModTime(void) const; 185 186 bool hasChanged() {return m_changed;} 186 187 int compare(const Metadata *other) const; 187 188 static void setArtistAndTrackFormats(); -
mythplugins/mythmusic/mythmusic/editmetadata.cpp
660 660 661 661 m_metadata->dumpToDatabase(); 662 662 *m_sourceMetadata = m_metadata; 663 663 664 accept(); 664 665 } 665 666 -
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(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 432 bool 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 458 bool 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
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->commitVolatileMetadata(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/musiccommon.h
51 51 void seekback(void); 52 52 void seek(int); 53 53 void stopAll(void); 54 void increaseRating(void); 55 void decreaseRating(void); 54 void changeRating(bool increase); 56 55 57 56 void showViewMenu(void); 58 57 void showPlaylistMenu(void); -
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 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 42 49 Metadata* read(QString filename); 43 50 static QImage getAlbumArt(QString filename, ImageType type); 44 51 … … 47 54 48 55 AlbumArtList readAlbumArt(TagLib::ID3v2::Tag *tag); 49 56 UserTextIdentificationFrame* find(TagLib::ID3v2::Tag *tag, const String &description); 57 PopularimeterFrame* findPOPM(TagLib::ID3v2::Tag *tag, const String &email); 50 58 }; 51 59 52 60 #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(); … … 413 413 } 414 414 } 415 415 else if (action == "THMBUP") 416 increaseRating();416 changeRating(true); 417 417 else if (action == "THMBDOWN") 418 decreaseRating();418 changeRating(false); 419 419 else if (action == "NEXTTRACK") 420 420 { 421 421 if (m_nextButton) … … 825 825 } 826 826 } 827 827 828 void MusicCommon:: increaseRating(void)828 void MusicCommon::changeRating(bool increase) 829 829 { 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) 833 833 return; 834 834 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 sync842 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 {853 835 Metadata *curMeta = gPlayer->getCurrentMetadata(); 854 836 855 837 if (!curMeta) 856 838 return; 857 839 858 if (m_ratingState) 859 { 840 if (increase) 841 curMeta->incRating(); 842 else 860 843 curMeta->decRating(); 861 curMeta->persist();862 m_ratingState->DisplayState(QString("%1").arg(curMeta->Rating()));863 844 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) 866 853 { 867 Metadata *mdata = gMusicData->all_music->getMetadata(curMeta->ID()); 868 if (mdata) 869 mdata->decRating(); 854 mdata->setRating(curMeta->Rating()); 870 855 } 871 856 } 872 857 } … … 1256 1241 MetadataMap metadataMap; 1257 1242 mdata->toMap(metadataMap); 1258 1243 SetTextFromMap(metadataMap); 1259 1244 1260 1245 m_maxTime = mdata->Length() / 1000; 1261 1246 if (m_coverartImage) 1262 1247 { … … 1383 1368 Metadata *mdata = gMusicData->all_music->getMetadata(trackid); 1384 1369 if (mdata) 1385 1370 { 1386 MythUIButtonListItem *item = 1371 MythUIButtonListItem *item = 1387 1372 new MythUIButtonListItem(m_currentPlaylist, "", qVariantFromValue(mdata)); 1388 1373 1389 1374 MetadataMap metadataMap;