Commit 8dcfb77d authored by Matěj Laitl's avatar Matěj Laitl
Browse files

Move WriteTagsJob out of IpodCollection and use it everywhere

CHANGES:
 * Album cover images are written in background to prevent freezes

BUG: 298332
FIXED-IN: 2.6
DIGEST: Amarok now writes back covers in background to prevent freezes
parent a3d378de
......@@ -46,6 +46,7 @@ VERSION 2.6-Beta 1
vice versa. (BR 142579)
CHANGES:
* Album cover images are written in background to prevent freezes. (BR 298332)
* Make keyboard & mouse behaviour of saved playlists browser same as of the
collection browser, including the delete key.
* Delete and Shift + Delete keys now work as expected in collection browser.
......
......@@ -37,16 +37,30 @@ namespace Meta
AMAROK_EXPORT Meta::FieldHash readTags( const QString &path, bool useCharsetDetector = true );
/**
* Writes tags stored in @param changes back to file. Respects
* AmarokConfig::writeBack() and AmarokConfig::writeBackStatistics().
*
* If you are about to call this from the main thread, you should really think
* of using WriteTagsJob instead.
*
* @see WriteTagsJob
*/
AMAROK_EXPORT void writeTags( const QString &path, const FieldHash &changes );
#ifndef UTILITIES_BUILD
// the utilities don't need to handle images
AMAROK_EXPORT QImage embeddedCover( const QString &path );
/** This will write an embedded cover.
It will also overwrite existing covers (Front), so make sure the user knows what he get's.
ASF, ID3v2 and MP4 covers are supported.
*/
/**
* Writes embedded cover back to file. Overwrites any possible existing covers.
* This function doesn't take any configuration any account.
*
* If you are about to call this from the main thread, you should really think
* of using WriteTagsJob instead.
*
* @see WriteTagsJob
*/
AMAROK_EXPORT void setEmbeddedCover( const QString &path, const QImage &cover );
#endif
}
......
......@@ -77,6 +77,7 @@ namespace Meta
// TODO: support for queryMaker
static const qint64 valCompilation = 1LL << 40;
static const qint64 valHasCover = (1LL << 40) + 1;
static const qint64 valImage = (1LL << 40) + 2;
// start for custom numbers
static const qint64 valCustom = 1LL << 60;
......
......@@ -311,6 +311,7 @@ endif( TAGLIB_FOUND )
# COLLECTION
#####################################################################
set(collection_SRCS
core-impl/collections/support/jobs/WriteTagsJob.cpp
core-impl/collections/support/ArtistHelper.cpp
core-impl/collections/support/CollectionManager.cpp
core-impl/collections/support/CollectionLocationDelegateImpl.cpp
......
......@@ -26,6 +26,7 @@
#include <core/support/Debug.h>
#include <core/meta/support/MetaUtility.h>
#include <shared/MetaTagLib.h> // for getting an embedded cover
#include "core-impl/collections/support/jobs/WriteTagsJob.h"
#include <core-impl/collections/support/ArtistHelper.h>
#include "SqlCollection.h"
#include "SqlQueryMaker.h"
......@@ -48,6 +49,7 @@
#include <KCodecs>
#include <KLocale>
#include <KSharedPtr>
#include <ThreadWeaver/Weaver>
// additional constants
namespace Meta
......@@ -1641,7 +1643,13 @@ SqlAlbum::setImage( const QImage &image )
// the song needs to be at least one mb big or we won't set an image
// that means that the new image will increase the file size by less than 2%
if( metaTrack->filesize() > 1024l * 1024l )
Meta::Tag::setEmbeddedCover( metaTrack->playableUrl().path(), scaledImage );
{
Meta::FieldHash fields;
fields.insert( Meta::valImage, scaledImage );
WriteTagsJob *job = new WriteTagsJob( metaTrack->playableUrl().path(), fields );
QObject::connect( job, SIGNAL(done(ThreadWeaver::Job*)), job, SLOT(deleteLater()) );
ThreadWeaver::Weaver::instance()->enqueue( job );
}
// note: we might want to update the track file size after writing the image
}
}
......
......@@ -36,7 +36,6 @@ if(IPOD_FOUND AND WITH_IPOD)
jobs/IpodDeleteTracksJob.cpp
jobs/IpodParseTracksJob.cpp
jobs/IpodWriteDatabaseJob.cpp
jobs/WriteTagsJob.cpp
support/IphoneMountPoint.cpp
support/IpodDeviceHelper.cpp
support/IpodTranscodeCapability.cpp
......
......@@ -18,10 +18,10 @@
#include "IpodCollection.h"
#include "IpodMetaEditCapability.h"
#include "jobs/WriteTagsJob.h"
#include "config-ipodcollection.h"
#include "amarokconfig.h"
#include "core/support/Debug.h"
#include "core-impl/collections/support/jobs/WriteTagsJob.h"
#include "core-impl/collections/support/ArtistHelper.h"
#include "covermanager/CoverCache.h"
#include "FileType.h"
......@@ -295,7 +295,7 @@ Track::setImage( const QImage &newImage, bool doCommit )
* and sets artwork_size, artwork_count and has_artwork m_track fields */
itdb_track_set_thumbnails( m_track, QFile::encodeName( m_tempImageFile->fileName() ) );
}
m_changedFields.insert( IpodMeta::valImage, newImage );
m_changedFields.insert( Meta::valImage, newImage );
locker.unlock();
if( doCommit )
......
......@@ -34,8 +34,6 @@ class IpodCollection;
namespace IpodMeta
{
static const qint64 valImage = Meta::valCustom + 1LL;
/**
* An iPod track. album, artist, composer etc. are invisible to ouside world, they are
* proxied in the MemoMeta track. All methods in this class are thread-safe with a few
......
......@@ -17,7 +17,6 @@
#include "WriteTagsJob.h"
#include "amarokconfig.h"
#include "IpodMeta.h"
#include "MetaTagLib.h"
......@@ -32,8 +31,8 @@ void WriteTagsJob::run()
{
Meta::Tag::writeTags( m_path, m_changes );
if( m_changes.contains( IpodMeta::valImage ) && AmarokConfig::writeBackCover() )
Meta::Tag::setEmbeddedCover( m_path, m_changes.value( IpodMeta::valImage ).value<QImage>() );
if( m_changes.contains( Meta::valImage ) && AmarokConfig::writeBackCover() )
Meta::Tag::setEmbeddedCover( m_path, m_changes.value( Meta::valImage ).value<QImage>() );
}
#include "WriteTagsJob.moc"
......@@ -19,6 +19,7 @@
#include "MetaValues.h"
#include "amarok_export.h"
#include <ThreadWeaver/Job>
......@@ -27,18 +28,18 @@
* is not blocked with IO. writeTags() respects AmarokConfig::writeBackStatistics,
* AmarokConfig::writeBack().
*
* If @param changes contains IpodMeta::valImage, writes back image too, respecting
* AmarokConfig.
* If @param changes contains Meta::valImage, writes back image too, respecting
* AmarokConfig::writeBackCover().
*
* The caller is responsible to delete this job after use, perhaps by connecting its
* done() signal to its deleteLater() slot.
*/
class WriteTagsJob : public ThreadWeaver::Job
class AMAROK_EXPORT WriteTagsJob : public ThreadWeaver::Job
{
Q_OBJECT
public:
explicit WriteTagsJob( const QString &path, const Meta::FieldHash &changes );
WriteTagsJob( const QString &path, const Meta::FieldHash &changes );
virtual void run();
private:
......
......@@ -27,10 +27,13 @@
#include "shared/MetaReplayGain.h"
#include "shared/MetaTagLib.h"
#include "core/statistics/StatisticsProvider.h"
#include "core-impl/collections/support/jobs/WriteTagsJob.h"
#include "core-impl/collections/support/ArtistHelper.h"
#include "core-impl/capabilities/AlbumActionsCapability.h"
#include "covermanager/CoverCache.h"
#include <ThreadWeaver/Weaver>
#include <QDateTime>
#include <QFile>
#include <QFileInfo>
......@@ -117,7 +120,6 @@ public:
QWeakPointer<Capabilities::LastfmReadLabelCapability> readLabelCapability;
QWeakPointer<Collections::Collection> collection;
void readMetaData();
Meta::FieldHash changes;
void writeMetaData()
......@@ -135,6 +137,9 @@ public:
MetaData m_data;
public slots:
void readMetaData();
private:
TagLib::FileRef getFileRef();
Track *track;
......@@ -349,10 +354,14 @@ public:
if( !d )
return;
Meta::Tag::setEmbeddedCover( d.data()->url.toLocalFile(), image );
Meta::FieldHash fields;
fields.insert( Meta::valImage, image );
WriteTagsJob *job = new WriteTagsJob( d.data()->url.toLocalFile(), fields );
QObject::connect( job, SIGNAL(done(ThreadWeaver::Job*)), job, SLOT(deleteLater()) );
ThreadWeaver::Weaver::instance()->enqueue( job );
if( d.data()->m_data.embeddedImage == image.isNull() )
// we need to toggle the embeddedImage switch in this case
d.data()->readMetaData();
QObject::connect( job, SIGNAL(done(ThreadWeaver::Job*)), d.data(), SLOT(readMetaData()) );
CoverCache::invalidateAlbum( this );
notifyObservers();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment