[vlc-devel] [PATCH v2 02/14] qt: cancel preparse requests before destroying/changing model of NetworkMediaModel

Pierre Lamot pierre at videolabs.io
Fri Feb 7 14:04:13 CET 2020


I though of getting rid of the semaphore and filtering callback requests 
in NetworkSourceListener::onItemPreparseEnded
with their status, but the status is ITEM_PREPARSE_FAILED when we cancel 
a request and when a parse actually fails (ie: wrong credential)
and we need to notify the end of preparse in this case.


On 2020-02-07 14:00, Pierre Lamot wrote:
> this caused a crash if the UI was destroyed when a request was pending
> ---
>  modules/gui/qt/network/networkmediamodel.cpp | 18 +++++++++++++++++-
>  modules/gui/qt/network/networkmediamodel.hpp |  5 ++++-
>  2 files changed, 21 insertions(+), 2 deletions(-)
> 
> diff --git a/modules/gui/qt/network/networkmediamodel.cpp
> b/modules/gui/qt/network/networkmediamodel.cpp
> index 1a24f3de91..ca1e94c51d 100644
> --- a/modules/gui/qt/network/networkmediamodel.cpp
> +++ b/modules/gui/qt/network/networkmediamodel.cpp
> @@ -40,10 +40,23 @@ enum Role {
> 
>  NetworkMediaModel::NetworkMediaModel( QObject* parent )
>      : QAbstractListModel( parent )
> +    , m_preparseSem(1)
>      , m_ml( nullptr )
>  {
>  }
> 
> +NetworkMediaModel::~NetworkMediaModel()
> +{
> +    //this can only be aquired from UI thread
> +    if (!m_preparseSem.tryAcquire())
> +    {
> +        auto libvlc = vlc_object_instance(m_ctx->getIntf());
> +        vlc_media_tree_PreparseCancel( libvlc, this );
> +        //wait for the callback call on cancel
> +        m_preparseSem.acquire();
> +    }
> +}
> +
>  QVariant NetworkMediaModel::data( const QModelIndex& index, int role ) 
> const
>  {
>      if (!m_ctx)
> @@ -255,6 +268,8 @@ bool NetworkMediaModel::initializeMediaSources()
>          emit isIndexedChanged();
>      }
> 
> +    vlc_media_tree_PreparseCancel( libvlc, this );
> +    m_preparseSem.acquire();
>      vlc_media_tree_Preparse( tree, libvlc, m_treeItem.media.get(), 
> this );
>      m_parsingPending = true;
>      emit parsingPendingChanged(m_parsingPending);
> @@ -335,8 +350,9 @@ void
> NetworkMediaModel::onItemRemoved(MediaSourcePtr, input_item_node_t *
> node,
>      }, Qt::QueuedConnection);
>  }
> 
> -void NetworkMediaModel::onItemPreparseEnded(MediaSourcePtr,
> input_item_node_t* node, enum input_item_preparse_status)
> +void NetworkMediaModel::onItemPreparseEnded(MediaSourcePtr,
> input_item_node_t* node, enum input_item_preparse_status )
>  {
> +    m_preparseSem.release();
>      InputItemPtr p_node { node->p_item };
>      QMetaObject::invokeMethod(this, [this, p_node=std::move(p_node)]() 
> {
>          if (p_node != m_treeItem.media)
> diff --git a/modules/gui/qt/network/networkmediamodel.hpp
> b/modules/gui/qt/network/networkmediamodel.hpp
> index bc6c2ea8b5..969d085dc4 100644
> --- a/modules/gui/qt/network/networkmediamodel.hpp
> +++ b/modules/gui/qt/network/networkmediamodel.hpp
> @@ -33,6 +33,8 @@
>  #include <util/qml_main_context.hpp>
>  #include "networksourcelistener.hpp"
> 
> +#include <QSemaphore>
> +
>  #include <memory>
> 
>  using MediaSourcePtr = vlc_shared_data_ptr_type(vlc_media_source_t,
> @@ -98,6 +100,7 @@ public:
> 
>      explicit NetworkMediaModel(QObject* parent = nullptr);
>      NetworkMediaModel( QmlMainContext* ctx, QString parentMrl,
> QObject* parent = nullptr );
> +    virtual ~NetworkMediaModel() override;
> 
>      QVariant data(const QModelIndex& index, int role) const override;
>      QHash<int, QByteArray> roleNames() const override;
> @@ -171,7 +174,7 @@ private:
>      bool m_indexed = false;
>      bool m_canBeIndexed  = false;
>      bool m_parsingPending = false;
> -
> +    QSemaphore m_preparseSem;
> 
>      std::vector<Item> m_items;
>      QmlMainContext* m_ctx = nullptr;
> --
> 2.17.1


More information about the vlc-devel mailing list