diff --git a/include/medialibrary/IMedia.h b/include/medialibrary/IMedia.h index 5bcfca4511535c0979a1be37b4342e595b881fb0..bda5795b1f1741fe2e7fcf25fc5c8c7b58ef7263 100644 --- a/include/medialibrary/IMedia.h +++ b/include/medialibrary/IMedia.h @@ -64,6 +64,12 @@ class IMedia * playback history. */ External, + /** + * Represent a stream, which is a specific kind of External media. + * This type of media is also intended to be inserted manually by + * the user. + */ + Stream, }; enum class SubType : uint8_t { diff --git a/include/medialibrary/IMediaLibrary.h b/include/medialibrary/IMediaLibrary.h index 7101b3b4ccd3cd528f7aa1711e703c61aa41a2c6..40f1632975b8f4d83121a5c7671d550d6f79c410 100644 --- a/include/medialibrary/IMediaLibrary.h +++ b/include/medialibrary/IMediaLibrary.h @@ -264,6 +264,13 @@ class IMediaLibrary * The media can be fetched using media( std::string ) afterward. */ virtual MediaPtr addExternalMedia( const std::string& mrl ) = 0; + /** + * @brief addStream Create an external media of type IMedia::Type::Stream + * + * This is equivalent to addExternalMedia, except for the resulting + * new media's type + */ + virtual MediaPtr addStream( const std::string& mrl ) = 0; virtual Query audioFiles( const QueryParameters* params = nullptr ) const = 0; virtual Query videoFiles( const QueryParameters* params = nullptr ) const = 0; virtual AlbumPtr album( int64_t id ) const = 0; diff --git a/src/Media.cpp b/src/Media.cpp index cf3e30843c4a3c989a47dfb0238d9428403262c9..e08400ee6a0cce78133952a2783fc984d462b03c 100644 --- a/src/Media.cpp +++ b/src/Media.cpp @@ -627,10 +627,10 @@ Query Media::search( MediaLibraryPtr ml, const std::string& title, " WHERE " + policy::MediaTable::Name + "Fts MATCH '*' || ? || '*')" " AND f.is_present = 1" " AND f.type = ?" - " AND m.type != ?"; + " AND m.type != ? AND m.type != ?"; req += sortRequest( params ); return make_query( ml, "m.*", req, title, File::Type::Main, - Media::Type::External ); + Media::Type::External, Media::Type::Stream ); } Query Media::search( MediaLibraryPtr ml, const std::string& title, diff --git a/src/MediaLibrary.cpp b/src/MediaLibrary.cpp index 6bb987b8ce720f46a458fc428463579bd8e70c0e..3973128956c807d09f53a761ac3bde442e7b2297 100644 --- a/src/MediaLibrary.cpp +++ b/src/MediaLibrary.cpp @@ -435,13 +435,13 @@ MediaPtr MediaLibrary::media( const std::string& mrl ) const return file->media(); } -MediaPtr MediaLibrary::addExternalMedia( const std::string& mrl ) +MediaPtr MediaLibrary::addExternalMedia( const std::string& mrl, IMedia::Type type ) { try { - return sqlite::Tools::withRetries( 3, [this, &mrl]() -> MediaPtr { + return sqlite::Tools::withRetries( 3, [this, &mrl, type]() -> MediaPtr { auto t = m_dbConnection->newTransaction(); - auto media = Media::create( this, IMedia::Type::External, utils::file::fileName( mrl ) ); + auto media = Media::create( this, type, utils::file::fileName( mrl ) ); if ( media == nullptr ) return nullptr; if ( media->addExternalMrl( mrl, IFile::Type::Main ) == nullptr ) @@ -457,6 +457,16 @@ MediaPtr MediaLibrary::addExternalMedia( const std::string& mrl ) } } +MediaPtr MediaLibrary::addExternalMedia( const std::string& mrl ) +{ + return addExternalMedia( mrl, IMedia::Type::External ); +} + +MediaPtr MediaLibrary::addStream( const std::string& mrl ) +{ + return addExternalMedia( mrl, IMedia::Type::Stream ); +} + Query MediaLibrary::audioFiles( const QueryParameters* params ) const { return Media::listAll( this, IMedia::Type::Audio, params ); diff --git a/src/MediaLibrary.h b/src/MediaLibrary.h index 620def623ac94d509f9734df8eab1e9139313356..28e180ee9abf16cbb4c115cfefa7f557c02b1a47 100644 --- a/src/MediaLibrary.h +++ b/src/MediaLibrary.h @@ -28,6 +28,7 @@ #include "Settings.h" #include "medialibrary/IDeviceLister.h" +#include "medialibrary/IMedia.h" namespace medialibrary { @@ -73,6 +74,7 @@ class MediaLibrary : public IMediaLibrary, public IDeviceListerCb virtual MediaPtr media( int64_t mediaId ) const override; virtual MediaPtr media( const std::string& mrl ) const override; virtual MediaPtr addExternalMedia( const std::string& mrl ) override; + virtual MediaPtr addStream( const std::string& mrl ) override; virtual Query audioFiles( const QueryParameters* params ) const override; virtual Query videoFiles( const QueryParameters* params ) const override; @@ -206,6 +208,8 @@ class MediaLibrary : public IMediaLibrary, public IDeviceListerCb bool onDeviceChanged( fs::IFileSystemFactory& fsFactory, Device& device ); bool createThumbnailFolder( const std::string& thumbnailPath ) const; + MediaPtr addExternalMedia( const std::string& mrl, IMedia::Type type ); + protected: virtual void addLocalFsFactory(); diff --git a/test/unittest/MediaTests.cpp b/test/unittest/MediaTests.cpp index 33ea540eb75e2a91f6d0abd3369a015592bff4e3..1dd278dc539b95a66db9595723153cad6da86eb2 100644 --- a/test/unittest/MediaTests.cpp +++ b/test/unittest/MediaTests.cpp @@ -685,6 +685,31 @@ TEST_F( Medias, SortFilename ) ASSERT_EQ( m3->id(), media[0]->id() ); } +TEST_F( Medias, CreateStream ) +{ + auto m1 = ml->addStream( "http://foo.bar/media.mkv" ); + ASSERT_EQ( IMedia::Type::Stream, m1->type() ); +} + +TEST_F( Medias, SearchExternal ) +{ + auto m1 = std::static_pointer_cast( ml->addExternalMedia( "localfile.mkv" ) ); + m1->setTitle( "local otter" ); + auto m2 = std::static_pointer_cast( ml->addStream( "http://remote.file/media.asf" ) ); + m2->setTitle( "remote otter" ); + + auto media = ml->searchMedia( "otter", nullptr )->all(); + ASSERT_EQ( 0u, media.size() ); + + m1->setType( IMedia::Type::Video ); + m1->save(); + m2->setType( IMedia::Type::Video ); + m2->save(); + + media = ml->searchMedia( "otter", nullptr )->all(); + ASSERT_EQ( 2u, media.size() ); +} + class FetchMedia : public Tests { protected: