File indexing completed on 2024-05-05 04:48:21

0001 /****************************************************************************************
0002  * Copyright (c) 2009 Rick W. Chen <stuffcorpse@archlinux.us>                           *
0003  *                                                                                      *
0004  * This program is free software; you can redistribute it and/or modify it under        *
0005  * the terms of the GNU General Public License as published by the Free Software        *
0006  * Foundation; either version 2 of the License, or (at your option) any later           *
0007  * version.                                                                             *
0008  *                                                                                      *
0009  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0010  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0011  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0012  *                                                                                      *
0013  * You should have received a copy of the GNU General Public License along with         *
0014  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0015  ****************************************************************************************/
0016 
0017 #ifndef AMAROK_COVERFETCHUNIT_H
0018 #define AMAROK_COVERFETCHUNIT_H
0019 
0020 #include "core/meta/Meta.h" // for AlbumPtr default argument
0021 
0022 #include "AmarokSharedPointer.h"
0023 
0024 #include <QStringList>
0025 #include <QUrl>
0026 #include <QXmlStreamReader>
0027 
0028 class CoverFetchPayload;
0029 class CoverFetchSearchPayload;
0030 
0031 namespace CoverFetch
0032 {
0033     enum Option
0034     {
0035         Automatic,      //!< Automatically save cover for the specified album, if one is found
0036         Interactive,    //!< Opens a dialog for the user to decide, and add more searches if desired
0037         WildInteractive //!< As @ref Interactive, but without filtering results (used for web search)
0038     };
0039 
0040     enum ImageSize
0041     {
0042         NormalSize,     //!< Normal cover size, for storage and display
0043         ThumbSize       //!< Thumbnail size, for icon views
0044     };
0045 
0046     enum Source
0047     {
0048         Discogs,        //!< Use Discogs as provider for cover images
0049         Google,         //!< Use Google image search as provider
0050         LastFm,         //!< Use Last.fm as provider for cover images
0051     };
0052 
0053     typedef QHash<QString, QString> Metadata;
0054     typedef QHash<QUrl, Metadata> Urls;
0055 }
0056 
0057 /**
0058  * A work unit for the cover fetcher queue.
0059  */
0060 class CoverFetchUnit : public QSharedData
0061 {
0062 public:
0063     typedef AmarokSharedPointer< CoverFetchUnit > Ptr;
0064 
0065     CoverFetchUnit( const Meta::AlbumPtr &album,
0066                     const CoverFetchPayload *payload,
0067                     CoverFetch::Option opt = CoverFetch::Automatic );
0068     CoverFetchUnit( const CoverFetchPayload *payload, CoverFetch::Option opt );
0069     explicit CoverFetchUnit( const CoverFetchSearchPayload *payload );
0070     ~CoverFetchUnit();
0071 
0072     Meta::AlbumPtr album() const;
0073     const QStringList &errors() const;
0074     CoverFetch::Option options() const;
0075     const CoverFetchPayload *payload() const;
0076 
0077     bool isInteractive() const;
0078 
0079     template< typename T >
0080         void addError( const T &error );
0081 
0082     bool operator==( const CoverFetchUnit &other ) const;
0083     bool operator!=( const CoverFetchUnit &other ) const;
0084 
0085 private:
0086     Meta::AlbumPtr m_album;
0087     QStringList m_errors;
0088     CoverFetch::Option m_options;
0089     const CoverFetchPayload *m_payload;
0090 
0091     Q_DISABLE_COPY( CoverFetchUnit )
0092 };
0093 
0094 /**
0095  * An abstract class for preparing URLs suitable for fetching album covers from
0096  * Last.fm.
0097  */
0098 class CoverFetchPayload
0099 {
0100 public:
0101     enum Type { Info, Search, Art };
0102     CoverFetchPayload( const Meta::AlbumPtr &album, enum Type type, const CoverFetch::Source src );
0103     virtual ~CoverFetchPayload();
0104 
0105     Meta::AlbumPtr album() const;
0106     CoverFetch::Source source() const;
0107     enum Type type() const;
0108     const CoverFetch::Urls &urls() const;
0109 
0110 protected:
0111     const CoverFetch::Source m_src;
0112     CoverFetch::Urls m_urls;
0113 
0114     QString sanitizeQuery( const QString &query );
0115     const QString  sourceString() const;
0116     const QString &method() const { return m_method; }
0117 
0118     bool isPrepared() const;
0119     virtual void prepareUrls() = 0;
0120 
0121 private:
0122     Meta::AlbumPtr m_album;
0123     const QString  m_method;
0124     enum Type      m_type;
0125 
0126     Q_DISABLE_COPY( CoverFetchPayload )
0127 };
0128 
0129 /**
0130  * Prepares URL suitable for getting an album's info from Last.fm.
0131  */
0132 class CoverFetchInfoPayload : public CoverFetchPayload
0133 {
0134 public:
0135     explicit CoverFetchInfoPayload( const Meta::AlbumPtr &album, const CoverFetch::Source src );
0136     explicit CoverFetchInfoPayload( const CoverFetch::Source src, const QByteArray &xml );
0137     ~CoverFetchInfoPayload() override;
0138 
0139 protected:
0140     void prepareUrls() override;
0141 
0142 private:
0143     void prepareDiscogsUrls( const QByteArray &data );
0144     Q_DISABLE_COPY( CoverFetchInfoPayload )
0145 };
0146 
0147 /**
0148  * Prepares URL for searching albums on Last.fm using wild mode.
0149  * See \ref CoverFetch::WildInteractive mode.
0150  */
0151 class CoverFetchSearchPayload : public CoverFetchPayload
0152 {
0153 public:
0154     explicit CoverFetchSearchPayload( const QString &query = QString(),
0155                                       const CoverFetch::Source src = CoverFetch::LastFm,
0156                                       unsigned int page = 0,
0157                                       const Meta::AlbumPtr &album = Meta::AlbumPtr() );
0158     ~CoverFetchSearchPayload() override;
0159 
0160     QString query() const;
0161 
0162 protected:
0163     void prepareUrls() override;
0164 
0165 private:
0166     const unsigned int m_page;
0167     const QString m_query;
0168 
0169     Q_DISABLE_COPY( CoverFetchSearchPayload )
0170 };
0171 
0172 /**
0173  * Prepares URL suitable for getting an album's cover from Last.fm.
0174  */
0175 class CoverFetchArtPayload : public CoverFetchPayload
0176 {
0177 public:
0178     explicit CoverFetchArtPayload( const Meta::AlbumPtr &album,
0179                                    const CoverFetch::ImageSize size = CoverFetch::NormalSize,
0180                                    const CoverFetch::Source src = CoverFetch::LastFm,
0181                                    bool wild = false );
0182     explicit CoverFetchArtPayload( const CoverFetch::ImageSize size,
0183                                    const CoverFetch::Source src = CoverFetch::LastFm,
0184                                    bool wild = false );
0185     ~CoverFetchArtPayload() override;
0186 
0187     bool isWild() const;
0188 
0189     CoverFetch::ImageSize imageSize() const;
0190 
0191     void setXml( const QByteArray &xml );
0192 
0193 protected:
0194     void prepareUrls() override;
0195 
0196 private:
0197     CoverFetch::ImageSize m_size;
0198     QString m_xml;
0199 
0200     /// search is wild mode?
0201     bool m_wild;
0202 
0203     /// lower, remove whitespace, and do Unicode normalization on a QString
0204     QString normalize( const QString &raw );
0205 
0206     /// lower, remove whitespace, and do Unicode normalization on a QStringList
0207     QStringList normalize( const QStringList &rawList );
0208 
0209     /// prepare urls from xml provided by Discogs
0210     void prepareDiscogsUrls( QXmlStreamReader &xml );
0211 
0212     /// prepare urls from xml provided by Last.fm
0213     void prepareLastFmUrls( QXmlStreamReader &xml );
0214 
0215     /// prepare urls from xml provided by Google Image Search
0216     void prepareGoogleUrls();
0217 
0218     /// gets the value of the first available key from hash
0219     QString firstAvailableValue( const QStringList &keys, const QHash<QString, QString> &hash );
0220 
0221     Q_DISABLE_COPY( CoverFetchArtPayload )
0222 };
0223 
0224 
0225 Q_DECLARE_METATYPE( CoverFetchUnit::Ptr )
0226 
0227 #endif /* AMAROK_COVERFETCHUNIT_H */