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

Allow albums to be sorted

parent 49c998cc
......@@ -25,7 +25,7 @@
#include <string>
#include <vector>
#include "Types.h"
#include "IMediaLibrary.h"
class IArtist
{
......@@ -34,7 +34,7 @@ public:
virtual unsigned int id() const = 0;
virtual const std::string& name() const = 0;
virtual const std::string& shortBio() const = 0;
virtual std::vector<AlbumPtr> albums() const = 0;
virtual std::vector<AlbumPtr> albums( medialibrary::SortingCriteria sort, bool desc ) const = 0;
virtual std::vector<MediaPtr> media( medialibrary::SortingCriteria sort, bool desc ) const = 0;
virtual const std::string& artworkMrl() const = 0;
virtual const std::string& musicBrainzId() const = 0;
......
......@@ -134,7 +134,7 @@ class IMediaLibrary
virtual std::vector<MediaPtr> audioFiles( medialibrary::SortingCriteria sort, bool desc ) = 0;
virtual std::vector<MediaPtr> videoFiles( medialibrary::SortingCriteria sort, bool desc ) = 0;
virtual AlbumPtr album( unsigned int id ) = 0;
virtual std::vector<AlbumPtr> albums() = 0;
virtual std::vector<AlbumPtr> albums( medialibrary::SortingCriteria sort, bool desc ) = 0;
virtual ShowPtr show( const std::string& name ) = 0;
virtual MoviePtr movie( const std::string& title ) = 0;
virtual ArtistPtr artist( unsigned int id ) = 0;
......
......@@ -137,7 +137,7 @@ bool Album::setArtworkMrl( const std::string& artworkMrl )
return true;
}
std::string Album::orderBy( medialibrary::SortingCriteria sort, bool desc ) const
std::string Album::orderTracksBy( medialibrary::SortingCriteria sort, bool desc )
{
std::string req = " ORDER BY ";
switch ( sort )
......@@ -164,7 +164,6 @@ std::string Album::orderBy( medialibrary::SortingCriteria sort, bool desc ) cons
return req;
}
std::vector<MediaPtr> Album::tracks( medialibrary::SortingCriteria sort, bool desc ) const
{
// This doesn't return the cached version, because it would be fairly complicated, if not impossible or
......@@ -172,7 +171,7 @@ std::vector<MediaPtr> Album::tracks( medialibrary::SortingCriteria sort, bool de
std::string req = "SELECT med.* FROM " + policy::MediaTable::Name + " med "
" INNER JOIN " + policy::AlbumTrackTable::Name + " att ON att.media_id = med.id_media "
" WHERE att.album_id = ? AND med.is_present = 1";
req += orderBy( sort, desc );
req += orderTracksBy( sort, desc );
return Media::fetchAll<IMedia>( m_ml, req, m_id );
}
......@@ -184,7 +183,7 @@ std::vector<std::shared_ptr<IMedia>> Album::tracks( GenrePtr genre, medialibrary
" INNER JOIN " + policy::AlbumTrackTable::Name + " att ON att.media_id = med.id_media "
" WHERE att.album_id = ? AND med.is_present = 1"
" AND genre_id = ?";
req += orderBy( sort, desc );
req += orderTracksBy( sort, desc );
return Media::fetchAll<IMedia>( m_ml, req, m_id, genre->id() );
}
......@@ -386,3 +385,49 @@ std::vector<AlbumPtr> Album::search( MediaLibraryPtr ml, const std::string& patt
"AND is_present = 1";
return fetchAll<IAlbum>( ml, req, pattern + "*" );
}
std::vector<AlbumPtr> Album::fromArtist( MediaLibraryPtr ml, unsigned int artistId, medialibrary::SortingCriteria sort, bool desc )
{
std::string req = "SELECT * FROM " + policy::AlbumTable::Name + " alb "
"WHERE artist_id = ? AND is_present=1 ORDER BY ";
switch ( sort )
{
case medialibrary::SortingCriteria::Alpha:
req += "title";
if ( desc == true )
req += " DESC";
break;
default:
// When listing albums of an artist, default order is by descending year (with album title
// discrimination in case 2+ albums went out the same year)
// This leads to DESC being used for "non-desc" case
if ( desc == true )
req += "release_year, title";
else
req += "release_year DESC, title";
break;
}
return fetchAll<IAlbum>( ml, req, artistId );
}
std::vector<AlbumPtr> Album::listAll( MediaLibraryPtr ml, medialibrary::SortingCriteria sort, bool desc )
{
std::string req = "SELECT * FROM " + policy::AlbumTable::Name +
" WHERE is_present=1 ORDER BY ";
switch ( sort )
{
case medialibrary::SortingCriteria::ReleaseDate:
if ( desc == true )
req += "release_year DESC, title";
else
req += "release_year, title";
break;
default:
req += "title";
if ( desc == true )
req += " DESC";
break;
}
return fetchAll<IAlbum>( ml, req );
}
......@@ -104,9 +104,11 @@ class Album : public IAlbum, public DatabaseHelpers<Album, policy::AlbumTable>
/// \return
///
static std::vector<AlbumPtr> search( MediaLibraryPtr ml, const std::string& pattern );
static std::vector<AlbumPtr> fromArtist(MediaLibraryPtr ml, unsigned int artistId , medialibrary::SortingCriteria sort, bool desc );
static std::vector<AlbumPtr> listAll( MediaLibraryPtr ml, medialibrary::SortingCriteria sort, bool desc );
private:
std::string orderBy( medialibrary::SortingCriteria sort, bool desc ) const;
static std::string orderTracksBy( medialibrary::SortingCriteria sort, bool desc );
protected:
MediaLibraryPtr m_ml;
......
......@@ -78,13 +78,9 @@ bool Artist::setShortBio(const std::string &shortBio)
return true;
}
std::vector<AlbumPtr> Artist::albums() const
std::vector<AlbumPtr> Artist::albums( medialibrary::SortingCriteria sort, bool desc ) const
{
if ( m_id == 0 )
return {};
static const std::string req = "SELECT * FROM " + policy::AlbumTable::Name + " alb "
"WHERE artist_id = ? ORDER BY release_year, title";
return Album::fetchAll<IAlbum>( m_ml, req, m_id );
return Album::fromArtist( m_ml, m_id, sort, desc );
}
std::vector<MediaPtr> Artist::media( medialibrary::SortingCriteria sort, bool desc ) const
......
......@@ -50,7 +50,7 @@ public:
virtual const std::string &name() const override;
virtual const std::string& shortBio() const override;
bool setShortBio( const std::string& shortBio );
virtual std::vector<AlbumPtr> albums() const override;
virtual std::vector<AlbumPtr> albums( medialibrary::SortingCriteria sort, bool desc ) const override;
virtual std::vector<MediaPtr> media(medialibrary::SortingCriteria sort, bool desc) const override;
bool addMedia( Media& media );
virtual const std::string& artworkMrl() const override;
......
......@@ -311,12 +311,9 @@ std::shared_ptr<Album> MediaLibrary::createAlbum(const std::string& title )
return Album::create( this, title );
}
std::vector<AlbumPtr> MediaLibrary::albums()
std::vector<AlbumPtr> MediaLibrary::albums( medialibrary::SortingCriteria sort, bool desc )
{
static const std::string req = "SELECT * FROM " + policy::AlbumTable::Name +
" WHERE is_present=1"
" ORDER BY title ASC";
return Album::fetchAll<IAlbum>( this, req );
return Album::listAll( this, sort, desc );
}
std::vector<GenrePtr> MediaLibrary::genres() const
......
......@@ -69,7 +69,7 @@ class MediaLibrary : public IMediaLibrary
virtual AlbumPtr album( unsigned int id ) override;
std::shared_ptr<Album> createAlbum( const std::string& title );
virtual std::vector<AlbumPtr> albums() override;
virtual std::vector<AlbumPtr> albums(medialibrary::SortingCriteria sort, bool desc) override;
virtual std::vector<GenrePtr> genres() const override;
......
......@@ -217,7 +217,7 @@ void Tests::checkArtists(const rapidjson::Value& expectedArtists, std::vector<Ar
}
if ( expectedArtist.HasMember( "nbAlbums" ) || expectedArtist.HasMember( "albums" ) )
{
auto albums = artist->albums();
auto albums = artist->albums( medialibrary::SortingCriteria::Default, false );
if ( expectedArtist.HasMember( "nbAlbums" ) )
{
if ( albums.size() != expectedArtist["nbAlbums"].GetUint() )
......
......@@ -64,7 +64,7 @@ TEST_P( Tests, Parse )
if ( expected.HasMember( "albums" ) == true )
{
checkAlbums( expected["albums" ], m_ml->albums() );
checkAlbums( expected["albums" ], m_ml->albums( medialibrary::SortingCriteria::Default, false ) );
}
if ( expected.HasMember( "media" ) == true )
checkMedias( expected["media"] );
......
......@@ -368,3 +368,39 @@ TEST_F( Albums, SortTracks )
ASSERT_EQ( t1->id(), tracks[1]->id() ); // B-track -> first
ASSERT_EQ( t2->id(), tracks[0]->id() ); // A-track -> second
}
TEST_F( Albums, Sort )
{
auto a1 = ml->createAlbum( "A" );
a1->setReleaseYear( 1000, false );
auto a2 = ml->createAlbum( "B" );
a2->setReleaseYear( 2000, false );
auto a3 = ml->createAlbum( "C" );
a3->setReleaseYear( 1000, false );
auto albums = ml->albums( medialibrary::SortingCriteria::ReleaseDate, false );
ASSERT_EQ( 3u, albums.size() );
ASSERT_EQ( a1->id(), albums[0]->id() );
ASSERT_EQ( a3->id(), albums[1]->id() );
ASSERT_EQ( a2->id(), albums[2]->id() );
albums = ml->albums( medialibrary::SortingCriteria::ReleaseDate, true );
// We do not invert the lexical order when sorting by DESC release date:
ASSERT_EQ( 3u, albums.size() );
ASSERT_EQ( a2->id(), albums[0]->id() );
ASSERT_EQ( a1->id(), albums[1]->id() );
ASSERT_EQ( a3->id(), albums[2]->id() );
// When listing all albums, default order is lexical order
albums = ml->albums( medialibrary::SortingCriteria::Default, false );
ASSERT_EQ( 3u, albums.size() );
ASSERT_EQ( a1->id(), albums[0]->id() );
ASSERT_EQ( a2->id(), albums[1]->id() );
ASSERT_EQ( a3->id(), albums[2]->id() );
albums = ml->albums( medialibrary::SortingCriteria::Default, true );
ASSERT_EQ( 3u, albums.size() );
ASSERT_EQ( a3->id(), albums[0]->id() );
ASSERT_EQ( a2->id(), albums[1]->id() );
ASSERT_EQ( a1->id(), albums[2]->id() );
}
......@@ -101,13 +101,13 @@ TEST_F( Artists, Albums )
album1->setAlbumArtist( artist.get() );
album2->setAlbumArtist( artist.get() );
auto albums = artist->albums();
auto albums = artist->albums( medialibrary::SortingCriteria::Default, false );
ASSERT_EQ( albums.size(), 2u );
Reload();
auto artist2 = ml->artist( "Cannibal Otters" );
auto albums2 = artist2->albums();
auto albums2 = artist2->albums( medialibrary::SortingCriteria::Default, false );
ASSERT_EQ( albums.size(), 2u );
}
......@@ -240,3 +240,43 @@ TEST_F( Artists, SortMedia )
ASSERT_EQ( "song2.mp3", tracks[1]->title() );
ASSERT_EQ( "song3.mp3", tracks[2]->title() );
}
TEST_F( Artists, SortAlbum )
{
auto artist = ml->createArtist( "Dream Seaotter" );
auto album1 = ml->createAlbum( "album1" );
album1->setReleaseYear( 2000, false );
auto album2 = ml->createAlbum( "album2" );
album2->setReleaseYear( 1000, false );
auto album3 = ml->createAlbum( "album3" );
album3->setReleaseYear( 2000, false );
album1->setAlbumArtist( artist.get() );
album2->setAlbumArtist( artist.get() );
album3->setAlbumArtist( artist.get() );
// Default order is by descending year, discriminated by lexical order
auto albums = artist->albums( medialibrary::SortingCriteria::Default, false );
ASSERT_EQ( 3u, albums.size() );
ASSERT_EQ( album1->id(), albums[0]->id() );
ASSERT_EQ( album3->id(), albums[1]->id() );
ASSERT_EQ( album2->id(), albums[2]->id() );
albums = artist->albums( medialibrary::SortingCriteria::Default, true );
ASSERT_EQ( 3u, albums.size() );
ASSERT_EQ( album2->id(), albums[0]->id() );
ASSERT_EQ( album1->id(), albums[1]->id() );
ASSERT_EQ( album3->id(), albums[2]->id() );
albums = artist->albums( medialibrary::SortingCriteria::Alpha, false );
ASSERT_EQ( 3u, albums.size() );
ASSERT_EQ( album1->id(), albums[0]->id() );
ASSERT_EQ( album2->id(), albums[1]->id() );
ASSERT_EQ( album3->id(), albums[2]->id() );
albums = artist->albums( medialibrary::SortingCriteria::Alpha, true );
ASSERT_EQ( 3u, albums.size() );
ASSERT_EQ( album3->id(), albums[0]->id() );
ASSERT_EQ( album2->id(), albums[1]->id() );
ASSERT_EQ( album1->id(), albums[2]->id() );
}
......@@ -270,7 +270,7 @@ TEST_F( DeviceFs, RemoveAlbum )
album->setAlbumArtist( artist.get() );
}
auto albums = ml->albums();
auto albums = ml->albums( medialibrary::SortingCriteria::Default, false );
ASSERT_EQ( 2u, albums.size() );
auto artists = ml->artists();
ASSERT_EQ( 2u, artists.size() );
......@@ -282,7 +282,7 @@ TEST_F( DeviceFs, RemoveAlbum )
bool reloaded = cbMock->waitForReload();
ASSERT_TRUE( reloaded );
albums = ml->albums();
albums = ml->albums( medialibrary::SortingCriteria::Default, false );
ASSERT_EQ( 1u, albums.size() );
artists = ml->artists();
ASSERT_EQ( 1u, artists.size() );
......@@ -307,7 +307,7 @@ TEST_F( DeviceFs, PartialAlbumRemoval )
newArtist->addMedia( static_cast<Media&>( *media2 ) );
}
auto albums = ml->albums();
auto albums = ml->albums( medialibrary::SortingCriteria::Default, false );
ASSERT_EQ( 1u, albums.size() );
auto artists = ml->artists();
ASSERT_EQ( 1u, artists.size() );
......@@ -320,7 +320,7 @@ TEST_F( DeviceFs, PartialAlbumRemoval )
bool reloaded = cbMock->waitForReload();
ASSERT_TRUE( reloaded );
albums = ml->albums();
albums = ml->albums( medialibrary::SortingCriteria::Default, false );
ASSERT_EQ( 1u, albums.size() );
artists = ml->artists();
ASSERT_EQ( 1u, artists.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