From 0cef0d32ee9383576724e10d209d6c0ea6f695c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Mon, 14 Sep 2020 15:32:32 +0200 Subject: [PATCH 01/17] fs: IFile: Remove LinkFileType And just use medialibrary::IFile::Type instead We soon will also expose the file type directly, and we don't want to duplicate the type again, so just use the regular file type for fs::IFile as well --- include/medialibrary/filesystem/IFile.h | 12 ++---------- src/discoverer/FsDiscoverer.cpp | 21 +++++---------------- src/filesystem/common/CommonFile.cpp | 8 ++++---- src/filesystem/common/CommonFile.h | 6 +++--- src/filesystem/libvlc/Directory.cpp | 12 ++++++------ src/filesystem/libvlc/Directory.h | 2 +- src/filesystem/libvlc/File.cpp | 2 +- src/filesystem/libvlc/File.h | 2 +- test/unittest/mocks/FileSystem.h | 4 ++-- test/unittest/mocks/filesystem/MockFile.cpp | 4 ++-- test/unittest/mocks/filesystem/MockFile.h | 2 +- 11 files changed, 28 insertions(+), 47 deletions(-) diff --git a/include/medialibrary/filesystem/IFile.h b/include/medialibrary/filesystem/IFile.h index 1bd6511d..6e2bcd81 100644 --- a/include/medialibrary/filesystem/IFile.h +++ b/include/medialibrary/filesystem/IFile.h @@ -24,6 +24,7 @@ #include #include +#include "medialibrary/IFile.h" namespace medialibrary { @@ -33,15 +34,6 @@ namespace fs class IFile { public: - enum class LinkedFileType : uint8_t - { - ///< This file is not a linked file - None, - ///< This is a linked subtitle file - Subtitles, - ///< This is a linked soundtrack file - SoundTrack, - }; virtual ~IFile() = default; /// Returns the URL encoded filename, including the extension virtual const std::string& name() const = 0; @@ -54,7 +46,7 @@ namespace fs /** * @brief type Returns the file type, or None if not linked with another file */ - virtual LinkedFileType linkedType() const = 0; + virtual medialibrary::IFile::Type linkedType() const = 0; /** * @brief linkedWith Return the MRL this file is linked to, or an empty * string if it's not linked with anything diff --git a/src/discoverer/FsDiscoverer.cpp b/src/discoverer/FsDiscoverer.cpp index 7b50b330..c29fce1a 100644 --- a/src/discoverer/FsDiscoverer.cpp +++ b/src/discoverer/FsDiscoverer.cpp @@ -462,7 +462,7 @@ void FsDiscoverer::checkFiles( std::shared_ptr parentFolderFs, }); if ( it == end( files ) ) { - if ( fileFs->linkedType() == fs::IFile::LinkedFileType::None ) + if ( fileFs->linkedType() == IFile::Type::Unknown ) { const auto ext = fileFs->extension(); IFile::Type fileType = IFile::Type::Unknown; @@ -475,21 +475,10 @@ void FsDiscoverer::checkFiles( std::shared_ptr parentFolderFs, } else { - auto fileType = IFile::Type::Unknown; - switch ( fileFs->linkedType() ) - { - case fs::IFile::LinkedFileType::None: - assert( !"The linked file type can't be none" ); - break; - case fs::IFile::LinkedFileType::Subtitles: - fileType = IFile::Type::Subtitles; - break; - case fs::IFile::LinkedFileType::SoundTrack: - fileType = IFile::Type::Soundtrack; - break; - } - if ( fileType != IFile::Type::Unknown ) - linkedFilesToAdd.emplace_back( fileFs, fileType ); + assert( fileFs->linkedType() == IFile::Type::Subtitles || + fileFs->linkedType() == IFile::Type::Soundtrack ); + auto linkedType = fileFs->linkedType(); + linkedFilesToAdd.emplace_back( fileFs, linkedType ); } continue; } diff --git a/src/filesystem/common/CommonFile.cpp b/src/filesystem/common/CommonFile.cpp index 2df6fca6..dd05a15c 100644 --- a/src/filesystem/common/CommonFile.cpp +++ b/src/filesystem/common/CommonFile.cpp @@ -39,11 +39,11 @@ CommonFile::CommonFile( std::string mrl ) : m_mrl( std::move( mrl ) ) , m_name( utils::file::fileName( m_mrl ) ) , m_extension( utils::file::extension( m_mrl ) ) - , m_linkedType( LinkedFileType::None ) + , m_linkedType( medialibrary::IFile::Type::Unknown ) { } -CommonFile::CommonFile( std::string mrl, IFile::LinkedFileType linkedType, +CommonFile::CommonFile(std::string mrl, medialibrary::IFile::Type linkedType, std::string linkedFile ) : m_mrl( std::move( mrl ) ) , m_name( utils::file::fileName( m_mrl ) ) @@ -74,14 +74,14 @@ bool CommonFile::isNetwork() const return false; } -IFile::LinkedFileType CommonFile::linkedType() const +medialibrary::IFile::Type CommonFile::linkedType() const { return m_linkedType; } const std::string& CommonFile::linkedWith() const { - assert( m_linkedType != LinkedFileType::None ); + assert( m_linkedType != medialibrary::IFile::Type::Unknown ); return m_linkedFile; } diff --git a/src/filesystem/common/CommonFile.h b/src/filesystem/common/CommonFile.h index ba666e27..43c764d0 100644 --- a/src/filesystem/common/CommonFile.h +++ b/src/filesystem/common/CommonFile.h @@ -34,13 +34,13 @@ class CommonFile : public IFile { public: explicit CommonFile( std::string mrl ); - explicit CommonFile( std::string mrl, LinkedFileType linkedType, + explicit CommonFile( std::string mrl, medialibrary::IFile::Type linkedType, std::string linkedFile ); virtual const std::string& name() const override; virtual const std::string& extension() const override; virtual const std::string& mrl() const override; virtual bool isNetwork() const override; - virtual LinkedFileType linkedType() const override; + virtual medialibrary::IFile::Type linkedType() const override; virtual const std::string& linkedWith() const override; protected: @@ -48,7 +48,7 @@ protected: const std::string m_name; const std::string m_extension; const std::string m_linkedFile; - const LinkedFileType m_linkedType; + const medialibrary::IFile::Type m_linkedType; }; } diff --git a/src/filesystem/libvlc/Directory.cpp b/src/filesystem/libvlc/Directory.cpp index 17594ab7..29542675 100644 --- a/src/filesystem/libvlc/Directory.cpp +++ b/src/filesystem/libvlc/Directory.cpp @@ -146,16 +146,16 @@ void Directory::read() const fileSize = std::get<1>( fileSizeTpl ); fileMtime = std::get<1>( fileMtimeTpl ); #endif - addFile( m->mrl(), IFile::LinkedFileType::None, {}, fileMtime, fileSize ); + addFile( m->mrl(), medialibrary::IFile::Type::Unknown, {}, fileMtime, fileSize ); for ( const auto& am : m->slaves() ) { - IFile::LinkedFileType linkedType; + medialibrary::IFile::Type linkedType; if ( am.type() == VLC::MediaSlave::Type::Audio ) - linkedType = IFile::LinkedFileType::SoundTrack; + linkedType = medialibrary::IFile::Type::Soundtrack; else { assert( am.type() == VLC::MediaSlave::Type::Subtitle ); - linkedType = IFile::LinkedFileType::Subtitles; + linkedType = medialibrary::IFile::Type::Subtitles; } addFile( am.uri(), linkedType, m->mrl(), 0, 0 ); } @@ -163,7 +163,7 @@ void Directory::read() const } } -void Directory::addFile( std::string mrl, fs::IFile::LinkedFileType linkedType, +void Directory::addFile( std::string mrl, medialibrary::IFile::Type linkedType, std::string linkedWith, time_t lastModificationDate, uint64_t fileSize ) const { @@ -214,7 +214,7 @@ void Directory::addFile( std::string mrl, fs::IFile::LinkedFileType linkedType, fileSize = s.st_size; #endif } - if ( linkedType == IFile::LinkedFileType::None ) + if ( linkedType == medialibrary::IFile::Type::Unknown ) m_files.push_back( std::make_shared( std::move( mrl ), m_fsFactory, lastModificationDate, fileSize ) ); else diff --git a/src/filesystem/libvlc/Directory.h b/src/filesystem/libvlc/Directory.h index da893cc0..49ee0829 100644 --- a/src/filesystem/libvlc/Directory.h +++ b/src/filesystem/libvlc/Directory.h @@ -42,7 +42,7 @@ private: // These are unintuitively const, because the files/subfolders list is // lazily initialized when calling files() / dirs() virtual void read() const override; - void addFile( std::string mrl, IFile::LinkedFileType fileType, + void addFile( std::string mrl, medialibrary::IFile::Type fileType, std::string linkedWith, time_t lastModificationDate, uint64_t fileSize ) const; diff --git a/src/filesystem/libvlc/File.cpp b/src/filesystem/libvlc/File.cpp index c6c044fc..1888dc3c 100644 --- a/src/filesystem/libvlc/File.cpp +++ b/src/filesystem/libvlc/File.cpp @@ -52,7 +52,7 @@ File::File( std::string mrl, fs::IFileSystemFactory& fsFactory, File::File( std::string mrl, IFileSystemFactory& fsFactory, time_t lastModificationDate, uint64_t size, - IFile::LinkedFileType linkedType, std::string linkedFile ) + medialibrary::IFile::Type linkedType, std::string linkedFile ) : CommonFile( std::move( mrl ), linkedType, std::move( linkedFile ) ) , m_lastModificationDate( lastModificationDate ) , m_size( size ) diff --git a/src/filesystem/libvlc/File.h b/src/filesystem/libvlc/File.h index 3fcda41a..7464fe01 100644 --- a/src/filesystem/libvlc/File.h +++ b/src/filesystem/libvlc/File.h @@ -41,7 +41,7 @@ public: time_t lastModificationDate, uint64_t size ); File( std::string mrl, IFileSystemFactory& fsFactory, time_t lastModificationDate, uint64_t size, - IFile::LinkedFileType linkedType, std::string linkedFile ); + medialibrary::IFile::Type linkedType, std::string linkedFile ); virtual time_t lastModificationDate() const override; virtual uint64_t size() const override; virtual bool isNetwork() const override; diff --git a/test/unittest/mocks/FileSystem.h b/test/unittest/mocks/FileSystem.h index 5067050e..f6fc4af0 100644 --- a/test/unittest/mocks/FileSystem.h +++ b/test/unittest/mocks/FileSystem.h @@ -350,9 +350,9 @@ public: return m_size; } - LinkedFileType linkedType() const + medialibrary::IFile::Type linkedType() const { - return LinkedFileType::None; + return medialibrary::IFile::Type::Unknown; } const std::string& linkedWith() const diff --git a/test/unittest/mocks/filesystem/MockFile.cpp b/test/unittest/mocks/filesystem/MockFile.cpp index 6607e1d5..222de406 100644 --- a/test/unittest/mocks/filesystem/MockFile.cpp +++ b/test/unittest/mocks/filesystem/MockFile.cpp @@ -64,9 +64,9 @@ bool File::isNetwork() const return false; } -fs::IFile::LinkedFileType File::linkedType() const +IFile::Type File::linkedType() const { - return LinkedFileType::None; + return medialibrary::IFile::Type::Unknown; } const std::string &File::linkedWith() const diff --git a/test/unittest/mocks/filesystem/MockFile.h b/test/unittest/mocks/filesystem/MockFile.h index 4ba91349..487368b0 100644 --- a/test/unittest/mocks/filesystem/MockFile.h +++ b/test/unittest/mocks/filesystem/MockFile.h @@ -44,7 +44,7 @@ public: void markAsModified(); virtual const std::string& mrl() const override; virtual bool isNetwork() const override; - virtual LinkedFileType linkedType() const override; + virtual medialibrary::IFile::Type linkedType() const override; virtual const std::string& linkedWith() const override; private: -- GitLab From 7996903111a47af46abbdd167e5724dd15ff9afc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Mon, 14 Sep 2020 16:12:21 +0200 Subject: [PATCH 02/17] fs: IFile: Expose a file type --- include/medialibrary/filesystem/IFile.h | 6 ++++++ src/filesystem/common/CommonFile.cpp | 9 ++++++++- src/filesystem/common/CommonFile.h | 2 ++ test/unittest/mocks/FileSystem.h | 5 +++++ test/unittest/mocks/filesystem/MockFile.cpp | 5 +++++ test/unittest/mocks/filesystem/MockFile.h | 1 + 6 files changed, 27 insertions(+), 1 deletion(-) diff --git a/include/medialibrary/filesystem/IFile.h b/include/medialibrary/filesystem/IFile.h index 6e2bcd81..24273afa 100644 --- a/include/medialibrary/filesystem/IFile.h +++ b/include/medialibrary/filesystem/IFile.h @@ -43,6 +43,12 @@ namespace fs virtual time_t lastModificationDate() const = 0; virtual uint64_t size() const = 0; virtual bool isNetwork() const = 0; + /** + * @brief type Returns the file type if it is known + * + * Otherwise this will default to medialibrary::IFile::Type::Unknown + */ + virtual medialibrary::IFile::Type type() const = 0; /** * @brief type Returns the file type, or None if not linked with another file */ diff --git a/src/filesystem/common/CommonFile.cpp b/src/filesystem/common/CommonFile.cpp index dd05a15c..678e13e6 100644 --- a/src/filesystem/common/CommonFile.cpp +++ b/src/filesystem/common/CommonFile.cpp @@ -39,15 +39,17 @@ CommonFile::CommonFile( std::string mrl ) : m_mrl( std::move( mrl ) ) , m_name( utils::file::fileName( m_mrl ) ) , m_extension( utils::file::extension( m_mrl ) ) + , m_type( medialibrary::IFile::Type::Unknown ) , m_linkedType( medialibrary::IFile::Type::Unknown ) { } -CommonFile::CommonFile(std::string mrl, medialibrary::IFile::Type linkedType, +CommonFile::CommonFile( std::string mrl, medialibrary::IFile::Type linkedType, std::string linkedFile ) : m_mrl( std::move( mrl ) ) , m_name( utils::file::fileName( m_mrl ) ) , m_extension( utils::file::extension( m_mrl ) ) + , m_type( medialibrary::IFile::Type::Unknown ) , m_linkedFile( std::move( linkedFile ) ) , m_linkedType( linkedType ) { @@ -74,6 +76,11 @@ bool CommonFile::isNetwork() const return false; } +medialibrary::IFile::Type CommonFile::type() const +{ + return m_type; +} + medialibrary::IFile::Type CommonFile::linkedType() const { return m_linkedType; diff --git a/src/filesystem/common/CommonFile.h b/src/filesystem/common/CommonFile.h index 43c764d0..e989dc8b 100644 --- a/src/filesystem/common/CommonFile.h +++ b/src/filesystem/common/CommonFile.h @@ -40,6 +40,7 @@ public: virtual const std::string& extension() const override; virtual const std::string& mrl() const override; virtual bool isNetwork() const override; + virtual medialibrary::IFile::Type type() const override; virtual medialibrary::IFile::Type linkedType() const override; virtual const std::string& linkedWith() const override; @@ -47,6 +48,7 @@ protected: const std::string m_mrl; const std::string m_name; const std::string m_extension; + const medialibrary::IFile::Type m_type; const std::string m_linkedFile; const medialibrary::IFile::Type m_linkedType; }; diff --git a/test/unittest/mocks/FileSystem.h b/test/unittest/mocks/FileSystem.h index f6fc4af0..93098bed 100644 --- a/test/unittest/mocks/FileSystem.h +++ b/test/unittest/mocks/FileSystem.h @@ -350,6 +350,11 @@ public: return m_size; } + medialibrary::IFile::Type type() const + { + return medialibrary::IFile::Type::Unknown; + } + medialibrary::IFile::Type linkedType() const { return medialibrary::IFile::Type::Unknown; diff --git a/test/unittest/mocks/filesystem/MockFile.cpp b/test/unittest/mocks/filesystem/MockFile.cpp index 222de406..6bbd004b 100644 --- a/test/unittest/mocks/filesystem/MockFile.cpp +++ b/test/unittest/mocks/filesystem/MockFile.cpp @@ -84,4 +84,9 @@ uint64_t File::size() const return 0; } +IFile::Type File::type() const +{ + return medialibrary::IFile::Type::Unknown; +} + } diff --git a/test/unittest/mocks/filesystem/MockFile.h b/test/unittest/mocks/filesystem/MockFile.h index 487368b0..b4169831 100644 --- a/test/unittest/mocks/filesystem/MockFile.h +++ b/test/unittest/mocks/filesystem/MockFile.h @@ -41,6 +41,7 @@ public: virtual const std::string& extension() const override; virtual time_t lastModificationDate() const override; virtual uint64_t size() const override; + virtual medialibrary::IFile::Type type() const override; void markAsModified(); virtual const std::string& mrl() const override; virtual bool isNetwork() const override; -- GitLab From 9fa50e25f7180a75f429ae59305d895e9f925624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Mon, 14 Sep 2020 17:07:52 +0200 Subject: [PATCH 03/17] fs: IFile: Merge linkedType() and type() --- include/medialibrary/filesystem/IFile.h | 6 +++--- src/discoverer/FsDiscoverer.cpp | 8 ++++---- src/filesystem/common/CommonFile.cpp | 21 +++++---------------- src/filesystem/common/CommonFile.h | 4 +--- src/filesystem/libvlc/Directory.cpp | 12 ++++-------- src/filesystem/libvlc/File.cpp | 16 +++------------- src/filesystem/libvlc/File.h | 6 ++---- test/unittest/mocks/FileSystem.h | 4 ++-- test/unittest/mocks/filesystem/MockFile.cpp | 4 ++-- test/unittest/mocks/filesystem/MockFile.h | 2 +- 10 files changed, 27 insertions(+), 56 deletions(-) diff --git a/include/medialibrary/filesystem/IFile.h b/include/medialibrary/filesystem/IFile.h index 24273afa..bf95e70f 100644 --- a/include/medialibrary/filesystem/IFile.h +++ b/include/medialibrary/filesystem/IFile.h @@ -50,14 +50,14 @@ namespace fs */ virtual medialibrary::IFile::Type type() const = 0; /** - * @brief type Returns the file type, or None if not linked with another file + * @brief isLinked Return true if this file is linked with another */ - virtual medialibrary::IFile::Type linkedType() const = 0; + virtual bool isLinked() const = 0; /** * @brief linkedWith Return the MRL this file is linked to, or an empty * string if it's not linked with anything * - * If type() is None, it's invalid to call this function + * If isLinked() is false, it's invalid to call this function */ virtual const std::string& linkedWith() const = 0; }; diff --git a/src/discoverer/FsDiscoverer.cpp b/src/discoverer/FsDiscoverer.cpp index c29fce1a..09ccb9bd 100644 --- a/src/discoverer/FsDiscoverer.cpp +++ b/src/discoverer/FsDiscoverer.cpp @@ -462,7 +462,7 @@ void FsDiscoverer::checkFiles( std::shared_ptr parentFolderFs, }); if ( it == end( files ) ) { - if ( fileFs->linkedType() == IFile::Type::Unknown ) + if ( fileFs->isLinked() == false ) { const auto ext = fileFs->extension(); IFile::Type fileType = IFile::Type::Unknown; @@ -475,9 +475,9 @@ void FsDiscoverer::checkFiles( std::shared_ptr parentFolderFs, } else { - assert( fileFs->linkedType() == IFile::Type::Subtitles || - fileFs->linkedType() == IFile::Type::Soundtrack ); - auto linkedType = fileFs->linkedType(); + assert( fileFs->type() == IFile::Type::Subtitles || + fileFs->type() == IFile::Type::Soundtrack ); + auto linkedType = fileFs->type(); linkedFilesToAdd.emplace_back( fileFs, linkedType ); } continue; diff --git a/src/filesystem/common/CommonFile.cpp b/src/filesystem/common/CommonFile.cpp index 678e13e6..7fcac77b 100644 --- a/src/filesystem/common/CommonFile.cpp +++ b/src/filesystem/common/CommonFile.cpp @@ -35,25 +35,14 @@ namespace medialibrary namespace fs { -CommonFile::CommonFile( std::string mrl ) - : m_mrl( std::move( mrl ) ) - , m_name( utils::file::fileName( m_mrl ) ) - , m_extension( utils::file::extension( m_mrl ) ) - , m_type( medialibrary::IFile::Type::Unknown ) - , m_linkedType( medialibrary::IFile::Type::Unknown ) -{ -} - -CommonFile::CommonFile( std::string mrl, medialibrary::IFile::Type linkedType, +CommonFile::CommonFile( std::string mrl, medialibrary::IFile::Type type, std::string linkedFile ) : m_mrl( std::move( mrl ) ) , m_name( utils::file::fileName( m_mrl ) ) , m_extension( utils::file::extension( m_mrl ) ) - , m_type( medialibrary::IFile::Type::Unknown ) + , m_type( type ) , m_linkedFile( std::move( linkedFile ) ) - , m_linkedType( linkedType ) { - } const std::string& CommonFile::name() const @@ -81,14 +70,14 @@ medialibrary::IFile::Type CommonFile::type() const return m_type; } -medialibrary::IFile::Type CommonFile::linkedType() const +bool CommonFile::isLinked() const { - return m_linkedType; + return m_linkedFile.empty() == false; } const std::string& CommonFile::linkedWith() const { - assert( m_linkedType != medialibrary::IFile::Type::Unknown ); + assert( isLinked() == true ); return m_linkedFile; } diff --git a/src/filesystem/common/CommonFile.h b/src/filesystem/common/CommonFile.h index e989dc8b..a1470455 100644 --- a/src/filesystem/common/CommonFile.h +++ b/src/filesystem/common/CommonFile.h @@ -33,7 +33,6 @@ namespace fs class CommonFile : public IFile { public: - explicit CommonFile( std::string mrl ); explicit CommonFile( std::string mrl, medialibrary::IFile::Type linkedType, std::string linkedFile ); virtual const std::string& name() const override; @@ -41,7 +40,7 @@ public: virtual const std::string& mrl() const override; virtual bool isNetwork() const override; virtual medialibrary::IFile::Type type() const override; - virtual medialibrary::IFile::Type linkedType() const override; + virtual bool isLinked() const override; virtual const std::string& linkedWith() const override; protected: @@ -50,7 +49,6 @@ protected: const std::string m_extension; const medialibrary::IFile::Type m_type; const std::string m_linkedFile; - const medialibrary::IFile::Type m_linkedType; }; } diff --git a/src/filesystem/libvlc/Directory.cpp b/src/filesystem/libvlc/Directory.cpp index 29542675..39ae4db0 100644 --- a/src/filesystem/libvlc/Directory.cpp +++ b/src/filesystem/libvlc/Directory.cpp @@ -163,7 +163,7 @@ void Directory::read() const } } -void Directory::addFile( std::string mrl, medialibrary::IFile::Type linkedType, +void Directory::addFile( std::string mrl, medialibrary::IFile::Type fileType, std::string linkedWith, time_t lastModificationDate, uint64_t fileSize ) const { @@ -214,13 +214,9 @@ void Directory::addFile( std::string mrl, medialibrary::IFile::Type linkedType, fileSize = s.st_size; #endif } - if ( linkedType == medialibrary::IFile::Type::Unknown ) - m_files.push_back( std::make_shared( std::move( mrl ), - m_fsFactory, lastModificationDate, fileSize ) ); - else - m_files.push_back( std::make_shared( std::move( mrl ), - m_fsFactory, lastModificationDate, fileSize, - linkedType, std::move( linkedWith ) ) ); + m_files.push_back( std::make_shared( std::move( mrl ), + m_fsFactory, fileType, lastModificationDate, fileSize, + std::move( linkedWith ) ) ); } } diff --git a/src/filesystem/libvlc/File.cpp b/src/filesystem/libvlc/File.cpp index 1888dc3c..a8322b9e 100644 --- a/src/filesystem/libvlc/File.cpp +++ b/src/filesystem/libvlc/File.cpp @@ -40,20 +40,10 @@ namespace fs namespace libvlc { -File::File( std::string mrl, fs::IFileSystemFactory& fsFactory, - time_t lastModificationDate, uint64_t size ) - : CommonFile( std::move( mrl ) ) - , m_lastModificationDate( lastModificationDate ) - , m_size( size ) - , m_isNetwork( fsFactory.isNetworkFileSystem() ) -{ - -} - File::File( std::string mrl, IFileSystemFactory& fsFactory, - time_t lastModificationDate, uint64_t size, - medialibrary::IFile::Type linkedType, std::string linkedFile ) - : CommonFile( std::move( mrl ), linkedType, std::move( linkedFile ) ) + medialibrary::IFile::Type type, time_t lastModificationDate, + uint64_t size, std::string linkedFile ) + : CommonFile( std::move( mrl ), type, std::move( linkedFile ) ) , m_lastModificationDate( lastModificationDate ) , m_size( size ) , m_isNetwork( fsFactory.isNetworkFileSystem() ) diff --git a/src/filesystem/libvlc/File.h b/src/filesystem/libvlc/File.h index 7464fe01..1bea4e00 100644 --- a/src/filesystem/libvlc/File.h +++ b/src/filesystem/libvlc/File.h @@ -38,10 +38,8 @@ class File : public CommonFile { public: File( std::string mrl, IFileSystemFactory& fsFactory, - time_t lastModificationDate, uint64_t size ); - File( std::string mrl, IFileSystemFactory& fsFactory, - time_t lastModificationDate, uint64_t size, - medialibrary::IFile::Type linkedType, std::string linkedFile ); + medialibrary::IFile::Type linkedType, time_t lastModificationDate, + uint64_t size, std::string linkedFile ); virtual time_t lastModificationDate() const override; virtual uint64_t size() const override; virtual bool isNetwork() const override; diff --git a/test/unittest/mocks/FileSystem.h b/test/unittest/mocks/FileSystem.h index 93098bed..58119a66 100644 --- a/test/unittest/mocks/FileSystem.h +++ b/test/unittest/mocks/FileSystem.h @@ -355,9 +355,9 @@ public: return medialibrary::IFile::Type::Unknown; } - medialibrary::IFile::Type linkedType() const + bool isLinked() const { - return medialibrary::IFile::Type::Unknown; + return m_linkedWith.empty() == false; } const std::string& linkedWith() const diff --git a/test/unittest/mocks/filesystem/MockFile.cpp b/test/unittest/mocks/filesystem/MockFile.cpp index 6bbd004b..06f8e611 100644 --- a/test/unittest/mocks/filesystem/MockFile.cpp +++ b/test/unittest/mocks/filesystem/MockFile.cpp @@ -64,9 +64,9 @@ bool File::isNetwork() const return false; } -IFile::Type File::linkedType() const +bool File::isLinked() const { - return medialibrary::IFile::Type::Unknown; + return m_linkedWith.empty() == false; } const std::string &File::linkedWith() const diff --git a/test/unittest/mocks/filesystem/MockFile.h b/test/unittest/mocks/filesystem/MockFile.h index b4169831..4b75d501 100644 --- a/test/unittest/mocks/filesystem/MockFile.h +++ b/test/unittest/mocks/filesystem/MockFile.h @@ -45,7 +45,7 @@ public: void markAsModified(); virtual const std::string& mrl() const override; virtual bool isNetwork() const override; - virtual medialibrary::IFile::Type linkedType() const override; + virtual bool isLinked() const override; virtual const std::string& linkedWith() const override; private: -- GitLab From a0dac2a34faa5a464567bc4ed13d7e16f043426b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Mon, 14 Sep 2020 17:15:14 +0200 Subject: [PATCH 04/17] fs: Directory: Start probing the actual file type Instead of always passing Unknown --- src/filesystem/libvlc/Directory.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/filesystem/libvlc/Directory.cpp b/src/filesystem/libvlc/Directory.cpp index 39ae4db0..7498503e 100644 --- a/src/filesystem/libvlc/Directory.cpp +++ b/src/filesystem/libvlc/Directory.cpp @@ -146,7 +146,17 @@ void Directory::read() const fileSize = std::get<1>( fileSizeTpl ); fileMtime = std::get<1>( fileMtimeTpl ); #endif - addFile( m->mrl(), medialibrary::IFile::Type::Unknown, {}, fileMtime, fileSize ); + medialibrary::IFile::Type fileType; + switch ( m->type() ) + { + case VLC::Media::Type::Playlist: + fileType = medialibrary::IFile::Type::Playlist; + break; + default: + fileType = medialibrary::IFile::Type::Unknown; + break; + } + addFile( m->mrl(), fileType, {}, fileMtime, fileSize ); for ( const auto& am : m->slaves() ) { medialibrary::IFile::Type linkedType; -- GitLab From d950b820b25e33499e9d069d07e05e37b985a159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Tue, 15 Sep 2020 11:31:08 +0200 Subject: [PATCH 05/17] FsDiscoverer: Probe the file for its type But keep the existing fallback in place since it's likely that the files won't have their type known in this code path --- src/discoverer/FsDiscoverer.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/discoverer/FsDiscoverer.cpp b/src/discoverer/FsDiscoverer.cpp index 09ccb9bd..832c7e69 100644 --- a/src/discoverer/FsDiscoverer.cpp +++ b/src/discoverer/FsDiscoverer.cpp @@ -464,12 +464,22 @@ void FsDiscoverer::checkFiles( std::shared_ptr parentFolderFs, { if ( fileFs->isLinked() == false ) { - const auto ext = fileFs->extension(); - IFile::Type fileType = IFile::Type::Unknown; - if ( m_ml->isMediaExtensionSupported( ext.c_str() ) == true ) - fileType = IFile::Type::Main; - else if ( m_ml->isPlaylistExtensionSupported( ext.c_str() ) == true ) - fileType = IFile::Type::Playlist; + IFile::Type fileType = fileFs->type(); + /* + * If the file type is known, then use it. VLC's demuxers know + * better than we do based on the extension only. + * However at this point, most files are the subitems of a "media" + * and are not preparsed, so we usually only know if they are a + * folder or a file, at least for now + */ + if ( fileType == IFile::Type::Unknown ) + { + const auto ext = fileFs->extension(); + if ( m_ml->isMediaExtensionSupported( ext.c_str() ) == true ) + fileType = IFile::Type::Main; + else if ( m_ml->isPlaylistExtensionSupported( ext.c_str() ) == true ) + fileType = IFile::Type::Playlist; + } if ( fileType != IFile::Type::Unknown ) filesToAdd.emplace_back( fileFs, fileType ); } -- GitLab From 91abe9343a943bd8f20154b203b1f779ec762e9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Wed, 16 Sep 2020 09:44:49 +0200 Subject: [PATCH 06/17] fs: Directory: Handle DVD folders refs #29 --- src/filesystem/libvlc/Directory.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/filesystem/libvlc/Directory.cpp b/src/filesystem/libvlc/Directory.cpp index 7498503e..67737481 100644 --- a/src/filesystem/libvlc/Directory.cpp +++ b/src/filesystem/libvlc/Directory.cpp @@ -116,6 +116,20 @@ void Directory::read() const if ( res == VLC::Media::ParsedStatus::Failed ) throw errors::System{ EIO, "Failed to browse network directory: Unknown error" }; + if ( media.type() == VLC::Media::Type::Disc ) + { + int64_t fileSize = 0; + int64_t fileMtime = 0; +#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(4, 0, 0, 0) + auto fileSizeTpl = media.fileStat( VLC::Media::FileStat::Size ); + auto fileMtimeTpl = media.fileStat( VLC::Media::FileStat::Mtime ); + fileSize = std::get<1>( fileSizeTpl ); + fileMtime = std::get<1>( fileMtimeTpl ); +#endif + addFile( media.mrl(), medialibrary::IFile::Type::Disc, {}, fileMtime, + fileSize ); + return; + } auto subItems = media.subitems(); for ( auto i = 0; i < subItems->count(); ++i ) { -- GitLab From 1abbb6c3d430fbd3b394fd530677e89bbb5bb9d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Tue, 15 Sep 2020 16:00:34 +0200 Subject: [PATCH 07/17] MetadataParser: Don't force the file type to Main Since we can now analyze disc files refs #29 --- src/metadata_services/MetadataParser.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/metadata_services/MetadataParser.cpp b/src/metadata_services/MetadataParser.cpp index 0c9b336b..0678d892 100644 --- a/src/metadata_services/MetadataParser.cpp +++ b/src/metadata_services/MetadataParser.cpp @@ -765,11 +765,12 @@ Status MetadataAnalyzer::createFileAndMedia( IItem& item ) const auto deviceFs = item.parentFolderFs()->device(); if ( deviceFs == nullptr ) throw fs::errors::DeviceRemoved{}; - // For now, assume all media are made of a single file try { + assert( item.fileType() == IFile::Type::Main || + item.fileType() == IFile::Type::Disc ); file = m->addFile( *item.fileFs(), item.parentFolder()->id(), - deviceFs->isRemovable(), File::Type::Main ); + deviceFs->isRemovable(), item.fileType() ); if ( file == nullptr ) { LOG_ERROR( "Failed to add file ", mrl, " to media #", m->id() ); -- GitLab From 1f1d4eb6223a21d24bf8204fcab3f9f2ba410052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Wed, 16 Sep 2020 09:41:14 +0200 Subject: [PATCH 08/17] File: Consider Disk files as Main files refs #29 --- src/File.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/File.cpp b/src/File.cpp index 19b6e7d3..42a66925 100644 --- a/src/File.cpp +++ b/src/File.cpp @@ -210,7 +210,8 @@ bool File::isNetwork() const bool File::isMain() const { return m_type == Type::Main || - m_type == Type::Cache; + m_type == Type::Cache || + m_type == Type::Disc; } time_t File::insertionDate() const -- GitLab From 08c8a648e875397f8f7f267a27aa30535d8024ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Wed, 16 Sep 2020 09:41:49 +0200 Subject: [PATCH 09/17] MetadataParser: Use the folder name as title for disc folders --- src/metadata_services/MetadataParser.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/metadata_services/MetadataParser.cpp b/src/metadata_services/MetadataParser.cpp index 0678d892..3b25363f 100644 --- a/src/metadata_services/MetadataParser.cpp +++ b/src/metadata_services/MetadataParser.cpp @@ -624,6 +624,12 @@ bool MetadataAnalyzer::parseVideoFile( IItem& item ) const // with a video file, we might be refreshing that media, and it might already // have a title, so let's analyse the filename again instead. auto title = utils::title::sanitize( item.media()->fileName() ); + if ( title.empty() == true && item.fileType() == IFile::Type::Disc ) + { + title = utils::title::sanitize( + utils::file::directoryName( + utils::url::decode( item.mrl() ) ) ); + } auto showInfo = utils::title::analyze( title ); const auto& embeddedThumbnails = item.embeddedThumbnails(); -- GitLab From b0d4715222a2ca726fefe00797d6f99177dbada2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Wed, 16 Sep 2020 09:42:18 +0200 Subject: [PATCH 10/17] MetadataParser: Consider Discs to be video media refs #29 --- src/metadata_services/MetadataParser.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/metadata_services/MetadataParser.cpp b/src/metadata_services/MetadataParser.cpp index 3b25363f..989b73d8 100644 --- a/src/metadata_services/MetadataParser.cpp +++ b/src/metadata_services/MetadataParser.cpp @@ -680,6 +680,9 @@ bool MetadataAnalyzer::parseVideoFile( IItem& item ) const IMedia::Type MetadataAnalyzer::guessMediaType( const IItem &item ) const { + if ( item.fileType() == IFile::Type::Disc ) + return IMedia::Type::Video; + auto ext = utils::file::extension( item.mrl() ); std::transform(cbegin( ext ), cend( ext ), begin( ext ), [](unsigned char c){ return tolower(c); } ); -- GitLab From 75a6758a3d17c6b1d90988a504097253c2d40a9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Wed, 16 Sep 2020 14:55:58 +0200 Subject: [PATCH 11/17] Directory: Explicitely handle Disc type for subitems --- src/filesystem/libvlc/Directory.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/filesystem/libvlc/Directory.cpp b/src/filesystem/libvlc/Directory.cpp index 67737481..1d8219a0 100644 --- a/src/filesystem/libvlc/Directory.cpp +++ b/src/filesystem/libvlc/Directory.cpp @@ -166,6 +166,9 @@ void Directory::read() const case VLC::Media::Type::Playlist: fileType = medialibrary::IFile::Type::Playlist; break; + case VLC::Media::Type::Disc: + fileType = medialibrary::IFile::Type::Disc; + break; default: fileType = medialibrary::IFile::Type::Unknown; break; -- GitLab From 221364577068140663359ac1a12a95a9f08f4799 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Wed, 16 Sep 2020 14:58:13 +0200 Subject: [PATCH 12/17] IItem: Add an helper to update a task file type --- include/medialibrary/parser/IItem.h | 6 ++++++ src/parser/Task.cpp | 12 ++++++++++++ src/parser/Task.h | 1 + 3 files changed, 19 insertions(+) diff --git a/include/medialibrary/parser/IItem.h b/include/medialibrary/parser/IItem.h index 8d020b74..60c62801 100644 --- a/include/medialibrary/parser/IItem.h +++ b/include/medialibrary/parser/IItem.h @@ -147,6 +147,12 @@ public: */ virtual IFile::Type fileType() const = 0; + /** + * @brief setFileType Updates the analyzed file type + * @return true in case of success or no-op, false in case of failure + */ + virtual bool setFileType( IFile::Type fileType ) = 0; + /** * @return The number of linked items for this item. */ diff --git a/src/parser/Task.cpp b/src/parser/Task.cpp index 92d0e792..6e56b679 100644 --- a/src/parser/Task.cpp +++ b/src/parser/Task.cpp @@ -971,6 +971,18 @@ IFile::Type Task::fileType() const return m_fileType; } +bool Task::setFileType( IFile::Type fileType ) +{ + if ( m_fileType == fileType ) + return true; + const std::string req = "UPDATE " + Table::Name + " SET file_type = ? " + "WHERE id_task = ?"; + if ( sqlite::Tools::executeUpdate( m_ml->getConn(), req, fileType, m_id ) == false ) + return false; + m_fileType = fileType; + return true; +} + size_t Task::nbLinkedItems() const { return m_linkedItems.size(); diff --git a/src/parser/Task.h b/src/parser/Task.h index 2a62245c..a1b1e255 100644 --- a/src/parser/Task.h +++ b/src/parser/Task.h @@ -284,6 +284,7 @@ public: virtual const std::string& mrl() const override; virtual IFile::Type fileType() const override; + virtual bool setFileType( IFile::Type fileType ) override; virtual size_t nbLinkedItems() const override; virtual const IItem& linkedItem( unsigned int index ) const override; -- GitLab From 7a9ce1b5094cb00de43dd2c93c5f337520b6c7fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Wed, 16 Sep 2020 15:02:39 +0200 Subject: [PATCH 13/17] VLCMetadataService: Handle filetype change after preparsing Refs #29 --- .../vlc/VLCMetadataService.cpp | 547 ++++++++++-------- .../vlc/VLCMetadataService.h | 1 + 2 files changed, 300 insertions(+), 248 deletions(-) diff --git a/src/metadata_services/vlc/VLCMetadataService.cpp b/src/metadata_services/vlc/VLCMetadataService.cpp index de7c24b6..05f15f95 100644 --- a/src/metadata_services/vlc/VLCMetadataService.cpp +++ b/src/metadata_services/vlc/VLCMetadataService.cpp @@ -51,142 +51,173 @@ namespace parser bool VLCMetadataService::initialize( IMediaLibrary* ) { - return true; + return true; } #if defined(FORCE_ATTACHMENTS_API) void VLCMetadataService::onAttachedThumbnailsFound( const libvlc_event_t* e, void* data ) { - assert( e->type == libvlc_MediaAttachedThumbnailsFound ); - auto item = reinterpret_cast( data ); - auto pictureList = e->u.media_attached_thumbnails_found.thumbnails; - if ( libvlc_picture_list_count( pictureList ) == 0 ) - return; - item->addEmbeddedThumbnail( std::make_shared( - libvlc_picture_list_at( pictureList, 0 ) ) ); + assert( e->type == libvlc_MediaAttachedThumbnailsFound ); + auto item = reinterpret_cast( data ); + auto pictureList = e->u.media_attached_thumbnails_found.thumbnails; + if ( libvlc_picture_list_count( pictureList ) == 0 ) + return; + item->addEmbeddedThumbnail( std::make_shared( + libvlc_picture_list_at( pictureList, 0 ) ) ); } #endif Status VLCMetadataService::run( IItem& item ) { - auto mrl = item.mrl(); + auto mrl = item.mrl(); - // Having a valid media means we're re-executing this parser after the thumbnailer, - // which isn't expected, as we always mark this task as completed. + // Having a valid media means we're re-executing this parser after the thumbnailer, + // which isn't expected, as we always mark this task as completed. #if LIBVLC_VERSION_INT >= LIBVLC_VERSION(4, 0, 0, 0) - VLC::Media vlcMedia{ mrl, VLC::Media::FromType::FromLocation }; + VLC::Media vlcMedia{ mrl, VLC::Media::FromType::FromLocation }; #else - VLC::Media vlcMedia{ VLCInstance::get(), mrl, VLC::Media::FromType::FromLocation }; + VLC::Media vlcMedia{ VLCInstance::get(), mrl, VLC::Media::FromType::FromLocation }; #endif - vlcMedia.addOption( ":no-lua" ); - - VLC::Media::ParsedStatus status; - bool done = false; - - { - /* - * Store a copy of the event manager. When the instance falls out of - * scope, all events registered through it will be unregistered - * automatically - */ - auto em = vlcMedia.eventManager(); - em.onParsedChanged( [this, &status, &done](VLC::Media::ParsedStatus s ) { - std::lock_guard lock( m_mutex ); - status = s; - done = true; - m_cond.notify_all(); - }); + vlcMedia.addOption( ":no-lua" ); + + VLC::Media::ParsedStatus status; + bool done = false; + + { + /* + * Store a copy of the event manager. When the instance falls out of + * scope, all events registered through it will be unregistered + * automatically + */ + auto em = vlcMedia.eventManager(); + em.onParsedChanged( [this, &status, &done](VLC::Media::ParsedStatus s ) { + std::lock_guard lock( m_mutex ); + status = s; + done = true; + m_cond.notify_all(); + }); #if LIBVLC_VERSION_INT >= LIBVLC_VERSION(4, 0, 0, 0) - em.onAttachedThumbnailsFound( [&item]( const std::vector& pics ) { - if ( pics.empty() == false ) - { - item.addEmbeddedThumbnail( - std::make_shared( pics[0] ) ); - } - }); + em.onAttachedThumbnailsFound( [&item]( const std::vector& pics ) { + if ( pics.empty() == false ) + { + item.addEmbeddedThumbnail( + std::make_shared( pics[0] ) ); + } + }); #elif defined(FORCE_ATTACHMENTS_API) - /* - * We can force the use of the 4.0 attachment API if the patches have - * been backported to 3.0, however libvlcpp doesn't expose it so we have - * to fallback to the C API - */ - if ( libvlc_event_attach( em, libvlc_MediaAttachedThumbnailsFound, - &onAttachedThumbnailsFound, &item ) != 0 ) - { - LOG_ERROR( "Failed to attach to thumbnail found event" ); - return Status::Fatal; - } - auto unregister = utils::make_defer([&em, &item]() { - libvlc_event_detach( em, libvlc_MediaAttachedThumbnailsFound, - &onAttachedThumbnailsFound, &item ); - }); + /* + * We can force the use of the 4.0 attachment API if the patches have + * been backported to 3.0, however libvlcpp doesn't expose it so we have + * to fallback to the C API + */ + if ( libvlc_event_attach( em, libvlc_MediaAttachedThumbnailsFound, + &onAttachedThumbnailsFound, &item ) != 0 ) + { + LOG_ERROR( "Failed to attach to thumbnail found event" ); + return Status::Fatal; + } + auto unregister = utils::make_defer([&em, &item]() { + libvlc_event_detach( em, libvlc_MediaAttachedThumbnailsFound, + &onAttachedThumbnailsFound, &item ); + }); #endif - { - // We need m_currentMedia to be updated from a locked context - // but we also need parseWithOption to be called with the lock - // unlocked, to avoid a potential lock inversion with VLC's internal - // mutexes. - std::unique_lock lock( m_mutex ); - m_currentMedia = vlcMedia; - } + { + // We need m_currentMedia to be updated from a locked context + // but we also need parseWithOption to be called with the lock + // unlocked, to avoid a potential lock inversion with VLC's internal + // mutexes. + std::unique_lock lock( m_mutex ); + m_currentMedia = vlcMedia; + } #if LIBVLC_VERSION_INT >= LIBVLC_VERSION(4, 0, 0, 0) - if ( vlcMedia.parseRequest( VLCInstance::get(), - VLC::Media::ParseFlags::Local | - VLC::Media::ParseFlags::Network, 5000 ) == false ) + if ( vlcMedia.parseRequest( VLCInstance::get(), + VLC::Media::ParseFlags::Local | + VLC::Media::ParseFlags::Network, 5000 ) == false ) #else - if ( vlcMedia.parseWithOptions( VLC::Media::ParseFlags::Local | - VLC::Media::ParseFlags::Network, 5000 ) == false ) + if ( vlcMedia.parseWithOptions( VLC::Media::ParseFlags::Local | + VLC::Media::ParseFlags::Network, 5000 ) == false ) #endif - { - std::unique_lock lock( m_mutex ); - m_currentMedia = VLC::Media{}; - return Status::Fatal; - } - std::unique_lock lock( m_mutex ); - m_cond.wait( lock, [&done]() { - return done == true; - }); - m_currentMedia = VLC::Media{}; - } - if ( status == VLC::Media::ParsedStatus::Failed || status == VLC::Media::ParsedStatus::Timeout ) - return Status::Fatal; - if ( ( item.fileType() == IFile::Type::Playlist || - item.fileType() == IFile::Type::Subscription ) && - vlcMedia.subitems()->count() == 0 ) - { - LOG_DEBUG( "Discarding ", - ( item.fileType() == IFile::Type::Playlist ? "playlist file" - : "subscription" ), - " with no subitem: ", mrl ); - return Status::Fatal; - } + { + std::unique_lock lock( m_mutex ); + m_currentMedia = VLC::Media{}; + return Status::Fatal; + } + std::unique_lock lock( m_mutex ); + m_cond.wait( lock, [&done]() { + return done == true; + }); + m_currentMedia = VLC::Media{}; + } + if ( status == VLC::Media::ParsedStatus::Failed || status == VLC::Media::ParsedStatus::Timeout ) + return Status::Fatal; + +#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(4, 0, 0, 0) + /* The type will always be "File" for any input when using VLC 3.x */ + auto fileType = mediaTypeToFileType( vlcMedia.type() ); + /* + * Most of the file type detection will happen when we really preparse + * the file using libvlc. We want to ensure to have that type stored + * in database later on since the Task filetype is usually the source + * of truth. + * However in the case of a linking task, a regular "Main" file can be + * forced to Soundtrack or another similar conversion. In which case, we + * want to preserve that information. + */ + if ( item.linkType() == IItem::LinkType::NoLink && + fileType != item.fileType() && + /* + * libvlc doesn't differenciate subscriptions & playlists so we need to + * avoid forcing a type change from subscription to playlist here + */ + ( fileType != IFile::Type::Playlist || + item.fileType() != IFile::Type::Subscription ) ) + { + LOG_DEBUG( "New filetype detected, converting ", mrl, " task from type ", + static_cast>( item.fileType() ), + " to type ", + static_cast>( fileType ) ); + if ( item.setFileType( fileType ) == false ) + return Status::Fatal; + } +#endif + + if ( ( item.fileType() == IFile::Type::Playlist || + item.fileType() == IFile::Type::Subscription ) && + vlcMedia.subitems()->count() == 0 ) + { + LOG_DEBUG( "Discarding ", + ( item.fileType() == IFile::Type::Playlist ? "playlist file" + : "subscription" ), + " with no subitem: ", mrl ); + return Status::Fatal; + } #if LIBVLC_VERSION_INT < LIBVLC_VERSION(4, 0, 0, 0) && !defined(FORCE_ATTACHMENTS_API) - auto artworkMrl = vlcMedia.meta( libvlc_meta_ArtworkURL ); - if ( artworkMrl.empty() == false ) - { - if ( utils::url::schemeIs( "attachment://", artworkMrl ) == true ) - { - LOG_WARN( "Artwork for ", mrl, " is an attachment. Falling back to playback" ); - VLC::MediaPlayer mp( vlcMedia ); - auto res = MetadataCommon::startPlayback( vlcMedia, mp, m_mutex, m_cond ); - if ( res == false ) - return Status::Fatal; - } - item.addEmbeddedThumbnail( std::make_shared( - utils::url::toLocalPath( vlcMedia.meta( libvlc_meta_ArtworkURL ) ) ) ); - } + auto artworkMrl = vlcMedia.meta( libvlc_meta_ArtworkURL ); + if ( artworkMrl.empty() == false ) + { + if ( utils::url::schemeIs( "attachment://", artworkMrl ) == true ) + { + LOG_WARN( "Artwork for ", mrl, " is an attachment. Falling back to playback" ); + VLC::MediaPlayer mp( vlcMedia ); + auto res = MetadataCommon::startPlayback( vlcMedia, mp, m_mutex, m_cond ); + if ( res == false ) + return Status::Fatal; + } + item.addEmbeddedThumbnail( std::make_shared( + utils::url::toLocalPath( vlcMedia.meta( libvlc_meta_ArtworkURL ) ) ) ); + } #endif - mediaToItem( vlcMedia, item ); - return Status::Success; + mediaToItem( vlcMedia, item ); + return Status::Success; } const char* VLCMetadataService::name() const { - return "VLC"; + return "VLC"; } void VLCMetadataService::onFlushing() @@ -199,233 +230,253 @@ void VLCMetadataService::onRestarted() Step VLCMetadataService::targetedStep() const { - return Step::MetadataExtraction; + return Step::MetadataExtraction; } void VLCMetadataService::stop() { - std::lock_guard lock{ m_mutex }; - if ( m_currentMedia.isValid() ) - { + std::lock_guard lock{ m_mutex }; + if ( m_currentMedia.isValid() ) + { #if LIBVLC_VERSION_INT >= LIBVLC_VERSION(4, 0, 0, 0) - m_currentMedia.parseStop( VLCInstance::get() ); + m_currentMedia.parseStop( VLCInstance::get() ); #else - m_currentMedia.parseStop(); + m_currentMedia.parseStop(); #endif - } + } } void VLCMetadataService::mediaToItem( VLC::Media& media, IItem& item ) { - item.setMeta( IItem::Metadata::Title, - media.meta( libvlc_meta_Title ) ); - item.setMeta( IItem::Metadata::ArtworkUrl, - media.meta( libvlc_meta_ArtworkURL ) ); - item.setMeta( IItem::Metadata::ShowName, - media.meta( libvlc_meta_ShowName ) ); - item.setMeta( IItem::Metadata::Episode, - media.meta( libvlc_meta_Episode ) ); - item.setMeta( IItem::Metadata::Album, - media.meta( libvlc_meta_Album ) ); - item.setMeta( IItem::Metadata::Genre, - media.meta( libvlc_meta_Genre ) ); - item.setMeta( IItem::Metadata::Date, - media.meta( libvlc_meta_Date ) ); - item.setMeta( IItem::Metadata::AlbumArtist, - media.meta( libvlc_meta_AlbumArtist ) ); - item.setMeta( IItem::Metadata::Artist, - media.meta( libvlc_meta_Artist ) ); - item.setMeta( IItem::Metadata::TrackNumber, - media.meta( libvlc_meta_TrackNumber ) ); - item.setMeta( IItem::Metadata::DiscNumber, - media.meta( libvlc_meta_DiscNumber ) ); - item.setMeta( IItem::Metadata::DiscTotal, - media.meta( libvlc_meta_DiscTotal ) ); - item.setMeta( IItem::Metadata::Description, - media.meta( libvlc_meta_Description ) ); - item.setDuration( media.duration() ); + item.setMeta( IItem::Metadata::Title, + media.meta( libvlc_meta_Title ) ); + item.setMeta( IItem::Metadata::ArtworkUrl, + media.meta( libvlc_meta_ArtworkURL ) ); + item.setMeta( IItem::Metadata::ShowName, + media.meta( libvlc_meta_ShowName ) ); + item.setMeta( IItem::Metadata::Episode, + media.meta( libvlc_meta_Episode ) ); + item.setMeta( IItem::Metadata::Album, + media.meta( libvlc_meta_Album ) ); + item.setMeta( IItem::Metadata::Genre, + media.meta( libvlc_meta_Genre ) ); + item.setMeta( IItem::Metadata::Date, + media.meta( libvlc_meta_Date ) ); + item.setMeta( IItem::Metadata::AlbumArtist, + media.meta( libvlc_meta_AlbumArtist ) ); + item.setMeta( IItem::Metadata::Artist, + media.meta( libvlc_meta_Artist ) ); + item.setMeta( IItem::Metadata::TrackNumber, + media.meta( libvlc_meta_TrackNumber ) ); + item.setMeta( IItem::Metadata::DiscNumber, + media.meta( libvlc_meta_DiscNumber ) ); + item.setMeta( IItem::Metadata::DiscTotal, + media.meta( libvlc_meta_DiscTotal ) ); + item.setMeta( IItem::Metadata::Description, + media.meta( libvlc_meta_Description ) ); + item.setDuration( media.duration() ); #if LIBVLC_VERSION_INT < LIBVLC_VERSION(4, 0, 0, 0) - auto tracks = media.tracks(); + auto tracks = media.tracks(); #else - std::vector tracks; - auto trackList = media.tracks( VLC::MediaTrack::Type::Audio ); - std::move( begin( trackList ), end( trackList ), std::back_inserter( tracks ) ); - trackList = media.tracks( VLC::MediaTrack::Type::Video ); - std::move( begin( trackList ), end( trackList ), std::back_inserter( tracks ) ); - trackList = media.tracks( VLC::MediaTrack::Type::Subtitle ); - std::move( begin( trackList ), end( trackList ), std::back_inserter( tracks ) ); + std::vector tracks; + auto trackList = media.tracks( VLC::MediaTrack::Type::Audio ); + std::move( begin( trackList ), end( trackList ), std::back_inserter( tracks ) ); + trackList = media.tracks( VLC::MediaTrack::Type::Video ); + std::move( begin( trackList ), end( trackList ), std::back_inserter( tracks ) ); + trackList = media.tracks( VLC::MediaTrack::Type::Subtitle ); + std::move( begin( trackList ), end( trackList ), std::back_inserter( tracks ) ); #endif - for ( const auto& track : tracks ) - { - IItem::Track t; - - if ( track.type() == VLC::MediaTrack::Type::Audio ) - { - t.type = IItem::Track::Type::Audio; - t.u.a.nbChannels = track.channels(); - t.u.a.rate = track.rate(); - } - else if ( track.type() == VLC::MediaTrack::Type::Video ) - { - t.type = IItem::Track::Type::Video; - t.u.v.fpsNum = track.fpsNum(); - t.u.v.fpsDen = track.fpsDen(); - t.u.v.width = track.width(); - t.u.v.height = track.height(); - t.u.v.sarNum = track.sarNum(); - t.u.v.sarDen = track.sarDen(); - } - else if ( track.type() == VLC::MediaTrack::Type::Subtitle ) - { - t.type = IItem::Track::Type::Subtitle; - t.language = track.language(); - t.description = track.description(); - const auto& enc = track.encoding(); - strncpy( t.u.s.encoding, enc.c_str(), sizeof(t.u.s.encoding) - 1 ); - } - else - continue; - auto codec = track.codec(); - std::string fcc( reinterpret_cast( &codec ), 4 ); - t.codec = std::move( fcc ); - - t.bitrate = track.bitrate(); - t.language = track.language(); - t.description = track.description(); - - item.addTrack( std::move( t ) ); - } - - auto subItems = media.subitems(); - if ( subItems != nullptr ) - { - for ( auto i = 0; i < subItems->count(); ++i ) - { - auto vlcMedia = subItems->itemAtIndex( i ); - assert( vlcMedia != nullptr ); - auto mrl = vlcMedia->mrl(); - mrl = utils::url::encode( utils::url::decode( mrl ) ); - IItem& subItem = item.createLinkedItem( mrl, - IFile::Type::Main, i ); - mediaToItem( *vlcMedia, subItem ); - } - } + for ( const auto& track : tracks ) + { + IItem::Track t; + + if ( track.type() == VLC::MediaTrack::Type::Audio ) + { + t.type = IItem::Track::Type::Audio; + t.u.a.nbChannels = track.channels(); + t.u.a.rate = track.rate(); + } + else if ( track.type() == VLC::MediaTrack::Type::Video ) + { + t.type = IItem::Track::Type::Video; + t.u.v.fpsNum = track.fpsNum(); + t.u.v.fpsDen = track.fpsDen(); + t.u.v.width = track.width(); + t.u.v.height = track.height(); + t.u.v.sarNum = track.sarNum(); + t.u.v.sarDen = track.sarDen(); + } + else if ( track.type() == VLC::MediaTrack::Type::Subtitle ) + { + t.type = IItem::Track::Type::Subtitle; + t.language = track.language(); + t.description = track.description(); + const auto& enc = track.encoding(); + strncpy( t.u.s.encoding, enc.c_str(), sizeof(t.u.s.encoding) - 1 ); + } + else + continue; + auto codec = track.codec(); + std::string fcc( reinterpret_cast( &codec ), 4 ); + t.codec = std::move( fcc ); + + t.bitrate = track.bitrate(); + t.language = track.language(); + t.description = track.description(); + + item.addTrack( std::move( t ) ); + } + + auto subItems = media.subitems(); + if ( subItems != nullptr ) + { + for ( auto i = 0; i < subItems->count(); ++i ) + { + auto vlcMedia = subItems->itemAtIndex( i ); + assert( vlcMedia != nullptr ); + auto mrl = vlcMedia->mrl(); + mrl = utils::url::encode( utils::url::decode( mrl ) ); + IItem& subItem = item.createLinkedItem( mrl, + IFile::Type::Main, i ); + mediaToItem( *vlcMedia, subItem ); + } + } } #if LIBVLC_VERSION_INT >= LIBVLC_VERSION(4, 0, 0, 0) VLCEmbeddedThumbnail4_0::VLCEmbeddedThumbnail4_0( VLC::Picture pic ) - : m_pic( std::move( pic ) ) + : m_pic( std::move( pic ) ) { } bool VLCEmbeddedThumbnail4_0::save( const std::string& path ) { - return m_pic.save( path ); + return m_pic.save( path ); } size_t VLCEmbeddedThumbnail4_0::size() const { - size_t size; - m_pic.buffer( &size ); - return size; + size_t size; + m_pic.buffer( &size ); + return size; } std::string VLCEmbeddedThumbnail4_0::hash() const { - size_t size; - auto buff = m_pic.buffer( &size ); - return utils::hash::toString( utils::hash::xxFromBuff( buff, size ) ); + size_t size; + auto buff = m_pic.buffer( &size ); + return utils::hash::toString( utils::hash::xxFromBuff( buff, size ) ); } std::string VLCEmbeddedThumbnail4_0::extension() const { - switch ( m_pic.type() ) - { - case VLC::Picture::Type::Argb: - return "bmp"; - case VLC::Picture::Type::Jpg: - return "jpg"; - case VLC::Picture::Type::Png: - return "png"; - } - assert( !"Invalid thumbnail type" ); - return {}; + switch ( m_pic.type() ) + { + case VLC::Picture::Type::Argb: + return "bmp"; + case VLC::Picture::Type::Jpg: + return "jpg"; + case VLC::Picture::Type::Png: + return "png"; + } + assert( !"Invalid thumbnail type" ); + return {}; +} + +IFile::Type VLCMetadataService::mediaTypeToFileType( VLC::Media::Type type ) +{ + switch ( type ) + { + case VLC::Media::Type::Unknown: + return IFile::Type::Unknown; + case VLC::Media::Type::File: + return IFile::Type::Main; + case VLC::Media::Type::Disc: + return IFile::Type::Disc; + case VLC::Media::Type::Playlist: + return IFile::Type::Playlist; + case VLC::Media::Type::Stream: + case VLC::Media::Type::Directory: + assert( !"Unexpected VLC media type" ); + break; + } + return IFile::Type::Unknown; } #elif defined(FORCE_ATTACHMENTS_API) VLCEmbeddedThumbnailForced::VLCEmbeddedThumbnailForced( libvlc_picture_t *pic ) - : m_pic( pic ) + : m_pic( pic ) { - libvlc_picture_retain( m_pic ); + libvlc_picture_retain( m_pic ); } VLCEmbeddedThumbnailForced::~VLCEmbeddedThumbnailForced() { - libvlc_picture_release( m_pic ); + libvlc_picture_release( m_pic ); } bool VLCEmbeddedThumbnailForced::save( const std::string& path ) { - return libvlc_picture_save( m_pic, path.c_str() ) == 0; + return libvlc_picture_save( m_pic, path.c_str() ) == 0; } size_t VLCEmbeddedThumbnailForced::size() const { - size_t size; - libvlc_picture_get_buffer( m_pic, &size ); - return size; + size_t size; + libvlc_picture_get_buffer( m_pic, &size ); + return size; } std::string VLCEmbeddedThumbnailForced::hash() const { - size_t size; - auto buff = libvlc_picture_get_buffer( m_pic, &size ); - return utils::hash::toString( utils::hash::xxFromBuff( buff, size ) ); + size_t size; + auto buff = libvlc_picture_get_buffer( m_pic, &size ); + return utils::hash::toString( utils::hash::xxFromBuff( buff, size ) ); } std::string VLCEmbeddedThumbnailForced::extension() const { - switch ( libvlc_picture_type( m_pic ) ) - { - case libvlc_picture_Argb: - return "bmp"; - case libvlc_picture_Jpg: - return "jpg"; - case libvlc_picture_Png: - return "png"; - } - assert( !"Invalid thumbnail type" ); - return nullptr; + switch ( libvlc_picture_type( m_pic ) ) + { + case libvlc_picture_Argb: + return "bmp"; + case libvlc_picture_Jpg: + return "jpg"; + case libvlc_picture_Png: + return "png"; + } + assert( !"Invalid thumbnail type" ); + return nullptr; } #else VLCEmbeddedThumbnail3_0::VLCEmbeddedThumbnail3_0( std::string path ) - : m_thumbnailPath( std::move( path ) ) + : m_thumbnailPath( std::move( path ) ) { } bool VLCEmbeddedThumbnail3_0::save( const std::string& path ) { - return utils::fs::copy( m_thumbnailPath, path ); + return utils::fs::copy( m_thumbnailPath, path ); } size_t VLCEmbeddedThumbnail3_0::size() const { - return utils::fs::fileSize( m_thumbnailPath ); + return utils::fs::fileSize( m_thumbnailPath ); } std::string VLCEmbeddedThumbnail3_0::hash() const { - return utils::hash::toString( utils::hash::xxFromFile( m_thumbnailPath ) ); + return utils::hash::toString( utils::hash::xxFromFile( m_thumbnailPath ) ); } std::string VLCEmbeddedThumbnail3_0::extension() const { - return utils::file::extension( m_thumbnailPath ); + return utils::file::extension( m_thumbnailPath ); } #endif diff --git a/src/metadata_services/vlc/VLCMetadataService.h b/src/metadata_services/vlc/VLCMetadataService.h index f30a50f3..205284bd 100644 --- a/src/metadata_services/vlc/VLCMetadataService.h +++ b/src/metadata_services/vlc/VLCMetadataService.h @@ -95,6 +95,7 @@ private: virtual void stop() override; void mediaToItem( VLC::Media& media, parser::IItem& item ); + IFile::Type mediaTypeToFileType( VLC::Media::Type type ); #if defined(FORCE_ATTACHMENTS_API) static void onAttachedThumbnailsFound( const libvlc_event_t* e, void* data ); -- GitLab From 2d146856019855d4470b2a3e385849bed4771abb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Wed, 16 Sep 2020 09:42:50 +0200 Subject: [PATCH 14/17] tests: Tester: Add an 'isDisc' check for media --- test/samples/Tester.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/samples/Tester.cpp b/test/samples/Tester.cpp index 83bfadf6..26ef1eac 100644 --- a/test/samples/Tester.cpp +++ b/test/samples/Tester.cpp @@ -584,6 +584,20 @@ void Tests::checkMedias(const rapidjson::Value& expectedMedias) { checkMediaFiles( media.get(), expectedMedia["files"] ); } + if ( expectedMedia.HasMember( "isDisc" ) ) + { + auto files = media->files(); + auto isDisc = false; + for ( const auto& f : files ) + { + if ( f->type() == IFile::Type::Disc ) + { + isDisc = true; + break; + } + } + ASSERT_EQ( isDisc, expectedMedia["isDisc"].GetBool() ); + } } } -- GitLab From c81cee78a9c460b0cf5344fa3eb7b1bf4fa31cd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Wed, 16 Sep 2020 09:45:06 +0200 Subject: [PATCH 15/17] tests: samples: Add functional tests for DVD folder & DVD isos --- test/samples/meson.build | 2 ++ test/samples/testcases/parse_dvd.json | 14 ++++++++++++++ test/samples/testcases/parse_iso.json | 14 ++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 test/samples/testcases/parse_dvd.json create mode 100644 test/samples/testcases/parse_iso.json diff --git a/test/samples/meson.build b/test/samples/meson.build index 88cda98f..c5115a5b 100644 --- a/test/samples/meson.build +++ b/test/samples/meson.build @@ -41,6 +41,8 @@ test_list = [ 'attached_subs', 'attached_audio', 'various', + 'parse_dvd', + 'parse_iso', ] if libvlc_dep.version().version_compare('>=4.0') diff --git a/test/samples/testcases/parse_dvd.json b/test/samples/testcases/parse_dvd.json new file mode 100644 index 00000000..7c86e6da --- /dev/null +++ b/test/samples/testcases/parse_dvd.json @@ -0,0 +1,14 @@ +{ + "input": [ + "discs/dvd_folder/" + ], + "expected": { + "nbVideos": 1, + "nbAudios": 0, + "media": [{ + "title": "dvd_folder", + "isDisc": true, + "snapshotExpected": true + }] + } +} diff --git a/test/samples/testcases/parse_iso.json b/test/samples/testcases/parse_iso.json new file mode 100644 index 00000000..22d970ba --- /dev/null +++ b/test/samples/testcases/parse_iso.json @@ -0,0 +1,14 @@ +{ + "input": [ + "discs/dvd_iso/" + ], + "expected": { + "nbVideos": 1, + "nbAudios": 0, + "media": [{ + "title": "super_dvd_iso", + "isDisc": true, + "snapshotExpected": true + }] + } +} -- GitLab From b19df2a7ecfe86020c7875ac85a66fd8a2de14b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Fri, 21 May 2021 12:23:11 +0200 Subject: [PATCH 16/17] WIP_test_on_msys2 --- src/filesystem/win32/DeviceLister.cpp | 4 ++++ test/samples/Tester.cpp | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/filesystem/win32/DeviceLister.cpp b/src/filesystem/win32/DeviceLister.cpp index 1f8c2a13..d71e4c4b 100644 --- a/src/filesystem/win32/DeviceLister.cpp +++ b/src/filesystem/win32/DeviceLister.cpp @@ -134,6 +134,10 @@ std::vector DeviceLister::localDevices() const std::vector{ utils::file::toMrl( mountpoint ) }, type == DRIVE_REMOVABLE ); } + auto fakeMountpoint = std::string{ }; + res.emplace_back( "{fake-uuid}", + std::vector{ "file:///Y:/" }, + false ); return res; } diff --git a/test/samples/Tester.cpp b/test/samples/Tester.cpp index 26ef1eac..7a23df8a 100644 --- a/test/samples/Tester.cpp +++ b/test/samples/Tester.cpp @@ -45,7 +45,8 @@ #include -const std::string Tests::Directory = SRC_DIR "/test/samples/"; +const std::string Tests::Directory = "../test/samples/"; +//const std::string Tests::Directory = SRC_DIR "/test/samples/"; MockCallback::MockCallback() : m_thumbnailDone( false ) -- GitLab From 90a1f9c1dc1d53ce4c22919bbeae28dc10de2d96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Thu, 14 Apr 2022 16:12:00 +0200 Subject: [PATCH 17/17] Revert "WIP_test_on_msys2" This reverts commit a47fe1b964686636d12811e1ad9e0b0603b036ff. --- src/filesystem/win32/DeviceLister.cpp | 4 ---- test/samples/Tester.cpp | 3 +-- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/filesystem/win32/DeviceLister.cpp b/src/filesystem/win32/DeviceLister.cpp index d71e4c4b..1f8c2a13 100644 --- a/src/filesystem/win32/DeviceLister.cpp +++ b/src/filesystem/win32/DeviceLister.cpp @@ -134,10 +134,6 @@ std::vector DeviceLister::localDevices() const std::vector{ utils::file::toMrl( mountpoint ) }, type == DRIVE_REMOVABLE ); } - auto fakeMountpoint = std::string{ }; - res.emplace_back( "{fake-uuid}", - std::vector{ "file:///Y:/" }, - false ); return res; } diff --git a/test/samples/Tester.cpp b/test/samples/Tester.cpp index 7a23df8a..26ef1eac 100644 --- a/test/samples/Tester.cpp +++ b/test/samples/Tester.cpp @@ -45,8 +45,7 @@ #include -const std::string Tests::Directory = "../test/samples/"; -//const std::string Tests::Directory = SRC_DIR "/test/samples/"; +const std::string Tests::Directory = SRC_DIR "/test/samples/"; MockCallback::MockCallback() : m_thumbnailDone( false ) -- GitLab