Merge branch 'develop' for release v3.46.1
This commit is contained in:
@@ -292,6 +292,13 @@ CREATE TABLE IF NOT EXISTS "track_backup" (
|
|||||||
session.getDboSession().execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
session.getDboSession().execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void migrateFromV48(Session& session)
|
||||||
|
{
|
||||||
|
// Regression for the extra tags not being parsed
|
||||||
|
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||||
|
session.getDboSession().execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||||
|
}
|
||||||
|
|
||||||
void doDbMigration(Session& session)
|
void doDbMigration(Session& session)
|
||||||
{
|
{
|
||||||
static const std::string outdatedMsg{ "Outdated database, please rebuild it (delete the .db file and restart)" };
|
static const std::string outdatedMsg{ "Outdated database, please rebuild it (delete the .db file and restart)" };
|
||||||
@@ -318,6 +325,7 @@ CREATE TABLE IF NOT EXISTS "track_backup" (
|
|||||||
{45, migrateFromV45},
|
{45, migrateFromV45},
|
||||||
{46, migrateFromV46},
|
{46, migrateFromV46},
|
||||||
{47, migrateFromV47},
|
{47, migrateFromV47},
|
||||||
|
{48, migrateFromV48},
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace Database
|
|||||||
class Session;
|
class Session;
|
||||||
|
|
||||||
using Version = std::size_t;
|
using Version = std::size_t;
|
||||||
static constexpr Version LMS_DATABASE_VERSION{ 48 };
|
static constexpr Version LMS_DATABASE_VERSION{ 49 };
|
||||||
class VersionInfo
|
class VersionInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -25,6 +25,8 @@
|
|||||||
#define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_MITCHELL
|
#define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_MITCHELL
|
||||||
#define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_CATMULLROM
|
#define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_CATMULLROM
|
||||||
|
|
||||||
|
#define STBI_FAILURE_USERMSG
|
||||||
|
|
||||||
#include <stb_image.h>
|
#include <stb_image.h>
|
||||||
#include <stb_image_resize.h>
|
#include <stb_image_resize.h>
|
||||||
|
|
||||||
@@ -34,99 +36,92 @@
|
|||||||
|
|
||||||
namespace Image
|
namespace Image
|
||||||
{
|
{
|
||||||
std::unique_ptr<IRawImage> decodeImage(const std::byte* encodedData, std::size_t encodedDataSize)
|
std::unique_ptr<IRawImage> decodeImage(const std::byte* encodedData, std::size_t encodedDataSize)
|
||||||
{
|
{
|
||||||
return std::make_unique<STB::RawImage>(encodedData, encodedDataSize);
|
return std::make_unique<STB::RawImage>(encodedData, encodedDataSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<IRawImage> decodeImage(const std::filesystem::path& path)
|
std::unique_ptr<IRawImage> decodeImage(const std::filesystem::path& path)
|
||||||
{
|
{
|
||||||
return std::make_unique<STB::RawImage>(path);
|
return std::make_unique<STB::RawImage>(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void init(const std::filesystem::path&)
|
||||||
init(const std::filesystem::path&)
|
{
|
||||||
{
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Image::STB
|
namespace Image::STB
|
||||||
{
|
{
|
||||||
RawImage::RawImage(const std::byte* encodedData, std::size_t encodedDataSize)
|
RawImage::RawImage(const std::byte* encodedData, std::size_t encodedDataSize)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
_data = UniquePtrFree {stbi_load_from_memory(reinterpret_cast<const stbi_uc*>(encodedData), encodedDataSize, &_width, &_height, &n, 3), std::free};
|
_data = UniquePtrFree{ ::stbi_load_from_memory(reinterpret_cast<const stbi_uc*>(encodedData), encodedDataSize, &_width, &_height, &n, 3), std::free };
|
||||||
if (!_data)
|
if (!_data)
|
||||||
throw ImageException {"Cannot load image from memory"};
|
throw ImageException{ "Cannot load image from memory: " + std::string{ ::stbi_failure_reason() } };
|
||||||
}
|
}
|
||||||
|
|
||||||
RawImage::RawImage(const std::filesystem::path& p)
|
RawImage::RawImage(const std::filesystem::path& p)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
_data = UniquePtrFree {stbi_load(p.string().c_str(), &_width, &_height, &n, 3), std::free};
|
_data = UniquePtrFree{ stbi_load(p.string().c_str(), &_width, &_height, &n, 3), std::free };
|
||||||
if (!_data)
|
if (!_data)
|
||||||
throw ImageException {"Cannot load image from memory"};
|
throw ImageException{ "Cannot load image from file: " + std::string{ ::stbi_failure_reason() } };
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void RawImage::resize(ImageSize width)
|
||||||
RawImage::resize(ImageSize width)
|
{
|
||||||
{
|
size_t height;
|
||||||
size_t height;
|
if (_width == _height)
|
||||||
if (_width == _height)
|
{
|
||||||
{
|
height = width;
|
||||||
height = width;
|
}
|
||||||
}
|
else if (_width > _height)
|
||||||
else if (_width > _height)
|
{
|
||||||
{
|
height = (size_t)((float)width / _width * _height);
|
||||||
height = (size_t)((float)width/_width*_height);
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
height = width;
|
||||||
height = width;
|
width = (size_t)((float)height / _height * _width);
|
||||||
width = (size_t)((float)height/_height*_width);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
UniquePtrFree resizedData {reinterpret_cast<unsigned char*>(malloc(width*height*3)), std::free};
|
UniquePtrFree resizedData{ reinterpret_cast<unsigned char*>(malloc(width * height * 3)), std::free };
|
||||||
if (!resizedData)
|
if (!resizedData)
|
||||||
throw ImageException {"Cannot allocate memory for resized image!"};
|
throw ImageException{ "Cannot allocate memory for resized image!" };
|
||||||
|
|
||||||
if (stbir_resize_uint8_srgb(reinterpret_cast<const unsigned char*>(_data.get()), _width, _height, 0,
|
if (::stbir_resize_uint8_srgb(reinterpret_cast<const unsigned char*>(_data.get()), _width, _height, 0,
|
||||||
reinterpret_cast<unsigned char*>(resizedData.get()), width, height, 0,
|
reinterpret_cast<unsigned char*>(resizedData.get()), width, height, 0,
|
||||||
3, STBIR_ALPHA_CHANNEL_NONE, 0) == 0)
|
3, STBIR_ALPHA_CHANNEL_NONE, 0) == 0)
|
||||||
{
|
{
|
||||||
throw ImageException {"Failed to resize image!"};
|
throw ImageException{ "Failed to resize image:" + std::string{ ::stbi_failure_reason() } };
|
||||||
}
|
}
|
||||||
|
|
||||||
_data = std::move(resizedData);
|
_data = std::move(resizedData);
|
||||||
_height = height;
|
_height = height;
|
||||||
_width = width;
|
_width = width;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<IEncodedImage>
|
std::unique_ptr<IEncodedImage> RawImage::encodeToJPEG(unsigned quality) const
|
||||||
RawImage::encodeToJPEG(unsigned quality) const
|
{
|
||||||
{
|
return std::make_unique<JPEGImage>(*this, quality);
|
||||||
return std::make_unique<JPEGImage>(*this, quality);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ImageSize
|
ImageSize RawImage::getWidth() const
|
||||||
RawImage::getWidth() const
|
{
|
||||||
{
|
return _width;
|
||||||
return _width;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ImageSize
|
ImageSize RawImage::getHeight() const
|
||||||
RawImage::getHeight() const
|
{
|
||||||
{
|
return _height;
|
||||||
return _height;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const std::byte*
|
const std::byte* RawImage::getData() const
|
||||||
RawImage::getData() const
|
{
|
||||||
{
|
if (!_data)
|
||||||
if (!_data)
|
return nullptr;
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return reinterpret_cast<const std::byte*>(_data.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return reinterpret_cast<const std::byte*>(_data.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,24 +31,24 @@
|
|||||||
|
|
||||||
namespace Image::STB
|
namespace Image::STB
|
||||||
{
|
{
|
||||||
class RawImage : public IRawImage
|
class RawImage : public IRawImage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RawImage(const std::byte* encodedData, std::size_t encodedDataSize);
|
RawImage(const std::byte* encodedData, std::size_t encodedDataSize);
|
||||||
RawImage(const std::filesystem::path& path);
|
RawImage(const std::filesystem::path& path);
|
||||||
|
|
||||||
void resize(ImageSize width) override;
|
void resize(ImageSize width) override;
|
||||||
std::unique_ptr<IEncodedImage> encodeToJPEG(unsigned quality) const override;
|
std::unique_ptr<IEncodedImage> encodeToJPEG(unsigned quality) const override;
|
||||||
|
|
||||||
ImageSize getWidth() const;
|
ImageSize getWidth() const;
|
||||||
ImageSize getHeight() const;
|
ImageSize getHeight() const;
|
||||||
const std::byte* getData() const;
|
const std::byte* getData() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _width;
|
int _width;
|
||||||
int _height;
|
int _height;
|
||||||
using UniquePtrFree = std::unique_ptr<unsigned char, decltype(&std::free)>;
|
using UniquePtrFree = std::unique_ptr<unsigned char, decltype(&std::free)>;
|
||||||
UniquePtrFree _data {nullptr, std::free};
|
UniquePtrFree _data{ nullptr, std::free };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -429,16 +429,22 @@ namespace Cover
|
|||||||
std::set<std::filesystem::path> parentPaths;
|
std::set<std::filesystem::path> parentPaths;
|
||||||
{
|
{
|
||||||
Session& session{ _db.getTLSSession() };
|
Session& session{ _db.getTLSSession() };
|
||||||
|
|
||||||
|
Track::FindParameters params;
|
||||||
|
params.setArtist(artistId, { TrackArtistLinkType::ReleaseArtist });
|
||||||
|
|
||||||
auto transaction{ session.createReadTransaction() };
|
auto transaction{ session.createReadTransaction() };
|
||||||
|
|
||||||
Track::find(session, Track::FindParameters{}.setArtist(artistId), [&](const Track::pointer& track)
|
Track::find(session, params, [&](const Track::pointer& track)
|
||||||
{
|
{
|
||||||
parentPaths.insert(track->getPath().parent_path());
|
parentPaths.insert(track->getPath().parent_path());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parentPaths.size() == 1)
|
if (parentPaths.size() == 1)
|
||||||
|
{
|
||||||
artistImage = getFromDirectory(parentPaths.begin()->parent_path(), width, _artistFileNames, false);
|
artistImage = getFromDirectory(parentPaths.begin()->parent_path(), width, _artistFileNames, false);
|
||||||
|
}
|
||||||
else if (parentPaths.size() > 1)
|
else if (parentPaths.size() > 1)
|
||||||
{
|
{
|
||||||
const std::filesystem::path longestCommonPath{ PathUtils::getLongestCommonPath(std::cbegin(parentPaths), std::cend(parentPaths)) };
|
const std::filesystem::path longestCommonPath{ PathUtils::getLongestCommonPath(std::cbegin(parentPaths), std::cend(parentPaths)) };
|
||||||
|
|||||||
@@ -224,7 +224,11 @@ namespace Scanner
|
|||||||
|
|
||||||
void ScanStepScanFiles::process(ScanContext& context)
|
void ScanStepScanFiles::process(ScanContext& context)
|
||||||
{
|
{
|
||||||
_metadataParser->setUserExtraTags(_extraTagsToParse);
|
{
|
||||||
|
std::vector<std::string> tagsToParse{ _extraTagsToParse };
|
||||||
|
tagsToParse.insert(std::end(tagsToParse), std::cbegin(_settings.extraTags), std::cend(_settings.extraTags));
|
||||||
|
_metadataParser->setUserExtraTags(tagsToParse);
|
||||||
|
}
|
||||||
|
|
||||||
context.currentStepStats.totalElems = context.stats.filesScanned;
|
context.currentStepStats.totalElems = context.stats.filesScanned;
|
||||||
|
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ TEST(Path, getLongestCommonPathIterator)
|
|||||||
{{"/foo", "/bar"}, "/"},
|
{{"/foo", "/bar"}, "/"},
|
||||||
{{"/foo/bar/file1.txt", "/foo/bar/file2.txt"}, "/foo/bar"},
|
{{"/foo/bar/file1.txt", "/foo/bar/file2.txt"}, "/foo/bar"},
|
||||||
{{"/foo", "/foo/"}, "/foo"},
|
{{"/foo", "/foo/"}, "/foo"},
|
||||||
|
{{"/foo", "/foo"}, "/foo"},
|
||||||
{{"/foo/", "/foo/"}, "/foo/"},
|
{{"/foo/", "/foo/"}, "/foo/"},
|
||||||
{{"/foo/", "/foo/", "/bar"}, "/"},
|
{{"/foo/", "/foo/", "/bar"}, "/"},
|
||||||
{{"/foo/", "/foo/", "/foo/bar"}, "/foo"},
|
{{"/foo/", "/foo/", "/foo/bar"}, "/foo"},
|
||||||
|
|||||||
Reference in New Issue
Block a user