File indexing completed on 2024-05-05 04:48:20
0001 /**************************************************************************************** 0002 * Copyright (c) 2011 Ralf Engels <ralf-engels@gmx.de> * 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 #include "covermanager/CoverCache.h" 0018 0019 #include "core/meta/Meta.h" 0020 #include "core/support/Amarok.h" 0021 0022 #include <QDir> 0023 #include <QImage> 0024 #include <QMutexLocker> 0025 #include <QPixmapCache> 0026 #include <QReadWriteLock> 0027 #include <QReadLocker> 0028 #include <QStandardPaths> 0029 #include <QWriteLocker> 0030 0031 #include <KLocalizedString> 0032 0033 #include <thread> 0034 0035 CoverCache* CoverCache::s_instance = nullptr; 0036 0037 CoverCache* 0038 CoverCache::instance() 0039 { 0040 return s_instance ? s_instance : (s_instance = new CoverCache()); 0041 } 0042 0043 void CoverCache::destroy() 0044 { 0045 if( s_instance ) 0046 { 0047 delete s_instance; 0048 s_instance = nullptr; 0049 } 0050 } 0051 0052 CoverCache::CoverCache() 0053 { } 0054 0055 CoverCache::~CoverCache() 0056 { 0057 m_lock.lockForWrite(); 0058 m_lock.unlock(); 0059 } 0060 0061 void 0062 CoverCache::invalidateAlbum( const Meta::Album* album ) 0063 { 0064 if( !s_instance ) 0065 return; 0066 0067 QWriteLocker locker( &s_instance->m_lock ); 0068 0069 if( !s_instance->m_keys.contains( album ) ) 0070 return; 0071 0072 CoverKeys allKeys = s_instance->m_keys.take( album ); 0073 foreach( const QPixmapCache::Key &key, allKeys.values() ) 0074 { 0075 QPixmapCache::remove( key ); 0076 } 0077 } 0078 0079 QPixmap 0080 CoverCache::getCover( const Meta::AlbumPtr &album, int size ) const 0081 { 0082 QPixmap pixmap; 0083 0084 if( size > 1 ) // full size covers are not cached 0085 { 0086 QReadLocker locker( &m_lock ); 0087 const CoverKeys &allKeys = m_keys.value( album.data() ); 0088 if( !allKeys.isEmpty() ) 0089 { 0090 QPixmapCache::Key key = allKeys.value( size ); 0091 if( key != QPixmapCache::Key() && QPixmapCache::find( key, &pixmap ) ) 0092 return pixmap; 0093 } 0094 } 0095 0096 QImage image = album->image( size ); 0097 0098 // -- get the null cover if someone really wants to have a pixmap 0099 // in this case the album hasCover should have already returned false 0100 if( image.isNull() ) 0101 { 0102 const QDir &cacheCoverDir = QDir( Amarok::saveLocation( "albumcovers/cache/" ) ); 0103 if( size <= 1 ) 0104 size = 100; 0105 const QString &noCoverKey = QString::number( size ) + "@nocover.png"; 0106 0107 QPixmap pixmap; 0108 // look in the memory pixmap cache 0109 if( QPixmapCache::find( noCoverKey, &pixmap ) ) 0110 return pixmap; 0111 0112 if( cacheCoverDir.exists( noCoverKey ) ) 0113 { 0114 pixmap.load( cacheCoverDir.filePath( noCoverKey ) ); 0115 } 0116 else 0117 { 0118 const QPixmap orgPixmap( QStandardPaths::locate( QStandardPaths::GenericDataLocation, "amarok/images/nocover.png" ) ); 0119 pixmap = orgPixmap.scaled( size, size, Qt::KeepAspectRatio, Qt::SmoothTransformation ); 0120 std::thread thread( QOverload<const QString&, const char*, int>::of( &QPixmap::save ), pixmap, cacheCoverDir.filePath( noCoverKey ), "PNG", -1 ); 0121 thread.detach(); 0122 } 0123 QPixmapCache::insert( noCoverKey, pixmap ); 0124 return pixmap; 0125 } 0126 0127 pixmap = QPixmap::fromImage( image ); 0128 0129 // -- add the cover to the cache if not full-scale or too big 0130 if( size > 1 && size < 1000 ) 0131 { 0132 // sadly I can't relock for write 0133 QWriteLocker locker( &m_lock ); 0134 0135 QPixmapCache::Key key = QPixmapCache::insert( pixmap ); 0136 m_keys[ album.data() ][ size ] = key; 0137 } 0138 0139 return pixmap; 0140 } 0141 0142 CoverCache* The::coverCache() 0143 { 0144 return CoverCache::instance(); 0145 } 0146