[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