Added a way to filter by codec
This commit is contained in:
@@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
#include "SqlQuery.hpp"
|
#include "SqlQuery.hpp"
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
|
#include "objects/detail/Types.hpp"
|
||||||
#include "traits/IdTypeTraits.hpp"
|
#include "traits/IdTypeTraits.hpp"
|
||||||
#include "traits/StringViewTraits.hpp"
|
#include "traits/StringViewTraits.hpp"
|
||||||
|
|
||||||
@@ -56,6 +57,7 @@ namespace lms::db
|
|||||||
|| params.track.isValid()
|
|| params.track.isValid()
|
||||||
|| params.release.isValid()
|
|| params.release.isValid()
|
||||||
|| params.filters.clusters.size() == 1
|
|| params.filters.clusters.size() == 1
|
||||||
|
|| params.filters.codec.has_value()
|
||||||
|| params.filters.mediaLibrary.isValid()
|
|| params.filters.mediaLibrary.isValid()
|
||||||
|| params.filters.label.isValid()
|
|| params.filters.label.isValid()
|
||||||
|| params.filters.releaseType.isValid())
|
|| params.filters.releaseType.isValid())
|
||||||
@@ -67,6 +69,7 @@ namespace lms::db
|
|||||||
|| params.sortMethod == ArtistSortMethod::AddedDesc
|
|| params.sortMethod == ArtistSortMethod::AddedDesc
|
||||||
|| params.writtenAfter.isValid()
|
|| params.writtenAfter.isValid()
|
||||||
|| params.release.isValid()
|
|| params.release.isValid()
|
||||||
|
|| params.filters.codec.has_value()
|
||||||
|| params.filters.mediaLibrary.isValid()
|
|| params.filters.mediaLibrary.isValid()
|
||||||
|| params.filters.label.isValid()
|
|| params.filters.label.isValid()
|
||||||
|| params.filters.releaseType.isValid())
|
|| params.filters.releaseType.isValid())
|
||||||
@@ -79,6 +82,9 @@ namespace lms::db
|
|||||||
if (params.release.isValid())
|
if (params.release.isValid())
|
||||||
query.where("t.release_id = ?").bind(params.release);
|
query.where("t.release_id = ?").bind(params.release);
|
||||||
|
|
||||||
|
if (params.filters.codec.has_value())
|
||||||
|
query.where("t.codec = ?").bind(detail::getDbCodecType(*params.filters.codec));
|
||||||
|
|
||||||
if (params.filters.mediaLibrary.isValid())
|
if (params.filters.mediaLibrary.isValid())
|
||||||
query.where("t.media_library_id = ?").bind(params.filters.mediaLibrary);
|
query.where("t.media_library_id = ?").bind(params.filters.mediaLibrary);
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#include "SqlQuery.hpp"
|
#include "SqlQuery.hpp"
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
|
#include "objects/detail/Types.hpp"
|
||||||
#include "traits/IdTypeTraits.hpp"
|
#include "traits/IdTypeTraits.hpp"
|
||||||
|
|
||||||
DBO_INSTANTIATE_TEMPLATES(lms::db::Listen)
|
DBO_INSTANTIATE_TEMPLATES(lms::db::Listen)
|
||||||
@@ -49,11 +50,15 @@ namespace lms::db
|
|||||||
assert(!params.artist.isValid()); // poor check
|
assert(!params.artist.isValid()); // poor check
|
||||||
|
|
||||||
if (params.filters.mediaLibrary.isValid()
|
if (params.filters.mediaLibrary.isValid()
|
||||||
|
|| params.filters.codec.has_value()
|
||||||
|| params.filters.label.isValid()
|
|| params.filters.label.isValid()
|
||||||
|| params.filters.releaseType.isValid())
|
|| params.filters.releaseType.isValid())
|
||||||
{
|
{
|
||||||
query.join("track t ON t.id = t_a_l.track_id");
|
query.join("track t ON t.id = t_a_l.track_id");
|
||||||
|
|
||||||
|
if (params.filters.codec.has_value())
|
||||||
|
query.where("t.codec = ?").bind(detail::getDbCodecType(*params.filters.codec));
|
||||||
|
|
||||||
if (params.filters.mediaLibrary.isValid())
|
if (params.filters.mediaLibrary.isValid())
|
||||||
query.where("t.media_library_id = ?").bind(params.filters.mediaLibrary);
|
query.where("t.media_library_id = ?").bind(params.filters.mediaLibrary);
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ namespace lms::db
|
|||||||
|| params.artist.isValid()
|
|| params.artist.isValid()
|
||||||
|| params.filters.clusters.size() == 1
|
|| params.filters.clusters.size() == 1
|
||||||
|| params.filters.mediaLibrary.isValid()
|
|| params.filters.mediaLibrary.isValid()
|
||||||
|
|| params.filters.codec.has_value()
|
||||||
|| params.directory.isValid()
|
|| params.directory.isValid()
|
||||||
|| params.parentDirectory.isValid())
|
|| params.parentDirectory.isValid())
|
||||||
{
|
{
|
||||||
@@ -218,6 +219,9 @@ namespace lms::db
|
|||||||
query.where(oss.str());
|
query.where(oss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (params.filters.codec.has_value())
|
||||||
|
query.where("t.codec = ?").bind(detail::getDbCodecType(params.filters.codec.value()));
|
||||||
|
|
||||||
if (params.releaseGroupMBID)
|
if (params.releaseGroupMBID)
|
||||||
query.where("group_mbid = ?").bind(params.releaseGroupMBID->getAsString());
|
query.where("group_mbid = ?").bind(params.releaseGroupMBID->getAsString());
|
||||||
|
|
||||||
|
|||||||
@@ -197,6 +197,9 @@ namespace lms::db
|
|||||||
query.where("t_e_i_l.track_embedded_image_id = ?").bind(params.embeddedImageId);
|
query.where("t_e_i_l.track_embedded_image_id = ?").bind(params.embeddedImageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (params.filters.codec.has_value())
|
||||||
|
query.where("t.codec = ?").bind(detail::getDbCodecType(*params.filters.codec));
|
||||||
|
|
||||||
switch (params.sortMethod)
|
switch (params.sortMethod)
|
||||||
{
|
{
|
||||||
case TrackSortMethod::None:
|
case TrackSortMethod::None:
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include "SqlQuery.hpp"
|
#include "SqlQuery.hpp"
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
|
#include "objects/detail/Types.hpp"
|
||||||
#include "traits/IdTypeTraits.hpp"
|
#include "traits/IdTypeTraits.hpp"
|
||||||
#include "traits/StringViewTraits.hpp"
|
#include "traits/StringViewTraits.hpp"
|
||||||
|
|
||||||
@@ -49,6 +50,7 @@ namespace lms::db
|
|||||||
auto query{ session.getDboSession()->query<ResultType>("SELECT " + std::string{ itemToSelect } + " FROM tracklist t_l") };
|
auto query{ session.getDboSession()->query<ResultType>("SELECT " + std::string{ itemToSelect } + " FROM tracklist t_l") };
|
||||||
|
|
||||||
if (!params.filters.clusters.empty()
|
if (!params.filters.clusters.empty()
|
||||||
|
|| params.filters.codec.has_value()
|
||||||
|| params.filters.mediaLibrary.isValid()
|
|| params.filters.mediaLibrary.isValid()
|
||||||
|| params.filters.label.isValid()
|
|| params.filters.label.isValid()
|
||||||
|| params.filters.releaseType.isValid())
|
|| params.filters.releaseType.isValid())
|
||||||
@@ -61,11 +63,15 @@ namespace lms::db
|
|||||||
query.where("t_l.name LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'").bind("%" + utils::escapeForLikeKeyword(keyword) + "%");
|
query.where("t_l.name LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'").bind("%" + utils::escapeForLikeKeyword(keyword) + "%");
|
||||||
|
|
||||||
if (params.filters.mediaLibrary.isValid()
|
if (params.filters.mediaLibrary.isValid()
|
||||||
|
|| params.filters.codec.has_value()
|
||||||
|| params.filters.label.isValid()
|
|| params.filters.label.isValid()
|
||||||
|| params.filters.releaseType.isValid())
|
|| params.filters.releaseType.isValid())
|
||||||
{
|
{
|
||||||
query.join("track t ON t.id = t_l_e.track_id");
|
query.join("track t ON t.id = t_l_e.track_id");
|
||||||
|
|
||||||
|
if (params.filters.codec.has_value())
|
||||||
|
query.where("t.codec = ?").bind(detail::getDbCodecType(*params.filters.codec));
|
||||||
|
|
||||||
if (params.filters.mediaLibrary.isValid())
|
if (params.filters.mediaLibrary.isValid())
|
||||||
query.where("t.media_library_id = ?").bind(params.filters.mediaLibrary);
|
query.where("t.media_library_id = ?").bind(params.filters.mediaLibrary);
|
||||||
|
|
||||||
|
|||||||
@@ -19,9 +19,12 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "core/media/CodecType.hpp"
|
||||||
|
|
||||||
#include "database/objects/ClusterId.hpp"
|
#include "database/objects/ClusterId.hpp"
|
||||||
#include "database/objects/LabelId.hpp"
|
#include "database/objects/LabelId.hpp"
|
||||||
#include "database/objects/MediaLibraryId.hpp"
|
#include "database/objects/MediaLibraryId.hpp"
|
||||||
@@ -31,10 +34,11 @@ namespace lms::db
|
|||||||
{
|
{
|
||||||
struct Filters
|
struct Filters
|
||||||
{
|
{
|
||||||
MediaLibraryId mediaLibrary; // tracks that belongs to this library
|
MediaLibraryId mediaLibrary; // tracks that belongs to this library
|
||||||
std::vector<ClusterId> clusters; // tracks that belong to all these clusters
|
std::vector<ClusterId> clusters; // tracks that belong to *all* these clusters
|
||||||
LabelId label; // tracks which release has this label
|
LabelId label; // tracks which release has this label
|
||||||
ReleaseTypeId releaseType; // tracks which release has this type
|
ReleaseTypeId releaseType; // tracks which release has this type
|
||||||
|
std::optional<core::media::CodecType> codec; // tracks that match this codec
|
||||||
|
|
||||||
Filters& setClusters(std::span<const ClusterId> _clusters)
|
Filters& setClusters(std::span<const ClusterId> _clusters)
|
||||||
{
|
{
|
||||||
@@ -56,5 +60,10 @@ namespace lms::db
|
|||||||
releaseType = _releaseType;
|
releaseType = _releaseType;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
Filters& setCodec(std::optional<core::media::CodecType> _codec)
|
||||||
|
{
|
||||||
|
codec = _codec;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // namespace lms::db
|
} // namespace lms::db
|
||||||
@@ -350,7 +350,7 @@ namespace lms::db
|
|||||||
Wt::Dbo::field(a, _copyright, "copyright");
|
Wt::Dbo::field(a, _copyright, "copyright");
|
||||||
Wt::Dbo::field(a, _copyrightURL, "copyright_url");
|
Wt::Dbo::field(a, _copyrightURL, "copyright_url");
|
||||||
Wt::Dbo::field(a, _artistDisplayName, "artist_display_name");
|
Wt::Dbo::field(a, _artistDisplayName, "artist_display_name");
|
||||||
Wt::Dbo::field(a, _comment, "comment"); // TODO: move in a dedicated table
|
Wt::Dbo::field(a, _comment, "comment"); // TODO: move in a dedicated table?
|
||||||
Wt::Dbo::field(a, _advisory, "advisory");
|
Wt::Dbo::field(a, _advisory, "advisory");
|
||||||
|
|
||||||
Wt::Dbo::belongsTo(a, _medium, "medium", Wt::Dbo::OnDeleteCascade);
|
Wt::Dbo::belongsTo(a, _medium, "medium", Wt::Dbo::OnDeleteCascade);
|
||||||
|
|||||||
@@ -518,6 +518,34 @@ namespace lms::db::tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(DatabaseFixture, Artist_findByCodec)
|
||||||
|
{
|
||||||
|
ScopedArtist artist1{ session, "A" };
|
||||||
|
ScopedArtist artist2{ session, "B" };
|
||||||
|
ScopedTrack track1{ session };
|
||||||
|
ScopedTrack track2{ session };
|
||||||
|
|
||||||
|
{
|
||||||
|
auto transaction{ session.createWriteTransaction() };
|
||||||
|
TrackArtistLink::create(session, track1.get(), artist1.get(), TrackArtistLinkType::Artist);
|
||||||
|
TrackArtistLink::create(session, track2.get(), artist2.get(), TrackArtistLinkType::Artist);
|
||||||
|
|
||||||
|
track1.get().modify()->setCodec(core::media::CodecType::MP3);
|
||||||
|
track2.get().modify()->setCodec(core::media::CodecType::FLAC);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto transaction{ session.createReadTransaction() };
|
||||||
|
|
||||||
|
Artist::FindParameters params;
|
||||||
|
params.setFilters(Filters{}.setCodec(core::media::CodecType::FLAC));
|
||||||
|
|
||||||
|
const auto artists{ Artist::find(session, params) };
|
||||||
|
ASSERT_EQ(artists.results.size(), 1);
|
||||||
|
EXPECT_EQ(artists.results.front()->getId(), artist2.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(DatabaseFixture, Artist_findByName)
|
TEST_F(DatabaseFixture, Artist_findByName)
|
||||||
{
|
{
|
||||||
ScopedArtist artist{ session, "AAA" };
|
ScopedArtist artist{ session, "AAA" };
|
||||||
|
|||||||
@@ -1248,6 +1248,40 @@ namespace lms::db::tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(DatabaseFixture, Release_findBycodec)
|
||||||
|
{
|
||||||
|
ScopedRelease release1{ session, "MyRelease1" };
|
||||||
|
ScopedTrack track1{ session };
|
||||||
|
|
||||||
|
ScopedRelease release2{ session, "MyRelease2" };
|
||||||
|
ScopedTrack track2{ session };
|
||||||
|
|
||||||
|
{
|
||||||
|
auto transaction{ session.createReadTransaction() };
|
||||||
|
ASSERT_EQ(release1->getCodecs().size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto transaction{ session.createWriteTransaction() };
|
||||||
|
track1.get().modify()->setCodec(core::media::CodecType::FLAC);
|
||||||
|
track1.get().modify()->setRelease(release1.get());
|
||||||
|
|
||||||
|
track2.get().modify()->setCodec(core::media::CodecType::MP3);
|
||||||
|
track2.get().modify()->setRelease(release2.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto transaction{ session.createReadTransaction() };
|
||||||
|
|
||||||
|
Release::FindParameters params;
|
||||||
|
params.setFilters(Filters{}.setCodec(core::media::CodecType::MP3));
|
||||||
|
|
||||||
|
auto releases{ Release::findIds(session, params) };
|
||||||
|
ASSERT_EQ(releases.results.size(), 1);
|
||||||
|
EXPECT_EQ(releases.results.front(), release2.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(DatabaseFixture, Release_trackCount)
|
TEST_F(DatabaseFixture, Release_trackCount)
|
||||||
{
|
{
|
||||||
ScopedRelease release1{ session, "MyRelease1" };
|
ScopedRelease release1{ session, "MyRelease1" };
|
||||||
|
|||||||
@@ -238,27 +238,26 @@ namespace lms::db::tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DatabaseFixture, Track_findAbsoluteFilePath)
|
TEST_F(DatabaseFixture, Track_findByCodec)
|
||||||
{
|
{
|
||||||
ScopedTrack track{ session };
|
ScopedTrack track1{ session };
|
||||||
const std::filesystem::path absoluteFilePath{ "/path/to/track.mp3" };
|
ScopedTrack track2{ session };
|
||||||
|
|
||||||
{
|
{
|
||||||
auto transaction{ session.createWriteTransaction() };
|
auto transaction{ session.createWriteTransaction() };
|
||||||
track.get().modify()->setAbsoluteFilePath(absoluteFilePath);
|
track1.get().modify()->setCodec(core::media::CodecType::MP3);
|
||||||
|
track2.get().modify()->setCodec(core::media::CodecType::FLAC);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto transaction{ session.createReadTransaction() };
|
auto transaction{ session.createReadTransaction() };
|
||||||
|
|
||||||
TrackId lastRetrievedTrackId;
|
Track::FindParameters params;
|
||||||
std::vector<std::pair<TrackId, std::filesystem::path>> visitedTracks;
|
params.setFilters(Filters{}.setCodec(core::media::CodecType::FLAC));
|
||||||
Track::findAbsoluteFilePath(session, lastRetrievedTrackId, 10, [&](TrackId trackId, const std::filesystem::path& filePath) {
|
|
||||||
visitedTracks.emplace_back(trackId, filePath);
|
const auto tracks{ Track::find(session, params) };
|
||||||
});
|
ASSERT_EQ(tracks.results.size(), 1);
|
||||||
ASSERT_EQ(visitedTracks.size(), 1);
|
EXPECT_EQ(tracks.results[0]->getId(), track2.getId());
|
||||||
EXPECT_EQ(visitedTracks[0].first, track.getId());
|
|
||||||
EXPECT_EQ(visitedTracks[0].second, absoluteFilePath);
|
|
||||||
EXPECT_EQ(lastRetrievedTrackId, track.getId());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user