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

Album: Provide a cached version of tracks() to increase parsing performances

parent 0cf35a58
......@@ -136,27 +136,40 @@ bool Album::setArtworkMrl( const std::string& artworkMrl )
std::vector<MediaPtr> Album::tracks() const
{
// This doesn't return the cached version, because it would be fairly complicated, if not impossible or
// counter productive, to maintain a cache that respects all orderings.
static const std::string req = "SELECT med.* FROM " + policy::MediaTable::Name + " med "
" LEFT JOIN " + policy::AlbumTrackTable::Name + " att ON att.media_id = med.id_media "
" WHERE att.album_id = ? AND med.is_present = 1 ORDER BY att.disc_number, att.track_number";
return Media::fetchAll<IMedia>( m_dbConnection, req, m_id );
}
std::shared_ptr<AlbumTrack> Album::addTrack( Media& media, unsigned int trackNb, unsigned int discNumber )
std::vector<MediaPtr> Album::cachedTracks() const
{
auto lock = m_tracks.lock();
if ( m_tracks.isCached() == false )
m_tracks = tracks();
return m_tracks.get();
}
std::shared_ptr<AlbumTrack> Album::addTrack( std::shared_ptr<Media> media, unsigned int trackNb, unsigned int discNumber )
{
auto t = m_dbConnection->newTransaction();
auto track = AlbumTrack::create( m_dbConnection, m_id, media.id(), trackNb, discNumber );
auto track = AlbumTrack::create( m_dbConnection, m_id, media->id(), trackNb, discNumber );
if ( track == nullptr )
return nullptr;
media.setAlbumTrack( track );
media.save();
media->setAlbumTrack( track );
media->save();
static const std::string req = "UPDATE " + policy::AlbumTable::Name +
" SET nb_tracks = nb_tracks + 1 WHERE id_album = ?";
if ( sqlite::Tools::executeUpdate( m_dbConnection, req, m_id ) == false )
return nullptr;
m_nbTracks++;
t->commit();
auto lock = m_tracks.lock();
if ( m_tracks.isCached() == true )
m_tracks.get().push_back( media );
return track;
}
......
......@@ -31,6 +31,7 @@
#include "database/DatabaseHelpers.h"
#include "IAlbum.h"
#include "utils/Cache.h"
class Album;
class AlbumTrack;
......@@ -72,7 +73,13 @@ class Album : public IAlbum, public DatabaseHelpers<Album, policy::AlbumTable>
virtual const std::string& artworkMrl() const override;
bool setArtworkMrl( const std::string& artworkMrl );
virtual std::vector<MediaPtr> tracks() const override;
std::shared_ptr<AlbumTrack> addTrack(Media& media, unsigned int trackNb , unsigned int discNumber);
///
/// \brief cachedTracks Returns a cached list of tracks
/// This has no warranty of ordering, validity, or anything else.
/// \return An unordered-list of this album's tracks
///
std::vector<MediaPtr> cachedTracks() const;
std::shared_ptr<AlbumTrack> addTrack( std::shared_ptr<Media> media, unsigned int trackNb , unsigned int discNumber);
unsigned int nbTracks() const override;
virtual ArtistPtr albumArtist() const override;
......@@ -97,6 +104,8 @@ class Album : public IAlbum, public DatabaseHelpers<Album, policy::AlbumTable>
unsigned int m_nbTracks;
bool m_isPresent;
mutable Cache<std::vector<MediaPtr>> m_tracks;
friend struct policy::AlbumTable;
};
......
......@@ -78,7 +78,7 @@ parser::Task::Status MetadataParser::run( parser::Task& task )
t->commit();
if ( isAudio == true )
{
if ( parseAudioFile( *media, *file, vlcMedia ) == false )
if ( parseAudioFile( media, *file, vlcMedia ) == false )
return parser::Task::Status::Fatal;
}
else
......@@ -135,13 +135,13 @@ bool MetadataParser::parseVideoFile( std::shared_ptr<Media> media, VLC::Media& v
/* Audio files */
bool MetadataParser::parseAudioFile( Media& media, File& file, VLC::Media& vlcMedia ) const
bool MetadataParser::parseAudioFile( std::shared_ptr<Media> media, File& file, VLC::Media& vlcMedia ) const
{
media.setType( IMedia::Type::AudioType );
media->setType( IMedia::Type::AudioType );
auto cover = vlcMedia.meta( libvlc_meta_ArtworkURL );
if ( cover.empty() == false )
media.setThumbnail( cover );
media->setThumbnail( cover );
auto artists = handleArtists( vlcMedia );
auto album = handleAlbum( media, file, vlcMedia, artists.first, artists.second );
......@@ -151,7 +151,7 @@ bool MetadataParser::parseAudioFile( Media& media, File& file, VLC::Media& vlcMe
return false;
}
auto t = m_dbConn->newTransaction();
auto res = link( media, album, artists.first, artists.second );
auto res = link( *media, album, artists.first, artists.second );
t->commit();
return res;
}
......@@ -208,7 +208,7 @@ std::shared_ptr<Album> MetadataParser::findAlbum( File& file, VLC::Media& vlcMed
++it;
continue;
}
const auto tracks = a->tracks();
const auto tracks = a->cachedTracks();
assert( tracks.size() > 0 );
auto multiDisc = false;
......@@ -257,7 +257,7 @@ std::shared_ptr<Album> MetadataParser::findAlbum( File& file, VLC::Media& vlcMed
return std::static_pointer_cast<Album>( albums[0] );
}
std::shared_ptr<Album> MetadataParser::handleAlbum( Media& media, File& file, VLC::Media& vlcMedia, std::shared_ptr<Artist> albumArtist, std::shared_ptr<Artist> trackArtist ) const
std::shared_ptr<Album> MetadataParser::handleAlbum( std::shared_ptr<Media> media, File& file, VLC::Media& vlcMedia, std::shared_ptr<Artist> albumArtist, std::shared_ptr<Artist> trackArtist ) const
{
auto albumTitle = vlcMedia.meta( libvlc_meta_Album );
std::shared_ptr<Album> album;
......@@ -350,7 +350,7 @@ std::pair<std::shared_ptr<Artist>, std::shared_ptr<Artist>> MetadataParser::hand
/* Tracks handling */
std::shared_ptr<AlbumTrack> MetadataParser::handleTrack( std::shared_ptr<Album> album, Media& media, VLC::Media& vlcMedia, std::shared_ptr<Artist> artist ) const
std::shared_ptr<AlbumTrack> MetadataParser::handleTrack( std::shared_ptr<Album> album, std::shared_ptr<Media> media, VLC::Media& vlcMedia, std::shared_ptr<Artist> artist ) const
{
auto trackNbStr = vlcMedia.meta( libvlc_meta_TrackNumber );
......@@ -365,7 +365,7 @@ std::shared_ptr<AlbumTrack> MetadataParser::handleTrack( std::shared_ptr<Album>
}
}
if ( title.empty() == false )
media.setTitle( title );
media->setTitle( title );
unsigned int trackNb;
if ( trackNbStr.empty() == false )
trackNb = atoi( trackNbStr.c_str() );
......
......@@ -38,12 +38,12 @@ protected:
virtual uint8_t nbThreads() const override;
std::shared_ptr<Album> findAlbum(File& file, VLC::Media& vlcMedia, const std::string& title, Artist* albumArtist ) const;
bool parseAudioFile(Media& media, File& file, VLC::Media &vlcMedia ) const;
bool parseAudioFile( std::shared_ptr<Media> media, File& file, VLC::Media &vlcMedia ) const;
bool parseVideoFile( std::shared_ptr<Media> media, VLC::Media& vlcMedia ) const;
std::pair<std::shared_ptr<Artist>, std::shared_ptr<Artist>> handleArtists(VLC::Media& vlcMedia ) const;
std::shared_ptr<AlbumTrack> handleTrack( std::shared_ptr<Album> album, Media& media, VLC::Media& vlcMedia , std::shared_ptr<Artist> artist) const;
std::shared_ptr<AlbumTrack> handleTrack(std::shared_ptr<Album> album, std::shared_ptr<Media> media, VLC::Media& vlcMedia , std::shared_ptr<Artist> artist) const;
bool link(Media& media, std::shared_ptr<Album> album, std::shared_ptr<Artist> albumArtist, std::shared_ptr<Artist> artist ) const;
std::shared_ptr<Album> handleAlbum(Media& media, File& file, VLC::Media& vlcMedia, std::shared_ptr<Artist> albumArtist, std::shared_ptr<Artist> artist ) const;
std::shared_ptr<Album> handleAlbum( std::shared_ptr<Media> media, File& file, VLC::Media& vlcMedia, std::shared_ptr<Artist> albumArtist, std::shared_ptr<Artist> artist ) const;
private:
MediaLibrary* m_ml;
......
......@@ -60,7 +60,7 @@ TEST_F( Albums, AddTrack )
{
auto a = ml->createAlbum( "albumtag" );
auto f = ml->addFile( "track.mp3" );
auto track = a->addTrack( *f, 10, 0 );
auto track = a->addTrack( f, 10, 0 );
ASSERT_NE( track, nullptr );
auto tracks = a->tracks();
......@@ -80,7 +80,7 @@ TEST_F( Albums, NbTracks )
for ( auto i = 1u; i <= 10; ++i )
{
auto f = ml->addFile( "track" + std::to_string(i) + ".mp3" );
auto track = a->addTrack( *f, i, i );
auto track = a->addTrack( f, i, i );
ASSERT_NE( track, nullptr );
}
auto tracks = a->tracks();
......@@ -97,7 +97,7 @@ TEST_F( Albums, SetGenre )
{
auto a = ml->createAlbum( "album" );
auto f = ml->addFile( "track.mp3" );
auto t = a->addTrack( *f, 1, 0 );
auto t = a->addTrack( f, 1, 0 );
t->setGenre( "happy underground post progressive death metal" );
ASSERT_EQ( t->genre(), "happy underground post progressive death metal" );
......@@ -168,7 +168,7 @@ TEST_F( Albums, FetchAlbumFromTrack )
{
auto a = ml->createAlbum( "album" );
auto f = ml->addFile( "file.mp3" );
auto t = a->addTrack( *f, 1, 0 );
auto t = a->addTrack( f, 1, 0 );
Reload();
......
......@@ -35,7 +35,7 @@ TEST_F( AlbumTracks, Create )
{
auto album = ml->createAlbum( "album" );
auto f = ml->addFile( "track1.mp3" );
auto track = album->addTrack( *f, 1, 10 );
auto track = album->addTrack( f, 1, 10 );
ASSERT_NE( nullptr, track );
ASSERT_EQ( 10u, track->discNumber() );
......@@ -49,7 +49,7 @@ TEST_F( AlbumTracks, Artist )
{
auto album = ml->createAlbum( "album" );
auto f = ml->addFile( "track1.mp3" );
auto track = album->addTrack( *f, 1, 0 );
auto track = album->addTrack( f, 1, 0 );
auto artist = track->artist();
ASSERT_EQ( nullptr, artist );
......@@ -74,7 +74,7 @@ TEST_F( AlbumTracks, SetReleaseYear )
{
auto a = ml->createAlbum( "album" );
auto m = ml->addFile( "test.mp3" );
auto t = a->addTrack( *m, 1, 0 );
auto t = a->addTrack( m, 1, 0 );
ASSERT_EQ( 0u, t->releaseYear() );
......
......@@ -243,7 +243,7 @@ TEST_F( DeviceFs, RemoveAlbum )
{
auto album = std::static_pointer_cast<Album>( ml->createAlbum( "album" ) );
auto media = ml->media( mock::FileSystemFactory::Root + "audio.mp3" );
album->addTrack( static_cast<Media&>( *media ), 1, 1 );
album->addTrack( std::static_pointer_cast<Media>( media ), 1, 1 );
auto artist = ml->createArtist( "artist" );
album->setAlbumArtist( artist.get() );
}
......@@ -252,8 +252,8 @@ TEST_F( DeviceFs, RemoveAlbum )
auto album = std::static_pointer_cast<Album>( ml->createAlbum( "album 2" ) );
auto media = ml->media( RemovableDeviceMountpoint + "removablefile.mp3" );
ml->media( RemovableDeviceMountpoint + "removablefile2.mp3" );
album->addTrack( static_cast<Media&>( *media ), 1, 1 );
album->addTrack( static_cast<Media&>( *media ), 2, 1 );
album->addTrack( std::static_pointer_cast<Media>( media ), 1, 1 );
album->addTrack( std::static_pointer_cast<Media>( media ), 2, 1 );
auto artist = ml->createArtist( "artist 2" );
album->setAlbumArtist( artist.get() );
}
......@@ -287,8 +287,8 @@ TEST_F( DeviceFs, PartialAlbumRemoval )
auto album = ml->createAlbum( "album" );
auto media = ml->media( mock::FileSystemFactory::SubFolder + "subfile.mp4" );
auto media2 = ml->media( RemovableDeviceMountpoint + "removablefile2.mp3" );
album->addTrack( static_cast<Media&>( *media ), 1, 1 );
album->addTrack( static_cast<Media&>( *media2 ), 2, 1 );
album->addTrack( std::static_pointer_cast<Media>( media ), 1, 1 );
album->addTrack( std::static_pointer_cast<Media>( media2 ), 2, 1 );
auto newArtist = ml->createArtist( "artist" );
album->setAlbumArtist( newArtist.get() );
newArtist->addMedia( static_cast<Media&>( *media ) );
......
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