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

Library: Merge Library & MediaLibrary classes

parent fd920fc7
......@@ -17,7 +17,6 @@ vlmc_SOURCES = \
src/Backend/MLT/MLTMultiTrack.cpp \
src/EffectsEngine/EffectHelper.cpp \
src/Library/Library.cpp \
src/Library/MediaLibrary.cpp \
src/Library/MediaLibraryModel.cpp \
src/Main/Core.cpp \
src/Main/main.cpp \
......@@ -92,7 +91,6 @@ vlmc_SOURCES += \
src/Backend/IMultiTrack.h \
src/Main/Core.h \
src/Library/Library.h \
src/Library/MediaLibrary.h \
src/Library/MediaLibraryModel.h \
src/Workflow/Helper.h \
src/Workflow/Types.h \
......@@ -126,7 +124,6 @@ nodist_vlmc_SOURCES = \
src/Tools/OutputEventWatcher.moc.cpp \
src/Services/UploaderIODevice.moc.cpp \
src/Library/Library.moc.cpp \
src/Library/MediaLibrary.moc.cpp \
src/Library/MediaLibraryModel.moc.cpp \
src/Gui/library/MediaLibraryView.moc.cpp \
$(NULL)
......
......@@ -43,7 +43,6 @@
#include "Tools/VlmcDebug.h"
#include "Tools/VlmcLogger.h"
#include "Backend/IBackend.h"
#include "Library/MediaLibrary.h"
#include "Workflow/MainWorkflow.h"
#include "Renderer/ClipRenderer.h"
#include "Commands/AbstractUndoStack.h"
......@@ -108,7 +107,7 @@ MainWindow::MainWindow( Backend::IBackend* backend, QWidget *parent )
this, &MainWindow::updateRecentProjects );
// Connect the medialibrary before it starts discovering/reloading
connect( Core::instance()->mediaLibrary(), &MediaLibrary::progressUpdated, this,
connect( Core::instance()->library(), &Library::progressUpdated, this,
[this]( int percent ) {
if ( percent < 100 )
m_progressBar->setValue( percent );
......@@ -119,11 +118,11 @@ MainWindow::MainWindow( Backend::IBackend* backend, QWidget *parent )
}
});
connect( Core::instance()->mediaLibrary(), &MediaLibrary::discoveryStarted, this,
connect( Core::instance()->library(), &Library::discoveryStarted, this,
[this](const QString& folder) {
m_ui.statusbar->showMessage( "Discovering " + folder + "...", 2500 );
}, Qt::QueuedConnection );
connect( Core::instance()->mediaLibrary(), &MediaLibrary::discoveryCompleted, this,
connect( Core::instance()->library(), &Library::discoveryCompleted, this,
[this]( const QString& ) {
m_ui.statusbar->showMessage( "Analyzing media" );
}, Qt::QueuedConnection );
......
......@@ -27,7 +27,6 @@
#include "MediaLibraryView.h"
#include "Library/Library.h"
#include "Library/MediaLibrary.h"
#include "Library/MediaLibraryModel.h"
#include "Main/Core.h"
#include "Media/Media.h"
......@@ -53,7 +52,7 @@ MediaLibraryView::MediaLibraryView( QWidget* parent )
m_container->setObjectName( objectName() );
auto ctx = view->rootContext();
ctx->setContextProperty( QStringLiteral( "mlModel" ), Core::instance()->mediaLibrary()->model( MediaLibrary::MediaType::Video ) );
ctx->setContextProperty( QStringLiteral( "mlModel" ), Core::instance()->library()->model( Library::MediaType::Video ) );
ctx->setContextProperty( QStringLiteral( "view" ), this );
view->setSource( QUrl( QStringLiteral( "qrc:/qml/MediaLibraryView.qml" ) ) );
......@@ -78,7 +77,7 @@ MediaLibraryView::startDrag( qint64 mediaId )
QSharedPointer<Media> media = Core::instance()->library()->media( mediaId );
if ( media == nullptr ) {
media.reset( new Media( Core::instance()->mediaLibrary()->model( MediaLibrary::MediaType::Video )->findMedia( mediaId ) ) );
media.reset( new Media( Core::instance()->library()->model( Library::MediaType::Video )->findMedia( mediaId ) ) );
Core::instance()->library()->addMedia( media );
}
......
......@@ -34,6 +34,7 @@
#include "Library.h"
#include "Media/Clip.h"
#include "Media/Media.h"
#include "MediaLibraryModel.h"
#include "Project/Project.h"
#include "Settings/Settings.h"
#include "Tools/VlmcDebug.h"
......@@ -42,14 +43,27 @@
#include <QHash>
#include <QUuid>
Library::Library( Settings *projectSettings )
: m_cleanState( true )
Library::Library( Settings* vlmcSettings, Settings *projectSettings )
: m_initialized( false )
, m_cleanState( true )
, m_settings( new Settings )
{
// Setting up the external media library
m_ml.reset( NewMediaLibrary() );
m_videoModel = new MediaLibraryModel( *m_ml, medialibrary::IMedia::Type::VideoType, this );
m_audioModel = new MediaLibraryModel( *m_ml, medialibrary::IMedia::Type::AudioType, this );
auto s = vlmcSettings->createVar( SettingValue::List, QStringLiteral( "vlmc/mlDirs" ), QVariantList(),
"Media Library folders", "List of folders VLMC will search for media files",
SettingValue::Folders );
connect( s, &SettingValue::changed, this, &Library::mlDirsChanged );
auto ws = vlmcSettings->value( "vlmc/WorkspaceLocation" );
connect( ws, &SettingValue::changed, this, &Library::workspaceChanged );
// Setting up the project section of the Library
m_settings->createVar( SettingValue::List, QString( "medias" ), QVariantList(), "", "", SettingValue::Nothing );
connect( m_settings, &Settings::postLoad, this, &Library::postLoad, Qt::DirectConnection );
connect( m_settings, &Settings::preSave, this, &Library::preSave, Qt::DirectConnection );
projectSettings->addSettings( "Library", *m_settings );
}
......@@ -109,7 +123,27 @@ Library::media( qint64 mediaId )
return m_media.value( mediaId );
}
QSharedPointer<Clip> Library::clip( const QUuid& uuid )
medialibrary::MediaPtr
Library::mlMedia( qint64 mediaId )
{
return m_ml->media( mediaId );
}
MediaLibraryModel*
Library::model(Library::MediaType type) const
{
switch ( type )
{
case MediaType::Video:
return m_videoModel;
case MediaType::Audio:
return m_audioModel;
}
Q_UNREACHABLE();
}
QSharedPointer<Clip>
Library::clip( const QUuid& uuid )
{
return m_clips.value( uuid );
......@@ -132,3 +166,148 @@ Library::setCleanState( bool newState )
emit cleanStateChanged( newState );
}
}
void
Library::mlDirsChanged(const QVariant& value)
{
// We can't handle this event without an initialized media library, and therefor without a valid
// workspace. In theory, the workspace SettingValue is created before the mlDirs,
// so it should be loaded before.
Q_ASSERT( m_initialized == true );
const auto list = value.toStringList();
Q_ASSERT( list.empty() == false );
for ( const auto f : list )
m_ml->discover( f.toStdString() );
}
void
Library::workspaceChanged(const QVariant& workspace)
{
Q_ASSERT( workspace.isNull() == false && workspace.canConvert<QString>() );
if ( m_initialized == false )
{
auto w = workspace.toString().toStdString();
Q_ASSERT( w.empty() == false );
// Initializing the medialibrary doesn't start new folders discovery.
// This will happen after the first call to IMediaLibrary::discover()
m_ml->initialize( w + "/ml.db", w + "/thumbnails/", this );
m_initialized = true;
}
//else FIXME, and relocate the media library
}
void
Library::onMediaAdded( std::vector<medialibrary::MediaPtr> mediaList )
{
for ( auto m : mediaList )
{
switch ( m->type() )
{
case medialibrary::IMedia::Type::VideoType:
m_videoModel->addMedia( m );
break;
case medialibrary::IMedia::Type::AudioType:
m_audioModel->addMedia( m );
break;
default:
Q_UNREACHABLE();
}
}
}
void
Library::onMediaUpdated( std::vector<medialibrary::MediaPtr> mediaList )
{
for ( auto m : mediaList )
{
switch ( m->type() )
{
case medialibrary::IMedia::Type::VideoType:
m_videoModel->updateMedia( m );
break;
case medialibrary::IMedia::Type::AudioType:
m_audioModel->updateMedia( m );
break;
default:
Q_UNREACHABLE();
}
}
}
void
Library::onMediaDeleted( std::vector<int64_t> mediaList )
{
for ( auto id : mediaList )
{
// We can't know the media type, however ID are unique regardless of the type
// so we are sure that we will remove the correct media.
if ( m_videoModel->removeMedia( id ) == true )
continue;
m_audioModel->removeMedia( id );
}
}
void
Library::onArtistsAdded( std::vector<medialibrary::ArtistPtr> )
{
}
void
Library::onArtistsModified( std::vector<medialibrary::ArtistPtr> )
{
}
void
Library::onArtistsDeleted( std::vector<int64_t> )
{
}
void
Library::onAlbumsAdded( std::vector<medialibrary::AlbumPtr> )
{
}
void
Library::onAlbumsModified( std::vector<medialibrary::AlbumPtr> )
{
}
void
Library::onAlbumsDeleted( std::vector<int64_t> )
{
}
void
Library::onTracksAdded( std::vector<medialibrary::AlbumTrackPtr> )
{
}
void
Library::onTracksDeleted( std::vector<int64_t> )
{
}
void
Library::onDiscoveryStarted( const std::string& entryPoint )
{
emit discoveryStarted( QString::fromStdString( entryPoint ) );
}
void
Library::onDiscoveryCompleted( const std::string& entryPoint )
{
if ( entryPoint.empty() == true )
{
m_videoModel->refresh();
m_audioModel->refresh();
}
emit discoveryCompleted( QString::fromStdString( entryPoint ) );
}
void
Library::onParsingStatsUpdated( uint32_t percent )
{
emit progressUpdated( static_cast<int>( percent ) );
}
......@@ -34,8 +34,13 @@
#include <QHash>
#include <QSharedPointer>
#include <medialibrary/IMediaLibrary.h>
#include <memory>
class Clip;
class Media;
class MediaLibraryModel;
class ProjectManager;
class Settings;
......@@ -43,17 +48,29 @@ class Settings;
* \class Library
* \brief Library Object that handles public Clips
*/
class Library : public QObject
class Library : public QObject, private medialibrary::IMediaLibraryCb
{
Q_OBJECT
Q_DISABLE_COPY( Library )
public:
Library( Settings* projectSettings );
enum class MediaType
{
Video,
Audio
};
Library( Settings* vlmcSettings, Settings* projectSettings );
virtual ~Library();
void addMedia( QSharedPointer<Media> media );
bool isInCleanState() const;
QSharedPointer<Media> media( qint64 mediaId );
//FIXME: This feels rather ugly
medialibrary::MediaPtr mlMedia( qint64 mediaId);
MediaLibraryModel* model( MediaType type ) const;
/**
* @brief clip returns an existing clip
* @param uuid the clip's UUID
......@@ -65,26 +82,53 @@ public:
private:
void setCleanState( bool newState );
void mlDirsChanged( const QVariant& value );
void workspaceChanged(const QVariant& workspace );
void preSave();
void postLoad();
private:
virtual void onMediaAdded( std::vector<medialibrary::MediaPtr> media ) override;
virtual void onMediaUpdated( std::vector<medialibrary::MediaPtr> media ) override;
virtual void onMediaDeleted( std::vector<int64_t> ids ) override;
virtual void onArtistsAdded( std::vector<medialibrary::ArtistPtr> artists ) override;
virtual void onArtistsModified( std::vector<medialibrary::ArtistPtr> artist ) override;
virtual void onArtistsDeleted( std::vector<int64_t> ids ) override;
virtual void onAlbumsAdded( std::vector<medialibrary::AlbumPtr> albums ) override;
virtual void onAlbumsModified( std::vector<medialibrary::AlbumPtr> albums ) override;
virtual void onAlbumsDeleted( std::vector<int64_t> ids ) override;
virtual void onTracksAdded( std::vector<medialibrary::AlbumTrackPtr> tracks ) override;
virtual void onTracksDeleted( std::vector<int64_t> trackIds ) override;
virtual void onDiscoveryStarted( const std::string& entryPoint ) override;
virtual void onDiscoveryCompleted( const std::string& entryPoint ) override;
virtual void onParsingStatsUpdated( uint32_t percent ) override;
private:
bool m_cleanState;
std::unique_ptr<medialibrary::IMediaLibrary> m_ml;
MediaLibraryModel* m_videoModel;
MediaLibraryModel* m_audioModel;
Settings* m_settings;
bool m_initialized;
bool m_cleanState;
Settings* m_settings;
QHash<qint64, QSharedPointer<Media>> m_media;
QHash<qint64, QSharedPointer<Media>> m_media;
/**
* @brief m_clips contains all the clips loaded in the library, without any
* subclip hierarchy
*/
QHash<QUuid, QSharedPointer<Clip>> m_clips;
void preSave();
void postLoad();
QHash<QUuid, QSharedPointer<Clip>> m_clips;
signals:
/**
* \brief
*/
void cleanStateChanged( bool newState );
void progressUpdated( int percent );
void discoveryStarted( QString );
void discoveryCompleted( QString );
};
#endif // LIBRARY_H
/*****************************************************************************
* MediaLibrary.cpp: Wraps the media library
*****************************************************************************
* Copyright (C) 2008-2016 VideoLAN
*
* Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include "MediaLibrary.h"
#include "Settings/Settings.h"
#include "MediaLibraryModel.h"
MediaLibrary::MediaLibrary( Settings* settings )
: m_initialized( false )
{
m_ml.reset( NewMediaLibrary() );
m_videoModel = new MediaLibraryModel( *m_ml, medialibrary::IMedia::Type::VideoType, this );
m_audioModel = new MediaLibraryModel( *m_ml, medialibrary::IMedia::Type::AudioType, this );
auto s = settings->createVar( SettingValue::List, QStringLiteral( "vlmc/mlDirs" ), QVariantList(),
"Media Library folders", "List of folders VLMC will search for media files",
SettingValue::Folders );
connect( s, &SettingValue::changed, this, &MediaLibrary::mlDirsChanged );
auto ws = settings->value( "vlmc/WorkspaceLocation" );
connect( ws, &SettingValue::changed, this, &MediaLibrary::workspaceChanged );
}
MediaLibraryModel* MediaLibrary::model( MediaLibrary::MediaType type ) const
{
switch ( type )
{
case MediaType::Video:
return m_videoModel;
case MediaType::Audio:
return m_audioModel;
}
Q_UNREACHABLE();
}
medialibrary::MediaPtr
MediaLibrary::media( qint64 mediaId ) const
{
return m_ml->media( mediaId );
}
void
MediaLibrary::mlDirsChanged( const QVariant& value )
{
// We can't handle this event without an initialized media library, and therefor without a valid
// workspace. In theory, the workspace SettingValue is created before the mlDirs,
// so it should be loaded before.
Q_ASSERT( m_initialized == true );
const auto list = value.toStringList();
Q_ASSERT( list.empty() == false );
for ( const auto f : list )
m_ml->discover( f.toStdString() );
}
void
MediaLibrary::workspaceChanged( const QVariant& workspace )
{
Q_ASSERT( workspace.isNull() == false && workspace.canConvert<QString>() );
if ( m_initialized == false )
{
auto w = workspace.toString().toStdString();
Q_ASSERT( w.empty() == false );
// Initializing the medialibrary doesn't start new folders discovery.
// This will happen after the first call to IMediaLibrary::discover()
m_ml->initialize( w + "/ml.db", w + "/thumbnails/", this );
m_initialized = true;
}
//else FIXME, and relocate the media library
}
void MediaLibrary::onMediaAdded( std::vector<medialibrary::MediaPtr> mediaList )
{
for ( auto m : mediaList )
{
switch ( m->type() )
{
case medialibrary::IMedia::Type::VideoType:
m_videoModel->addMedia( m );
break;
case medialibrary::IMedia::Type::AudioType:
m_audioModel->addMedia( m );
break;
default:
Q_UNREACHABLE();
}
}
}
void MediaLibrary::onMediaUpdated( std::vector<medialibrary::MediaPtr> mediaList )
{
for ( auto m : mediaList )
{
switch ( m->type() )
{
case medialibrary::IMedia::Type::VideoType:
m_videoModel->updateMedia( m );
break;
case medialibrary::IMedia::Type::AudioType:
m_audioModel->updateMedia( m );
break;
default:
Q_UNREACHABLE();
}
}
}
void MediaLibrary::onMediaDeleted( std::vector<int64_t> mediaList )
{
for ( auto id : mediaList )
{
// We can't know the media type, however ID are unique regardless of the type
// so we are sure that we will remove the correct media.
if ( m_videoModel->removeMedia( id ) == true )
continue;
m_audioModel->removeMedia( id );
}
}
void MediaLibrary::onArtistsAdded( std::vector<medialibrary::ArtistPtr> )
{
}
void MediaLibrary::onArtistsModified( std::vector<medialibrary::ArtistPtr> )
{
}
void MediaLibrary::onArtistsDeleted( std::vector<int64_t> )
{
}
void MediaLibrary::onAlbumsAdded( std::vector<medialibrary::AlbumPtr> )
{
}
void MediaLibrary::onAlbumsModified( std::vector<medialibrary::AlbumPtr> )
{
}
void MediaLibrary::onAlbumsDeleted( std::vector<int64_t> )
{
}
void MediaLibrary::onTracksAdded( std::vector<medialibrary::AlbumTrackPtr> )
{
}
void MediaLibrary::onTracksDeleted( std::vector<int64_t> )
{
}
void MediaLibrary::onDiscoveryStarted( const std::string& entryPoint )
{
emit discoveryStarted( QString::fromStdString( entryPoint ) );
}
void MediaLibrary::onDiscoveryCompleted( const std::string& entryPoint )
{
if ( entryPoint.empty() == true )
{
m_videoModel->refresh();
m_audioModel->refresh();
}
emit discoveryCompleted( QString::fromStdString( entryPoint ) );
}
void MediaLibrary::onParsingStatsUpdated( uint32_t percent )
{
emit progressUpdated( static_cast<int>( percent ) );
}
/*****************************************************************************
* MediaLibrary.h: Wraps the media library
*****************************************************************************
* Copyright (C) 2008-2016 VideoLAN
*
* Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef MEDIALIBRARY_H
#define MEDIALIBRARY_H
#include <medialibrary/IMediaLibrary.h>
#include <QObject>
#include <memory>
class Settings;
class MediaLibraryModel;
class MediaLibrary : public QObject, private medialibrary::IMediaLibraryCb
{
Q_OBJECT
Q_DISABLE_COPY( MediaLibrary )
public:
enum class MediaType
{
Video,
Audio
};
explicit MediaLibrary( Settings* settings );
MediaLibraryModel* model( MediaType type ) const;
medialibrary::MediaPtr media( qint64 mediaId ) const;
signals:
void progressUpdated( int percent );
void discoveryStarted( QString );
void discoveryCompleted( QString );
private:
void mlDirsChanged( const QVariant& value );
void workspaceChanged(const QVariant& workspace );
private:
virtual void onMediaAdded( std::vector<medialibrary::MediaPtr> media ) override;
virtual void onMediaUpdated( std::vector<medialibrary::MediaPtr> media ) override;
virtual void onMediaDeleted( std::vector<int64_t> ids ) override;
virtual void onArtistsAdded( std::vector<medialibrary::ArtistPtr> artists ) override;
virtual void onArtistsModified( std::vector<medialibrary::ArtistPtr> artist ) override;
virtual void onArtistsDeleted( std::vector<int64_t> ids ) override;
virtual void onAlbumsAdded( std::vector<medialibrary::AlbumPtr> albums ) override;
virtual void onAlbumsModified( std::vector<medialibrary::AlbumPtr> albums ) override;
virtual void onAlbumsDeleted( std::vector<int64_t> ids ) override;
virtual void onTracksAdded( std::vector<medialibrary::AlbumTrackPtr> tracks ) override;
virtual void onTracksDeleted( std::vector<int64_t> trackIds ) override;
virtual void onDiscoveryStarted( const std::string& entryPoint ) override;
virtual void onDiscoveryCompleted( const std::string& entryPoint ) override;
virtual void onParsingStatsUpdated( uint32_t percent ) override;
private:
std::unique_ptr<medialibrary::IMediaLibrary> m_ml;
MediaLibraryModel* m_videoModel;
MediaLibraryModel* m_audioModel;
bool m_initialized;
};
#endif // MEDIALIBRARY_H
......@@ -34,7 +34,6 @@
#include <Backend/IBackend.h>
#include "Library/Library.h"
#include "Library/MediaLibrary.h"
#include "Project/RecentProjects.h"
#include "Project/Workspace.h"
#include <Settings/Settings.h>
......@@ -48,10 +47,9 @@ Core::Core()
createSettings();
m_currentProject = new Project( m_settings );
m_library = new Library( m_currentProject->settings() );
m_library = new Library( m_settings, m_currentProject->settings() );
m_recentProjects = new RecentProjects( m_settings );
m_workspace = new Workspace( m_settings );
m_ml.reset( new MediaLibrary( m_settings ) );
m_workflow = new MainWorkflow( m_currentProject->settings() );
QObject::connect( m_workflow, &MainWorkflow::cleanChanged, m_currentProject, &Project::cleanChanged );
......@@ -156,12 +154,6 @@ Core::library()
return m_library;
}
MediaLibrary*
Core::mediaLibrary()
{
return m_ml.get();
}
qint64
Core::runtime()
{
......
......@@ -26,7 +26,6 @@
class AutomaticBackup;
class Library;
class MainWorkflow;
class MediaLibrary;
class Project;
class RecentProjects;
class Settings;
......@@ -52,7 +51,6 @@ class Core : public ScopedSingleton<Core>
Project* project();
MainWorkflow* workflow();
Library* library();
MediaLibrary* mediaLibrary();
/**
* @brief runtime returns the application runtime
*/
......@@ -77,7 +75,6 @@ class Core : public ScopedSingleton<Core>
Project* m_currentProject;
MainWorkflow* m_workflow;
Library* m_library;
std::unique_ptr<MediaLibrary> m_ml;
QElapsedTimer m_timer;
friend Singleton_t::AllowInstantiation;
......
......@@ -40,7 +40,6 @@
#include "Clip.h"
#include "Main/Core.h"
#include "Library/Library.h"
#include "Library/MediaLibrary.h"
#include "Tools/VlmcDebug.h"
#include "Project/Workspace.h"
......@@ -191,7 +190,7 @@ Media::fromVariant( const QVariant& v )
}