From f8340452c35823369a1fd5458da5fb8a8541eb01 Mon Sep 17 00:00:00 2001 From: Benjamin Arnaud <benjamin.arnaud@videolabs.io> Date: Fri, 19 Feb 2021 11:25:28 +0100 Subject: [PATCH] qt/medialibrary: Create MLPlaylistMedia Signed-off-by: Pierre Lamot <pierre@videolabs.io> --- modules/gui/qt/Makefile.am | 2 + .../gui/qt/medialibrary/mlplaylistmedia.cpp | 236 ++++++++++++++++++ .../gui/qt/medialibrary/mlplaylistmedia.hpp | 99 ++++++++ po/POTFILES.in | 2 + 4 files changed, 339 insertions(+) create mode 100644 modules/gui/qt/medialibrary/mlplaylistmedia.cpp create mode 100644 modules/gui/qt/medialibrary/mlplaylistmedia.hpp diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am index 6c0516dbced5..4365fda0f8f1 100644 --- a/modules/gui/qt/Makefile.am +++ b/modules/gui/qt/Makefile.am @@ -172,6 +172,8 @@ libqt_plugin_la_SOURCES = \ gui/qt/medialibrary/mlplaylist.hpp \ gui/qt/medialibrary/mlplaylistlistmodel.cpp \ gui/qt/medialibrary/mlplaylistlistmodel.hpp \ + gui/qt/medialibrary/mlplaylistmedia.cpp \ + gui/qt/medialibrary/mlplaylistmedia.hpp \ gui/qt/menus/custom_menus.cpp \ gui/qt/menus/custom_menus.hpp \ gui/qt/menus/qml_menu_wrapper.cpp \ diff --git a/modules/gui/qt/medialibrary/mlplaylistmedia.cpp b/modules/gui/qt/medialibrary/mlplaylistmedia.cpp new file mode 100644 index 000000000000..2eb9855fcc80 --- /dev/null +++ b/modules/gui/qt/medialibrary/mlplaylistmedia.cpp @@ -0,0 +1,236 @@ +/***************************************************************************** + * Copyright (C) 2021 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 "mlplaylistmedia.hpp" + +// VLC includes +#include <qt.hpp> + +//------------------------------------------------------------------------------------------------- +// Ctor / dtor +//------------------------------------------------------------------------------------------------- + +MLPlaylistMedia::MLPlaylistMedia(vlc_medialibrary_t * ml, const vlc_ml_media_t * data) + : MLItem(MLItemId(data->i_id, VLC_ML_PARENT_UNKNOWN)) + , m_ml(ml) + , m_type(data->i_type) + , m_title(qfu(data->psz_title)) + , m_thumbnail(qfu(data->thumbnails[VLC_ML_THUMBNAIL_SMALL].psz_mrl)) + , m_duration(data->i_duration) + , m_progress(data->f_progress) + , m_playCount(data->i_playcount) + , m_handle(nullptr, [this](vlc_ml_event_callback_t * cb) { + assert(m_ml != nullptr); + + vlc_ml_event_unregister_callback(m_ml, cb); + }) +{ + for (const vlc_ml_file_t & file : ml_range_iterate<vlc_ml_file_t>(data->p_files)) + { + if (file.i_type != VLC_ML_FILE_TYPE_MAIN) + continue; + + //FIXME: Should we store every mrl ? + m_mrl = QUrl::fromEncoded(file.psz_mrl); + } + + unsigned int width = 0; + unsigned int height = 0; + + unsigned int nbChannels = 0; + + for(const vlc_ml_media_track_t & track + : ml_range_iterate<vlc_ml_media_track_t>(data->p_tracks)) + { + if (track.i_type == VLC_ML_TRACK_TYPE_VIDEO) + { + width = std::max(width, track.v.i_width); + height = std::max(height, track.v.i_height); + + m_video.push_back( + { + qfu(track.psz_codec), + qfu(track.psz_language), + track.v.i_fpsNum + }); + } + else if (track.i_type == VLC_ML_TRACK_TYPE_AUDIO) + { + nbChannels = std::max(nbChannels, track.a.i_nbChannels); + + m_audio.push_back( + { + qfu(track.psz_codec), + qfu(track.psz_language), + track.a.i_nbChannels, track.a.i_sampleRate + }); + } + } + + if (nbChannels >= 8) + m_channel = "7.1"; + else if (nbChannels >= 6) + m_channel = "5.1"; + else + m_channel = ""; + + if (width >= 7680 && height >= 4320) + m_resolution = "8K"; + else if (width >= 3840 && height >= 2160) + m_resolution = "4K"; + else if (width >= 1440 && height >= 1080) + m_resolution = "HD"; + else if (width >= 720 && height >= 1280) + m_resolution = "720p"; + else + m_resolution = ""; +} + +//------------------------------------------------------------------------------------------------- +// Interface +//------------------------------------------------------------------------------------------------- + +QString MLPlaylistMedia::getTitle() const +{ + return m_title; +} + +// FIXME: We have the same code in MLVideo implementation. +QString MLPlaylistMedia::getThumbnail() +{ + // NOTE: We don't need to generate a cover for audio media(s). + if (m_type != VLC_ML_MEDIA_TYPE_AUDIO + && + (m_thumbnailStatus == VLC_ML_THUMBNAIL_STATUS_MISSING + || + m_thumbnailStatus == VLC_ML_THUMBNAIL_STATUS_FAILURE)) + { + m_handle.reset(vlc_ml_event_register_callback(m_ml, onMlEvent, this)); + + vlc_ml_media_generate_thumbnail(m_ml, getId().id, VLC_ML_THUMBNAIL_SMALL, + 512, 320, 0.15); + } + + return m_thumbnail; +} + +//------------------------------------------------------------------------------------------------- + +QString MLPlaylistMedia::getDuration() const +{ + return MsToString(m_duration); +} + +QString MLPlaylistMedia::getDurationShort() const +{ + return MsToString(m_duration, true); +} + +//------------------------------------------------------------------------------------------------- + +QString MLPlaylistMedia::getResolutionName() const +{ + return m_resolution; +} + +//------------------------------------------------------------------------------------------------- + +QString MLPlaylistMedia::getChannel() const +{ + return m_channel; +} + +//------------------------------------------------------------------------------------------------- + +QString MLPlaylistMedia::getMRL() const +{ + return m_mrl.toEncoded(); +} + +QString MLPlaylistMedia::getMRLDisplay() const +{ + return m_mrl.toString(QUrl::PrettyDecoded | QUrl::RemoveUserInfo | QUrl::PreferLocalFile | + QUrl::NormalizePathSegments); +} + +//------------------------------------------------------------------------------------------------- + +float MLPlaylistMedia::getProgress() const +{ + return m_progress; +} + +QString MLPlaylistMedia::getProgressTime() const +{ + return MsToString(m_duration * m_progress); +} + +//------------------------------------------------------------------------------------------------- + +unsigned int MLPlaylistMedia::getPlayCount() const +{ + return m_playCount; +} + +//------------------------------------------------------------------------------------------------- + +QList<VideoDescription> MLPlaylistMedia::getVideo() const +{ + return m_video; +} + +QList<AudioDescription> MLPlaylistMedia::getAudio() const +{ + return m_audio; +} + +//------------------------------------------------------------------------------------------------- +// Private events +//------------------------------------------------------------------------------------------------- + +/* static */ void MLPlaylistMedia::onMlEvent(void * data, const vlc_ml_event_t * event) +{ + MLPlaylistMedia * self = static_cast<MLPlaylistMedia *>(data); + + self->onMlEvent(event); +} + +void MLPlaylistMedia::onMlEvent(const vlc_ml_event_t * event) +{ + if (event->i_type != VLC_ML_EVENT_MEDIA_THUMBNAIL_GENERATED + || + event->media_thumbnail_generated.i_size != VLC_ML_THUMBNAIL_SMALL + || + event->media_thumbnail_generated.p_media->i_id != getId().id) + return; + + if (event->media_thumbnail_generated.b_success == false) + { + m_thumbnailStatus = VLC_ML_THUMBNAIL_STATUS_FAILURE; + + return; + } + + vlc_ml_thumbnail_size_t size = event->media_thumbnail_generated.i_size; + + m_thumbnail = qfu(event->media_thumbnail_generated.p_media->thumbnails[size].psz_mrl); + + m_thumbnailStatus = VLC_ML_THUMBNAIL_STATUS_AVAILABLE; + + vlc_ml_event_unregister_from_callback(m_ml, m_handle.release()); +} diff --git a/modules/gui/qt/medialibrary/mlplaylistmedia.hpp b/modules/gui/qt/medialibrary/mlplaylistmedia.hpp new file mode 100644 index 000000000000..a1e0da230400 --- /dev/null +++ b/modules/gui/qt/medialibrary/mlplaylistmedia.hpp @@ -0,0 +1,99 @@ +/***************************************************************************** + * Copyright (C) 2021 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 MLPLAYLISTMEDIA_H +#define MLPLAYLISTMEDIA_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +// MediaLibrary includes +// NOTE: We need that header for VideoDescription and AudioDescription. +#include "mlvideo.hpp" + +// Qt includes +#include <QUrl> + +// Forward declarations +class vlc_medialibrary_t; + +class MLPlaylistMedia : public MLItem +{ +public: + MLPlaylistMedia(vlc_medialibrary_t * ml, const vlc_ml_media_t * data); + +public: // Interface + QString getTitle() const; + + QString getThumbnail(); + + QString getDuration () const; + QString getDurationShort() const; + + QString getResolutionName() const; + + QString getChannel() const; + + QString getMRL () const; + QString getMRLDisplay() const; + + float getProgress () const; + QString getProgressTime() const; + + unsigned int getPlayCount() const; + + QList<VideoDescription> getVideo() const; + QList<AudioDescription> getAudio() const; + +private: // Events + static void onMlEvent(void * data, const vlc_ml_event_t * event); + + void onMlEvent(const vlc_ml_event_t * event); + +private: // Properties + vlc_medialibrary_t * m_ml; + + vlc_ml_media_type_t m_type; + + QString m_title; + + QString m_thumbnail; + vlc_ml_thumbnail_status_t m_thumbnailStatus; + + int64_t m_duration; + + QString m_resolution; + + QString m_channel; + + QUrl m_mrl; + + float m_progress; + QString m_progressTime; + + unsigned int m_playCount; + + QList<VideoDescription> m_video; + QList<AudioDescription> m_audio; + + std::unique_ptr<vlc_ml_event_callback_t, + std::function<void(vlc_ml_event_callback_t*)>> m_handle; +}; + +#endif // MLPLAYLISTMEDIA_H diff --git a/po/POTFILES.in b/po/POTFILES.in index 396418fb24f3..d765d7899181 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -772,6 +772,8 @@ modules/gui/qt/medialibrary/mlfoldersmodel.cpp modules/gui/qt/medialibrary/mlfoldersmodel.hpp modules/gui/qt/medialibrary/mlplaylistlistmodel.cpp modules/gui/qt/medialibrary/mlplaylistlistmodel.hpp +modules/gui/qt/medialibrary/mlplaylistmedia.cpp +modules/gui/qt/medialibrary/mlplaylistmedia.hpp modules/gui/qt/menus/menus.cpp modules/gui/qt/menus/menus.hpp modules/gui/qt/qt.cpp -- GitLab