[vlc-devel] [PATCH 4/4] medialibrary: Bump version & update API usages
Hugo Beauzée-Luyssen
hugo at beauzee.fr
Tue Jun 25 16:04:55 CEST 2019
- Multiple thumbnail can now be used
- Discovery, thumbnailing & metadata extractions are now interruptible
- An entry_point_added event has been added
--
Appologies for the big commit, but splitting it in multiple chunk would
break incremental build
---
contrib/src/medialibrary/rules.mak | 2 +-
include/vlc_media_library.h | 62 +++++++++++++----
.../gui/qt/components/mediacenter/mlalbum.cpp | 2 +-
.../qt/components/mediacenter/mlartist.cpp | 2 +-
.../gui/qt/components/mediacenter/mlvideo.cpp | 13 ++--
.../misc/medialibrary/MetadataExtractor.cpp | 30 ++++----
modules/misc/medialibrary/Thumbnailer.cpp | 67 +++++++++---------
modules/misc/medialibrary/entities.cpp | 68 ++++++++++++-------
modules/misc/medialibrary/medialib.cpp | 31 +++++++--
modules/misc/medialibrary/medialibrary.h | 39 +++++++++--
src/misc/medialibrary.c | 12 +++-
11 files changed, 221 insertions(+), 107 deletions(-)
diff --git a/contrib/src/medialibrary/rules.mak b/contrib/src/medialibrary/rules.mak
index 799f9b6db5..e9d5359f97 100644
--- a/contrib/src/medialibrary/rules.mak
+++ b/contrib/src/medialibrary/rules.mak
@@ -1,4 +1,4 @@
-MEDIALIBRARY_HASH := 60073666abbd5f604dddbfd600968bac7f94cd5e
+MEDIALIBRARY_HASH := d92baf8033c72f687d9853a483d27a70fd4e196e
MEDIALIBRARY_VERSION := git-$(MEDIALIBRARY_HASH)
MEDIALIBRARY_GITURL := https://code.videolan.org/videolan/medialibrary.git
diff --git a/include/vlc_media_library.h b/include/vlc_media_library.h
index 6d2d39d0a0..e6205f31ca 100644
--- a/include/vlc_media_library.h
+++ b/include/vlc_media_library.h
@@ -68,6 +68,24 @@ typedef enum vlc_ml_track_type_t
VLC_ML_TRACK_TYPE_AUDIO,
} vlc_ml_track_type_t;
+typedef enum vlc_ml_thumbnail_size_t
+{
+ VLC_ML_THUMBNAIL_SMALL,
+ VLC_ML_THUMBNAIL_BANNER,
+
+ VLC_ML_THUMBNAIL_SIZE_COUNT
+} vlc_ml_thumbnail_size_t;
+
+typedef struct vlc_ml_thumbnail_t
+{
+ char* psz_mrl;
+ /**
+ * True if a thumbnail is available, or if thumbnail generation was
+ * attempted but failed
+ */
+ bool b_generated;
+} vlc_ml_thumbnail_t;
+
typedef struct vlc_ml_movie_t
{
char* psz_summary;
@@ -182,10 +200,8 @@ typedef struct vlc_ml_media_t
time_t i_last_played_date;
char* psz_title;
- char* psz_artwork_mrl;
- /* True if a thumbnail is available, or if thumbnail generation was
- * attempted but failed */
- bool b_artwork_generated;
+ vlc_ml_thumbnail_t thumbnails[VLC_ML_THUMBNAIL_SIZE_COUNT];
+
bool b_is_favorite;
union
@@ -209,7 +225,7 @@ typedef struct vlc_ml_artist_t
int64_t i_id;
char* psz_name;
char* psz_shortbio;
- char* psz_artwork_mrl;
+ vlc_ml_thumbnail_t thumbnails[VLC_ML_THUMBNAIL_SIZE_COUNT];
char* psz_mb_id;
unsigned int i_nb_album;
@@ -226,7 +242,7 @@ typedef struct vlc_ml_album_t {
int64_t i_id;
char* psz_title;
char* psz_summary;
- char* psz_artwork_mrl;
+ vlc_ml_thumbnail_t thumbnails[VLC_ML_THUMBNAIL_SIZE_COUNT];
char* psz_artist;
int64_t i_artist_id;
@@ -439,8 +455,8 @@ enum vlc_ml_control
VLC_ML_MEDIA_INCREASE_PLAY_COUNT, /**< arg1: media id; can fail */
VLC_ML_MEDIA_GET_MEDIA_PLAYBACK_PREF, /**< arg1: media id; arg2: vlc_ml_playback_pref; arg3: char**; */
VLC_ML_MEDIA_SET_MEDIA_PLAYBACK_PREF, /**< arg1: media id; arg2: vlc_ml_playback_pref; arg3: const char*; */
- VLC_ML_MEDIA_SET_THUMBNAIL, /**< arg1: media id; arg2: const char*; */
- VLC_ML_MEDIA_GENERATE_THUMBNAIL, /**< arg1: media id; */
+ VLC_ML_MEDIA_SET_THUMBNAIL, /**< arg1: media id; arg2: const char*; arg3: vlc_ml_thumbnail_size_t */
+ VLC_ML_MEDIA_GENERATE_THUMBNAIL, /**< arg1: media id; arg2: vlc_ml_thumbnail_size_t; arg3: width; arg4: height; arg5: position */
VLC_ML_MEDIA_ADD_EXTERNAL_MRL, /**< arg1: media id; arg2: const char*; arg3: type(vlc_ml_file_type_t) */
};
@@ -542,6 +558,16 @@ enum vlc_ml_event_type
* vlc_ml_event_t::reload_completed::b_success
*/
VLC_ML_EVENT_RELOAD_COMPLETED,
+ /**
+ * Sent when a new entry point gets added to the database.
+ * The entry point that was added is stored in
+ * vlc::ml_event_t::entry_point_added::psz_entry_point, and the success or failure
+ * state is stored in vlc_ml_event_t::entry_point_added::b_success
+ * If successful, this event won't be emited again for this entry point.
+ * In case of failure, this event will be fired again if the same entry point
+ * is queued for discovery again.
+ */
+ VLC_ML_EVENT_ENTRY_POINT_ADDED,
/**
* Sent when an entry point removal request has been processed.
* The removed entry point is stored in
@@ -615,6 +641,11 @@ typedef struct vlc_ml_event_t
bool b_success;
} reload_completed;
struct
+ {
+ const char* psz_entry_point;
+ bool b_success;
+ } entry_point_added;
+ struct
{
const char* psz_entry_point;
bool b_success;
@@ -652,6 +683,7 @@ typedef struct vlc_ml_event_t
struct
{
const vlc_ml_media_t* p_media;
+ vlc_ml_thumbnail_size_t i_size;
bool b_success;
} media_thumbnail_generated;
};
@@ -848,14 +880,20 @@ static inline int vlc_ml_media_set_playback_pref( vlc_medialibrary_t* p_ml, int6
return vlc_ml_control( p_ml, VLC_ML_MEDIA_SET_MEDIA_PLAYBACK_PREF, i_media_id, i_pref, psz_value );
}
-static inline int vlc_ml_media_set_thumbnail( vlc_medialibrary_t* p_ml, int64_t i_media_id, const char* psz_mrl )
+static inline int vlc_ml_media_set_thumbnail( vlc_medialibrary_t* p_ml, int64_t i_media_id,
+ const char* psz_mrl, vlc_ml_thumbnail_size_t sizeType )
{
- return vlc_ml_control( p_ml, VLC_ML_MEDIA_SET_THUMBNAIL, i_media_id, psz_mrl );
+ return vlc_ml_control( p_ml, VLC_ML_MEDIA_SET_THUMBNAIL, i_media_id, psz_mrl, sizeType );
}
-static inline int vlc_ml_media_generate_thumbnail( vlc_medialibrary_t* p_ml, int64_t i_media_id )
+static inline int vlc_ml_media_generate_thumbnail( vlc_medialibrary_t* p_ml, int64_t i_media_id,
+ vlc_ml_thumbnail_size_t size_type,
+ uint32_t i_desired_width,
+ uint32_t i_desired_height,
+ float position )
{
- return vlc_ml_control( p_ml, VLC_ML_MEDIA_GENERATE_THUMBNAIL, i_media_id );
+ return vlc_ml_control( p_ml, VLC_ML_MEDIA_GENERATE_THUMBNAIL, i_media_id,
+ size_type, i_desired_width, i_desired_height, position );
}
static inline int vlc_ml_media_add_external_mrl( vlc_medialibrary_t* p_ml, int64_t i_media_id,
diff --git a/modules/gui/qt/components/mediacenter/mlalbum.cpp b/modules/gui/qt/components/mediacenter/mlalbum.cpp
index 271133f8f8..88df4f034a 100644
--- a/modules/gui/qt/components/mediacenter/mlalbum.cpp
+++ b/modules/gui/qt/components/mediacenter/mlalbum.cpp
@@ -25,7 +25,7 @@ MLAlbum::MLAlbum(vlc_medialibrary_t* _ml, const vlc_ml_album_t *_data, QObject *
, m_title ( QString::fromUtf8( _data->psz_title ) )
, m_releaseYear ( _data->i_year )
, m_shortSummary( QString::fromUtf8( _data->psz_summary ) )
- , m_cover ( QString::fromUtf8( _data->psz_artwork_mrl ) )
+ , m_cover ( QString::fromUtf8( _data->thumbnails[VLC_ML_THUMBNAIL_SMALL].psz_mrl ) )
, m_mainArtist ( QString::fromUtf8( _data->psz_artist ) )
, m_nbTracks ( _data->i_nb_tracks )
{
diff --git a/modules/gui/qt/components/mediacenter/mlartist.cpp b/modules/gui/qt/components/mediacenter/mlartist.cpp
index bf4e2ee2a7..98a6b0b96b 100644
--- a/modules/gui/qt/components/mediacenter/mlartist.cpp
+++ b/modules/gui/qt/components/mediacenter/mlartist.cpp
@@ -24,7 +24,7 @@ MLArtist::MLArtist(const vlc_ml_artist_t* _data, QObject *_parent)
, m_id ( _data->i_id, VLC_ML_PARENT_ARTIST )
, m_name ( QString::fromUtf8( _data->psz_name ) )
, m_shortBio( QString::fromUtf8( _data->psz_shortbio ) )
- , m_cover ( QString::fromUtf8( _data->psz_artwork_mrl ) )
+ , m_cover ( QString::fromUtf8( _data->thumbnails[VLC_ML_THUMBNAIL_SMALL].psz_mrl ) )
, m_nbAlbums( _data->i_nb_album )
{
assert( _data );
diff --git a/modules/gui/qt/components/mediacenter/mlvideo.cpp b/modules/gui/qt/components/mediacenter/mlvideo.cpp
index 84190f6ad7..4305327be0 100644
--- a/modules/gui/qt/components/mediacenter/mlvideo.cpp
+++ b/modules/gui/qt/components/mediacenter/mlvideo.cpp
@@ -27,9 +27,9 @@ MLVideo::MLVideo(vlc_medialibrary_t* ml, const vlc_ml_media_t* data, QObject* pa
, m_ml( ml )
, m_id( data->i_id, VLC_ML_PARENT_UNKNOWN )
, m_title( QString::fromUtf8( data->psz_title ) )
- , m_thumbnail( QString::fromUtf8( data->psz_artwork_mrl ) )
+ , m_thumbnail( QString::fromUtf8( data->thumbnails[VLC_ML_THUMBNAIL_SMALL].psz_mrl ) )
, m_playCount( data->i_playcount )
- , m_thumbnailGenerated( data->b_artwork_generated )
+ , m_thumbnailGenerated( data->thumbnails[VLC_ML_THUMBNAIL_SMALL].b_generated )
, m_ml_event_handle( nullptr, [this](vlc_ml_event_callback_t* cb ) {
assert( m_ml != nullptr );
vlc_ml_event_unregister_callback( m_ml, cb );
@@ -88,14 +88,16 @@ void MLVideo::onMlEvent( void* data, const vlc_ml_event_t* event )
void MLVideo::onMlEvent( const vlc_ml_event_t* event )
{
- if ( event->i_type != VLC_ML_EVENT_MEDIA_THUMBNAIL_GENERATED )
+ if ( event->i_type != VLC_ML_EVENT_MEDIA_THUMBNAIL_GENERATED ||
+ event->media_thumbnail_generated.i_size != VLC_ML_THUMBNAIL_SMALL )
return;
m_thumbnailGenerated = true;
if ( event->media_thumbnail_generated.p_media->i_id != m_id.id )
return;
if ( event->media_thumbnail_generated.b_success == false )
return;
- auto thumbnailMrl = event->media_thumbnail_generated.p_media->psz_artwork_mrl;
+ auto thumbnailMrl = event->media_thumbnail_generated
+ .p_media->thumbnails[event->media_thumbnail_generated.i_size].psz_mrl;
m_thumbnail = QString::fromUtf8( thumbnailMrl );
vlc_ml_event_unregister_from_callback( m_ml, m_ml_event_handle.release() );
emit onThumbnailChanged( m_thumbnail );
@@ -116,7 +118,8 @@ QString MLVideo::getThumbnail()
if ( m_thumbnailGenerated == false )
{
m_ml_event_handle.reset( vlc_ml_event_register_callback( m_ml, onMlEvent, this ) );
- vlc_ml_media_generate_thumbnail( m_ml, m_id.id );
+ vlc_ml_media_generate_thumbnail( m_ml, m_id.id, VLC_ML_THUMBNAIL_SMALL,
+ 512, 320, .15 );
}
return m_thumbnail;
diff --git a/modules/misc/medialibrary/MetadataExtractor.cpp b/modules/misc/medialibrary/MetadataExtractor.cpp
index 7348ab3be3..0047b7b0fc 100644
--- a/modules/misc/medialibrary/MetadataExtractor.cpp
+++ b/modules/misc/medialibrary/MetadataExtractor.cpp
@@ -31,12 +31,12 @@ MetadataExtractor::MetadataExtractor( vlc_object_t* parent )
void MetadataExtractor::onParserEnded( ParseContext& ctx, int status )
{
- vlc::threads::mutex_locker lock( ctx.m_mutex );
+ vlc::threads::mutex_locker lock( ctx.mde->m_mutex );
// We need to probe the item now, but not from the input thread
ctx.success = status == VLC_SUCCESS;
ctx.needsProbing = true;
- ctx.m_cond.signal();
+ ctx.mde->m_cond.signal();
}
void MetadataExtractor::populateItem( medialibrary::parser::IItem& item, input_item_t* inputItem )
@@ -150,7 +150,7 @@ medialibrary::parser::Status MetadataExtractor::run( medialibrary::parser::IItem
&MetadataExtractor::onParserEnded,
&MetadataExtractor::onParserSubtreeAdded,
};
-
+ m_currentCtx = &ctx;
ctx.inputItem->i_preparse_depth = 1;
ctx.inputParser = {
input_item_Parse( ctx.inputItem.get(), m_obj, &cbs,
@@ -158,14 +158,17 @@ medialibrary::parser::Status MetadataExtractor::run( medialibrary::parser::IItem
&input_item_parser_id_Release
};
if ( ctx.inputParser == nullptr )
+ {
+ m_currentCtx = nullptr;
return medialibrary::parser::Status::Fatal;
+ }
{
- vlc::threads::mutex_locker lock( ctx.m_mutex );
+ vlc::threads::mutex_locker lock( m_mutex );
auto deadline = vlc_tick_now() + VLC_TICK_FROM_SEC( 5 );
- while ( ctx.needsProbing == false )
+ while ( ctx.needsProbing == false && ctx.inputParser != nullptr )
{
- auto res = ctx.m_cond.timedwait( ctx.m_mutex, deadline );
+ auto res = m_cond.timedwait( m_mutex, deadline );
if ( res != 0 )
{
msg_Dbg( m_obj, "Timed out while extracting %s metadata",
@@ -173,9 +176,10 @@ medialibrary::parser::Status MetadataExtractor::run( medialibrary::parser::IItem
break;
}
}
+ m_currentCtx = nullptr;
}
- if ( !ctx.success )
+ if ( !ctx.success || ctx.inputParser == nullptr )
return medialibrary::parser::Status::Fatal;
populateItem( item, ctx.inputItem.get() );
@@ -188,11 +192,6 @@ const char* MetadataExtractor::name() const
return "libvlccore extraction";
}
-uint8_t MetadataExtractor::nbThreads() const
-{
- return 1;
-}
-
medialibrary::parser::Step MetadataExtractor::targetedStep() const
{
return medialibrary::parser::Step::MetadataExtraction;
@@ -210,3 +209,10 @@ void MetadataExtractor::onFlushing()
void MetadataExtractor::onRestarted()
{
}
+
+void MetadataExtractor::stop()
+{
+ vlc::threads::mutex_locker lock{ m_mutex };
+ if ( m_currentCtx != nullptr )
+ input_item_parser_id_Interrupt( m_currentCtx->inputParser.get() );
+}
diff --git a/modules/misc/medialibrary/Thumbnailer.cpp b/modules/misc/medialibrary/Thumbnailer.cpp
index 33d90732cd..c96dbc9769 100644
--- a/modules/misc/medialibrary/Thumbnailer.cpp
+++ b/modules/misc/medialibrary/Thumbnailer.cpp
@@ -30,9 +30,8 @@
#include <vlc_url.h>
#include <vlc_cxx_helpers.hpp>
-Thumbnailer::Thumbnailer( vlc_medialibrary_module_t* ml, std::string thumbnailsDir )
+Thumbnailer::Thumbnailer( vlc_medialibrary_module_t* ml )
: m_ml( ml )
- , m_thumbnailDir( std::move( thumbnailsDir ) )
, m_thumbnailer( nullptr, &vlc_thumbnailer_Release )
{
m_thumbnailer.reset( vlc_thumbnailer_Create( VLC_OBJECT( ml ) ) );
@@ -40,71 +39,67 @@ Thumbnailer::Thumbnailer( vlc_medialibrary_module_t* ml, std::string thumbnailsD
throw std::runtime_error( "Failed to instantiate a vlc_thumbnailer_t" );
}
-struct ThumbnailerCtx
-{
- ~ThumbnailerCtx()
- {
- if ( item != nullptr )
- input_item_Release( item );
- if ( thumbnail != nullptr )
- picture_Release( thumbnail );
- }
- vlc::threads::condition_variable cond;
- vlc::threads::mutex mutex;
- input_item_t* item;
- bool done;
- picture_t* thumbnail;
-};
-
-static void onThumbnailComplete( void* data, picture_t* thumbnail )
+void Thumbnailer::onThumbnailComplete( void* data, picture_t* thumbnail )
{
ThumbnailerCtx* ctx = static_cast<ThumbnailerCtx*>( data );
{
- vlc::threads::mutex_locker lock( ctx->mutex );
+ vlc::threads::mutex_locker lock( ctx->thumbnailer->m_mutex );
ctx->done = true;
ctx->thumbnail = thumbnail ? picture_Hold( thumbnail ) : nullptr;
+ ctx->thumbnailer->m_currentContext = nullptr;
}
- ctx->cond.signal();
+ ctx->thumbnailer->m_cond.signal();
}
-bool Thumbnailer::generate( medialibrary::MediaPtr media, const std::string& mrl )
+bool Thumbnailer::generate( const std::string& mrl, uint32_t desiredWidth,
+ uint32_t desiredHeight, float position,
+ const std::string& dest )
{
ThumbnailerCtx ctx{};
- ctx.item = input_item_New( mrl.c_str(), media->title().c_str() );
- if ( unlikely( ctx.item == nullptr ) )
+ auto item = vlc::wrap_cptr( input_item_New( mrl.c_str(), nullptr ),
+ &input_item_Release );
+ if ( unlikely( item == nullptr ) )
return false;
- input_item_AddOption( ctx.item, "no-hwdec", VLC_INPUT_OPTION_TRUSTED );
+ input_item_AddOption( item.get(), "no-hwdec", VLC_INPUT_OPTION_TRUSTED );
ctx.done = false;
{
- vlc::threads::mutex_locker lock( ctx.mutex );
- vlc_thumbnailer_RequestByPos( m_thumbnailer.get(), .3f,
- VLC_THUMBNAILER_SEEK_FAST, ctx.item,
+ vlc::threads::mutex_locker lock( m_mutex );
+ m_currentContext = &ctx;
+ ctx.request = vlc_thumbnailer_RequestByPos( m_thumbnailer.get(), position,
+ VLC_THUMBNAILER_SEEK_FAST, item.get(),
VLC_TICK_FROM_SEC( 3 ),
&onThumbnailComplete, &ctx );
while ( ctx.done == false )
- ctx.cond.wait( ctx.mutex );
+ m_cond.wait( m_mutex );
+ m_currentContext = nullptr;
}
if ( ctx.thumbnail == nullptr )
return false;
block_t* block;
if ( picture_Export( VLC_OBJECT( m_ml ), &block, nullptr, ctx.thumbnail,
- VLC_CODEC_JPEG, 512, 320, true ) != VLC_SUCCESS )
+ VLC_CODEC_JPEG, desiredWidth, desiredHeight, true ) != VLC_SUCCESS )
return false;
auto blockPtr = vlc::wrap_cptr( block, &block_Release );
- std::string outputPath = m_thumbnailDir + std::to_string( media->id() ) + ".jpg";
- auto f = vlc::wrap_cptr( vlc_fopen( outputPath.c_str(), "wb" ), &fclose );
+ auto f = vlc::wrap_cptr( vlc_fopen( dest.c_str(), "wb" ), &fclose );
if ( f == nullptr )
return false;
if ( fwrite( block->p_buffer, block->i_buffer, 1, f.get() ) != 1 )
return false;
- auto thumbnailMrl = vlc::wrap_cptr( vlc_path2uri( outputPath.c_str(), nullptr ) );
- if ( thumbnailMrl == nullptr )
- return false;
+ return true;
+}
- return media->setThumbnail( thumbnailMrl.get() );
+void Thumbnailer::stop()
+{
+ vlc::threads::mutex_locker lock{ m_mutex };
+ if ( m_currentContext != nullptr )
+ {
+ vlc_thumbnailer_Cancel( m_thumbnailer.get(), m_currentContext->request );
+ m_currentContext->done = true;
+ m_cond.signal();
+ }
}
diff --git a/modules/misc/medialibrary/entities.cpp b/modules/misc/medialibrary/entities.cpp
index ecbf9396cd..35975c8ab7 100644
--- a/modules/misc/medialibrary/entities.cpp
+++ b/modules/misc/medialibrary/entities.cpp
@@ -50,6 +50,40 @@ static auto const strdup_helper = []( std::string const& src, char*& dst )
return true;
};
+static_assert( static_cast<uint32_t>( VLC_ML_THUMBNAIL_SMALL ) ==
+ static_cast<uint32_t>( medialibrary::ThumbnailSizeType::Thumbnail ) &&
+ static_cast<uint32_t>( VLC_ML_THUMBNAIL_BANNER ) ==
+ static_cast<uint32_t>( medialibrary::ThumbnailSizeType::Banner ) &&
+ static_cast<uint32_t>( VLC_ML_THUMBNAIL_SIZE_COUNT ) ==
+ static_cast<uint32_t>( medialibrary::ThumbnailSizeType::Count ),
+ "Mismatched thumbnail sizes" );
+
+template <typename T>
+static bool convertThumbnails( const T input, vlc_ml_thumbnail_t *output )
+{
+ for ( auto i = 0u; i < VLC_ML_THUMBNAIL_SIZE_COUNT; ++i )
+ {
+ auto sizeType = static_cast<medialibrary::ThumbnailSizeType>( i );
+ if ( input->isThumbnailGenerated( sizeType ) == false )
+ {
+ output[i].psz_mrl = nullptr;
+ output[i].b_generated = false;
+ continue;
+ }
+ output[i].b_generated = true;
+ const auto thumbnailMrl = input->thumbnailMrl( sizeType );
+ if ( thumbnailMrl.empty() == false )
+ {
+ output[i].psz_mrl = strdup( thumbnailMrl.c_str() );
+ if ( output[i].psz_mrl == nullptr )
+ return false;
+ }
+ else
+ output[i].psz_mrl = nullptr;
+ }
+ return true;
+}
+
bool Convert( const medialibrary::IAlbumTrack* input, vlc_ml_album_track_t& output )
{
output.i_artist_id = input->artistId();
@@ -218,24 +252,8 @@ bool Convert( const medialibrary::IMedia* input, vlc_ml_media_t& output )
if ( convertTracks( input, output ) == false )
return false;
- if ( input->isThumbnailGenerated() == true )
- {
- output.b_artwork_generated = true;
- const auto& thumbnail = input->thumbnail();
- if ( thumbnail.empty() == true )
- output.psz_artwork_mrl = nullptr;
- else
- {
- output.psz_artwork_mrl = strdup( thumbnail.c_str() );
- if ( unlikely( output.psz_artwork_mrl == nullptr ) )
- return false;
- }
- }
- else
- {
- output.psz_artwork_mrl = nullptr;
- output.b_artwork_generated = false;
- }
+ if ( convertThumbnails( input, output.thumbnails ) == false )
+ return false;
return true;
}
@@ -288,8 +306,10 @@ bool Convert( const medialibrary::IAlbum* input, vlc_ml_album_t& output )
output.i_year = input->releaseYear();
if( !strdup_helper( input->title(), output.psz_title ) ||
- !strdup_helper( input->shortSummary(), output.psz_summary ) ||
- !strdup_helper( input->thumbnailMrl(), output.psz_artwork_mrl ) )
+ !strdup_helper( input->shortSummary(), output.psz_summary ) )
+ return false;
+
+ if ( convertThumbnails( input, output.thumbnails ) == false )
return false;
auto artist = input->albumArtist();
@@ -337,10 +357,10 @@ bool Convert( const medialibrary::IArtist* input, vlc_ml_artist_t& output )
return false;
if( !strdup_helper( input->shortBio(), output.psz_shortbio ) ||
- !strdup_helper( input->thumbnailMrl(), output.psz_artwork_mrl ) ||
!strdup_helper( input->musicBrainzId(), output.psz_mb_id ) )
return false;
- return true;
+
+ return convertThumbnails( input, output.thumbnails );
}
bool Convert( const medialibrary::IGenre* input, vlc_ml_genre_t& output )
@@ -423,9 +443,9 @@ input_item_t* MediaToInputItem( const medialibrary::IMedia* media )
VLC_TICK_FROM_MS( media->duration() ),
ITEM_TYPE_FILE, ITEM_NET_UNKNOWN ),
&input_item_Release );
- if ( media->isThumbnailGenerated() == true )
+ if ( media->isThumbnailGenerated( medialibrary::ThumbnailSizeType::Thumbnail ) == true )
{
- auto thumbnail = media->thumbnail();
+ auto thumbnail = media->thumbnailMrl( medialibrary::ThumbnailSizeType::Thumbnail );
if ( thumbnail.length() > 0 )
input_item_SetArtworkURL( inputItem.get(), thumbnail.c_str() );
}
diff --git a/modules/misc/medialibrary/medialib.cpp b/modules/misc/medialibrary/medialib.cpp
index c518bc9c4b..f19579d14f 100644
--- a/modules/misc/medialibrary/medialib.cpp
+++ b/modules/misc/medialibrary/medialib.cpp
@@ -63,6 +63,10 @@ private:
{
msg_Dbg( m_obj, "%s", msg.c_str() );
}
+ virtual void Verbose( const std::string& msg ) override
+ {
+ msg_Dbg( m_obj, "%s", msg.c_str() );
+ }
private:
vlc_object_t* m_obj;
@@ -227,6 +231,15 @@ void MediaLibrary::onReloadCompleted( const std::string& entryPoint, bool succes
m_vlc_ml->cbs->pf_send_event( m_vlc_ml, &ev );
}
+void MediaLibrary::onEntryPointAdded( const std::string& entryPoint, bool success )
+{
+ vlc_ml_event_t ev;
+ ev.i_type = VLC_ML_EVENT_ENTRY_POINT_ADDED;
+ ev.entry_point_added.psz_entry_point = entryPoint.c_str();
+ ev.entry_point_added.b_success = success;
+ m_vlc_ml->cbs->pf_send_event( m_vlc_ml, &ev );
+}
+
void MediaLibrary::onEntryPointRemoved( const std::string& entryPoint, bool success )
{
vlc_ml_event_t ev;
@@ -270,11 +283,14 @@ void MediaLibrary::onBackgroundTasksIdleChanged( bool idle )
m_vlc_ml->cbs->pf_send_event( m_vlc_ml, &ev );
}
-void MediaLibrary::onMediaThumbnailReady( medialibrary::MediaPtr media, bool success )
+void MediaLibrary::onMediaThumbnailReady( medialibrary::MediaPtr media,
+ medialibrary::ThumbnailSizeType sizeType,
+ bool success )
{
vlc_ml_event_t ev;
ev.i_type = VLC_ML_EVENT_MEDIA_THUMBNAIL_GENERATED;
ev.media_thumbnail_generated.b_success = success;
+ ev.media_thumbnail_generated.i_size = static_cast<vlc_ml_thumbnail_size_t>( sizeType );
auto mPtr = vlc::wrap_cptr<vlc_ml_media_t>(
static_cast<vlc_ml_media_t*>( malloc( sizeof( vlc_ml_media_t ) ) ),
vlc_ml_media_release );
@@ -327,8 +343,7 @@ bool MediaLibrary::Start()
ml->addParserService( std::make_shared<MetadataExtractor>( VLC_OBJECT( m_vlc_ml ) ) );
try
{
- ml->addThumbnailer( std::make_shared<Thumbnailer>(
- m_vlc_ml, std::move( thumbnailsDir ) ) );
+ ml->addThumbnailer( std::make_shared<Thumbnailer>( m_vlc_ml ) );
}
catch ( const std::runtime_error& ex )
{
@@ -966,12 +981,18 @@ int MediaLibrary::controlMedia( int query, va_list args )
case VLC_ML_MEDIA_SET_THUMBNAIL:
{
auto mrl = va_arg( args, const char* );
- m->setThumbnail( mrl );
+ auto sizeType = va_arg( args, int );
+ m->setThumbnail( mrl, static_cast<medialibrary::ThumbnailSizeType>( sizeType ) );
return VLC_SUCCESS;
}
case VLC_ML_MEDIA_GENERATE_THUMBNAIL:
{
- auto res = m_ml->requestThumbnail( m );
+ auto sizeType = va_arg( args, int );
+ auto width = va_arg( args, uint32_t );
+ auto height = va_arg( args, uint32_t );
+ auto position = va_arg( args, double );
+ auto res = m->requestThumbnail( static_cast<medialibrary::ThumbnailSizeType>( sizeType ),
+ width, height, position );
return res == true ? VLC_SUCCESS : VLC_EGENERIC;
}
case VLC_ML_MEDIA_ADD_EXTERNAL_MRL:
diff --git a/modules/misc/medialibrary/medialibrary.h b/modules/misc/medialibrary/medialibrary.h
index 42cda31c35..861a41c44a 100644
--- a/modules/misc/medialibrary/medialibrary.h
+++ b/modules/misc/medialibrary/medialibrary.h
@@ -40,6 +40,7 @@
struct vlc_event_t;
struct vlc_object_t;
struct vlc_thumbnailer_t;
+struct vlc_thumbnailer_request_t;
class Logger;
@@ -58,8 +59,6 @@ private:
{
}
- vlc::threads::condition_variable m_cond;
- vlc::threads::mutex m_mutex;
bool needsProbing;
bool success;
MetadataExtractor* mde;
@@ -79,11 +78,11 @@ public:
private:
virtual medialibrary::parser::Status run( medialibrary::parser::IItem& item ) override;
virtual const char*name() const override;
- virtual uint8_t nbThreads() const override;
virtual medialibrary::parser::Step targetedStep() const override;
virtual bool initialize( medialibrary::IMediaLibrary* ml ) override;
virtual void onFlushing() override;
virtual void onRestarted() override;
+ virtual void stop() override;
void onParserEnded( ParseContext& ctx, int status );
void addSubtree( ParseContext& ctx, input_item_node_t *root );
@@ -94,18 +93,41 @@ private:
void *user_data );
private:
+ vlc::threads::condition_variable m_cond;
+ vlc::threads::mutex m_mutex;
+ ParseContext* m_currentCtx;
vlc_object_t* m_obj;
};
class Thumbnailer : public medialibrary::IThumbnailer
{
+ struct ThumbnailerCtx
+ {
+ ~ThumbnailerCtx()
+ {
+ if ( thumbnail != nullptr )
+ picture_Release( thumbnail );
+ }
+ Thumbnailer* thumbnailer;
+ bool done;
+ picture_t* thumbnail;
+ vlc_thumbnailer_request_t* request;
+ };
public:
- Thumbnailer( vlc_medialibrary_module_t* ml, std::string thumbnailsDir);
- virtual bool generate( medialibrary::MediaPtr media, const std::string& mrl ) override;
+ Thumbnailer(vlc_medialibrary_module_t* ml);
+ virtual bool generate( const std::string& mrl, uint32_t desiredWidth,
+ uint32_t desiredHeight, float position,
+ const std::string& dest ) override;
+ virtual void stop() override;
+
+private:
+ static void onThumbnailComplete( void* data, picture_t* thumbnail );
private:
vlc_medialibrary_module_t* m_ml;
- std::string m_thumbnailDir;
+ vlc::threads::mutex m_mutex;
+ vlc::threads::condition_variable m_cond;
+ ThumbnailerCtx* m_currentContext;
std::unique_ptr<vlc_thumbnailer_t, void(*)(vlc_thumbnailer_t*)> m_thumbnailer;
};
@@ -162,12 +184,15 @@ public:
virtual void onDiscoveryCompleted(const std::string& entryPoint, bool success) override;
virtual void onReloadStarted(const std::string& entryPoint) override;
virtual void onReloadCompleted(const std::string& entryPoint, bool success) override;
+ virtual void onEntryPointAdded(const std::string& entryPoint, bool success) override;
virtual void onEntryPointRemoved(const std::string& entryPoint, bool success) override;
virtual void onEntryPointBanned(const std::string& entryPoint, bool success) override;
virtual void onEntryPointUnbanned(const std::string& entryPoint, bool success) override;
virtual void onParsingStatsUpdated(uint32_t percent) override;
virtual void onBackgroundTasksIdleChanged(bool isIdle) override;
- virtual void onMediaThumbnailReady(medialibrary::MediaPtr media, bool success) override;
+ virtual void onMediaThumbnailReady(medialibrary::MediaPtr media,
+ medialibrary::ThumbnailSizeType sizeType,
+ bool success) override;
};
bool Convert( const medialibrary::IMedia* input, vlc_ml_media_t& output );
diff --git a/src/misc/medialibrary.c b/src/misc/medialibrary.c
index 436a5b226f..f100f29b81 100644
--- a/src/misc/medialibrary.c
+++ b/src/misc/medialibrary.c
@@ -134,6 +134,12 @@ vlc_medialibrary_t* vlc_ml_instance_get( vlc_object_t* p_obj )
return p_priv->p_media_library;
}
+static void vlc_ml_thumbnails_release( vlc_ml_thumbnail_t *p_thumbnails )
+{
+ for ( int i = 0; i < VLC_ML_THUMBNAIL_SIZE_COUNT; ++i )
+ free( p_thumbnails[i].psz_mrl );
+}
+
static void vlc_ml_show_release_inner( vlc_ml_show_t* p_show )
{
free( p_show->psz_artwork_mrl );
@@ -169,7 +175,7 @@ static void vlc_ml_media_release_inner( vlc_ml_media_t* p_media )
vlc_ml_file_list_release( p_media->p_files );
vlc_ml_media_release_tracks_inner( p_media->p_tracks );
free( p_media->psz_title );
- free( p_media->psz_artwork_mrl );
+ vlc_ml_thumbnails_release( p_media->thumbnails );
switch( p_media->i_subtype )
{
case VLC_ML_MEDIA_SUBTYPE_ALBUMTRACK:
@@ -189,7 +195,7 @@ static void vlc_ml_media_release_inner( vlc_ml_media_t* p_media )
static void vlc_ml_artist_release_inner( vlc_ml_artist_t* p_artist )
{
- free( p_artist->psz_artwork_mrl );
+ vlc_ml_thumbnails_release( p_artist->thumbnails );
free( p_artist->psz_name );
free( p_artist->psz_shortbio );
free( p_artist->psz_mb_id );
@@ -205,8 +211,8 @@ void vlc_ml_artist_release( vlc_ml_artist_t* p_artist )
static void vlc_ml_album_release_inner( vlc_ml_album_t* p_album )
{
+ vlc_ml_thumbnails_release( p_album->thumbnails );
free( p_album->psz_artist );
- free( p_album->psz_artwork_mrl );
free( p_album->psz_summary );
free( p_album->psz_title );
}
--
2.20.1
More information about the vlc-devel
mailing list