Ticket #2942: mythmusic_apic.diff
| File mythmusic_apic.diff, 20.8 KB (added by stuartm, 5 years ago) |
|---|
-
mythmusic/mythmusic/visualize.cpp
389 389 return false; 390 390 } 391 391 392 QString AlbumArt::getImageFilename()393 {394 return m_pParent->metadata()->getAlbumArt(m_currImageType);395 }396 397 392 bool AlbumArt::draw(QPainter *p, const QColor &back) 398 393 { 399 394 if (!m_pParent->decoder()) … … 402 397 // If the directory has changed (new album) or the size, reload 403 398 if (needsUpdate()) 404 399 { 405 QImage art( getImageFilename());400 QImage art(m_pParent->metadata()->getAlbumArt(m_currImageType)); 406 401 if (art.isNull()) 407 402 { 408 403 m_cursize = m_size; -
mythmusic/mythmusic/metadata.cpp
381 381 382 382 if (m_id < 1 && query.isActive() && 1 == query.numRowsAffected()) 383 383 m_id = query.lastInsertId().toInt(); 384 385 if (! m_albumart.empty()) 386 { 387 QValueList<struct AlbumArtImage>::iterator it; 388 for ( it = m_albumart.begin(); it != m_albumart.end(); ++it ) 389 { 390 query.prepare("SELECT albumart_id FROM music_albumart WHERE " 391 "song_id=:SONGID AND imagetype=:TYPE;"); 392 query.bindValue(":TYPE", (*it).imageType); 393 query.bindValue(":SONGID", m_id); 394 query.exec(); 395 396 if (query.next()) 397 { 398 int artid = query.value(0).toInt(); 399 400 query.prepare("UPDATE music_albumart SET " 401 "filename=:FILENAME, imagetype=:TYPE, " 402 "song_id=:SONGID, embedded=:EMBED " 403 "WHERE albumart_id=:ARTID"); 404 405 query.bindValue(":ARTID", artid); 406 } 407 else 408 { 409 query.prepare("INSERT INTO music_albumart ( filename, " 410 "imagetype, song_id, embedded ) VALUES ( " 411 ":FILENAME, :TYPE, :SONGID, :EMBED );"); 412 } 413 414 query.bindValue(":FILENAME", (*it).description); 415 query.bindValue(":TYPE", (*it).imageType); 416 query.bindValue(":SONGID", m_id); 417 query.bindValue(":EMBED", 1); 418 419 query.exec(); 420 } 421 } 384 422 } 385 423 386 424 // Default values for formats … … 616 654 m_changed = true; 617 655 } 618 656 657 void Metadata::setEmbeddedAlbumArt(QValueList<struct AlbumArtImage> albumart) 658 { 659 m_albumart = albumart; 660 } 661 619 662 QStringList Metadata::fillFieldList(QString field) 620 663 { 621 664 QStringList searchList; … … 658 701 return searchList; 659 702 } 660 703 661 Q StringList Metadata::AlbumArtInDir(QString directory)704 QImage Metadata::getAlbumArt(ImageType type) 662 705 { 663 QStringList paths;706 AlbumArtImages albumArt(this); 664 707 665 directory.remove(0, m_startdir.length());708 QImage image; 666 709 667 MSqlQuery query(MSqlQuery::InitCon()); 668 query.prepare("SELECT CONCAT_WS('/', music_directories.path, " 669 "music_albumart.filename) FROM music_albumart " 670 "LEFT JOIN music_directories ON " 671 "music_directories.directory_id=music_albumart.directory_id " 672 "WHERE music_directories.path = :DIR;"); 673 query.bindValue(":DIR", directory.utf8()); 674 if (query.exec()) 710 if (albumArt.isImageAvailable(type)) 675 711 { 676 while (query.next()) 677 { 678 paths += m_startdir + "/" + 679 QString::fromUtf8(query.value(0).toString()); 680 } 712 AlbumArtImage albumart_image = albumArt.getImage(type); 713 714 if (albumart_image.embedded) 715 image = QImage(MetaIOTagLib::getAlbumArt(m_filename, type)); 716 else 717 image = QImage(albumart_image.filename); 681 718 } 682 return paths;683 }684 719 685 QString Metadata::getAlbumArt(ImageType type) 686 { 687 QString res = ""; 688 AlbumArtImages albumArt(this); 689 690 res = albumArt.getImageFilename(type); 691 692 return res; 720 return image; 693 721 } 694 722 695 723 MetadataLoadingThread::MetadataLoadingThread(AllMusic *parent_ptr) … … 1389 1417 if (m_parent == NULL) 1390 1418 return; 1391 1419 1420 int trackid = m_parent->ID(); 1421 1392 1422 QFileInfo fi(m_parent->Filename()); 1393 1423 QString dir = fi.dirPath(true); 1394 1424 dir.remove(0, Metadata::GetStartdir().length()); 1395 1425 1396 1426 MSqlQuery query(MSqlQuery::InitCon()); 1397 1427 query.prepare("SELECT albumart_id, CONCAT_WS('/', music_directories.path, " 1398 "music_albumart.filename), music_albumart.imagetype " 1428 "music_albumart.filename), music_albumart.imagetype, " 1429 "music_albumart.embedded " 1399 1430 "FROM music_albumart " 1400 1431 "LEFT JOIN music_directories ON " 1401 1432 "music_directories.directory_id=music_albumart.directory_id " 1402 1433 "WHERE music_directories.path = :DIR " 1434 "OR song_id = :SONGID " 1403 1435 "ORDER BY music_albumart.imagetype;"); 1404 1436 query.bindValue(":DIR", dir.utf8()); 1437 query.bindValue(":SONGID", trackid); 1405 1438 if (query.exec()) 1406 1439 { 1407 1440 while (query.next()) … … 1412 1445 QString::fromUtf8(query.value(1).toString()); 1413 1446 image->imageType = (ImageType) query.value(2).toInt(); 1414 1447 image->typeName = getTypeName(image->imageType); 1448 if (query.value(3).toInt() == 1) 1449 { 1450 image->description = query.value(1).toString(); 1451 image->embedded = true; 1452 } 1453 else { 1454 image->embedded = false; 1455 } 1415 1456 m_imageList.append(image); 1416 1457 } 1417 1458 } 1418 1459 } 1419 1460 1420 QString AlbumArtImages::getImageFilename(ImageType type)1461 AlbumArtImage AlbumArtImages::getImage(ImageType type) 1421 1462 { 1422 1463 // try to find a matching image 1423 1464 AlbumArtImage *image; … … 1425 1466 for (image = m_imageList.first(); image; image = m_imageList.next()) 1426 1467 { 1427 1468 if (image->imageType == type) 1428 return image->filename;1469 return *image; 1429 1470 } 1430 1471 1431 return "";1472 return *image; 1432 1473 } 1433 1474 1434 1475 QStringList AlbumArtImages::getImageFilenames() … … 1445 1486 return paths; 1446 1487 } 1447 1488 1489 AlbumArtImage AlbumArtImages::getImageAt(uint index) 1490 { 1491 return *(m_imageList.at(index)); 1492 } 1493 1448 1494 bool AlbumArtImages::isImageAvailable(ImageType type) 1449 1495 { 1450 1496 // try to find a matching image … … 1459 1505 return false; 1460 1506 } 1461 1507 1462 bool AlbumArtImages::saveImageType(const QString &filename, ImageType type)1508 bool AlbumArtImages::saveImageType(const int id, ImageType type) 1463 1509 { 1464 // try to find a matching filename 1465 AlbumArtImage *image; 1466 1467 for (image = m_imageList.first(); image; image = m_imageList.next()) 1468 { 1469 if (image->filename == filename) 1470 { 1471 image->imageType = type; 1472 1473 MSqlQuery query(MSqlQuery::InitCon()); 1474 query.prepare("UPDATE music_albumart SET imagetype = :TYPE " 1475 "WHERE albumart_id = :ID"); 1476 query.bindValue(":TYPE", type); 1477 query.bindValue(":ID", image->id); 1478 return (query.exec()); 1479 } 1480 } 1481 1482 return false; 1510 MSqlQuery query(MSqlQuery::InitCon()); 1511 query.prepare("UPDATE music_albumart SET imagetype = :TYPE " 1512 "WHERE albumart_id = :ID"); 1513 query.bindValue(":TYPE", type); 1514 query.bindValue(":ID", id); 1515 return (query.exec()); 1483 1516 } 1484 1517 1485 1518 QString AlbumArtImages::getTypeName(ImageType type) -
mythmusic/mythmusic/dbcheck.cpp
9 9 #include "mythtv/mythcontext.h" 10 10 #include "mythtv/mythdbcon.h" 11 11 12 const QString currentDatabaseVersion = "101 1";12 const QString currentDatabaseVersion = "1012"; 13 13 14 14 static bool UpdateDBVersionNumber(const QString &newnumber) 15 15 { … … 587 587 return false; 588 588 589 589 } 590 591 if (dbver == "1011") 592 { 593 const QString updates[] = { 594 "ALTER TABLE music_albumart ADD COLUMN song_id int(11) NOT NULL DEFAULT '0', ADD COLUMN embedded TINYINT(1) NOT NULL DEFAULT '0';", 595 "" 596 }; 597 598 if (!performActualUpdate(updates, "1012", dbver)) 599 return false; 600 601 } 590 602 /* in 0.21 */ 591 603 //"DROP TABLE musicmetadata;", 592 604 //"DROP TABLE musicplaylist;", -
mythmusic/mythmusic/metadata.h
4 4 #include <qstring.h> 5 5 #include <qstringlist.h> 6 6 #include <qptrlist.h> 7 #include <qvaluelist.h> 7 8 #include <qmap.h> 8 9 #include <qthread.h> 9 10 10 11 #include "treecheckitem.h" 11 12 #include <mythtv/uitypes.h> 12 13 14 13 15 class AllMusic; 14 16 class CoverArt; 15 17 … … 23 25 IT_LAST 24 26 }; 25 27 28 #include "metaiotaglib.h" 29 26 30 typedef struct AlbumArtImage 27 31 { 28 32 int id; 29 33 QString filename; 30 34 ImageType imageType; 31 35 QString typeName; 36 QString description; 37 bool embedded; 32 38 } AlbumArtImage; 33 39 40 //typedef QValueList<struct AlbumArtImage> AlbumArtList; 41 34 42 class Metadata 35 43 { 36 44 public: … … 59 67 m_lastplay(llastplay), 60 68 m_playcount(lplaycount), 61 69 m_compilation(lcompilation), 70 m_albumart(), 62 71 m_id(lid), 63 72 m_filename(lfilename), 64 73 m_changed(false), … … 159 168 } 160 169 bool determineIfCompilation(bool cd = false); 161 170 171 void setEmbeddedAlbumArt(QValueList<struct AlbumArtImage> art); 172 162 173 bool isInDatabase(void); 163 174 void dumpToDatabase(void); 164 175 void setField(const QString &field, const QString &data); … … 173 184 174 185 static QStringList fillFieldList(QString field); 175 186 176 QStringList AlbumArtInDir(QString directory); 177 QString getAlbumArt(ImageType type); 187 QImage getAlbumArt(ImageType type); 178 188 179 189 private: 180 190 void setCompilationFormatting(bool cd = false); … … 201 211 QString m_lastplay; 202 212 int m_playcount; 203 213 bool m_compilation; 214 QValueList<struct AlbumArtImage> m_albumart; 204 215 205 216 unsigned int m_id; 206 217 QString m_filename; … … 389 400 AlbumArtImages(Metadata *metadata); 390 401 391 402 uint getImageCount() { return m_imageList.count(); } 392 QString getImageFilename(ImageType type);403 AlbumArtImage getImage(ImageType type); 393 404 QString getTypeName(ImageType type); 394 405 QStringList getImageFilenames(); 395 406 QPtrList<AlbumArtImage> *getImageList() { return &m_imageList; } … … 397 408 398 409 bool isImageAvailable(ImageType type); 399 410 400 bool saveImageType(const QString &filename, ImageType type);411 bool saveImageType(const int id, ImageType type); 401 412 402 413 static ImageType guessImageType(const QString &filename); 403 414 -
mythmusic/mythmusic/editmetadata.cpp
148 148 149 149 for (uint x = 0; x < albumArtList->count(); x++) 150 150 { 151 if (albumArtList->at(x)->embedded) 152 continue; 153 151 154 QPixmap *pixmap = createScaledPixmap(albumArtList->at(x)->filename, 152 155 size.width(), size.height(), 153 156 QImage::ScaleMin); … … 738 741 image->typeName = item->text; 739 742 740 743 // save the image type to the DB 741 albumArt->saveImageType(image-> filename, image->imageType);744 albumArt->saveImageType(image->id, image->imageType); 742 745 743 746 gridItemChanged(item); 744 747 } -
mythmusic/mythmusic/metaiotaglib.h
2 2 #define METAIOTAGLIB_H_ 3 3 4 4 #include "metaio.h" 5 #include "metadata.h" 5 6 #include <id3v2tag.h> 6 7 #include <textidentificationframe.h> 8 #include <attachedpictureframe.h> 7 9 #include <mpegfile.h> 10 #include <mpegproperties.h> 8 11 9 12 using TagLib::MPEG::File; 10 13 using TagLib::Tag; 11 14 using TagLib::ID3v2::UserTextIdentificationFrame; 15 using TagLib::ID3v2::AttachedPictureFrame; 12 16 using TagLib::String; 17 using TagLib::MPEG::Properties; 13 18 14 19 class MetaIOTagLib : public MetaIO 15 20 { … … 20 25 bool write(Metadata* mdata, bool exclusive = false); 21 26 Metadata* read(QString filename); 22 27 28 static QImage getAlbumArt(QString filename, ImageType type); 29 23 30 private: 24 31 25 int getTrackLength(QString filename);32 int getTrackLength(QString filename); 26 33 27 UserTextIdentificationFrame* find(TagLib::ID3v2::Tag *tag, const String &description); 34 QValueList<struct AlbumArtImage> readAlbumArt(TagLib::ID3v2::Tag *tag); 35 UserTextIdentificationFrame* find(TagLib::ID3v2::Tag *tag, const String &description); 28 36 }; 29 37 30 38 #endif -
mythmusic/mythmusic/metaiotaglib.cpp
102 102 genre = ""; 103 103 int year = 0, tracknum = 0, length = 0, playcount = 0, rating = 0, id = 0; 104 104 bool compilation = false; 105 QValueList<struct AlbumArtImage> albumart; 105 106 106 107 QString extension = filename.section( '.', -1 ) ; 107 108 … … 151 152 // Length 152 153 if(!taglib->ID3v2Tag()->frameListMap()["TLEN"].isEmpty()) 153 154 length = taglib->ID3v2Tag()->frameListMap()["TLEN"].front()->toString().toInt(); 155 156 // Album Art 157 if(!taglib->ID3v2Tag()->frameListMap()["APIC"].isEmpty()) 158 { 159 albumart = readAlbumArt(taglib->ID3v2Tag()); 160 } 154 161 } 155 162 156 163 // Fallback to filename reading … … 183 190 id, rating, playcount); 184 191 185 192 retdata->setCompilation(compilation); 193 retdata->setEmbeddedAlbumArt(albumart); 186 194 187 195 return retdata; 188 196 } … … 203 211 } 204 212 205 213 /*! 214 * \brief Read the albumart image from the file 215 * 216 * \param filename The filename for which we want to find the length. 217 * \param type The type of image we want - front/back etc 218 * \returns A QByteArray that can contains the image data. 219 */ 220 QImage MetaIOTagLib::getAlbumArt(QString filename, ImageType type) 221 { 222 QImage picture; 223 224 AttachedPictureFrame::Type apicType 225 = AttachedPictureFrame::FrontCover; 226 227 switch (type) 228 { 229 case IT_UNKNOWN : 230 apicType = AttachedPictureFrame::Other; 231 break; 232 case IT_FRONTCOVER : 233 apicType = AttachedPictureFrame::FrontCover; 234 break; 235 case IT_BACKCOVER : 236 apicType = AttachedPictureFrame::BackCover; 237 break; 238 case IT_CD : 239 apicType = AttachedPictureFrame::Media; 240 break; 241 case IT_INLAY : 242 apicType = AttachedPictureFrame::LeafletPage; 243 break; 244 default: 245 return picture; 246 } 247 248 File *taglib = new TagLib::MPEG::File(filename.local8Bit()); 249 250 if (taglib->isOpen() && !taglib->ID3v2Tag()->frameListMap()["APIC"].isEmpty()) 251 { 252 TagLib::ID3v2::FrameList apicframes = taglib->ID3v2Tag()->frameListMap()["APIC"]; 253 254 for(TagLib::ID3v2::FrameList::Iterator it = apicframes.begin(); it != apicframes.end(); ++it) { 255 AttachedPictureFrame *frame = static_cast<AttachedPictureFrame *>(*it); 256 if(frame && frame->type() == apicType) 257 { 258 QImage picture; 259 picture.loadFromData((const uchar *)frame->picture().data(), frame->picture().size()); 260 return picture; 261 } 262 } 263 } 264 265 return picture; 266 } 267 268 /*! 269 * \brief Read the albumart image from the file 270 * 271 * \param tag The ID3v2 tag object in which to look for Album Art 272 * \returns A QValueList containing a list of AlbumArtImage structs 273 * with the type and description of the APIC tag. 274 */ 275 QValueList<struct AlbumArtImage> MetaIOTagLib::readAlbumArt(TagLib::ID3v2::Tag *tag) 276 { 277 278 QValueList<struct AlbumArtImage> artlist; 279 280 if (!tag->frameListMap()["APIC"].isEmpty()) 281 { 282 TagLib::ID3v2::FrameList apicframes = tag->frameListMap()["APIC"]; 283 284 for(TagLib::ID3v2::FrameList::Iterator it = apicframes.begin(); 285 it != apicframes.end(); ++it) 286 { 287 288 AttachedPictureFrame *frame = 289 static_cast<AttachedPictureFrame *>(*it); 290 291 // Assume a valid image would have at least 292 // 100 bytes of data (1x1 indexed gif is 35 bytes) 293 if (frame->picture().size() < 100) 294 { 295 VERBOSE(VB_GENERAL, "Music Scanner - Discarding APIC frame " 296 "with size less than 100 bytes"); 297 continue; 298 } 299 300 AlbumArtImage art; 301 302 if (frame->description().isEmpty()) 303 { 304 art.description = ""; 305 } 306 else { 307 art.description = TStringToQString(frame->description()); 308 } 309 310 art.embedded = true; 311 312 switch (frame->type()) 313 { 314 case AttachedPictureFrame::FrontCover : 315 art.imageType = IT_FRONTCOVER; 316 break; 317 case AttachedPictureFrame::BackCover : 318 art.imageType = IT_BACKCOVER; 319 break; 320 case AttachedPictureFrame::Media : 321 art.imageType = IT_CD; 322 break; 323 case AttachedPictureFrame::LeafletPage : 324 art.imageType = IT_INLAY; 325 break; 326 case AttachedPictureFrame::Other : 327 art.imageType = IT_UNKNOWN; 328 break; 329 default: 330 VERBOSE(VB_GENERAL, "Music Scanner - APIC tag found " 331 "with unsupported type"); 332 continue; 333 } 334 335 artlist.append(art); 336 } 337 } 338 339 return artlist; 340 } 341 342 /*! 206 343 * \brief Find the a custom comment tag by description. 207 344 * This is a copy of the same function in the 208 345 * TagLib::ID3v2::UserTextIdentificationFrame Class with a static -
mythmusic/mythmusic/mainvisual.cpp
353 353 return; 354 354 355 355 QString text = "\"" + mdata->Title() + "\"\n" + mdata->Artist() + "\n" + mdata->Album(); 356 Q StringalbumArt = mdata->getAlbumArt(IT_FRONTCOVER);356 QImage albumArt = mdata->getAlbumArt(IT_FRONTCOVER); 357 357 358 358 if (text == info) 359 359 return; … … 373 373 } 374 374 375 375 // ...and only then when we have an album art image to show 376 if (visMode != 2 && fullScreen && albumArt == "")376 if (visMode != 2 && fullScreen && albumArt.isNull()) 377 377 { 378 378 hide(); 379 379 return; 380 380 } 381 381 382 if (fullScreen && albumArt != "")382 if (fullScreen && ! albumArt.isNull()) 383 383 { 384 384 resize(parentWidget()->width(), parentWidget()->height()); 385 385 move(0, 0); … … 403 403 int x = indent; 404 404 int y = indent; 405 405 406 if (fullScreen && albumArt != "")406 if (fullScreen && ! albumArt.isNull()) 407 407 { 408 408 p.fillRect(0, 0, info_pixmap.width(), info_pixmap.height(), QColor ("black")); 409 409 … … 422 422 { 423 423 p.fillRect(0, 0, info_pixmap.width(), info_pixmap.height(), QColor ("darkblue")); 424 424 425 if ( albumArt != "")425 if (! albumArt.isNull()) 426 426 { 427 427 // draw the albumArt image 428 428 -
mythmusic/mythmusic/visualize.h
91 91 92 92 private: 93 93 bool needsUpdate(void); 94 QString getImageFilename(void);95 94 void findFrontCover(void); 96 95 97 96 QSize m_size, m_cursize; -
mythmusic/mythmusic/filescanner.cpp
469 469 MSqlQuery query(MSqlQuery::InitCon()); 470 470 query.exec("SELECT CONCAT_WS('/', path, filename) " 471 471 "FROM music_albumart LEFT JOIN music_directories " 472 "ON music_albumart.directory_id=music_directories.directory_id "); 472 "ON music_albumart.directory_id=music_directories.directory_id " 473 "WHERE music_albumart.embedded=0"); 473 474 474 475 int counter = 0; 475 476
