Add option to embed covers when copying songs to devices. (ID3v2, mp4, vorbis comment tag types only)

This commit is contained in:
craig.p.drummond
2012-12-10 19:56:16 +00:00
parent ec4f910d60
commit c86ef5e44d
10 changed files with 187 additions and 59 deletions

View File

@@ -14,6 +14,8 @@
7. Allow editing of tags, and replaygain calculation, of files from folder view
which do not contain tags.
8. Merge 'External Settings' into 'Interface Settingst'
9. Add option to embed covers when copying songs to devices. (ID3v2, mp4,
vorbis comment tag types only)
0.9.1
-----

View File

@@ -25,6 +25,7 @@
#include "device.h"
#include "covers.h"
#include "utils.h"
#include <QtCore/QBuffer>
#include <QtCore/QDir>
#include <QtCore/QTemporaryFile>
#ifndef Q_OS_WIN
@@ -130,6 +131,7 @@ void Device::cleanDir(const QString &dir, const QString &base, const QString &co
#include <unistd.h>
const QLatin1String Device::constNoCover("-");
const QLatin1String Device::constEmbedCover("+");
Device * Device::create(DevicesModel *m, const QString &udi)
{
@@ -191,6 +193,38 @@ bool Device::fixVariousArtists(const QString &file, Song &song, bool applyFix)
return false;
}
static QByteArray save(const QImage &img) {
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
img.save(&buffer, "JPG");
buffer.close();
return ba;
}
void Device::embedCover(const QString &file, Song &song, unsigned int coverMaxSize)
{
if (Tags::readImage(file).isNull()) {
Covers::Image coverImage=Covers::self()->getImage(song);
if (!coverImage.img.isNull()) {
QByteArray imgData;
if (coverImage.img.width()>(int)coverMaxSize || coverImage.img.height()>(int)coverMaxSize) {
imgData=save(coverImage.img.scaled(QSize(coverMaxSize, coverMaxSize), Qt::KeepAspectRatio, Qt::SmoothTransformation));
} else if (!coverImage.fileName.endsWith(".jpg", Qt::CaseInsensitive) || !QFile::exists(coverImage.fileName)) {
imgData=save(coverImage.img);
} else {
QFile f(coverImage.fileName);
if (f.open(QIODevice::ReadOnly)) {
imgData=f.readAll();
} else {
imgData=save(coverImage.img);
}
}
Tags::embedImage(file, imgData);
}
}
}
QTemporaryFile * Device::copySongToTemp(Song &song)
{
QTemporaryFile *temp=new QTemporaryFile();

View File

@@ -55,11 +55,13 @@ class Device : public MusicLibraryItemRoot
public:
static Device * create(DevicesModel *m, const QString &udi);
static bool fixVariousArtists(const QString &file, Song &song, bool applyFix);
static void embedCover(const QString &file, Song &song, unsigned int coverMaxSize);
static QTemporaryFile * copySongToTemp(Song &song);
static void moveDir(const QString &from, const QString &to, const QString &base, const QString &coverFile);
static void cleanDir(const QString &dir, const QString &base, const QString &coverFile, int level=0);
static const QLatin1String constNoCover;
static const QLatin1String constEmbedCover;
enum Status {
Ok,

View File

@@ -80,12 +80,13 @@ DevicePropertiesWidget::DevicePropertiesWidget(QWidget *parent)
: QWidget(parent)
, schemeDlg(0)
, noCoverText(i18n("Don't copy covers"))
, embedCoverText(i18n("Embed cover within each file"))
, modified(false)
, saveable(false)
{
setupUi(this);
configFilename->setIcon(Icons::configureIcon);
albumCovers->insertItems(0, QStringList() << noCoverText << Covers::standardNames());
albumCovers->insertItems(0, QStringList() << noCoverText << embedCoverText << Covers::standardNames());
coverMaxSize->insertItems(0, QStringList() << i18n("No maximum size") << i18n("400 pixels") << i18n("300 pixels") << i18n("200 pixels") << i18n("100 pixels"));
fixVariousArtists->setToolTip(i18n("<p>When copying tracks to a device, and the 'Album Artist' is set to 'Various Artists', "
"then Cantata will set the 'Artist' tag of all tracks to 'Various Artists' and the "
@@ -110,6 +111,7 @@ DevicePropertiesWidget::DevicePropertiesWidget(QWidget *parent)
void DevicePropertiesWidget::update(const QString &path, const DeviceOptions &opts, int props)
{
bool allowCovers=(props&Prop_CoversAll)||(props&Prop_CoversBasic);
filenameScheme->setText(opts.scheme);
vfatSafe->setChecked(opts.vfatSafe);
asciiOnly->setChecked(opts.asciiOnly);
@@ -118,10 +120,11 @@ void DevicePropertiesWidget::update(const QString &path, const DeviceOptions &op
musicFolder->setText(path);
musicFolder->setVisible(props&Prop_Folder);
musicFolderLabel->setVisible(props&Prop_Folder);
albumCovers->setVisible(props&Prop_Covers);
albumCoversLabel->setVisible(props&Prop_Covers);
coverMaxSize->setVisible(props&Prop_Covers);
coverMaxSizeLabel->setVisible(props&Prop_Covers);
albumCovers->setVisible(allowCovers);
albumCoversLabel->setVisible(allowCovers);
coverMaxSize->setVisible(allowCovers);
coverMaxSizeLabel->setVisible(allowCovers);
albumCovers->setEditable(props&Prop_CoversAll);
fixVariousArtists->setVisible(props&Prop_Va);
fixVariousArtistsLabel->setVisible(props&Prop_Va);
fixVariousArtists->setChecked(opts.fixVariousArtists);
@@ -169,14 +172,20 @@ void DevicePropertiesWidget::update(const QString &path, const DeviceOptions &op
}
origOpts=opts;
albumCovers->setCurrentIndex(0);
if (origOpts.coverName==Device::constNoCover) {
origOpts.coverName=noCoverText;
albumCovers->setCurrentIndex(0);
}
for (int i=1; i<albumCovers->count(); ++i) {
if (albumCovers->itemText(i)==origOpts.coverName) {
albumCovers->setCurrentIndex(i);
break;
if (origOpts.coverName==Device::constEmbedCover) {
origOpts.coverName=embedCoverText;
albumCovers->setCurrentIndex(1);
} else {
albumCovers->setCurrentIndex(0);
for (int i=1; i<albumCovers->count(); ++i) {
if (albumCovers->itemText(i)==origOpts.coverName) {
albumCovers->setCurrentIndex(i);
break;
}
}
}
@@ -251,7 +260,12 @@ void DevicePropertiesWidget::checkSaveable()
if (!modified && checkFolder) {
modified=musicFolder->text().trimmed()!=origMusicFolder;
}
saveable=!opts.scheme.isEmpty() && (!checkFolder || !musicFolder->text().trimmed().isEmpty()) && !albumCovers->currentText().isEmpty();
saveable=!opts.scheme.isEmpty() && (!checkFolder || !musicFolder->text().trimmed().isEmpty()) && !opts.coverName.isEmpty();
if (saveable &&
( (-1!=opts.coverName.indexOf(noCoverText) && opts.coverName!=noCoverText) ||
(-1!=opts.coverName.indexOf(embedCoverText) && opts.coverName!=embedCoverText) ) ) {
saveable=false;
}
emit updated();
}
@@ -278,7 +292,7 @@ DeviceOptions DevicePropertiesWidget::settings()
opts.transcoderCodec=QString();
opts.transcoderValue=0;
opts.transcoderWhenDifferent=false;
opts.coverName=albumCovers->currentText();
opts.coverName=cover();
opts.coverMaxSize=0==coverMaxSize->currentIndex() ? 0 : ((coverMaxSize->count()-coverMaxSize->currentIndex())*100);
if (transcoderFrame->isVisible()) {
opts.transcoderCodec=transcoderName->itemData(transcoderName->currentIndex()).toString();
@@ -297,5 +311,10 @@ DeviceOptions DevicePropertiesWidget::settings()
QString DevicePropertiesWidget::cover() const
{
return albumCovers->currentText()==noCoverText ? Device::constNoCover : albumCovers->currentText();
QString coverName=albumCovers->currentText().trimmed();
return coverName==noCoverText
? Device::constNoCover
: coverName==embedCoverText
? Device::constEmbedCover
: coverName;
}

View File

@@ -34,16 +34,17 @@ class DevicePropertiesWidget : public QWidget, Ui::DevicePropertiesWidget
public:
enum Properties {
Prop_Basic = 0x00,
Prop_Basic = 0x00,
Prop_Folder = 0x01,
Prop_Covers = 0x02,
Prop_Va = 0x04,
Prop_Transcoder = 0x08,
Prop_Cache = 0x10,
Prop_AutoScan = 0x20,
Prop_Folder = 0x01,
Prop_CoversAll = 0x02,
Prop_CoversBasic = 0x04,
Prop_Va = 0x08,
Prop_Transcoder = 0x10,
Prop_Cache = 0x20,
Prop_AutoScan = 0x40,
Prop_All = 0xFF
Prop_All = 0xFF
};
DevicePropertiesWidget(QWidget *parent);
virtual ~DevicePropertiesWidget() { }
@@ -68,6 +69,7 @@ private:
DeviceOptions origOpts;
QString origMusicFolder;
QString noCoverText;
QString embedCoverText;
bool modified;
bool saveable;
};

View File

@@ -109,13 +109,20 @@ QString CopyJob::updateTagsLocal()
{
// First, if we are going to update tags (e.g. to fix various artists), then check if we want to do that locally, before
// copying to device. For UMS devices, we just modify on device, but for remote (e.g. sshfs) then it'd be better to do locally :-)
if (copyOpts&OptsFixLocal && (copyOpts&OptsApplyVaFix || copyOpts&OptsUnApplyVaFix)) {
if (copyOpts&OptsFixLocal && (copyOpts&OptsApplyVaFix || copyOpts&OptsUnApplyVaFix || Device::constEmbedCover==deviceOpts.coverName)) {
song.file=srcFile;
temp=Device::copySongToTemp(song);
if (!temp || !Device::fixVariousArtists(temp->fileName(), song, copyOpts&OptsApplyVaFix)) {
if (!temp) {
emit result(StatusFailed);
return QString();
}
if ((copyOpts&OptsApplyVaFix || copyOpts&OptsUnApplyVaFix) && !Device::fixVariousArtists(temp->fileName(), song, copyOpts&OptsApplyVaFix)) {
emit result(StatusFailed);
return QString();
}
if (Device::constEmbedCover==deviceOpts.coverName) {
Device::embedCover(temp->fileName(), song, deviceOpts.coverMaxSize);
}
return temp->fileName();
}
return srcFile;
@@ -123,14 +130,19 @@ QString CopyJob::updateTagsLocal()
void CopyJob::updateTagsDest()
{
if (!stopRequested && !(copyOpts&OptsFixLocal) && (copyOpts&OptsApplyVaFix || copyOpts&OptsUnApplyVaFix)) {
Device::fixVariousArtists(destFile, song, copyOpts&OptsApplyVaFix);
if (!stopRequested && !(copyOpts&OptsFixLocal) && (copyOpts&OptsApplyVaFix || copyOpts&OptsUnApplyVaFix || Device::constEmbedCover==deviceOpts.coverName)) {
if (copyOpts&OptsApplyVaFix || copyOpts&OptsUnApplyVaFix) {
Device::fixVariousArtists(destFile, song, copyOpts&OptsApplyVaFix);
}
if (!stopRequested && Device::constEmbedCover==deviceOpts.coverName) {
Device::embedCover(destFile, song, deviceOpts.coverMaxSize);
}
}
}
void CopyJob::copyCover(const QString &origSrcFile)
{
if (!stopRequested && Device::constNoCover!=deviceOpts.coverName) {
if (!stopRequested && Device::constNoCover!=deviceOpts.coverName && Device::constEmbedCover!=deviceOpts.coverName) {
song.file=destFile;
copiedCover=Covers::copyCover(song, Utils::getDir(origSrcFile), Utils::getDir(destFile), deviceOpts.coverName, deviceOpts.coverMaxSize);
}

View File

@@ -507,10 +507,11 @@ static LIBMTP_filetype_t mtpFileType(const Song &s)
return LIBMTP_FILETYPE_UNDEF_AUDIO;
}
void MtpConnection::putSong(const Song &s, bool fixVa)
void MtpConnection::putSong(const Song &s, bool fixVa, const DeviceOptions &opts)
{
bool added=false;
bool fixedVa=false;
bool embedCoverImage=Device::constEmbedCover==opts.coverName;
LIBMTP_track_t *meta=0;
if (device) {
meta=LIBMTP_new_track_t();
@@ -528,14 +529,17 @@ void MtpConnection::putSong(const Song &s, bool fixVa)
QString fileName=song.file;
QTemporaryFile *temp=0;
if (fixVa) {
if (fixVa || embedCoverImage) {
// Need to 'workaround' broken various artists handling, so write to a temporary file first...
temp=Device::copySongToTemp(song);
if (temp) {
song.file=temp->fileName();
if (Device::fixVariousArtists(temp->fileName(), song, true)) {
if (embedCoverImage) {
Device::embedCover(song.file, song, opts.coverMaxSize);
}
if (fixVa && Device::fixVariousArtists(temp->fileName(), song, true)) {
fixedVa=true;
}
song.file=temp->fileName();
}
}
meta->title=createString(song.title);
@@ -924,6 +928,7 @@ MtpDevice::MtpDevice(DevicesModel *m, Solid::Device &dev)
static bool registeredTypes=false;
if (!registeredTypes) {
qRegisterMetaType<QSet<QString> >("QSet<QString>");
qRegisterMetaType<DeviceOptions >("DeviceOptions");
registeredTypes=true;
}
@@ -941,7 +946,7 @@ MtpDevice::MtpDevice(DevicesModel *m, Solid::Device &dev)
connect(this, SIGNAL(updateLibrary()), connection, SLOT(updateLibrary()));
connect(connection, SIGNAL(libraryUpdated()), this, SLOT(libraryUpdated()));
connect(connection, SIGNAL(progress(int)), this, SLOT(emitProgress(int)));
connect(this, SIGNAL(putSong(const Song &, bool)), connection, SLOT(putSong(const Song &, bool)));
connect(this, SIGNAL(putSong(const Song &, bool, const DeviceOptions &)), connection, SLOT(putSong(const Song &, bool, const DeviceOptions &)));
connect(connection, SIGNAL(putSongStatus(bool, int, const QString &, bool)), this, SLOT(putSongStatus(bool, int, const QString &, bool)));
connect(this, SIGNAL(getSong(const Song &, const QString &)), connection, SLOT(getSong(const Song &, const QString &)));
connect(connection, SIGNAL(getSongStatus(bool)), this, SLOT(getSongStatus(bool)));
@@ -994,7 +999,7 @@ void MtpDevice::configure(QWidget *parent)
if (!configured) {
connect(dlg, SIGNAL(cancelled()), SLOT(saveProperties()));
}
dlg->show(QString(), opts, DevicePropertiesWidget::Prop_Va|DevicePropertiesWidget::Prop_Transcoder);
dlg->show(QString(), opts, DevicePropertiesWidget::Prop_CoversBasic|DevicePropertiesWidget::Prop_Va|DevicePropertiesWidget::Prop_Transcoder);
}
void MtpDevice::rescan(bool full)
@@ -1092,7 +1097,7 @@ void MtpDevice::addSong(const Song &s, bool overwrite, bool copyCover)
}
}
transcoding=false;
emit putSong(currentSong, needToFixVa);
emit putSong(currentSong, needToFixVa, opts);
}
void MtpDevice::copySongTo(const Song &s, const QString &baseDir, const QString &musicPath, bool overwrite, bool copyCover)
@@ -1203,7 +1208,7 @@ void MtpDevice::transcodeSongResult(int status)
if (FileJob::StatusOk!=status) {
emit actionStatus(TranscodeFailed);
} else {
emit putSong(currentSong, needToFixVa);
emit putSong(currentSong, needToFixVa, DeviceOptions(Device::constNoCover));
}
}

View File

@@ -66,7 +66,7 @@ public Q_SLOTS:
void connectToDevice();
void disconnectFromDevice(bool showStatus=true);
void updateLibrary();
void putSong(const Song &song, bool fixVa);
void putSong(const Song &song, bool fixVa, const DeviceOptions &opts);
void getSong(const Song &song, const QString &dest, bool fixVa, bool copyCover);
void delSong(const Song &song);
void cleanDirs(const QSet<QString> &dirs);
@@ -145,7 +145,7 @@ public:
Q_SIGNALS:
// These are for talking to connection thread...
void updateLibrary();
void putSong(const Song &song, bool fixVa);
void putSong(const Song &song, bool fixVa, const DeviceOptions &opts);
void getSong(const Song &song, const QString &dest, bool fixVa, bool copyCover);
void delSong(const Song &song);
void cleanMusicDirs(const QSet<QString> &dirs);

View File

@@ -365,7 +365,7 @@ static bool updateID3v2Tag(TagLib::ID3v2::Tag *tag, const char *tagName, const Q
return false;
}
static bool writeID3v2Tags(TagLib::ID3v2::Tag *tag, const Song &from, const Song &to, const RgTags &rg)
static bool writeID3v2Tags(TagLib::ID3v2::Tag *tag, const Song &from, const Song &to, const RgTags &rg, const QByteArray &img)
{
bool changed=false;
@@ -396,6 +396,17 @@ static bool writeID3v2Tags(TagLib::ID3v2::Tag *tag, const Song &from, const Song
}
changed=true;
}
if (!img.isEmpty()) {
TagLib::ByteVector imgData(img.constData(), img.length());
TagLib::ID3v2::AttachedPictureFrame *pic=new TagLib::ID3v2::AttachedPictureFrame;
pic->setType(TagLib::ID3v2::AttachedPictureFrame::FrontCover);
pic->setMimeType("image/jpeg");
pic->setPicture(imgData);
tag->addFrame(pic);
changed=true;
}
return changed;
}
@@ -548,7 +559,7 @@ static bool updateVorbisCommentTag(TagLib::Ogg::XiphComment *tag, const char *ta
return false;
}
static bool writeVorbisCommentTags(TagLib::Ogg::XiphComment *tag, const Song &from, const Song &to, const RgTags &rg)
static bool writeVorbisCommentTags(TagLib::Ogg::XiphComment *tag, const Song &from, const Song &to, const RgTags &rg, const QByteArray &img)
{
bool changed=false;
@@ -574,6 +585,11 @@ static bool writeVorbisCommentTags(TagLib::Ogg::XiphComment *tag, const Song &fr
}
changed=true;
}
if (!img.isEmpty()) {
tag->addField("COVERART", qString2TString(QString::fromAscii(img.toBase64())));
changed=true;
}
return changed;
}
@@ -632,7 +648,7 @@ static bool updateMP4Tag(TagLib::MP4::Tag *tag, const char *tagName, const QStri
return false;
}
static bool writeMP4Tags(TagLib::MP4::Tag *tag, const Song &from, const Song &to, const RgTags &rg)
static bool writeMP4Tags(TagLib::MP4::Tag *tag, const Song &from, const Song &to, const RgTags &rg, const QByteArray &img)
{
bool changed=false;
@@ -659,6 +675,17 @@ static bool writeMP4Tags(TagLib::MP4::Tag *tag, const Song &from, const Song &to
}
changed=true;
}
if (!img.isEmpty()) {
TagLib::ByteVector imgData(img.constData(), img.length());
TagLib::MP4::CoverArt coverArt(TagLib::MP4::CoverArt::JPEG, imgData);
TagLib::MP4::CoverArtList coverArtList;
coverArtList.append(coverArt);
TagLib::MP4::Item coverItem(coverArtList);
TagLib::MP4::ItemListMap &map = tag->itemListMap();
map.insert("covr", coverItem);
}
return changed;
}
#endif
@@ -802,7 +829,7 @@ static void readTags(const TagLib::FileRef fileref, Song *song, ReplayGain *rg,
}
}
static bool writeTags(const TagLib::FileRef fileref, const Song &from, const Song &to, const RgTags &rg)
static bool writeTags(const TagLib::FileRef fileref, const Song &from, const Song &to, const RgTags &rg, const QByteArray &img)
{
bool changed=false;
TagLib::Tag *tag=fileref.tag();
@@ -834,56 +861,56 @@ static bool writeTags(const TagLib::FileRef fileref, const Song &from, const Son
}
if (TagLib::MPEG::File *file = dynamic_cast< TagLib::MPEG::File * >(fileref.file())) {
if (file->ID3v2Tag()) {
changed=writeID3v2Tags(file->ID3v2Tag(), from, to, rg) || changed;
changed=writeID3v2Tags(file->ID3v2Tag(), from, to, rg, img) || changed;
} else if (file->APETag()) {
changed=writeAPETags(file->APETag(), from, to, rg) || changed;
// } else if (file->ID3v1Tag()) {
// changed=writeID3v1Tags(fileref, from, to, rg) || changed;
// changed=writeID3v1Tags(fileref, from, to, rg, img) || changed;
} else if (file->ID3v2Tag(true)) {
changed=writeID3v2Tags(file->ID3v2Tag(), from, to, rg) || changed;
changed=writeID3v2Tags(file->ID3v2Tag(), from, to, rg, img) || changed;
}
} else if (TagLib::Ogg::Vorbis::File *file = dynamic_cast< TagLib::Ogg::Vorbis::File * >(fileref.file())) {
if (file->tag()) {
changed=writeVorbisCommentTags(file->tag(), from, to, rg) || changed;
changed=writeVorbisCommentTags(file->tag(), from, to, rg, img) || changed;
}
} else if (TagLib::Ogg::FLAC::File *file = dynamic_cast< TagLib::Ogg::FLAC::File * >(fileref.file())) {
if (file->tag()) {
changed=writeVorbisCommentTags(file->tag(), from, to, rg) || changed;
changed=writeVorbisCommentTags(file->tag(), from, to, rg, img) || changed;
}
} else if (TagLib::Ogg::Speex::File *file = dynamic_cast< TagLib::Ogg::Speex::File * >(fileref.file())) {
if (file->tag()) {
changed=writeVorbisCommentTags(file->tag(), from, to, rg) || changed;
changed=writeVorbisCommentTags(file->tag(), from, to, rg, img) || changed;
}
} else if (TagLib::FLAC::File *file = dynamic_cast< TagLib::FLAC::File * >(fileref.file())) {
if (file->xiphComment()) {
changed=writeVorbisCommentTags(file->xiphComment(), from, to, rg) || changed;
changed=writeVorbisCommentTags(file->xiphComment(), from, to, rg, img) || changed;
} else if (file->ID3v2Tag()) {
changed=writeID3v2Tags(file->ID3v2Tag(), from, to, rg) || changed;
changed=writeID3v2Tags(file->ID3v2Tag(), from, to, rg, img) || changed;
// } else if (file->ID3v1Tag()) {
// changed=writeID3v1Tags(fileref, from, to, rg) || changed;
// changed=writeID3v1Tags(fileref, from, to, rg, img) || changed;
} else if (file->ID3v2Tag(true)) {
changed=writeID3v2Tags(file->ID3v2Tag(), from, to, rg) || changed;
changed=writeID3v2Tags(file->ID3v2Tag(), from, to, rg, img) || changed;
}
#ifdef TAGLIB_MP4_FOUND
} else if (TagLib::MP4::File *file = dynamic_cast< TagLib::MP4::File * >(fileref.file())) {
TagLib::MP4::Tag *tag = dynamic_cast<TagLib::MP4::Tag * >(file->tag());
if (tag) {
changed=writeMP4Tags(tag, from, to, rg) || changed;
changed=writeMP4Tags(tag, from, to, rg, img) || changed;
}
#endif
} else if (TagLib::MPC::File *file = dynamic_cast< TagLib::MPC::File * >(fileref.file())) {
if (file->APETag(true)) {
changed=writeAPETags(file->APETag(), from, to, rg) || changed;
// } else if (file->ID3v1Tag()) {
// changed=writeID3v1Tags(fileref, from, to, rg) || changed;
// changed=writeID3v1Tags(fileref, from, to, rg, img) || changed;
}
} else if (TagLib::RIFF::AIFF::File *file = dynamic_cast< TagLib::RIFF::AIFF::File * >(fileref.file())) {
if (file->tag()) {
changed=writeID3v2Tags(file->tag(), from, to, rg) || changed;
changed=writeID3v2Tags(file->tag(), from, to, rg, img) || changed;
}
} else if (TagLib::RIFF::WAV::File *file = dynamic_cast< TagLib::RIFF::WAV::File * >(fileref.file())) {
if (file->tag()) {
changed=writeID3v2Tags(file->tag(), from, to, rg) || changed;
changed=writeID3v2Tags(file->tag(), from, to, rg, img) || changed;
}
#ifdef TAGLIB_ASF_FOUND
} else if (TagLib::ASF::File *file = dynamic_cast< TagLib::ASF::File * >(fileref.file())) {
@@ -894,15 +921,15 @@ static bool writeTags(const TagLib::FileRef fileref, const Song &from, const Son
#endif
} else if (TagLib::TrueAudio::File *file = dynamic_cast< TagLib::TrueAudio::File * >(fileref.file())) {
if (file->ID3v2Tag(true)) {
changed=writeID3v2Tags(file->ID3v2Tag(), from, to, rg) || changed;
changed=writeID3v2Tags(file->ID3v2Tag(), from, to, rg, img) || changed;
// } else if (file->ID3v1Tag()) {
// changed=writeID3v1Tags(fileref, from, to, rg) || changed;
// changed=writeID3v1Tags(fileref, from, to, rg, img) || changed;
}
} else if (TagLib::WavPack::File *file = dynamic_cast< TagLib::WavPack::File * >(fileref.file())) {
if (file->APETag(true)) {
changed=writeAPETags(file->APETag(), from, to, rg) || changed;
// } else if (file->ID3v1Tag()) {
// changed=writeID3v1Tags(fileref, from, to, rg) || changed;
// changed=writeID3v1Tags(fileref, from, to, rg, img) || changed;
}
}
@@ -1000,7 +1027,7 @@ Update update(const QString &fileName, const Song &from, const Song &to)
TagLib::ID3v1::Tag *v1=mpeg ? mpeg->ID3v1Tag(false) : 0;
bool haveV1=v1 && (!v1->title().isEmpty() || !v1->artist().isEmpty() || !v1->album().isEmpty());
if (writeTags(fileref, from, to, RgTags())) {
if (writeTags(fileref, from, to, RgTags(), QByteArray())) {
if (mpeg && !haveV1) {
return mpeg->save(TagLib::MPEG::File::ID3v2) ? Update_Modified : Update_Failed;
}
@@ -1040,7 +1067,31 @@ Update updateReplaygain(const QString &fileName, const ReplayGain &rg)
TagLib::ID3v1::Tag *v1=mpeg ? mpeg->ID3v1Tag(false) : 0;
bool haveV1=v1 && (!v1->title().isEmpty() || !v1->artist().isEmpty() || !v1->album().isEmpty());
if (writeTags(fileref, Song(), Song(), RgTags(rg))) {
if (writeTags(fileref, Song(), Song(), RgTags(rg), QByteArray())) {
if (mpeg && !haveV1) {
return mpeg->save(TagLib::MPEG::File::ID3v2) ? Update_Modified : Update_Failed;
}
return fileref.file()->save() ? Update_Modified : Update_Failed;
}
return Update_None;
}
Update embedImage(const QString &fileName, const QByteArray &cover)
{
QMutexLocker locker(&mutex);
ensureFileTypeResolvers();
TagLib::FileRef fileref = getFileRef(fileName);
if (fileref.isNull()) {
return Update_Failed;
}
TagLib::MPEG::File *mpeg=dynamic_cast<TagLib::MPEG::File *>(fileref.file());
TagLib::ID3v1::Tag *v1=mpeg ? mpeg->ID3v1Tag(false) : 0;
bool haveV1=v1 && (!v1->title().isEmpty() || !v1->artist().isEmpty() || !v1->album().isEmpty());
if (writeTags(fileref, Song(), Song(), RgTags(), cover)) {
if (mpeg && !haveV1) {
return mpeg->save(TagLib::MPEG::File::ID3v2) ? Update_Modified : Update_Failed;
}

View File

@@ -60,6 +60,7 @@ namespace Tags
extern Update update(const QString &fileName, const Song &from, const Song &to);
extern ReplayGain readReplaygain(const QString &fileName);
extern Update updateReplaygain(const QString &fileName, const ReplayGain &rg);
extern Update embedImage(const QString &fileName, const QByteArray &cover);
};
#endif