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

Media: Expose a media history based on the media table itself

parent 2185a36d
......@@ -119,7 +119,8 @@ class IMediaLibrary
* History
*/
virtual bool addToHistory( const std::string& mrl ) = 0;
virtual std::vector<HistoryPtr> history() const = 0;
virtual std::vector<HistoryPtr> lastStreamsPlayed() const = 0;
virtual std::vector<MediaPtr> lastMediaPlayed() const = 0;
/**
* Search
......
......@@ -57,6 +57,7 @@ Media::Media( DBConnection dbConnection, sqlite::Row& row )
>> m_subType
>> m_duration
>> m_playCount
>> m_lastPlayedDate
>> m_progress
>> m_rating
>> m_insertionDate
......@@ -72,6 +73,7 @@ Media::Media( const std::string& title, Type type )
, m_subType( SubType::Unknown )
, m_duration( -1 )
, m_playCount( 0 )
, m_lastPlayedDate( 0 )
, m_progress( .0f )
, m_rating( -1 )
, m_insertionDate( time( nullptr ) )
......@@ -160,6 +162,7 @@ int Media::playCount() const
void Media::increasePlayCount()
{
m_playCount++;
m_lastPlayedDate = time( nullptr );
m_changed = true;
}
......@@ -281,12 +284,13 @@ void Media::setThumbnail(const std::string& thumbnail )
bool Media::save()
{
static const std::string req = "UPDATE " + policy::MediaTable::Name + " SET "
"type = ?, subtype = ?, duration = ?, play_count = ?, progress = ?, rating = ?,"
"type = ?, subtype = ?, duration = ?, play_count = ?, last_played_date = ?, progress = ?, rating = ?,"
"thumbnail = ?, title = ?, is_favorite = ? WHERE id_media = ?";
if ( m_changed == false )
return true;
if ( sqlite::Tools::executeUpdate( m_dbConnection, req, m_type, m_subType, m_duration, m_playCount,
m_progress, m_rating, m_thumbnail, m_title, m_isFavorite, m_id ) == false )
m_lastPlayedDate, m_progress, m_rating, m_thumbnail, m_title,
m_isFavorite, m_id ) == false )
{
return false;
}
......@@ -360,6 +364,7 @@ bool Media::createTable( DBConnection connection )
"subtype INTEGER,"
"duration INTEGER DEFAULT -1,"
"play_count UNSIGNED INTEGER,"
"last_played_date UNSIGNED INTEGER,"
"progress REAL,"
"rating INTEGER DEFAULT -1,"
"insertion_date UNSIGNED INTEGER,"
......@@ -368,12 +373,15 @@ bool Media::createTable( DBConnection connection )
"is_favorite BOOLEAN NOT NULL DEFAULT 0,"
"is_present BOOLEAN NOT NULL DEFAULT 1"
")";
static const std::string indexReq = "CREATE INDEX IF NOT EXISTS index_last_played_date ON "
+ policy::MediaTable::Name + "(last_played_date DESC)";
static const std::string vtableReq = "CREATE VIRTUAL TABLE IF NOT EXISTS "
+ policy::MediaTable::Name + "Fts USING FTS3("
"title,"
"labels"
")";
return sqlite::Tools::executeRequest( connection, req ) &&
sqlite::Tools::executeRequest( connection, indexReq ) &&
sqlite::Tools::executeRequest( connection, vtableReq );
}
......@@ -455,3 +463,10 @@ std::vector<MediaPtr> Media::search( DBConnection dbConn, const std::string& tit
"AND is_present = 1";
return Media::fetchAll<IMedia>( dbConn, req, title + "*" );
}
std::vector<MediaPtr> Media::fetchHistory( DBConnection dbConn )
{
static const std::string req = "SELECT * FROM " + policy::MediaTable::Name + " WHERE last_played_date IS NOT NULL"
" ORDER BY last_played_date DESC LIMIT 100";
return fetchAll<IMedia>( dbConn, req );
}
......@@ -104,6 +104,7 @@ class Media : public IMedia, public DatabaseHelpers<Media, policy::MediaTable>
void removeFile( File& file );
static std::vector<MediaPtr> search( DBConnection dbConn, const std::string& title );
static std::vector<MediaPtr> fetchHistory( DBConnection dbConn );
private:
......@@ -115,6 +116,7 @@ private:
SubType m_subType;
int64_t m_duration;
unsigned int m_playCount;
unsigned int m_lastPlayedDate;
float m_progress;
int m_rating;
unsigned int m_insertionDate;
......
......@@ -380,11 +380,16 @@ bool MediaLibrary::addToHistory( const std::string& mrl )
return History::insert( m_dbConnection.get(), mrl );
}
std::vector<HistoryPtr> MediaLibrary::history() const
std::vector<HistoryPtr> MediaLibrary::lastStreamsPlayed() const
{
return History::fetch( m_dbConnection.get() );
}
std::vector<MediaPtr> MediaLibrary::lastMediaPlayed() const
{
return Media::fetchHistory( m_dbConnection.get() );
}
medialibrary::MediaSearchAggregate MediaLibrary::searchMedia( const std::string& title ) const
{
if ( validateSearchPattern( title ) == false )
......
......@@ -89,7 +89,8 @@ class MediaLibrary : public IMediaLibrary
virtual bool deletePlaylist( unsigned int playlistId ) override;
virtual bool addToHistory( const std::string& mrl );
virtual std::vector<HistoryPtr> history() const;
virtual std::vector<HistoryPtr> lastStreamsPlayed() const override;
virtual std::vector<MediaPtr> lastMediaPlayed() const override;
virtual medialibrary::MediaSearchAggregate searchMedia( const std::string& title ) const override;
virtual std::vector<PlaylistPtr> searchPlaylists( const std::string& name ) const override;
......
......@@ -34,7 +34,7 @@ class HistoryTest : public Tests
TEST_F( HistoryTest, InsertMrl )
{
ml->addToHistory( "upnp://stream" );
auto hList = ml->history();
auto hList = ml->lastStreamsPlayed();
ASSERT_EQ( 1u, hList.size() );
auto h = hList[0];
ASSERT_EQ( h->mrl(), "upnp://stream" );
......@@ -47,10 +47,10 @@ TEST_F( HistoryTest, MaxEntries )
{
ml->addToHistory( std::to_string( i ) );
}
auto hList = ml->history();
auto hList = ml->lastStreamsPlayed();
ASSERT_EQ( History::MaxEntries, hList.size() );
ml->addToHistory( "new-media" );
hList = ml->history();
hList = ml->lastStreamsPlayed();
ASSERT_EQ( History::MaxEntries, hList.size() );
}
......@@ -59,7 +59,7 @@ TEST_F( HistoryTest, Ordering )
ml->addToHistory( "first-stream" );
std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
ml->addToHistory( "second-stream" );
auto hList = ml->history();
auto hList = ml->lastStreamsPlayed();
ASSERT_EQ( 2u, hList.size() );
ASSERT_EQ( hList[0]->mrl(), "second-stream" );
ASSERT_EQ( hList[1]->mrl(), "first-stream" );
......@@ -68,12 +68,12 @@ TEST_F( HistoryTest, Ordering )
TEST_F( HistoryTest, UpdateInsertionDate )
{
ml->addToHistory( "stream" );
auto hList = ml->history();
auto hList = ml->lastStreamsPlayed();
ASSERT_EQ( 1u, hList.size() );
auto date = hList[0]->insertionDate();
std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
ml->addToHistory( "stream" );
hList = ml->history();
hList = ml->lastStreamsPlayed();
ASSERT_EQ( 1u, hList.size() );
ASSERT_NE( date, hList[0]->insertionDate() );
}
......@@ -81,7 +81,7 @@ TEST_F( HistoryTest, UpdateInsertionDate )
TEST_F( HistoryTest, FavoriteMrl )
{
ml->addToHistory( "stream" );
auto hList = ml->history();
auto hList = ml->lastStreamsPlayed();
ASSERT_EQ( 1u, hList.size() );
auto item = hList[0];
ASSERT_FALSE( item->isFavorite() );
......@@ -92,13 +92,13 @@ TEST_F( HistoryTest, FavoriteMrl )
TEST_F( HistoryTest, ReinsertFavorited )
{
ml->addToHistory( "stream" );
auto hList = ml->history();
auto hList = ml->lastStreamsPlayed();
auto item = hList[0];
auto date = item->insertionDate();
item->setFavorite( true );
std::this_thread::sleep_for( std::chrono::seconds{ 1 } );
ml->addToHistory( "stream" );
hList = ml->history();
hList = ml->lastStreamsPlayed();
item = hList[0];
ASSERT_NE( date, item->insertionDate() );
ASSERT_TRUE( item->isFavorite() );
......
......@@ -276,3 +276,27 @@ TEST_F( Medias, Favorite )
m = ml->media( m->id() );
ASSERT_TRUE( m->isFavorite() );
}
TEST_F( Medias, History )
{
auto m = ml->addFile( "media.mkv" );
auto history = ml->lastMediaPlayed();
ASSERT_EQ( 0u, history.size() );
m->increasePlayCount();
m->save();
history = ml->lastMediaPlayed();
ASSERT_EQ( 1u, history.size() );
ASSERT_EQ( m->id(), history[0]->id() );
std::this_thread::sleep_for( std::chrono::seconds{ 1 } );
auto m2 = ml->addFile( "media.mkv" );
m2->increasePlayCount();
m2->save();
history = ml->lastMediaPlayed();
ASSERT_EQ( 2u, history.size() );
ASSERT_EQ( m2->id(), history[0]->id() );
ASSERT_EQ( m->id(), history[1]->id() );
}
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