Commit 3391641e authored by Hugo Beauzée-Luyssen's avatar Hugo Beauzée-Luyssen

Media: Allow search results to be sorted

parent 2dfecbf9
......@@ -304,7 +304,9 @@ class IMediaLibrary
/**
* Search
*/
virtual MediaSearchAggregate searchMedia( const std::string& pattern ) const = 0;
virtual MediaSearchAggregate searchMedia( const std::string& pattern,
SortingCriteria sort = SortingCriteria::Default,
bool desc = false ) const = 0;
virtual std::vector<PlaylistPtr> searchPlaylists( const std::string& name ) const = 0;
virtual std::vector<AlbumPtr> searchAlbums( const std::string& pattern ) const = 0;
virtual std::vector<GenrePtr> searchGenre( const std::string& genre ) const = 0;
......
......@@ -709,15 +709,17 @@ bool Media::removeLabel( LabelPtr label )
}
}
std::vector<MediaPtr> Media::search( MediaLibraryPtr ml, const std::string& title )
std::vector<MediaPtr> Media::search( MediaLibraryPtr ml, const std::string& title,
SortingCriteria sort, bool desc )
{
static const std::string req = "SELECT m.* FROM " + policy::MediaTable::Name + " m "
std::string req = "SELECT m.* FROM " + policy::MediaTable::Name + " m "
" INNER JOIN " + policy::FileTable::Name + " f ON m.id_media = f.media_id"
" WHERE"
" m.id_media IN (SELECT rowid FROM " + policy::MediaTable::Name + "Fts"
" WHERE " + policy::MediaTable::Name + "Fts MATCH '*' || ? || '*')"
" AND f.is_present = 1"
" AND f.type = ?";
req += sortRequest( sort, desc );
return Media::fetchAll<IMedia>( ml, req, title, File::Type::Main );
}
......
......@@ -143,7 +143,8 @@ class Media : public IMedia, public DatabaseHelpers<Media, policy::MediaTable>
void removeFile( File& file );
static std::vector<MediaPtr> listAll(MediaLibraryPtr ml, Type type , SortingCriteria sort, bool desc);
static std::vector<MediaPtr> search( MediaLibraryPtr ml, const std::string& title );
static std::vector<MediaPtr> search( MediaLibraryPtr ml, const std::string& title,
SortingCriteria sort, bool desc );
static std::vector<MediaPtr> fetchHistory( MediaLibraryPtr ml );
static void clearHistory( MediaLibraryPtr ml );
......
......@@ -649,11 +649,12 @@ bool MediaLibrary::clearHistory()
}
}
MediaSearchAggregate MediaLibrary::searchMedia( const std::string& title ) const
MediaSearchAggregate MediaLibrary::searchMedia( const std::string& title,
SortingCriteria sort, bool desc ) const
{
if ( validateSearchPattern( title ) == false )
return {};
auto tmp = Media::search( this, title );
auto tmp = Media::search( this, title, sort, desc );
MediaSearchAggregate res;
for ( auto& m : tmp )
{
......@@ -712,7 +713,7 @@ SearchAggregate MediaLibrary::search( const std::string& pattern ) const
res.albums = searchAlbums( pattern );
res.artists = searchArtists( pattern, SortingCriteria::Default, false );
res.genres = searchGenre( pattern );
res.media = searchMedia( pattern );
res.media = searchMedia( pattern, SortingCriteria::Default, false );
res.playlists = searchPlaylists( pattern );
return res;
}
......
......@@ -115,7 +115,8 @@ class MediaLibrary : public IMediaLibrary, public IDeviceListerCb
virtual std::vector<MediaPtr> lastMediaPlayed() const override;
virtual bool clearHistory() override;
virtual MediaSearchAggregate searchMedia( const std::string& title ) const override;
virtual MediaSearchAggregate searchMedia( const std::string& title,
SortingCriteria sort, bool desc ) const override;
virtual std::vector<PlaylistPtr> searchPlaylists( const std::string& name ) const override;
virtual std::vector<AlbumPtr> searchAlbums( const std::string& pattern ) const override;
virtual std::vector<GenrePtr> searchGenre( const std::string& genre ) const override;
......
......@@ -160,33 +160,57 @@ TEST_F( Medias, Search )
{
ml->addMedia( "track " + std::to_string( i ) + ".mp3" );
}
auto media = ml->searchMedia( "tra" ).others;
auto media = ml->searchMedia( "tra", SortingCriteria::Default, false ).others;
ASSERT_EQ( 10u, media.size() );
media = ml->searchMedia( "track 1" ).others;
media = ml->searchMedia( "track 1", SortingCriteria::Default, false ).others;
ASSERT_EQ( 2u, media.size() );
media = ml->searchMedia( "grouik" ).others;
media = ml->searchMedia( "grouik", SortingCriteria::Default, false ).others;
ASSERT_EQ( 0u, media.size() );
media = ml->searchMedia( "rack" ).others;
media = ml->searchMedia( "rack", SortingCriteria::Default, false ).others;
ASSERT_EQ( 0u, media.size() );
}
TEST_F( Medias, SearchAndSort )
{
for ( auto i = 1u; i <= 3u; ++i )
{
auto m = std::static_pointer_cast<Media>(
ml->addMedia( "track " + std::to_string( i ) + ".mp3" ) );
m->setDuration( 3 - i );
m->save();
}
ml->addMedia( "this pattern doesn't match.mp3" );
auto media = ml->searchMedia( "tra", SortingCriteria::Default, false ).others;
ASSERT_EQ( 3u, media.size() );
ASSERT_EQ( media[0]->title(), "track 1.mp3" );
ASSERT_EQ( media[1]->title(), "track 2.mp3" );
ASSERT_EQ( media[2]->title(), "track 3.mp3" );
media = ml->searchMedia( "tra", SortingCriteria::Duration, false ).others;
ASSERT_EQ( 3u, media.size() );
ASSERT_EQ( media[0]->title(), "track 3.mp3" );
ASSERT_EQ( media[1]->title(), "track 2.mp3" );
ASSERT_EQ( media[2]->title(), "track 1.mp3" );
}
TEST_F( Medias, SearchAfterEdit )
{
auto m = std::static_pointer_cast<Media>( ml->addMedia( "media.mp3" ) );
auto media = ml->searchMedia( "media" ).others;
auto media = ml->searchMedia( "media", SortingCriteria::Default, false ).others;
ASSERT_EQ( 1u, media.size() );
m->setTitleBuffered( "otters are awesome" );
m->save();
media = ml->searchMedia( "media" ).others;
media = ml->searchMedia( "media", SortingCriteria::Default, false ).others;
ASSERT_EQ( 0u, media.size() );
media = ml->searchMedia( "otters" ).others;
media = ml->searchMedia( "otters", SortingCriteria::Default, false ).others;
ASSERT_EQ( 1u, media.size() );
}
......@@ -194,59 +218,59 @@ TEST_F( Medias, SearchAfterDelete )
{
auto m = std::static_pointer_cast<Media>( ml->addMedia( "media.mp3" ) );
auto media = ml->searchMedia( "media" ).others;
auto media = ml->searchMedia( "media", SortingCriteria::Default, false ).others;
ASSERT_EQ( 1u, media.size() );
auto f = m->files()[0];
m->removeFile( static_cast<File&>( *f ) );
media = ml->searchMedia( "media" ).others;
media = ml->searchMedia( "media", SortingCriteria::Default, false ).others;
ASSERT_EQ( 0u, media.size() );
}
TEST_F( Medias, SearchByLabel )
{
auto m = std::static_pointer_cast<Media>( ml->addMedia( "media.mkv" ) );
auto media = ml->searchMedia( "otter" ).others;
auto media = ml->searchMedia( "otter", SortingCriteria::Default, false ).others;
ASSERT_EQ( 0u, media.size() );
auto l = ml->createLabel( "otter" );
m->addLabel( l );
media = ml->searchMedia( "otter" ).others;
media = ml->searchMedia( "otter", SortingCriteria::Default, false ).others;
ASSERT_EQ( 1u, media.size() );
auto l2 = ml->createLabel( "pangolins" );
m->addLabel( l2 );
media = ml->searchMedia( "otter" ).others;
media = ml->searchMedia( "otter", SortingCriteria::Default, false ).others;
ASSERT_EQ( 1u, media.size() );
media = ml->searchMedia( "pangolin" ).others;
media = ml->searchMedia( "pangolin", SortingCriteria::Default, false ).others;
ASSERT_EQ( 1u, media.size() );
m->removeLabel( l );
media = ml->searchMedia( "otter" ).others;
media = ml->searchMedia( "otter", SortingCriteria::Default, false ).others;
ASSERT_EQ( 0u, media.size() );
media = ml->searchMedia( "pangolin" ).others;
media = ml->searchMedia( "pangolin", SortingCriteria::Default, false ).others;
ASSERT_EQ( 1u, media.size() );
m->addLabel( l );
media = ml->searchMedia( "otter" ).others;
media = ml->searchMedia( "otter", SortingCriteria::Default, false ).others;
ASSERT_EQ( 1u, media.size() );
media = ml->searchMedia( "pangolin" ).others;
media = ml->searchMedia( "pangolin", SortingCriteria::Default, false ).others;
ASSERT_EQ( 1u, media.size() );
ml->deleteLabel( l );
media = ml->searchMedia( "otter" ).others;
media = ml->searchMedia( "otter", SortingCriteria::Default, false ).others;
ASSERT_EQ( 0u, media.size() );
media = ml->searchMedia( "pangolin" ).others;
media = ml->searchMedia( "pangolin", SortingCriteria::Default, false ).others;
ASSERT_EQ( 1u, media.size() );
}
......@@ -258,16 +282,16 @@ TEST_F( Medias, SearchTracks )
auto m = std::static_pointer_cast<Media>( ml->addMedia( "track " + std::to_string( i ) + ".mp3" ) );
a->addTrack( m, i, 1, 0, 0 );
}
auto tracks = ml->searchMedia( "tra" ).tracks;
auto tracks = ml->searchMedia( "tra", SortingCriteria::Default, false ).tracks;
ASSERT_EQ( 10u, tracks.size() );
tracks = ml->searchMedia( "track 1" ).tracks;
tracks = ml->searchMedia( "track 1", SortingCriteria::Default, false ).tracks;
ASSERT_EQ( 2u, tracks.size() );
tracks = ml->searchMedia( "grouik" ).tracks;
tracks = ml->searchMedia( "grouik", SortingCriteria::Default, false ).tracks;
ASSERT_EQ( 0u, tracks.size() );
tracks = ml->searchMedia( "rack" ).tracks;
tracks = ml->searchMedia( "rack", SortingCriteria::Default, false ).tracks;
ASSERT_EQ( 0u, tracks.size() );
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment