[vlc-devel] [PATCH 4/4] medialibrary: Bump version & update API usages

Thomas Guillem thomas at gllm.fr
Tue Jun 25 20:36:14 CEST 2019



On Tue, Jun 25, 2019, at 16:04, Hugo Beauzée-Luyssen wrote:
> - 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

No version check in configure.ac ?

> ---
>  contrib/src/medialibrary/rules.mak            |  2 +-

I think we generally split contrib commits, even if it break incremental build on some build bot configuration.

Otherwise, OK for the set.

>  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
> 
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel



More information about the vlc-devel mailing list