Ticket #2942: mythmusic_apic2.diff

File mythmusic_apic2.diff, 17.4 KB (added by myth@…, 13 years ago)

updated version that works on files with "Other" type images.

  • mythmusic/mythmusic/visualize.cpp

     
    389389    return false;
    390390}
    391391
    392 QString AlbumArt::getImageFilename()
    393 {
    394     return m_pParent->metadata()->getAlbumArt(m_currImageType);
    395 }
    396 
    397392bool AlbumArt::draw(QPainter *p, const QColor &back)
    398393{
    399394    if (!m_pParent->decoder())
     
    402397    // If the directory has changed (new album) or the size, reload
    403398    if (needsUpdate())
    404399    {
    405         QImage art(getImageFilename());
     400        QImage art(m_pParent->metadata()->getAlbumArt(m_currImageType));
    406401        if (art.isNull())
    407402        {
    408403            m_cursize = m_size;
  • mythmusic/mythmusic/metadata.cpp

     
    381381
    382382    if (m_id < 1 && query.isActive() && 1 == query.numRowsAffected())
    383383        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("INSERT INTO music_albumart ( filename, "
     391                        "imagetype, song_id, embedded ) VALUES ( "
     392                        ":FILENAME, :TYPE, :SONGID, :EMBED );");
     393
     394            query.bindValue(":FILENAME", (*it).description);
     395            query.bindValue(":TYPE", (*it).imageType);
     396            query.bindValue(":SONGID", m_id);
     397            query.bindValue(":EMBED", 1);
     398
     399            if (!query.exec() || !query.isActive() || query.numRowsAffected() <= 0)
     400            {
     401                MythContext::DBError("music insert albumart", query);
     402            }
     403        }
     404    }
    384405}
    385406
    386407// Default values for formats
     
    616637    m_changed = true;
    617638}
    618639
     640void Metadata::setEmbeddedAlbumArt(QValueList<struct AlbumArtImage> albumart)
     641{
     642    m_albumart = albumart;
     643}
     644
    619645QStringList Metadata::fillFieldList(QString field)
    620646{
    621647    QStringList searchList;
     
    658684    return searchList;
    659685}
    660686
    661 QStringList Metadata::AlbumArtInDir(QString directory)
     687QImage Metadata::getAlbumArt(ImageType type)
    662688{
    663     QStringList paths;
     689    AlbumArtImages albumArt(this);
    664690
    665     directory.remove(0, m_startdir.length());
     691    QImage image;
    666692
    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())
     693    if (albumArt.isImageEmbedded(type))
    675694    {
    676         while (query.next())
    677         {
    678             paths += m_startdir + "/" +
    679                 QString::fromUtf8(query.value(0).toString());
    680         }
     695        image = QImage(MetaIOTagLib::getAlbumArt(m_filename, type));
    681696    }
    682     return paths;
    683 }
     697    else
     698    {
     699        image = QImage(albumArt.getImageFilename(type));
     700    }
    684701
    685 QString Metadata::getAlbumArt(ImageType type)
    686 {
    687     QString res = "";
    688     AlbumArtImages albumArt(this);
    689 
    690     res = albumArt.getImageFilename(type);
    691 
    692     return res;
     702    return image;
    693703}
    694704
    695705MetadataLoadingThread::MetadataLoadingThread(AllMusic *parent_ptr)
     
    13751385/**************************************************************************/
    13761386
    13771387AlbumArtImages::AlbumArtImages(Metadata *metadata)
     1388    : m_parent(metadata)
    13781389{
    1379     m_parent = metadata;
    13801390    m_imageList.setAutoDelete(true);
    13811391
    13821392    findImages();
     
    13861396{
    13871397    m_imageList.clear();
    13881398
     1399    if (m_parent == NULL)
     1400        return;
     1401
     1402    int trackid = m_parent->ID();
     1403
    13891404    QFileInfo fi(m_parent->Filename());
    13901405    QString dir = fi.dirPath(true);
    13911406    dir.remove(0, Metadata::GetStartdir().length());
    13921407
    13931408    MSqlQuery query(MSqlQuery::InitCon());
    13941409    query.prepare("SELECT albumart_id, CONCAT_WS('/', music_directories.path, "
    1395             "music_albumart.filename), music_albumart.imagetype "
     1410            "music_albumart.filename), music_albumart.imagetype, "
     1411            "music_albumart.embedded "
    13961412            "FROM music_albumart "
    13971413            "LEFT JOIN music_directories ON "
    13981414            "music_directories.directory_id=music_albumart.directory_id "
    13991415            "WHERE music_directories.path = :DIR "
     1416            "OR song_id = :SONGID "
    14001417            "ORDER BY music_albumart.imagetype;");
    14011418    query.bindValue(":DIR", dir.utf8());
     1419    query.bindValue(":SONGID", trackid);
    14021420    if (query.exec())
    14031421    {
    14041422        while (query.next())
     
    14091427                    QString::fromUtf8(query.value(1).toString());
    14101428            image->imageType = (ImageType) query.value(2).toInt();
    14111429            image->typeName = getTypeName(image->imageType);
     1430            if (query.value(3).toInt() == 1)
     1431            {
     1432                image->description = query.value(1).toString();
     1433                image->embedded = true;
     1434            }
     1435            else {
     1436                image->embedded = false;
     1437            }
    14121438            m_imageList.append(image);
    14131439        }
    14141440    }
     
    14221448    for (image = m_imageList.first(); image; image = m_imageList.next())
    14231449    {
    14241450        if (image->imageType == type)
     1451        {
     1452            if (image->embedded)
     1453                return "embedded";
     1454
    14251455            return image->filename;
     1456        }
    14261457    }
    14271458
    14281459    return "";
     
    14421473    return paths;
    14431474}
    14441475
     1476AlbumArtImage AlbumArtImages::getImageAt(uint index)
     1477{
     1478    return *(m_imageList.at(index));
     1479}
     1480
     1481bool AlbumArtImages::isImageEmbedded(ImageType type)
     1482{
     1483    AlbumArtImage *image;
     1484
     1485    for (image = m_imageList.first(); image; image = m_imageList.next())
     1486    {
     1487        if (image->imageType == type)
     1488            return image->embedded;
     1489    }
     1490
     1491    return false;
     1492}
     1493
    14451494bool AlbumArtImages::isImageAvailable(ImageType type)
    14461495{
    14471496    // try to find a matching image
  • mythmusic/mythmusic/dbcheck.cpp

     
    99#include "mythtv/mythcontext.h"
    1010#include "mythtv/mythdbcon.h"
    1111
    12 const QString currentDatabaseVersion = "1011";
     12const QString currentDatabaseVersion = "1012";
    1313
    1414static bool UpdateDBVersionNumber(const QString &newnumber)
    1515{   
     
    587587            return false;
    588588
    589589    }
     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    }
    590602/* in 0.21 */
    591603//"DROP TABLE musicmetadata;",
    592604//"DROP TABLE musicplaylist;",
  • mythmusic/mythmusic/metadata.h

     
    44#include <qstring.h>
    55#include <qstringlist.h>
    66#include <qptrlist.h>
     7#include <qvaluelist.h>
    78#include <qmap.h>
    89#include <qthread.h>
    910
    1011#include "treecheckitem.h"
    1112#include <mythtv/uitypes.h>
    1213
     14
    1315class AllMusic;
    1416class CoverArt;
    1517
     
    2325    IT_LAST
    2426};
    2527
     28#include "metaiotaglib.h"
     29
    2630typedef struct AlbumArtImage
    2731{
    2832    int       id;
    2933    QString   filename;
    3034    ImageType imageType;
    3135    QString   typeName;
     36    QString   description;
     37    bool      embedded;
    3238} AlbumArtImage;
    3339
     40//typedef QValueList<struct AlbumArtImage> AlbumArtList;
     41
    3442class Metadata
    3543{
    3644  public:
     
    5967                   m_lastplay(llastplay),
    6068                   m_playcount(lplaycount),
    6169                   m_compilation(lcompilation),
     70                   m_albumart(),
    6271                   m_id(lid),
    6372                   m_filename(lfilename),
    6473                   m_changed(false),
     
    159168    }
    160169    bool determineIfCompilation(bool cd = false);
    161170
     171    void setEmbeddedAlbumArt(QValueList<struct AlbumArtImage> art);
     172
    162173    bool isInDatabase(void);
    163174    void dumpToDatabase(void);
    164175    void setField(const QString &field, const QString &data);
     
    173184
    174185    static QStringList fillFieldList(QString field);
    175186
    176     QStringList AlbumArtInDir(QString directory);
    177     QString getAlbumArt(ImageType type);
     187    QImage getAlbumArt(ImageType type);
    178188
    179189  private:
    180190    void setCompilationFormatting(bool cd = false);
     
    201211    QString m_lastplay;
    202212    int m_playcount;
    203213    bool m_compilation;
     214    QValueList<struct AlbumArtImage> m_albumart;
    204215
    205216    unsigned int m_id;
    206217    QString m_filename;
     
    394405    QStringList              getImageFilenames();
    395406    QPtrList<AlbumArtImage> *getImageList() { return &m_imageList; }
    396407    AlbumArtImage            getImageAt(uint index);
     408        bool                     isImageEmbedded(ImageType type);
    397409
    398410    bool isImageAvailable(ImageType type);
    399411
  • mythmusic/mythmusic/metaiotaglib.h

     
    22#define METAIOTAGLIB_H_
    33
    44#include "metaio.h"
     5#include "metadata.h"
    56#include <id3v2tag.h>
    67#include <textidentificationframe.h>
     8#include <attachedpictureframe.h>
    79#include <mpegfile.h>
     10#include <mpegproperties.h>
    811
    912using TagLib::MPEG::File;
    1013using TagLib::Tag;
    1114using TagLib::ID3v2::UserTextIdentificationFrame;
     15using TagLib::ID3v2::AttachedPictureFrame;
    1216using TagLib::String;
     17using TagLib::MPEG::Properties;
    1318
    1419class MetaIOTagLib : public MetaIO
    1520{
     
    2025    bool write(Metadata* mdata, bool exclusive = false);
    2126    Metadata* read(QString filename);
    2227
     28    static QImage getAlbumArt(QString filename, ImageType type);
     29
    2330private:
    2431
    25      int getTrackLength(QString filename);
     32    int getTrackLength(QString filename);
    2633
    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);
    2836};
    2937
    3038#endif
  • mythmusic/mythmusic/metaiotaglib.cpp

     
    102102            genre = "";
    103103    int year = 0, tracknum = 0, length = 0, playcount = 0, rating = 0, id = 0;
    104104    bool compilation = false;
     105    QValueList<struct AlbumArtImage> albumart;
    105106
    106107    QString extension = filename.section( '.', -1 ) ;
    107108
     
    151152        // Length
    152153        if(!taglib->ID3v2Tag()->frameListMap()["TLEN"].isEmpty())
    153154            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        }
    154161    }
    155162
    156163    // Fallback to filename reading
     
    183190                                     id, rating, playcount);
    184191
    185192    retdata->setCompilation(compilation);
     193    retdata->setEmbeddedAlbumArt(albumart);
    186194
    187195    return retdata;
    188196}
     
    203211}
    204212
    205213/*!
     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 */
     220QImage 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 */
     275QValueList<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            AlbumArtImage art;
     292
     293            if (!frame->description().isEmpty())
     294            {
     295                art.description = TStringToQString(frame->description());
     296            } else
     297            {
     298                art.description = "";
     299            }
     300
     301            art.embedded = true;
     302
     303            switch (frame->type())
     304            {
     305                case AttachedPictureFrame::FrontCover :
     306                    art.imageType = IT_FRONTCOVER;
     307                    art.typeName = "Front Cover";
     308                    break;
     309                case AttachedPictureFrame::BackCover :
     310                    art.imageType = IT_BACKCOVER;
     311                    art.typeName = "Back Cover";
     312                    break;
     313                case AttachedPictureFrame::Media :
     314                    art.imageType = IT_CD;
     315                    art.typeName = "CD";
     316                    break;
     317                case AttachedPictureFrame::LeafletPage :
     318                    art.imageType = IT_INLAY;
     319                    art.typeName = "Inlay";
     320                    break;
     321                case AttachedPictureFrame::Other :
     322                    art.imageType = IT_UNKNOWN;
     323                    art.typeName = "Other";
     324                    break;
     325                default:
     326                    VERBOSE(VB_GENERAL, "Music Scanner - APIC tag found "
     327                                        "with unsupported type");
     328                    continue;
     329            }
     330
     331            artlist.append(art);
     332        }
     333    }
     334
     335    return artlist;
     336}
     337
     338/*!
    206339 * \brief Find the a custom comment tag by description.
    207340 *        This is a copy of the same function in the
    208341 *        TagLib::ID3v2::UserTextIdentificationFrame Class with a static
  • mythmusic/mythmusic/mainvisual.cpp

     
    350351        return;
    351352
    352353    QString  text = "\"" + mdata->Title() + "\"\n" +  mdata->Artist() + "\n" + mdata->Album();
    353     QString albumArt = mdata->getAlbumArt(IT_FRONTCOVER);
     354    QImage albumArt = mdata->getAlbumArt(IT_FRONTCOVER);
    354355
    355356    if (text == info)
    356357        return;
     
    370371    }
    371372
    372373    // ...and only then when we have an album art image to show
    373     if (visMode != 2 && fullScreen && albumArt == "")
     374    if (visMode != 2 && fullScreen && ! albumArt.isNull())
    374375    {
    375376        hide();
    376377        return;
    377378    }
    378379
    379     if (fullScreen && albumArt != "")
     380    if (fullScreen && ! albumArt.isNull())
    380381    {
    381382        resize(parentWidget()->width(), parentWidget()->height());
    382383        move(0, 0);
     
    400401    int x = indent;
    401402    int y = indent;
    402403
    403     if (fullScreen && albumArt != "")
     404    if (fullScreen && ! albumArt.isNull())
    404405    {
    405406        p.fillRect(0, 0, info_pixmap.width(), info_pixmap.height(), QColor ("black"));
    406407
     
    419420    {
    420421        p.fillRect(0, 0, info_pixmap.width(), info_pixmap.height(), QColor ("darkblue"));
    421422
    422         if (albumArt != "")
     423        if (! albumArt.isNull())
    423424        {
    424425            // draw the albumArt image
    425426
  • mythmusic/mythmusic/visualize.h

     
    9191
    9292  private:
    9393    bool needsUpdate(void);
    94     QString getImageFilename(void);
    9594    void findFrontCover(void);
    9695
    9796    QSize m_size, m_cursize;