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

Refactor Parser & Services

This cleans the way we signal task completion, reduces contention, and
will allow us to handle multithreading better
parent b37a0da0
......@@ -70,6 +70,7 @@ list(APPEND SRC_LIST ${HEADERS_LIST}
Playlist.cpp
parser/Parser.cpp
parser/ParserService.cpp
factory/FileSystem.cpp
filesystem/common/CommonFile.cpp
......
......@@ -35,7 +35,6 @@
#include "Folder.h"
#include "Media.h"
#include "MediaLibrary.h"
#include "IMetadataService.h"
#include "Label.h"
#include "logging/Logger.h"
#include "Movie.h"
......@@ -365,20 +364,9 @@ bool MediaLibrary::deletePlaylist( unsigned int playlistId )
return Playlist::destroy( m_dbConnection.get(), playlistId );
}
void MediaLibrary::addMetadataService(std::unique_ptr<IMetadataService> service)
{
if ( service->initialize( m_parser.get(), this ) == false )
{
//FIXME: This is missing a name or something more specific
LOG_ERROR( "Failed to initialize service" );
return;
}
m_parser->addService( std::move( service ) );
}
void MediaLibrary::startParser()
{
m_parser.reset( new Parser( m_dbConnection.get(), m_callback ) );
m_parser.reset( new Parser( m_dbConnection.get(), this, m_callback ) );
const char* args[] = {
"-vv",
......@@ -397,8 +385,8 @@ void MediaLibrary::startParser()
auto vlcService = std::unique_ptr<VLCMetadataService>( new VLCMetadataService( m_vlcInstance, m_dbConnection.get(), m_fsFactory ) );
auto thumbnailerService = std::unique_ptr<VLCThumbnailer>( new VLCThumbnailer( m_vlcInstance ) );
addMetadataService( std::move( vlcService ) );
addMetadataService( std::move( thumbnailerService ) );
m_parser->addService( std::move( vlcService ) );
m_parser->addService( std::move( thumbnailerService ) );
m_parser->start();
}
......
......@@ -24,6 +24,7 @@
#define MEDIALIBRARY_H
class Parser;
class ParserService;
class DiscovererWorker;
class SqliteConnection;
......@@ -100,7 +101,6 @@ class MediaLibrary : public IMediaLibrary
static const std::vector<std::string> supportedAudioExtensions;
private:
void addMetadataService( std::unique_ptr<IMetadataService> service );
virtual void startParser();
virtual void startDiscoverer();
bool updateDatabaseModel( unsigned int previousVersion );
......
......@@ -31,37 +31,30 @@
#include "Show.h"
#include "utils/Filename.h"
VLCMetadataService::VLCMetadataService(const VLC::Instance& vlc, DBConnection dbConnection, std::shared_ptr<factory::IFileSystem> fsFactory )
VLCMetadataService::VLCMetadataService( const VLC::Instance& vlc, DBConnection dbConnection, std::shared_ptr<factory::IFileSystem> fsFactory )
: m_instance( vlc )
, m_cb( nullptr )
, m_ml( nullptr )
, m_dbConn( dbConnection )
, m_fsFactory( fsFactory )
{
}
bool VLCMetadataService::initialize( IMetadataServiceCb* callback, MediaLibrary* ml )
bool VLCMetadataService::initialize()
{
m_cb = callback;
m_ml = ml;
m_ml = mediaLibrary();
m_unknownArtist = Artist::fetch( m_dbConn, medialibrary::UnknownArtistID );
if ( m_unknownArtist == nullptr )
LOG_ERROR( "Failed to cache unknown artist" );
return m_unknownArtist != nullptr;
}
unsigned int VLCMetadataService::priority() const
{
return 100;
}
void VLCMetadataService::run(std::shared_ptr<Media> media, std::shared_ptr<File> file, void* data )
parser::Task::Status VLCMetadataService::run( parser::Task& task )
{
auto media = task.media;
auto file = task.file;
if ( media->duration() != -1 )
{
LOG_INFO( file->mrl(), " was already parsed" );
m_cb->done( media, file, Status::Success, data );
return;
return parser::Task::Status::Success;
}
LOG_INFO( "Parsing ", file->mrl() );
auto chrono = std::chrono::steady_clock::now();
......@@ -86,23 +79,20 @@ void VLCMetadataService::run(std::shared_ptr<Media> media, std::shared_ptr<File>
ctx->vlcMedia.parseAsync();
auto success = m_cond.wait_for( lock, std::chrono::seconds( 5 ), [&done]() { return done == true; } );
if ( success == false )
m_cb->done( ctx->media, file, Status::Fatal, data );
else
{
auto status = handleMediaMeta( media, file, ctx->vlcMedia );
m_cb->done( ctx->media, file, status, data );
}
return parser::Task::Status::Fatal;
auto status = handleMediaMeta( media, file, ctx->vlcMedia );
auto duration = std::chrono::steady_clock::now() - chrono;
LOG_DEBUG( "Parsed ", file->mrl(), " in ", std::chrono::duration_cast<std::chrono::milliseconds>( duration ).count(), "ms" );
return status;
}
IMetadataService::Status VLCMetadataService::handleMediaMeta( std::shared_ptr<Media> media, std::shared_ptr<File> file, VLC::Media& vlcMedia ) const
parser::Task::Status VLCMetadataService::handleMediaMeta( std::shared_ptr<Media> media, std::shared_ptr<File> file, VLC::Media& vlcMedia ) const
{
const auto tracks = vlcMedia.tracks();
if ( tracks.size() == 0 )
{
LOG_ERROR( "Failed to fetch tracks" );
return Status::Fatal;
return parser::Task::Status::Fatal;
}
auto t = m_dbConn->newTransaction();
......@@ -127,18 +117,18 @@ IMetadataService::Status VLCMetadataService::handleMediaMeta( std::shared_ptr<Me
if ( isAudio == true )
{
if ( parseAudioFile( *media, *file, vlcMedia ) == false )
return Status::Fatal;
return parser::Task::Status::Fatal;
}
else
{
if (parseVideoFile( media, vlcMedia ) == false )
return Status::Fatal;
return parser::Task::Status::Fatal;
}
auto duration = vlcMedia.duration();
media->setDuration( duration );
if ( media->save() == false )
return Status::Error;
return Status::Success;
return parser::Task::Status::Error;
return parser::Task::Status::Success;
}
/* Video files */
......
......@@ -27,15 +27,16 @@
#include <vlcpp/vlc.hpp>
#include <mutex>
#include "IMetadataService.h"
#include "parser/ParserService.h"
#include "MediaLibrary.h"
#include "AlbumTrack.h"
class VLCMetadataService : public IMetadataService
class VLCMetadataService : public ParserService
{
struct Context
{
explicit Context( std::shared_ptr<Media> media_ )
: media( media_ )
explicit Context( std::shared_ptr<Media> media )
: media( media )
{
}
......@@ -44,14 +45,13 @@ class VLCMetadataService : public IMetadataService
};
public:
explicit VLCMetadataService(const VLC::Instance& vlc, DBConnection dbConnection, std::shared_ptr<factory::IFileSystem> fsFactory);
explicit VLCMetadataService( const VLC::Instance& vlc, DBConnection dbConnection, std::shared_ptr<factory::IFileSystem> fsFactory );
virtual bool initialize( IMetadataServiceCb *callback, MediaLibrary* ml ) override;
virtual unsigned int priority() const override;
virtual void run( std::shared_ptr<Media> media, std::shared_ptr<File> file, void *data ) override;
virtual bool initialize() override;
virtual parser::Task::Status run( parser::Task& task ) override;
private:
Status handleMediaMeta(std::shared_ptr<Media> media , std::shared_ptr<File> file, VLC::Media &vlcMedia ) const;
parser::Task::Status handleMediaMeta(std::shared_ptr<Media> media , std::shared_ptr<File> file, VLC::Media &vlcMedia ) const;
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 parseVideoFile( std::shared_ptr<Media> media, VLC::Media& vlcMedia ) const;
......@@ -61,14 +61,13 @@ private:
std::shared_ptr<Album> handleAlbum(Media& media, File& file, VLC::Media& vlcMedia, std::shared_ptr<Artist> albumArtist, std::shared_ptr<Artist> artist ) const;
VLC::Instance m_instance;
IMetadataServiceCb* m_cb;
MediaLibrary* m_ml;
std::vector<Context*> m_keepAlive;
std::mutex m_mutex;
std::condition_variable m_cond;
DBConnection m_dbConn;
std::shared_ptr<factory::IFileSystem> m_fsFactory;
std::shared_ptr<Artist> m_unknownArtist;
MediaLibrary* m_ml;
};
#endif // VLCMETADATASERVICE_H
......@@ -42,9 +42,8 @@
#include "logging/Logger.h"
#include "MediaLibrary.h"
VLCThumbnailer::VLCThumbnailer(const VLC::Instance &vlc)
VLCThumbnailer::VLCThumbnailer( const VLC::Instance &vlc )
: m_instance( vlc )
, m_cb( nullptr )
, m_ml( nullptr )
#ifdef WITH_EVAS
, m_canvas( nullptr, &evas_free )
......@@ -86,40 +85,33 @@ VLCThumbnailer::~VLCThumbnailer()
#endif
}
bool VLCThumbnailer::initialize(IMetadataServiceCb *callback, MediaLibrary* ml)
bool VLCThumbnailer::initialize()
{
m_cb = callback;
m_ml = ml;
m_ml = mediaLibrary();
return true;
}
unsigned int VLCThumbnailer::priority() const
parser::Task::Status VLCThumbnailer::run( parser::Task& task )
{