[vlc-devel] [RFC 49/82] qt: add base classes for medialibrary model
Pierre Lamot
pierre at videolabs.io
Fri Feb 1 14:01:53 CET 2019
---
modules/gui/qt/Makefile.am | 9 +
.../qt/components/mediacenter/mcmedialib.cpp | 237 ++++++++++++++++++
.../qt/components/mediacenter/mcmedialib.hpp | 82 ++++++
.../qt/components/mediacenter/mlbasemodel.cpp | 181 +++++++++++++
.../qt/components/mediacenter/mlbasemodel.hpp | 210 ++++++++++++++++
.../qt/components/mediacenter/mlhelper.hpp | 74 ++++++
.../qt/components/mediacenter/mlqmltypes.hpp | 61 +++++
7 files changed, 854 insertions(+)
create mode 100644 modules/gui/qt/components/mediacenter/mcmedialib.cpp
create mode 100644 modules/gui/qt/components/mediacenter/mcmedialib.hpp
create mode 100644 modules/gui/qt/components/mediacenter/mlbasemodel.cpp
create mode 100644 modules/gui/qt/components/mediacenter/mlbasemodel.hpp
create mode 100644 modules/gui/qt/components/mediacenter/mlhelper.hpp
create mode 100644 modules/gui/qt/components/mediacenter/mlqmltypes.hpp
diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am
index e9cd3e61d4..12a21ec7d6 100644
--- a/modules/gui/qt/Makefile.am
+++ b/modules/gui/qt/Makefile.am
@@ -118,6 +118,12 @@ libqt_plugin_la_SOURCES = \
gui/qt/components/epg/EPGView.cpp gui/qt/components/epg/EPGView.hpp \
gui/qt/components/epg/EPGWidget.cpp \
gui/qt/components/epg/EPGWidget.hpp \
+ gui/qt/components/mediacenter/mcmedialib.cpp \
+ gui/qt/components/mediacenter/mcmedialib.hpp \
+ gui/qt/components/mediacenter/mlhelper.hpp \
+ gui/qt/components/mediacenter/mlqmltypes.hpp \
+ gui/qt/components/mediacenter/mlbasemodel.cpp \
+ gui/qt/components/mediacenter/mlbasemodel.hpp \
gui/qt/components/playlist/media.hpp \
gui/qt/components/playlist/playlist_common.cpp \
gui/qt/components/playlist/playlist_common.hpp \
@@ -238,6 +244,9 @@ nodist_libqt_plugin_la_SOURCES = \
gui/qt/components/epg/EPGRuler.moc.cpp \
gui/qt/components/epg/EPGView.moc.cpp \
gui/qt/components/epg/EPGWidget.moc.cpp \
+ gui/qt/components/mediacenter/mcmedialib.moc.cpp \
+ gui/qt/components/mediacenter/mlqmltypes.moc.cpp \
+ gui/qt/components/mediacenter/mlbasemodel.moc.cpp \
gui/qt/components/playlist/playlist_common.moc.cpp \
gui/qt/components/playlist/playlist_item.moc.cpp \
gui/qt/components/playlist/playlist_model.moc.cpp \
diff --git a/modules/gui/qt/components/mediacenter/mcmedialib.cpp b/modules/gui/qt/components/mediacenter/mcmedialib.cpp
new file mode 100644
index 0000000000..15ae56fc65
--- /dev/null
+++ b/modules/gui/qt/components/mediacenter/mcmedialib.cpp
@@ -0,0 +1,237 @@
+/*****************************************************************************
+ * Copyright (C) 2019 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include "mcmedialib.hpp"
+#include "mlhelper.hpp"
+#include "recents.hpp"
+
+#include <vlc_playlist.h>
+#include <vlc_input_item.h>
+#include "components/playlist/media.hpp"
+#include "components/playlist/playlist_controler.hpp"
+
+MCMediaLib::MCMediaLib(intf_thread_t *_intf, QObject *_parent)
+ : QObject( _parent )
+ , m_intf( _intf )
+ , m_gridView( true )
+ , m_ml( vlcMl() )
+ , m_event_cb( nullptr, [this](vlc_ml_event_callback_t* cb ) {
+ vlc_ml_event_unregister_callback( m_ml, cb );
+ })
+{
+ m_event_cb.reset( vlc_ml_event_register_callback( m_ml, MCMediaLib::onMediaLibraryEvent,
+ this ) );
+}
+
+// Should the items be displayed as a grid or as list ?
+bool MCMediaLib::isGridView() const
+{
+ return m_gridView;
+}
+
+void MCMediaLib::setGridView(bool state)
+{
+ m_gridView = state;
+ emit gridViewChanged();
+}
+
+void MCMediaLib::openMRLFromMedia(const vlc_ml_media_t& media, bool start )
+{
+ if (!media.p_files)
+ return;
+ for ( const vlc_ml_file_t& mediafile: ml_range_iterate<vlc_ml_file_t>(media.p_files) )
+ {
+ if (mediafile.psz_mrl)
+ Open::openMRL(m_intf, mediafile.psz_mrl, start);
+ start = false;
+ }
+}
+
+void MCMediaLib::addToPlaylist(const QString& mrl)
+{
+ vlc::playlist::Media media{ mrl, mrl };
+ m_intf->p_sys->p_mainPlaylistControler->append( {media}, false );
+}
+
+void MCMediaLib::addToPlaylist(const QUrl& mrl)
+{
+ vlc::playlist::Media media{ mrl.toString(QUrl::None), mrl.fileName() };
+ m_intf->p_sys->p_mainPlaylistControler->append( {media} , false );
+}
+
+// A specific item has been asked to be added to the playlist
+void MCMediaLib::addToPlaylist(const MLParentId & itemId)
+{
+ //invalid item
+ if (itemId.id == 0)
+ return;
+
+ if (itemId.type == VLC_ML_PARENT_UNKNOWN)
+ {
+ input_item_t* item = vlc_ml_get_input_item( m_ml, itemId.id );
+ if (item) {
+ QVector<vlc::playlist::Media> medias = { vlc::playlist::Media(item) };
+ m_intf->p_sys->p_mainPlaylistControler->append(medias, false);
+ }
+ }
+ else
+ {
+ vlc_ml_query_params_t query;
+ memset(&query, 0, sizeof(vlc_ml_query_params_t));
+ ml_unique_ptr<vlc_ml_media_list_t> media_list(vlc_ml_list_media_of( m_ml, &query, itemId.type, itemId.id));
+
+ auto mediaRange = ml_range_iterate<vlc_ml_media_t>( media_list );
+ QVector<vlc::playlist::Media> medias;
+ std::transform(mediaRange.begin(), mediaRange.end(), std::back_inserter(medias), [&](vlc_ml_media_t& m) {
+ input_item_t* item = vlc_ml_get_input_item( m_ml, m.i_id );
+ return vlc::playlist::Media(item);
+ });
+ m_intf->p_sys->p_mainPlaylistControler->append(medias, false);
+ }
+}
+
+void MCMediaLib::addToPlaylist(const QVariantList& itemIdList)
+{
+ for (const QVariant& varValue: itemIdList)
+ {
+ if (varValue.canConvert<QUrl>())
+ {
+ auto mrl = varValue.value<QUrl>();
+ addToPlaylist(mrl);
+ }
+ else if (varValue.canConvert<QString>())
+ {
+ auto mrl = varValue.value<QString>();
+ addToPlaylist(mrl);
+ }
+ else if (varValue.canConvert<MLParentId>())
+ {
+ MLParentId itemId = varValue.value<MLParentId>();
+ addToPlaylist(itemId);
+ }
+ }
+}
+
+// A specific item has been asked to be played,
+// so it's added to the playlist and played
+void MCMediaLib::addAndPlay(const MLParentId & itemId )
+{
+ if (itemId.id == 0)
+ return;
+ if (itemId.type == VLC_ML_PARENT_UNKNOWN)
+ {
+ input_item_t* item = vlc_ml_get_input_item( m_ml, itemId.id );
+ if (item) {
+ QVector<vlc::playlist::Media> medias = { vlc::playlist::Media(item) };
+ m_intf->p_sys->p_mainPlaylistControler->append(medias, true);
+ input_item_Release( item );
+ }
+ }
+ else
+ {
+ vlc_ml_query_params_t query;
+ memset(&query, 0, sizeof(vlc_ml_query_params_t));
+ ml_unique_ptr<vlc_ml_media_list_t> media_list(vlc_ml_list_media_of( m_ml, &query, itemId.type, itemId.id));
+
+ auto mediaRange = ml_range_iterate<vlc_ml_media_t>( media_list );
+ QVector<vlc::playlist::Media> medias;
+ std::transform(mediaRange.begin(), mediaRange.end(), std::back_inserter(medias), [&](vlc_ml_media_t& m) {
+ input_item_t* item = vlc_ml_get_input_item( m_ml, m.i_id );
+ auto res = vlc::playlist::Media(item);
+ if ( item )
+ input_item_Release( item );
+ return res;
+ });
+ m_intf->p_sys->p_mainPlaylistControler->append(medias, true);
+ }
+}
+
+void MCMediaLib::addAndPlay(const QString& mrl)
+{
+ vlc::playlist::Media media{ mrl, mrl };
+ m_intf->p_sys->p_mainPlaylistControler->append( {media}, true );
+}
+
+void MCMediaLib::addAndPlay(const QUrl& mrl)
+{
+ vlc::playlist::Media media{ mrl.toString(QUrl::None), mrl.fileName() };
+ m_intf->p_sys->p_mainPlaylistControler->append( {media}, true );
+}
+
+
+void MCMediaLib::addAndPlay(const QVariantList& itemIdList)
+{
+ bool b_start = true;
+ for (const QVariant& varValue: itemIdList)
+ {
+ if (varValue.canConvert<QUrl>())
+ {
+ auto mrl = varValue.value<QUrl>();
+ if (b_start)
+ addAndPlay(mrl);
+ else
+ addToPlaylist(mrl);
+ }
+ if (varValue.canConvert<QString>())
+ {
+ auto mrl = varValue.value<QString>();
+ if (b_start)
+ addAndPlay(mrl);
+ else
+ addToPlaylist(mrl);
+ }
+ else if (varValue.canConvert<MLParentId>())
+ {
+ MLParentId itemId = varValue.value<MLParentId>();
+ if (b_start)
+ addAndPlay(itemId);
+ else
+ addToPlaylist(itemId);
+ } else {
+ continue;
+ }
+ b_start = false;
+ }
+}
+
+vlc_medialibrary_t* MCMediaLib::vlcMl()
+{
+ return vlc_ml_instance_get( m_intf );
+}
+
+void MCMediaLib::onMediaLibraryEvent( void* data, const vlc_ml_event_t* event )
+{
+ MCMediaLib* self = static_cast<MCMediaLib*>( data );
+ switch ( event->i_type )
+ {
+ case VLC_ML_EVENT_PARSING_PROGRESS_UPDATED:
+ self->emit progressUpdated( event->parsing_progress.i_percent );
+ break;
+ case VLC_ML_EVENT_DISCOVERY_STARTED:
+ self->emit discoveryStarted();
+ break;
+ case VLC_ML_EVENT_DISCOVERY_PROGRESS:
+ self->emit discoveryProgress( event->discovery_progress.psz_entry_point );
+ break;
+ case VLC_ML_EVENT_DISCOVERY_COMPLETED:
+ self->emit discoveryCompleted();
+ break;
+ default:
+ break;
+ }
+}
diff --git a/modules/gui/qt/components/mediacenter/mcmedialib.hpp b/modules/gui/qt/components/mediacenter/mcmedialib.hpp
new file mode 100644
index 0000000000..0eeb714c9a
--- /dev/null
+++ b/modules/gui/qt/components/mediacenter/mcmedialib.hpp
@@ -0,0 +1,82 @@
+/*****************************************************************************
+ * Copyright (C) 2019 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#pragma once
+
+#include <Qt>
+#include <QAbstractListModel>
+#include <QVariant>
+#include <QHash>
+#include <QByteArray>
+#include <QList>
+#include <QQuickWidget>
+#include <QQuickItem>
+#include <QMetaObject>
+#include <QMetaMethod>
+#include <QQmlEngine>
+
+#include <memory>
+
+#include "qt.hpp"
+#include "mlqmltypes.hpp"
+
+class MCMediaLib : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool gridView READ isGridView WRITE setGridView NOTIFY gridViewChanged)
+
+public:
+ MCMediaLib(intf_thread_t* _intf, QObject* _parent = nullptr );
+
+ Q_INVOKABLE void addToPlaylist(const MLParentId &itemId);
+ Q_INVOKABLE void addToPlaylist(const QString& mrl);
+ Q_INVOKABLE void addToPlaylist(const QUrl& mrl);
+ Q_INVOKABLE void addToPlaylist(const QVariantList& itemIdList);
+
+ Q_INVOKABLE void addAndPlay(const MLParentId &itemId);
+ Q_INVOKABLE void addAndPlay(const QString& mrl);
+ Q_INVOKABLE void addAndPlay(const QUrl& mrl);
+ Q_INVOKABLE void addAndPlay(const QVariantList&itemIdList);
+
+
+ vlc_medialibrary_t* vlcMl();
+
+signals:
+ void gridViewChanged();
+ void discoveryStarted();
+ void discoveryProgress( QString entryPoint );
+ void discoveryCompleted();
+ void progressUpdated( quint32 percent );
+
+private:
+ bool isGridView() const;
+ void setGridView(bool);
+ static void onMediaLibraryEvent( void* data, const vlc_ml_event_t* event );
+
+private:
+ void openMRLFromMedia(const vlc_ml_media_t& media, bool start );
+
+ intf_thread_t* m_intf;
+
+ bool m_gridView;
+
+ /* Medialibrary */
+ vlc_medialibrary_t* m_ml;
+ std::unique_ptr<vlc_ml_event_callback_t, std::function<void(vlc_ml_event_callback_t*)>> m_event_cb;
+
+};
diff --git a/modules/gui/qt/components/mediacenter/mlbasemodel.cpp b/modules/gui/qt/components/mediacenter/mlbasemodel.cpp
new file mode 100644
index 0000000000..64d87f9be3
--- /dev/null
+++ b/modules/gui/qt/components/mediacenter/mlbasemodel.cpp
@@ -0,0 +1,181 @@
+/*****************************************************************************
+ * Copyright (C) 2019 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include <cassert>
+#include "mlbasemodel.hpp"
+#include "mcmedialib.hpp"
+#include <vlc_cxx_helpers.hpp>
+
+MLBaseModel::MLBaseModel(QObject *parent)
+ : QAbstractListModel(parent)
+ , m_ml(nullptr)
+ , m_search_pattern_cstr( nullptr, &free )
+ , m_nb_max_items( 0 )
+ , m_ml_event_handle( nullptr, [this](vlc_ml_event_callback_t* cb ) {
+ assert( m_ml != nullptr );
+ vlc_ml_event_unregister_callback( m_ml, cb );
+ })
+ , m_need_reset( false )
+ , m_is_reloading( false )
+{
+ vlc_mutex_init( &m_item_lock );
+ memset(&m_query_param, 0, sizeof(vlc_ml_query_params_t));
+ m_query_param.b_desc = false;
+ m_query_param.i_nbResults = 20; //FIXME: value for test
+ m_query_param.i_sort = VLC_ML_SORTING_DEFAULT;
+
+ connect( this, &MLBaseModel::resetRequested, this, &MLBaseModel::onResetRequested );
+}
+
+MLBaseModel::~MLBaseModel()
+{
+ vlc_mutex_destroy( &m_item_lock );
+}
+
+void MLBaseModel::sortByColumn(QByteArray name, Qt::SortOrder order)
+{
+ beginResetModel();
+ m_query_param.b_desc = (order == Qt::SortOrder::DescendingOrder);
+ m_query_param.i_sort = nameToCriteria(name);
+ clear();
+ endResetModel();
+}
+
+void MLBaseModel::onResetRequested()
+{
+ beginResetModel();
+ clear();
+ endResetModel();
+}
+
+void MLBaseModel::onVlcMlEvent(const vlc_ml_event_t* event)
+{
+ switch(event->i_type)
+ {
+ case VLC_ML_EVENT_BACKGROUND_IDLE_CHANGED:
+ if ( event->background_idle_changed.b_idle == false )
+ m_is_reloading = true;
+ else
+ {
+ m_is_reloading = false;
+ if ( m_need_reset )
+ {
+ emit resetRequested();
+ m_need_reset = false;
+ }
+ }
+ break;
+ }
+}
+
+void MLBaseModel::onVlcMlEvent(void* data, const vlc_ml_event_t* event)
+{
+ auto self = static_cast<MLBaseModel*>(data);
+ self->onVlcMlEvent(event);
+}
+
+MLParentId MLBaseModel::parentId() const
+{
+ return m_parent;
+}
+
+void MLBaseModel::setParentId(MLParentId parentId)
+{
+ beginResetModel();
+ m_parent = parentId;
+ clear();
+ endResetModel();
+ emit parentIdChanged();
+}
+
+void MLBaseModel::unsetParentId()
+{
+ beginResetModel();
+ m_parent = MLParentId();
+ clear();
+ endResetModel();
+ emit parentIdChanged();
+}
+
+MCMediaLib* MLBaseModel::ml() const
+{
+ return m_mcMediaLib;
+}
+
+void MLBaseModel::setMl(MCMediaLib* mcMl)
+{
+ m_ml = mcMl->vlcMl();
+ m_mcMediaLib = mcMl;
+ if ( m_ml_event_handle == nullptr )
+ m_ml_event_handle.reset( vlc_ml_event_register_callback( m_ml, onVlcMlEvent, this ) );
+}
+
+const QString& MLBaseModel::searchPattern() const
+{
+ return m_search_pattern;
+}
+
+void MLBaseModel::setSearchPattern( const QString& pattern )
+{
+ beginResetModel();
+ if ( pattern.length() >= 3 )
+ m_search_pattern_cstr = vlc::wrap_cptr( strdup( qtu( pattern ) ) );
+ else
+ m_search_pattern_cstr.reset();
+ m_search_pattern = pattern;
+ m_query_param.psz_pattern = m_search_pattern_cstr.get();
+ clear();
+ endResetModel();
+}
+
+Qt::SortOrder MLBaseModel::getSortOrder() const
+{
+ return m_query_param.b_desc ? Qt::SortOrder::DescendingOrder : Qt::SortOrder::AscendingOrder;
+}
+
+void MLBaseModel::setSortOder(Qt::SortOrder order)
+{
+ beginResetModel();
+ m_query_param.b_desc = (order == Qt::SortOrder::DescendingOrder);
+ clear();
+ endResetModel();
+ emit sortOrderChanged();
+}
+
+const QString MLBaseModel::getSortCriteria() const
+{
+ return criteriaToName(m_query_param.i_sort);
+}
+
+void MLBaseModel::setSortCriteria(const QString& criteria)
+{
+ beginResetModel();
+ m_query_param.i_sort = nameToCriteria(criteria.toUtf8());
+ clear();
+ endResetModel();
+ emit sortCriteriaChanged();
+}
+
+void MLBaseModel::unsetSortCriteria()
+{
+ beginResetModel();
+ m_query_param.i_sort = VLC_ML_SORTING_DEFAULT;
+ clear();
+ endResetModel();
+ emit sortCriteriaChanged();
+}
diff --git a/modules/gui/qt/components/mediacenter/mlbasemodel.hpp b/modules/gui/qt/components/mediacenter/mlbasemodel.hpp
new file mode 100644
index 0000000000..cb8af2ca90
--- /dev/null
+++ b/modules/gui/qt/components/mediacenter/mlbasemodel.hpp
@@ -0,0 +1,210 @@
+/*****************************************************************************
+ * Copyright (C) 2019 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef MLBASEMODEL_HPP
+#define MLBASEMODEL_HPP
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "vlc_common.h"
+
+#include <memory>
+#include <QObject>
+#include <QAbstractListModel>
+#include "vlc_media_library.h"
+#include "mlqmltypes.hpp"
+#include "mcmedialib.hpp"
+#include <memory>
+
+class MCMediaLib;
+
+class MLBaseModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+ explicit MLBaseModel(QObject *parent = nullptr);
+ virtual ~MLBaseModel();
+
+ Q_INVOKABLE void sortByColumn(QByteArray name, Qt::SortOrder order);
+
+ Q_INVOKABLE virtual QObject *get(unsigned int idx) const = 0;
+
+ Q_PROPERTY( MLParentId parentId READ parentId WRITE setParentId NOTIFY parentIdChanged RESET unsetParentId )
+ Q_PROPERTY( MCMediaLib* ml READ ml WRITE setMl )
+ Q_PROPERTY( unsigned int maxItems MEMBER m_nb_max_items )
+ Q_PROPERTY( QString searchPattern READ searchPattern WRITE setSearchPattern )
+
+ Q_PROPERTY( Qt::SortOrder sortOrder READ getSortOrder WRITE setSortOder NOTIFY sortOrderChanged )
+ Q_PROPERTY( QString sortCriteria READ getSortCriteria WRITE setSortCriteria NOTIFY sortCriteriaChanged RESET unsetSortCriteria )
+
+signals:
+ void parentIdChanged();
+ void resetRequested();
+ void sortOrderChanged();
+ void sortCriteriaChanged();
+
+protected slots:
+ void onResetRequested();
+
+private:
+ static void onVlcMlEvent( void* data, const vlc_ml_event_t* event );
+
+protected:
+ virtual void clear() = 0;
+ virtual vlc_ml_sorting_criteria_t roleToCriteria(int role) const = 0;
+ virtual vlc_ml_sorting_criteria_t nameToCriteria(QByteArray) const {
+ return VLC_ML_SORTING_DEFAULT;
+ }
+ virtual QByteArray criteriaToName(vlc_ml_sorting_criteria_t ) const
+ {
+ return "";
+ }
+
+ MLParentId parentId() const;
+ void setParentId(MLParentId parentId);
+ void unsetParentId();
+
+ MCMediaLib* ml() const;
+ void setMl(MCMediaLib* ml);
+
+ const QString& searchPattern() const;
+ void setSearchPattern( const QString& pattern );
+
+ Qt::SortOrder getSortOrder() const;
+ void setSortOder(Qt::SortOrder order);
+ const QString getSortCriteria() const;
+ void setSortCriteria(const QString& criteria);
+ void unsetSortCriteria();
+
+ virtual void onVlcMlEvent( const vlc_ml_event_t* event );
+
+ MLParentId m_parent;
+
+ vlc_medialibrary_t* m_ml;
+ MCMediaLib* m_mcMediaLib;
+ mutable vlc_ml_query_params_t m_query_param;
+ std::unique_ptr<char, void(*)(void*)> m_search_pattern_cstr;
+ QString m_search_pattern;
+
+ unsigned int m_nb_max_items;
+
+ mutable vlc_mutex_t m_item_lock;
+
+ std::unique_ptr<vlc_ml_event_callback_t,
+ std::function<void(vlc_ml_event_callback_t*)>> m_ml_event_handle;
+ std::atomic_bool m_need_reset;
+ std::atomic_bool m_is_reloading;
+};
+
+/**
+ * Implements a basic sliding window.
+ * const_cast & immutable are unavoidable, since all access member functions
+ * are marked as const. fetchMore & canFetchMore don't allow for the full size
+ * to be known (so the scrollbar would grow as we scroll, until we displayed all
+ * elements), and implies having all elements loaded in RAM at all time.
+ */
+template <typename T>
+class MLSlidingWindowModel : public MLBaseModel
+{
+public:
+ static constexpr size_t BatchSize = 100;
+
+ MLSlidingWindowModel(QObject* parent = nullptr)
+ : MLBaseModel(parent)
+ , m_initialized(false)
+ {
+ m_query_param.i_nbResults = BatchSize;
+ }
+
+ int rowCount(const QModelIndex &parent) const override
+ {
+ if (parent.isValid())
+ return 0;
+ vlc_mutex_locker lock( &m_item_lock );
+ if ( m_initialized == false )
+ {
+ m_total_count = countTotalElements();
+ m_initialized = true;
+ m_item_list = const_cast<MLSlidingWindowModel<T>*>(this)->fetch();
+ }
+ return m_total_count;
+ }
+
+ QObject* get(unsigned int idx) const override
+ {
+ vlc_mutex_locker lock( &m_item_lock );
+ T* obj = item( idx );
+ if (!obj)
+ return nullptr;
+ return obj->clone();
+ }
+
+ void clear() override
+ {
+ vlc_mutex_locker lock( &m_item_lock );
+ m_query_param.i_offset = 0;
+ m_initialized = false;
+ m_total_count = 0;
+ m_item_list.clear();
+ }
+
+protected:
+ T* item(unsigned int idx) const
+ {
+ // Must be called in a locked context
+ if ( m_initialized == false )
+ {
+ m_total_count = countTotalElements();
+ if ( m_total_count > 0 )
+ m_item_list = const_cast<MLSlidingWindowModel<T>*>(this)->fetch();
+ m_initialized = true;
+ }
+
+ if ( m_total_count == 0 || idx >= m_total_count || idx < 0 )
+ return nullptr;
+
+ if ( idx < m_query_param.i_offset || idx >= m_query_param.i_offset + m_item_list.size() )
+ {
+ if (m_query_param.i_nbResults == 0)
+ m_query_param.i_offset = 0;
+ else
+ m_query_param.i_offset = idx - idx % m_query_param.i_nbResults;
+ m_item_list = const_cast<MLSlidingWindowModel<T>*>(this)->fetch();
+ }
+
+ //db has changed
+ if ( idx - m_query_param.i_offset >= m_item_list.size() || idx - m_query_param.i_offset < 0 )
+ return nullptr;
+ return m_item_list[idx - m_query_param.i_offset].get();
+ }
+
+private:
+ virtual size_t countTotalElements() const = 0;
+ virtual std::vector<std::unique_ptr<T>> fetch() = 0;
+
+protected:
+ mutable std::vector<std::unique_ptr<T>> m_item_list;
+
+private:
+ mutable bool m_initialized;
+ mutable size_t m_total_count;
+};
+
+#endif // MLBASEMODEL_HPP
diff --git a/modules/gui/qt/components/mediacenter/mlhelper.hpp b/modules/gui/qt/components/mediacenter/mlhelper.hpp
new file mode 100644
index 0000000000..e4369b2795
--- /dev/null
+++ b/modules/gui/qt/components/mediacenter/mlhelper.hpp
@@ -0,0 +1,74 @@
+/*****************************************************************************
+ * Copyright (C) 2019 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef MLHELPER_HPP
+#define MLHELPER_HPP
+
+#include <memory>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "vlc_media_library.h"
+
+template<typename T>
+class MLDeleter
+{
+public:
+ void operator() (T* obj) {
+ vlc_ml_release(obj);
+ }
+};
+
+template<typename T>
+using ml_unique_ptr = std::unique_ptr<T, MLDeleter<T> >;
+
+template<typename T>
+class MLListRange
+{
+public:
+ MLListRange( T* begin, T* end )
+ : m_begin(begin)
+ , m_end(end)
+ {
+ }
+
+ T* begin() const
+ {
+ return m_begin;
+ }
+
+ T* end() const
+ {
+ return m_end;
+ }
+
+private:
+ T* m_begin;
+ T* m_end;
+};
+
+template<typename T, typename L>
+MLListRange<T> ml_range_iterate(L& list)
+{
+ return MLListRange<T>{ list->p_items, list->p_items + list->i_nb_items };
+}
+
+
+#endif // MLHELPER_HPP
diff --git a/modules/gui/qt/components/mediacenter/mlqmltypes.hpp b/modules/gui/qt/components/mediacenter/mlqmltypes.hpp
new file mode 100644
index 0000000000..7e963521b8
--- /dev/null
+++ b/modules/gui/qt/components/mediacenter/mlqmltypes.hpp
@@ -0,0 +1,61 @@
+/*****************************************************************************
+ * Copyright (C) 2019 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef MLQMLTYPES_HPP
+#define MLQMLTYPES_HPP
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <QObject>
+#include <vlc_common.h>
+#include <vlc_media_library.h>
+
+class MLParentId
+{
+ Q_GADGET
+public:
+ MLParentId() : id(0), type( VLC_ML_PARENT_UNKNOWN ) {}
+ MLParentId( int64_t i, vlc_ml_parent_type t ) : id( i ), type( t ) {}
+ bool operator!=( const MLParentId& lhs )
+ {
+ return id != lhs.id || type != lhs.type;
+ }
+ int64_t id;
+ vlc_ml_parent_type type;
+
+ Q_INVOKABLE inline QString toString() const {
+
+#define ML_PARENT_TYPE_CASE(type) case type: return QString("%1 - %2").arg(#type).arg(id)
+ switch (type) {
+ ML_PARENT_TYPE_CASE(VLC_ML_PARENT_ALBUM);
+ ML_PARENT_TYPE_CASE(VLC_ML_PARENT_ARTIST);
+ ML_PARENT_TYPE_CASE(VLC_ML_PARENT_SHOW);
+ ML_PARENT_TYPE_CASE(VLC_ML_PARENT_GENRE);
+ ML_PARENT_TYPE_CASE(VLC_ML_PARENT_PLAYLIST);
+ default:
+ return QString("UNKNONW - %2").arg(id);
+ }
+#undef ML_PARENT_TYPE_CASE
+ }
+};
+
+Q_DECLARE_METATYPE(MLParentId)
+
+#endif // MLQMLTYPES_HPP
--
2.19.1
More information about the vlc-devel
mailing list