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

Metadata: Handle metadata for multiple types

parent 0f94a8d4
......@@ -34,7 +34,7 @@ namespace medialibrary
class IAlbumTrack;
class IShowEpisode;
class ITrackInformation;
class IMediaMetadata;
class IMetadata;
class IMedia
{
......@@ -150,7 +150,7 @@ class IMedia
/// \param type The metadata type
/// \return A reference to a wrapper object representing the metadata.
///
virtual const IMediaMetadata& metadata( MetadataType type ) const = 0;
virtual const IMetadata& metadata( MetadataType type ) const = 0;
///
/// \brief setMetadata Immediatly saves a metadata in database
///
......
......@@ -27,10 +27,14 @@
namespace medialibrary
{
class IMediaMetadata
class IMetadata
{
public:
virtual ~IMediaMetadata() = default;
enum class EntityType : uint8_t
{
Media = 1,
};
virtual ~IMetadata() = default;
virtual bool isSet() const = 0;
virtual int64_t integer() const = 0;
virtual const std::string& str() const = 0;
......
......@@ -59,7 +59,7 @@ int64_t Media::* const policy::MediaTable::PrimaryKey = &Media::m_id;
Media::Media( MediaLibraryPtr ml, sqlite::Row& row )
: m_ml( ml )
, m_metadata( m_ml )
, m_metadata( m_ml, IMetadata::EntityType::Media )
, m_changed( false )
{
row >> m_id
......@@ -95,7 +95,7 @@ Media::Media( MediaLibraryPtr ml, const std::string& title, Type type )
, m_filename( title )
, m_isFavorite( false )
, m_isPresent( true )
, m_metadata( m_ml )
, m_metadata( m_ml, IMetadata::EntityType::Media )
, m_changed( false )
{
}
......@@ -298,25 +298,28 @@ unsigned int Media::releaseDate() const
return m_releaseDate;
}
const IMediaMetadata& Media::metadata( IMedia::MetadataType type ) const
const IMetadata& Media::metadata( IMedia::MetadataType type ) const
{
using MDType = typename std::underlying_type<IMedia::MetadataType>::type;
if ( m_metadata.isReady() == false )
m_metadata.init( m_id, IMedia::NbMeta );
return m_metadata.get( type );
return m_metadata.get( static_cast<MDType>( type ) );
}
bool Media::setMetadata( IMedia::MetadataType type, const std::string& value )
{
using MDType = typename std::underlying_type<IMedia::MetadataType>::type;
if ( m_metadata.isReady() == false )
m_metadata.init( m_id, IMedia::NbMeta );
return m_metadata.set( type, value );
return m_metadata.set( static_cast<MDType>( type ), value );
}
bool Media::setMetadata( IMedia::MetadataType type, int64_t value )
{
using MDType = typename std::underlying_type<IMedia::MetadataType>::type;
if ( m_metadata.isReady() == false )
m_metadata.init( m_id, IMedia::NbMeta );
return m_metadata.set( type, value );
return m_metadata.set( static_cast<MDType>( type ), value );
}
void Media::setReleaseDate( unsigned int date )
......@@ -695,12 +698,14 @@ void Media::clearHistory( MediaLibraryPtr ml )
static const std::string req = "UPDATE " + policy::MediaTable::Name + " SET "
"play_count = 0,"
"last_played_date = NULL";
static const std::string flushProgress = "DELETE FROM " + policy::MediaMetadataTable::Name +
" WHERE type = ?";
// Clear the entire cache since quite a few items are now containing invalid info.
clear();
using MDType = typename std::underlying_type<IMedia::MetadataType>::type;
Metadata::unset( dbConn, IMetadata::EntityType::Media,
static_cast<MDType>( IMedia::MetadataType::Progress ) );
sqlite::Tools::executeUpdate( dbConn, req );
sqlite::Tools::executeDelete( dbConn, flushProgress, IMedia::MetadataType::Progress );
}
}
......@@ -110,7 +110,7 @@ class Media : public IMedia, public DatabaseHelpers<Media, policy::MediaTable>
virtual unsigned int insertionDate() const override;
virtual unsigned int releaseDate() const override;
virtual const IMediaMetadata& metadata( MetadataType type ) const override;
virtual const IMetadata& metadata( MetadataType type ) const override;
virtual bool setMetadata( MetadataType type, const std::string& value ) override;
virtual bool setMetadata( MetadataType type, int64_t value ) override;
......@@ -159,7 +159,7 @@ private:
mutable Cache<ShowEpisodePtr> m_showEpisode;
mutable Cache<MoviePtr> m_movie;
mutable Cache<std::vector<FilePtr>> m_files;
mutable MediaMetadata m_metadata;
mutable Metadata m_metadata;
mutable Cache<std::shared_ptr<Thumbnail>> m_thumbnail;
bool m_changed;
......
......@@ -169,7 +169,7 @@ void MediaLibrary::createAllTables()
History::createTable( m_dbConnection.get() );
Settings::createTable( m_dbConnection.get() );
parser::Task::createTable( m_dbConnection.get() );
MediaMetadata::createTable( m_dbConnection.get() );
Metadata::createTable( m_dbConnection.get() );
}
void MediaLibrary::createAllTriggers()
......
......@@ -33,44 +33,45 @@
namespace medialibrary
{
const std::string policy::MediaMetadataTable::Name = "MediaMetadata";
const std::string policy::MetadataTable::Name = "MediaMetadata";
MediaMetadata::Record::Record( IMedia::MetadataType t, std::string v )
Metadata::Record::Record( uint32_t t, std::string v )
: m_type( t )
, m_value( std::move( v ) )
, m_isSet( true )
{
}
MediaMetadata::Record::Record( IMedia::MetadataType t )
Metadata::Record::Record( uint32_t t )
: m_type( t )
, m_isSet( false )
{
}
bool MediaMetadata::Record::isSet() const
bool Metadata::Record::isSet() const
{
return m_isSet;
}
int64_t MediaMetadata::Record::integer() const
int64_t Metadata::Record::integer() const
{
return atoll( m_value.c_str() );
}
const std::string& MediaMetadata::Record::str() const
const std::string& Metadata::Record::str() const
{
return m_value;
}
MediaMetadata::MediaMetadata( MediaLibraryPtr ml )
Metadata::Metadata(MediaLibraryPtr ml , IMetadata::EntityType entityType)
: m_ml( ml )
, m_entityType( entityType )
, m_nbMeta( 0 )
, m_entityId( 0 )
{
}
void MediaMetadata::init( int64_t entityId, uint32_t nbMeta )
void Metadata::init( int64_t entityId, uint32_t nbMeta )
{
if ( isReady() == true )
return;
......@@ -82,26 +83,27 @@ void MediaMetadata::init( int64_t entityId, uint32_t nbMeta )
// to another IMediaMetadata held by another thread.
// This guarantees the vector will not grow afterward.
m_records.reserve( m_nbMeta );
static const std::string req = "SELECT * FROM " + policy::MediaMetadataTable::Name +
" WHERE id_media = ?";
static const std::string req = "SELECT * FROM " + policy::MetadataTable::Name +
" WHERE id_media = ? AND entity_type = ?";
auto conn = m_ml->getConn();
auto ctx = conn->acquireReadContext();
sqlite::Statement stmt( conn->handle(), req );
stmt.execute( m_entityId );
stmt.execute( m_entityId, m_entityType );
for ( sqlite::Row row = stmt.row(); row != nullptr; row = stmt.row() )
{
assert( row.load<int64_t>( 0 ) == m_entityId );
m_records.emplace_back( row.load<decltype(Record::m_type)>( 1 ),
row.load<decltype(Record::m_value)>( 2 ) );
assert( row.load<IMetadata::EntityType>( 1 ) == m_entityType );
m_records.emplace_back( row.load<decltype(Record::m_type)>( 2 ),
row.load<decltype(Record::m_value)>( 3 ) );
}
}
bool MediaMetadata::isReady() const
bool Metadata::isReady() const
{
return m_nbMeta != 0;
}
IMediaMetadata&MediaMetadata::get( IMedia::MetadataType type ) const
IMetadata& Metadata::get( uint32_t type ) const
{
assert( isReady() == true );
......@@ -118,7 +120,7 @@ IMediaMetadata&MediaMetadata::get( IMedia::MetadataType type ) const
return *it;
}
bool MediaMetadata::set( IMedia::MetadataType type, const std::string& value )
bool Metadata::set( uint32_t type, const std::string& value )
{
assert( isReady() == true );
......@@ -131,9 +133,10 @@ bool MediaMetadata::set( IMedia::MetadataType type, const std::string& value )
m_records.emplace_back( type, value );
try
{
static const std::string req = "INSERT OR REPLACE INTO " + policy::MediaMetadataTable::Name +
"(id_media, type, value) VALUES(?, ?, ?)";
return sqlite::Tools::executeInsert( m_ml->getConn(), req, m_entityId, type, value );
static const std::string req = "INSERT OR REPLACE INTO " + policy::MetadataTable::Name +
"(id_media, entity_type, type, value) VALUES(?, ?, ?, ?)";
return sqlite::Tools::executeInsert( m_ml->getConn(), req, m_entityId, m_entityType,
type, value );
}
catch ( const sqlite::errors::Generic& ex )
{
......@@ -142,16 +145,24 @@ bool MediaMetadata::set( IMedia::MetadataType type, const std::string& value )
}
}
bool MediaMetadata::set( IMedia::MetadataType type, int64_t value )
bool Metadata::set( uint32_t type, int64_t value )
{
auto str = std::to_string( value );
return set( type, str );
}
void MediaMetadata::createTable(sqlite::Connection* connection)
void Metadata::unset( sqlite::Connection* dbConn, IMetadata::EntityType entityType, uint32_t type )
{
const std::string req = "CREATE TABLE IF NOT EXISTS " + policy::MediaMetadataTable::Name + "("
static const std::string req = "DELETE FROM " + policy::MetadataTable::Name +
" WHERE entity_type = ? AND type = ? ";
sqlite::Tools::executeDelete( dbConn, req, entityType, type );
}
void Metadata::createTable(sqlite::Connection* connection)
{
const std::string req = "CREATE TABLE IF NOT EXISTS " + policy::MetadataTable::Name + "("
"id_media INTEGER,"
"entity_type INTEGER,"
"type INTEGER,"
"value TEXT,"
"PRIMARY KEY (id_media, type)"
......@@ -159,7 +170,7 @@ void MediaMetadata::createTable(sqlite::Connection* connection)
sqlite::Tools::executeRequest( connection, req );
}
void MediaMetadata::Record::set( const std::string& value )
void Metadata::Record::set( const std::string& value )
{
m_value = value;
m_isSet = true;
......
......@@ -36,16 +36,16 @@ class Connection;
namespace policy
{
struct MediaMetadataTable
struct MetadataTable
{
static const std::string Name;
};
}
class MediaMetadata
class Metadata
{
public:
MediaMetadata( MediaLibraryPtr ml );
Metadata( MediaLibraryPtr ml, IMetadata::EntityType entityType );
// We have to "lazy init" this object since during containing object creation,
// we might not know the ID yet (for instance. when instantiating the
......@@ -53,34 +53,37 @@ public:
void init( int64_t entityId, uint32_t nbMeta );
bool isReady() const;
IMediaMetadata& get( IMedia::MetadataType type ) const;
bool set( IMedia::MetadataType type, const std::string& value );
bool set( IMedia::MetadataType type, int64_t value );
IMetadata& get( uint32_t type ) const;
bool set( uint32_t type, const std::string& value );
bool set( uint32_t type, int64_t value );
static void unset( sqlite::Connection* dbConn, IMetadata::EntityType entityType, uint32_t type );
static void createTable( sqlite::Connection* connection );
private:
class Record : public IMediaMetadata
class Record : public IMetadata
{
public:
virtual ~Record() = default;
Record( IMedia::MetadataType t, std::string v );
Record( IMedia::MetadataType t );
Record( uint32_t t, std::string v );
Record( uint32_t t );
virtual bool isSet() const override;
virtual int64_t integer() const override;
virtual const std::string& str() const override;
void set( const std::string& value );
private:
IMedia::MetadataType m_type;
uint32_t m_type;
std::string m_value;
bool m_isSet;
friend MediaMetadata;
friend Metadata;
};
private:
MediaLibraryPtr m_ml;
IMetadata::EntityType m_entityType;
uint32_t m_nbMeta;
int64_t m_entityId;
mutable std::vector<Record> m_records;
......
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