46
src/utilities/coveroptions.h
Normal file
46
src/utilities/coveroptions.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2023, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef COVEROPTIONS_H
|
||||
#define COVEROPTIONS_H
|
||||
|
||||
class CoverOptions {
|
||||
public:
|
||||
|
||||
enum class CoverType {
|
||||
Cache = 1,
|
||||
Album = 2,
|
||||
Embedded = 3
|
||||
};
|
||||
|
||||
enum class CoverFilename {
|
||||
Hash = 1,
|
||||
Pattern = 2
|
||||
};
|
||||
|
||||
explicit CoverOptions() : cover_type(CoverType::Cache), cover_filename(CoverFilename::Hash), cover_overwrite(false), cover_lowercase(true), cover_replace_spaces(true) {}
|
||||
CoverType cover_type;
|
||||
CoverFilename cover_filename;
|
||||
QString cover_pattern;
|
||||
bool cover_overwrite;
|
||||
bool cover_lowercase;
|
||||
bool cover_replace_spaces;
|
||||
};
|
||||
|
||||
#endif // COVEROPTIONS_H
|
||||
166
src/utilities/coverutils.cpp
Normal file
166
src/utilities/coverutils.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2019-2023, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QRegularExpression>
|
||||
#include <QUrl>
|
||||
#include <QDir>
|
||||
#include <QStandardPaths>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
#include "filenameconstants.h"
|
||||
#include "transliterate.h"
|
||||
#include "coverutils.h"
|
||||
#include "core/logging.h"
|
||||
|
||||
QByteArray CoverUtils::Sha1CoverHash(const QString &artist, const QString &album) {
|
||||
|
||||
QCryptographicHash hash(QCryptographicHash::Sha1);
|
||||
hash.addData(artist.toLower().toUtf8());
|
||||
hash.addData(album.toLower().toUtf8());
|
||||
|
||||
return hash.result();
|
||||
|
||||
}
|
||||
|
||||
QString CoverUtils::AlbumCoverFilename(QString artist, QString album, const QString &extension) {
|
||||
|
||||
artist.remove('/').remove('\\');
|
||||
album.remove('/').remove('\\');
|
||||
|
||||
QString filename = artist + "-" + album;
|
||||
filename = Utilities::Transliterate(filename.toLower());
|
||||
filename = filename.replace(' ', '-')
|
||||
.replace("--", "-")
|
||||
.remove(QRegularExpression(QString(kInvalidFatCharactersRegex), QRegularExpression::CaseInsensitiveOption))
|
||||
.simplified();
|
||||
|
||||
if (!extension.isEmpty()) {
|
||||
filename.append('.');
|
||||
filename.append(extension);
|
||||
}
|
||||
|
||||
return filename;
|
||||
|
||||
}
|
||||
|
||||
QString CoverUtils::CoverFilePath(const CoverOptions &options, const Song &song, const QString &album_dir, const QUrl &cover_url, const QString &extension) {
|
||||
return CoverFilePath(options, song.source(), song.effective_albumartist(), song.album(), song.album_id(), album_dir, cover_url, extension);
|
||||
}
|
||||
|
||||
QString CoverUtils::CoverFilePath(const CoverOptions &options, const Song::Source source, const QString &artist, const QString &album, const QString &album_id, const QString &album_dir, const QUrl &cover_url, const QString &extension) {
|
||||
|
||||
QString path;
|
||||
if (source == Song::Source::Collection && options.cover_type == CoverOptions::CoverType::Album && !album_dir.isEmpty()) {
|
||||
path = album_dir;
|
||||
}
|
||||
else {
|
||||
path = Song::ImageCacheDir(source);
|
||||
}
|
||||
|
||||
if (path.right(1) == QDir::separator() || path.right(1) == "/") {
|
||||
path.chop(1);
|
||||
}
|
||||
|
||||
QDir dir;
|
||||
if (!dir.mkpath(path)) {
|
||||
qLog(Error) << "Unable to create directory" << path;
|
||||
path = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
|
||||
}
|
||||
|
||||
QString filename;
|
||||
if (source == Song::Source::Collection &&
|
||||
options.cover_type == CoverOptions::CoverType::Album &&
|
||||
options.cover_filename == CoverOptions::CoverFilename::Pattern &&
|
||||
!options.cover_pattern.isEmpty()) {
|
||||
filename = CoverFilenameFromVariable(options, artist, album);
|
||||
filename.remove(QRegularExpression(QString(kInvalidFatCharactersRegex), QRegularExpression::CaseInsensitiveOption)).remove('/').remove('\\');
|
||||
if (options.cover_lowercase) filename = filename.toLower();
|
||||
if (options.cover_replace_spaces) filename.replace(QRegularExpression("\\s"), "-");
|
||||
if (!extension.isEmpty()) {
|
||||
filename.append('.');
|
||||
filename.append(extension);
|
||||
}
|
||||
}
|
||||
|
||||
if (filename.isEmpty()) {
|
||||
filename = CoverFilenameFromSource(source, cover_url, artist, album, album_id, extension);
|
||||
}
|
||||
|
||||
QString filepath(path + "/" + filename);
|
||||
|
||||
return filepath;
|
||||
|
||||
}
|
||||
|
||||
QString CoverUtils::CoverFilenameFromSource(const Song::Source source, const QUrl &cover_url, const QString &artist, const QString &album, const QString &album_id, const QString &extension) {
|
||||
|
||||
QString filename;
|
||||
|
||||
switch (source) {
|
||||
case Song::Source::Tidal:
|
||||
if (!album_id.isEmpty()) {
|
||||
filename = album_id + "-" + cover_url.fileName();
|
||||
break;
|
||||
}
|
||||
[[fallthrough]];
|
||||
case Song::Source::Subsonic:
|
||||
case Song::Source::Qobuz:
|
||||
if (!album_id.isEmpty()) {
|
||||
filename = album_id;
|
||||
break;
|
||||
}
|
||||
[[fallthrough]];
|
||||
case Song::Source::Collection:
|
||||
case Song::Source::LocalFile:
|
||||
case Song::Source::CDDA:
|
||||
case Song::Source::Device:
|
||||
case Song::Source::Stream:
|
||||
case Song::Source::SomaFM:
|
||||
case Song::Source::RadioParadise:
|
||||
case Song::Source::Unknown:
|
||||
filename = Sha1CoverHash(artist, album).toHex();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!extension.isEmpty()) {
|
||||
filename.append('.');
|
||||
filename.append(extension);
|
||||
}
|
||||
|
||||
return filename;
|
||||
|
||||
}
|
||||
|
||||
QString CoverUtils::CoverFilenameFromVariable(const CoverOptions &options, const QString &artist, QString album, const QString &extension) {
|
||||
|
||||
album = album.remove(Song::kAlbumRemoveDisc);
|
||||
|
||||
QString filename(options.cover_pattern);
|
||||
filename.replace("%albumartist", artist);
|
||||
filename.replace("%artist", artist);
|
||||
filename.replace("%album", album);
|
||||
if (!extension.isEmpty()) {
|
||||
filename.append('.');
|
||||
filename.append(extension);
|
||||
}
|
||||
return filename;
|
||||
|
||||
}
|
||||
42
src/utilities/coverutils.h
Normal file
42
src/utilities/coverutils.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2019-2023, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef COVERUTILS_H
|
||||
#define COVERUTILS_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
#include "core/song.h"
|
||||
#include "coveroptions.h"
|
||||
|
||||
class CoverUtils {
|
||||
|
||||
public:
|
||||
static QByteArray Sha1CoverHash(const QString &artist, const QString &album);
|
||||
static QString AlbumCoverFilename(QString artist, QString album, const QString &extension);
|
||||
static QString CoverFilenameFromSource(const Song::Source source, const QUrl &cover_url, const QString &artist, const QString &album, const QString &album_id, const QString &extension);
|
||||
static QString CoverFilenameFromVariable(const CoverOptions &options, const QString &artist, QString album, const QString &extension = QString());
|
||||
static QString CoverFilePath(const CoverOptions &options, const Song &song, const QString &album_dir, const QUrl &cover_url, const QString &extension = QString());
|
||||
static QString CoverFilePath(const CoverOptions &options, const Song::Source source, const QString &artist, const QString &album, const QString &album_id, const QString &album_dir, const QUrl &cover_url, const QString &extension = QString());
|
||||
|
||||
};
|
||||
|
||||
#endif // COVERUTILS_H
|
||||
@@ -62,14 +62,4 @@ QByteArray HmacSha1(const QByteArray &key, const QByteArray &data) {
|
||||
return Hmac(key, data, QCryptographicHash::Sha1);
|
||||
}
|
||||
|
||||
QByteArray Sha1CoverHash(const QString &artist, const QString &album) {
|
||||
|
||||
QCryptographicHash hash(QCryptographicHash::Sha1);
|
||||
hash.addData(artist.toLower().toUtf8());
|
||||
hash.addData(album.toLower().toUtf8());
|
||||
|
||||
return hash.result();
|
||||
|
||||
}
|
||||
|
||||
} // namespace Utilities
|
||||
|
||||
@@ -30,7 +30,6 @@ QByteArray Hmac(const QByteArray &key, const QByteArray &data, const QCryptograp
|
||||
QByteArray HmacMd5(const QByteArray &key, const QByteArray &data);
|
||||
QByteArray HmacSha256(const QByteArray &key, const QByteArray &data);
|
||||
QByteArray HmacSha1(const QByteArray &key, const QByteArray &data);
|
||||
QByteArray Sha1CoverHash(const QString &artist, const QString &album);
|
||||
|
||||
} // namespace Utilities
|
||||
|
||||
|
||||
31
src/utilities/filenameconstants.h
Normal file
31
src/utilities/filenameconstants.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2023, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FILENAMECONSTANTS_H
|
||||
#define FILENAMECONSTANTS_H
|
||||
|
||||
#include "core/arraysize.h"
|
||||
|
||||
constexpr char kProblematicCharactersRegex[] = "[:?*\"<>|]";
|
||||
constexpr char kInvalidFatCharactersRegex[] = "[^a-zA-Z0-9!#\\$%&'()\\-@\\^_`{}~/. ]";
|
||||
constexpr char kInvalidDirCharactersRegex[] = "[/\\\\]";
|
||||
constexpr char kInvalidPrefixCharacters[] = ".";
|
||||
constexpr int kInvalidPrefixCharactersCount = arraysize(kInvalidPrefixCharacters) - 1;
|
||||
|
||||
#endif // FILENAMECONSTANTS_H
|
||||
Reference in New Issue
Block a user