Better handle badly tagged multi-discs releases
This commit is contained in:
@@ -178,7 +178,7 @@ AudioFile::getBestStream() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AudioFile::hasAttachedPictures(void) const
|
AudioFile::hasAttachedPictures() const
|
||||||
{
|
{
|
||||||
for (std::size_t i = 0; i < _context->nb_streams; ++i)
|
for (std::size_t i = 0; i < _context->nb_streams; ++i)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ Release::find(Session& session, const FindParameters& params)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::size_t>
|
std::optional<std::size_t>
|
||||||
Release::getTotalTrack(void) const
|
Release::getTotalTrack() const
|
||||||
{
|
{
|
||||||
assert(session());
|
assert(session());
|
||||||
|
|
||||||
@@ -276,7 +276,7 @@ Release::getTotalTrack(void) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::size_t>
|
std::optional<std::size_t>
|
||||||
Release::getTotalDisc(void) const
|
Release::getTotalDisc() const
|
||||||
{
|
{
|
||||||
assert(session());
|
assert(session());
|
||||||
|
|
||||||
@@ -287,6 +287,18 @@ Release::getTotalDisc(void) const
|
|||||||
return (res > 0) ? std::make_optional<std::size_t>(res) : std::nullopt;
|
return (res > 0) ? std::make_optional<std::size_t>(res) : std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::size_t
|
||||||
|
Release::getDiscCount() const
|
||||||
|
{
|
||||||
|
assert(session());
|
||||||
|
int res {session()->query<int>("SELECT COUNT(DISTINCT disc_number) FROM track t")
|
||||||
|
.join("release r ON r.id = t.release_id")
|
||||||
|
.where("r.id = ?")
|
||||||
|
.bind(getId())};
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<int>
|
std::optional<int>
|
||||||
Release::getReleaseYear(bool original) const
|
Release::getReleaseYear(bool original) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ WhereClause::Or(const WhereClause& otherClause)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
WhereClause::get(void) const
|
WhereClause::get() const
|
||||||
{
|
{
|
||||||
if (!_clause.empty())
|
if (!_clause.empty())
|
||||||
return "WHERE " + _clause;
|
return "WHERE " + _clause;
|
||||||
@@ -176,7 +176,7 @@ FromClause::get() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
SqlQuery::get(void) const
|
SqlQuery::get() const
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class WhereClause
|
|||||||
WhereClause& bind(const std::string& arg);
|
WhereClause& bind(const std::string& arg);
|
||||||
|
|
||||||
std::string get() const;
|
std::string get() const;
|
||||||
const std::list<std::string>& getBindArgs(void) const {return _bindArgs;}
|
const std::list<std::string>& getBindArgs() const {return _bindArgs;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _clause; // WHERE clause
|
std::string _clause; // WHERE clause
|
||||||
@@ -101,15 +101,15 @@ class FromClause
|
|||||||
class SqlQuery
|
class SqlQuery
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SelectStatement& select(void) { return _selectStatement;}
|
SelectStatement& select() { return _selectStatement;}
|
||||||
SelectStatement& select(const std::string& statement) { _selectStatement = SelectStatement(statement); return _selectStatement; }
|
SelectStatement& select(const std::string& statement) { _selectStatement = SelectStatement(statement); return _selectStatement; }
|
||||||
FromClause& from(void) { return _fromClause; }
|
FromClause& from() { return _fromClause; }
|
||||||
FromClause& from(const std::string& clause) { _whereClause = WhereClause(clause); return _fromClause; }
|
FromClause& from(const std::string& clause) { _whereClause = WhereClause(clause); return _fromClause; }
|
||||||
InnerJoinClause& innerJoin(void) { return _innerJoinClause; }
|
InnerJoinClause& innerJoin() { return _innerJoinClause; }
|
||||||
WhereClause& where(void) { return _whereClause; }
|
WhereClause& where() { return _whereClause; }
|
||||||
const WhereClause& where(void) const { return _whereClause; }
|
const WhereClause& where() const { return _whereClause; }
|
||||||
GroupByStatement& groupBy(void) { return _groupByStatement; }
|
GroupByStatement& groupBy() { return _groupByStatement; }
|
||||||
const GroupByStatement& groupBy(void) const { return _groupByStatement; }
|
const GroupByStatement& groupBy() const { return _groupByStatement; }
|
||||||
|
|
||||||
std::string get() const;
|
std::string get() const;
|
||||||
|
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ class Release : public Object<Release, ReleaseId>
|
|||||||
std::optional<UUID> getMBID() const { return UUID::fromString(_MBID); }
|
std::optional<UUID> getMBID() const { return UUID::fromString(_MBID); }
|
||||||
std::optional<std::size_t> getTotalTrack() const;
|
std::optional<std::size_t> getTotalTrack() const;
|
||||||
std::optional<std::size_t> getTotalDisc() const;
|
std::optional<std::size_t> getTotalDisc() const;
|
||||||
|
std::size_t getDiscCount() const; // may not be total disc (if incomplete for example)
|
||||||
std::chrono::milliseconds getDuration() const;
|
std::chrono::milliseconds getDuration() const;
|
||||||
Wt::WDateTime getLastWritten() const;
|
Wt::WDateTime getLastWritten() const;
|
||||||
|
|
||||||
|
|||||||
@@ -207,5 +207,3 @@ TEST_F(DatabaseFixture, Common_subRange)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -464,3 +464,47 @@ TEST_F(DatabaseFixture, Release_artist)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(DatabaseFixture, Release_getDiscCount)
|
||||||
|
{
|
||||||
|
ScopedRelease release {session, "MyRelease"};
|
||||||
|
ScopedTrack track {session, "MyTrack"};
|
||||||
|
ScopedTrack track2 {session, "MyTrack2"};
|
||||||
|
|
||||||
|
{
|
||||||
|
auto transaction {session.createSharedTransaction()};
|
||||||
|
EXPECT_EQ(release.get()->getDiscCount(), 0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto transaction {session.createUniqueTransaction()};
|
||||||
|
track.get().modify()->setRelease(release.get());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto transaction {session.createSharedTransaction()};
|
||||||
|
EXPECT_EQ(release.get()->getDiscCount(), 1);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto transaction {session.createUniqueTransaction()};
|
||||||
|
track.get().modify()->setDiscNumber(5);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto transaction {session.createSharedTransaction()};
|
||||||
|
EXPECT_EQ(release.get()->getDiscCount(), 1);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto transaction {session.createUniqueTransaction()};
|
||||||
|
track2.get().modify()->setRelease(release.get());
|
||||||
|
track2.get().modify()->setDiscNumber(5);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto transaction {session.createSharedTransaction()};
|
||||||
|
EXPECT_EQ(release.get()->getDiscCount(), 1);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto transaction {session.createUniqueTransaction()};
|
||||||
|
track2.get().modify()->setDiscNumber(6);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto transaction {session.createSharedTransaction()};
|
||||||
|
EXPECT_EQ(release.get()->getDiscCount(), 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -197,7 +197,8 @@ Release::refreshView()
|
|||||||
|
|
||||||
const bool variousArtists {release->hasVariousArtists()};
|
const bool variousArtists {release->hasVariousArtists()};
|
||||||
const auto totalDisc {release->getTotalDisc()};
|
const auto totalDisc {release->getTotalDisc()};
|
||||||
const bool isReleaseMultiDisc {totalDisc && *totalDisc > 1};
|
const std::size_t discCount {release->getDiscCount()};
|
||||||
|
const bool isReleaseMultiDisc {(discCount > 1) || (totalDisc && *totalDisc > 1)};
|
||||||
|
|
||||||
// Expect to be called in asc order
|
// Expect to be called in asc order
|
||||||
std::map<std::size_t, Wt::WContainerWidget*> trackContainers;
|
std::map<std::size_t, Wt::WContainerWidget*> trackContainers;
|
||||||
|
|||||||
Reference in New Issue
Block a user