Added disc subtitles support. Fixes #56

This commit is contained in:
emeric
2020-05-11 18:38:28 +02:00
parent 633395cc60
commit b0c6aa746c
9 changed files with 49 additions and 15 deletions
+8 -1
View File
@@ -40,7 +40,7 @@
namespace Database {
#define LMS_DATABASE_VERSION 22
#define LMS_DATABASE_VERSION 23
using Version = std::size_t;
@@ -254,6 +254,13 @@ CREATE TABLE "user_backup" (
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
ScanSettings::get(*this).modify()->incScanVersion();
}
else if (version == 22)
{
_session.execute("ALTER TABLE track ADD disc_subtitle TEXT NOT NULL DEFAULT ''");
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
ScanSettings::get(*this).modify()->incScanVersion();
}
else
{
LMS_LOG(DB, ERROR) << "Database version " << version << " cannot be handled using migration";
@@ -91,6 +91,7 @@ class Track : public Wt::Dbo::Dbo<Track>
void setDiscNumber(int num) { _discNumber = num; }
void setTotalTrack(std::optional<int> totalTrack) { totalTrack ? _totalTrack = *totalTrack : 0; }
void setTotalDisc(std::optional<int> totalDisc) { totalDisc ? _totalDisc = *totalDisc : 0; }
void setDiscSubtitle(const std::string& name) { _discSubtitle = name; }
void setName(const std::string& name) { _name = std::string(name, 0, _maxNameLength); }
void setDuration(std::chrono::milliseconds duration) { _duration = duration; }
void setLastWriteTime(Wt::WDateTime time) { _fileLastWrite = time; }
@@ -113,6 +114,7 @@ class Track : public Wt::Dbo::Dbo<Track>
std::optional<std::size_t> getTrackNumber() const;
std::optional<std::size_t> getTotalTrack() const;
std::optional<std::size_t> getDiscNumber() const;
const std::string& getDiscSubtitle() const { return _discSubtitle; }
std::optional<std::size_t> getTotalDisc() const;
std::string getName() const { return _name; }
std::filesystem::path getPath() const { return _filePath; }
@@ -145,6 +147,7 @@ class Track : public Wt::Dbo::Dbo<Track>
Wt::Dbo::field(a, _scanVersion, "scan_version");
Wt::Dbo::field(a, _trackNumber, "track_number");
Wt::Dbo::field(a, _discNumber, "disc_number");
Wt::Dbo::field(a, _discSubtitle, "disc_subtitle");
Wt::Dbo::field(a, _totalTrack, "total_track");
Wt::Dbo::field(a, _totalDisc, "total_disc");
Wt::Dbo::field(a, _name, "name");
@@ -177,6 +180,7 @@ class Track : public Wt::Dbo::Dbo<Track>
int _scanVersion {};
int _trackNumber {};
int _discNumber {};
std::string _discSubtitle;
int _totalTrack {};
int _totalDisc {};
std::string _name;
@@ -211,6 +211,12 @@ AvFormatParser::parse(const std::filesystem::path& p, bool debug)
{
track.musicBrainzTrackID = UUID::fromString(value);
}
else if (tag == "TSST"
|| tag == "DISCSUBTITLE"
|| tag == "SETSUBTITLE")
{
track.discSubtitle = value;
}
else if (_clusterTypeNames.find(tag) != _clusterTypeNames.end())
{
std::vector<std::string> clusterNames {StringUtils::splitString(value, "/,;")};
+7 -1
View File
@@ -270,6 +270,8 @@ TagLibParser::processTag(Track& track, const std::string& tag, const TagLib::Str
track.albumReplayGain = StringUtils::readAs<float>(value);
else if (tag == "REPLAYGAIN_TRACK_GAIN")
track.trackReplayGain = StringUtils::readAs<float>(value);
else if (tag == "DISCSUBTITLE" || tag == "SETSUBTITLE")
track.discSubtitle = value;
else if (_clusterTypeNames.find(tag) != _clusterTypeNames.end())
{
std::set<std::string> clusterNames;
@@ -372,8 +374,12 @@ TagLibParser::parse(const std::filesystem::path& p, bool debug)
{
if (mp3File->ID3v2Tag())
{
if (!mp3File->ID3v2Tag()->frameListMap()["APIC"].isEmpty())
const auto& frameListMap {mp3File->ID3v2Tag()->frameListMap()};
if (!frameListMap["APIC"].isEmpty())
track.hasCover = true;
if (!frameListMap["TSST"].isEmpty())
properties.insert("DISCSUBTITLE", frameListMap["TSST"].front()->toString());
}
getAPETags(mp3File->APETag());
+10 -9
View File
@@ -58,25 +58,26 @@ namespace MetaData
{
std::vector<Artist> artists;
std::vector<Artist> albumArtists;
std::string title;
std::string title;
std::optional<UUID> musicBrainzTrackID;
std::optional<UUID> musicBrainzRecordID;
std::optional<Album> album;
Clusters clusters;
std::chrono::milliseconds duration {};
std::optional<Album> album;
Clusters clusters;
std::chrono::milliseconds duration;
std::optional<std::size_t> trackNumber;
std::optional<std::size_t> totalTrack;
std::optional<std::size_t> discNumber;
std::optional<std::size_t> totalDisc;
std::optional<int> year;
std::optional<int> originalYear;
bool hasCover {false};
bool hasCover {};
std::vector<AudioStream> audioStreams;
std::optional<UUID> acoustID;
std::string copyright;
std::string copyrightURL;
std::optional<float> trackReplayGain;
std::optional<float> albumReplayGain;
std::string copyright;
std::string copyrightURL;
std::optional<float> trackReplayGain;
std::optional<float> albumReplayGain;
std::string discSubtitle;
};
class IParser
+2
View File
@@ -738,6 +738,8 @@ MediaScanner::scanAudioFile(const std::filesystem::path& file, bool forceScan, S
track.modify()->setDiscNumber(trackInfo->discNumber ? *trackInfo->discNumber : 0);
track.modify()->setTotalTrack(trackInfo->totalTrack);
track.modify()->setTotalDisc(trackInfo->totalDisc);
if (!trackInfo->discSubtitle.empty())
track.modify()->setDiscSubtitle(trackInfo->discSubtitle);
track.modify()->setYear(trackInfo->year ? *trackInfo->year : 0);
track.modify()->setOriginalYear(trackInfo->originalYear ? *trackInfo->originalYear : 0);
+7 -3
View File
@@ -169,7 +169,7 @@ Release::refreshView()
// Expect to be call in asc order
std::map<std::size_t, Wt::WContainerWidget*> trackContainers;
auto getOrAddDiscContainer = [&](std::size_t discNumber) -> Wt::WContainerWidget*
auto getOrAddDiscContainer = [&](std::size_t discNumber, const std::string& discSubtitle) -> Wt::WContainerWidget*
{
{
auto it = trackContainers.find(discNumber);
@@ -178,9 +178,13 @@ Release::refreshView()
}
Wt::WTemplate* disc {rootContainer->addNew<Wt::WTemplate>(Wt::WString::tr("Lms.Explore.Release.template.disc-entry"))};
disc->bindNew<Wt::WText>("disc-title", Wt::WString::tr("Lms.Explore.Release.disc").arg(discNumber));
disc->addFunction("tr", &Wt::WTemplate::Functions::tr);
if (discSubtitle.empty())
disc->bindNew<Wt::WText>("disc-title", Wt::WString::tr("Lms.Explore.Release.disc").arg(discNumber));
else
disc->bindString("disc-title", Wt::WString::fromUTF8(discSubtitle), Wt::TextFormat::Plain);
Wt::WContainerWidget* tracksContainer {disc->bindNew<Wt::WContainerWidget>("tracks")};
trackContainers[discNumber] = tracksContainer;
@@ -198,7 +202,7 @@ Release::refreshView()
Wt::WContainerWidget* container {rootContainer};
if (isReleaseMultiDisc && discNumber)
container = getOrAddDiscContainer(*discNumber);
container = getOrAddDiscContainer(*discNumber, track->getDiscSubtitle());
Wt::WTemplate* entry {container->addNew<Wt::WTemplate>(Wt::WString::tr("Lms.Explore.Release.template.entry"))};
+3
View File
@@ -110,6 +110,9 @@ void parse(MetaData::IParser& parser, const std::filesystem::path& file)
if (track->discNumber)
std::cout << "Disc: " << *track->discNumber << std::endl;
if (!track->discSubtitle.empty())
std::cout << "Disc Subtitle: " << track->discSubtitle << std::endl;
if (track->totalDisc)
std::cout << "TotalDisc: " << *track->totalDisc << std::endl;