Store audio properties in database also for podcasts

This commit is contained in:
emeric
2025-11-29 15:37:04 +01:00
parent c70935a5a2
commit c3cd30f248
10 changed files with 202 additions and 24 deletions
+14 -1
View File
@@ -24,6 +24,7 @@
#include "core/Exception.hpp"
#include "core/ILogger.hpp"
#include "core/ITraceLogger.hpp"
#include "database/Session.hpp"
#include "database/objects/ScanSettings.hpp"
@@ -34,7 +35,7 @@ namespace lms::db
{
namespace
{
static constexpr Version LMS_DATABASE_VERSION{ 101 };
static constexpr Version LMS_DATABASE_VERSION{ 102 };
}
VersionInfo::VersionInfo()
@@ -1669,6 +1670,17 @@ FROM track)");
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET audio_scan_version = audio_scan_version + 1");
}
void migrateFromV101(Session& session)
{
// Add audio properties for podcast episodes
utils::executeCommand(*session.getDboSession(), "ALTER TABLE podcast_episode ADD container INTEGER NOT NULL DEFAULT(0)"); // 0 means unknown
utils::executeCommand(*session.getDboSession(), "ALTER TABLE podcast_episode ADD codec INTEGER NOT NULL DEFAULT(0)"); // 0 means unknown
utils::executeCommand(*session.getDboSession(), "ALTER TABLE podcast_episode ADD bitrate INTEGER NOT NULL DEFAULT(0)");
utils::executeCommand(*session.getDboSession(), "ALTER TABLE podcast_episode ADD channel_count INTEGER NOT NULL DEFAULT(0)");
utils::executeCommand(*session.getDboSession(), "ALTER TABLE podcast_episode ADD sample_rate INTEGER NOT NULL DEFAULT(0)");
utils::executeCommand(*session.getDboSession(), "ALTER TABLE podcast_episode ADD bits_per_sample INTEGER");
}
bool doDbMigration(Session& session)
{
constexpr std::string_view outdatedMsg{ "Outdated database, please rebuild it (delete the .db file and restart)" };
@@ -1746,6 +1758,7 @@ FROM track)");
{ 98, migrateFromV98 },
{ 99, migrateFromV99 },
{ 100, migrateFromV100 },
{ 101, migrateFromV101 },
};
bool migrationPerformed{};
@@ -91,6 +91,15 @@ namespace lms::db
ManualDownloadState getManualDownloadState() const { return _manualDownloadState; }
const std::filesystem::path& getAudioRelativeFilePath() const { return _audioRelativeFilePath; }
// Audio properties
std::chrono::milliseconds getDuration() const { return _duration; }
ContainerType getContainer() const { return _container; }
CodecType getCodec() const { return _codec; }
std::size_t getBitrate() const { return _bitrate; }
std::size_t getChannelCount() const { return _channelCount; }
std::size_t getSampleRate() const { return _sampleRate; }
std::optional<std::size_t> getBitsPerSample() const { return _bitsPerSample; }
std::string_view getTitle() const { return _title; }
std::string_view getLink() const { return _link; }
std::string_view getDescription() const { return _description; }
@@ -104,7 +113,6 @@ namespace lms::db
std::string_view getSubtitle() const { return _subtitle; }
std::string_view getSummary() const { return _summary; }
bool isExplicit() const { return _explicit; }
std::chrono::duration<int, std::milli> getDuration() const { return _duration; }
ObjectPtr<Podcast> getPodcast() const { return _podcast; }
PodcastId getPodcastId() const { return _podcast.id(); }
ObjectPtr<Artwork> getArtwork() const;
@@ -114,6 +122,15 @@ namespace lms::db
void setManualDownloadState(ManualDownloadState state) { _manualDownloadState = state; }
void setAudioRelativeFilePath(const std::filesystem::path& relativeFilePath) { _audioRelativeFilePath = relativeFilePath; }
// Audio properties
void setDuration(std::chrono::milliseconds duration) { _duration = duration; }
void setContainer(ContainerType container) { _container = container; }
void setCodec(CodecType codec) { _codec = codec; }
void setBitrate(std::size_t bitrate) { _bitrate = bitrate; }
void setChannelCount(std::size_t channelCount) { _channelCount = channelCount; }
void setSampleRate(std::size_t sampleRate) { _sampleRate = sampleRate; }
void setBitsPerSample(std::optional<std::size_t> bitsPerSample) { _bitsPerSample = bitsPerSample; }
void setTitle(std::string_view title) { _title = title; }
void setLink(std::string_view link) { _link = link; }
void setDescription(std::string_view description) { _description = description; }
@@ -136,6 +153,14 @@ namespace lms::db
Wt::Dbo::field(a, _manualDownloadState, "manual_download_state");
Wt::Dbo::field(a, _audioRelativeFilePath, "audio_relative_file_path");
Wt::Dbo::field(a, _duration, "duration");
Wt::Dbo::field(a, _container, "container");
Wt::Dbo::field(a, _codec, "codec");
Wt::Dbo::field(a, _bitrate, "bitrate");
Wt::Dbo::field(a, _channelCount, "channel_count");
Wt::Dbo::field(a, _sampleRate, "sample_rate");
Wt::Dbo::field(a, _bitsPerSample, "bits_per_sample");
Wt::Dbo::field(a, _title, "title");
Wt::Dbo::field(a, _link, "link");
Wt::Dbo::field(a, _description, "description");
@@ -149,7 +174,6 @@ namespace lms::db
Wt::Dbo::field(a, _subtitle, "subtitle");
Wt::Dbo::field(a, _summary, "summary");
Wt::Dbo::field(a, _explicit, "explicit");
Wt::Dbo::field(a, _duration, "duration");
Wt::Dbo::belongsTo(a, _artwork, "artwork", Wt::Dbo::OnDeleteSetNull);
Wt::Dbo::belongsTo(a, _podcast, "podcast", Wt::Dbo::OnDeleteCascade);
@@ -163,6 +187,15 @@ namespace lms::db
ManualDownloadState _manualDownloadState{ ManualDownloadState::None };
std::filesystem::path _audioRelativeFilePath; // relative to cache dir, only set if downloaded
// Audio properties
std::chrono::duration<int, std::milli> _duration{ 0 };
ContainerType _container{ ContainerType::Unknown };
CodecType _codec{ CodecType::Unknown };
int _bitrate{}; // in bps
int _channelCount{};
int _sampleRate{};
std::optional<int> _bitsPerSample;
std::string _url;
std::string _title;
std::string _link;
@@ -179,7 +212,6 @@ namespace lms::db
std::string _subtitle;
std::string _summary;
bool _explicit{};
std::chrono::duration<int, std::milli> _duration{ 0 };
Wt::Dbo::ptr<Artwork> _artwork;
Wt::Dbo::ptr<Podcast> _podcast;
+1
View File
@@ -20,6 +20,7 @@
#include "Common.hpp"
#include "core/String.hpp"
#include "database/objects/Artist.hpp"
#include "database/objects/ArtistInfo.hpp"
#include "database/objects/AuthToken.hpp"