From 711b219a001d0c4fdd61367903696fa1c6ff1a3d Mon Sep 17 00:00:00 2001 From: ZackaryWelch Date: Tue, 3 Oct 2017 15:24:26 -0400 Subject: Added experimental video thumbnails in lumina-fm and fileinfo --- src-qt5/core/libLumina/LVideoSurface.cpp | 32 +++++++++++ src-qt5/core/libLumina/LVideoSurface.h | 20 +++++++ src-qt5/core/libLumina/LVideoSurface.pri | 9 +++ src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp | 25 ++++++++- src-qt5/desktop-utils/lumina-fileinfo/MainUI.h | 9 ++- .../lumina-fileinfo/lumina-fileinfo.pro | 3 +- src-qt5/desktop-utils/lumina-fm/Browser.cpp | 62 +++++++++++++++++---- src-qt5/desktop-utils/lumina-fm/Browser.h | 10 +++- src-qt5/desktop-utils/lumina-fm/lumina-fm.pro | 1 + src-qt5/src-glwidgets/gltest/colorchange.h | 11 +--- src-qt5/src-glwidgets/gltest/main.cpp | 13 +++-- src-qt5/src-glwidgets/gltest/test | Bin 59456 -> 58272 bytes src-qt5/src-glwidgets/glw-base.cpp | 21 +++++-- 13 files changed, 179 insertions(+), 37 deletions(-) create mode 100644 src-qt5/core/libLumina/LVideoSurface.cpp create mode 100644 src-qt5/core/libLumina/LVideoSurface.h create mode 100644 src-qt5/core/libLumina/LVideoSurface.pri diff --git a/src-qt5/core/libLumina/LVideoSurface.cpp b/src-qt5/core/libLumina/LVideoSurface.cpp new file mode 100644 index 00000000..6adec5d2 --- /dev/null +++ b/src-qt5/core/libLumina/LVideoSurface.cpp @@ -0,0 +1,32 @@ +#include "LVideoSurface.h" +#include + +LVideoSurface::LVideoSurface() : QAbstractVideoSurface() { + recording = 0; + frameImage = QImage(); +} + +QImage LVideoSurface::currentFrame() { + return frameImage; +} + +bool LVideoSurface::present(const QVideoFrame &frame) { + if(frame.isValid()) { + qDebug() << "Recording Frame" << frame.pixelFormat(); + QVideoFrame icon(frame); + icon.map(QAbstractVideoBuffer::ReadOnly); + frameImage = QImage(icon.bits(), icon.width(), icon.height(), icon.bytesPerLine(), QImage::Format_ARGB32_Premultiplied); + icon.unmap(); + emit frameReceived(frameImage); + if(recording++ == 2) ready = true; + return true; + } + ready = false; + return false; +} + +QList LVideoSurface::supportedPixelFormats(QAbstractVideoBuffer::HandleType type = QAbstractVideoBuffer::NoHandle) const { + Q_UNUSED(type); + return QList() << QVideoFrame::Format_ARGB32 << QVideoFrame::Format_RGB32 << QVideoFrame::Format_RGB24 + << QVideoFrame::Format_RGB565 << QVideoFrame::Format_RGB555 << QVideoFrame::Format_BGRA32 << QVideoFrame::Format_BGR32; +} diff --git a/src-qt5/core/libLumina/LVideoSurface.h b/src-qt5/core/libLumina/LVideoSurface.h new file mode 100644 index 00000000..adb4611d --- /dev/null +++ b/src-qt5/core/libLumina/LVideoSurface.h @@ -0,0 +1,20 @@ +#include +#include +#include + +class LVideoSurface : public QAbstractVideoSurface { + Q_OBJECT + + public: + LVideoSurface(); + virtual bool present(const QVideoFrame&); + virtual QList supportedPixelFormats(QAbstractVideoBuffer::HandleType) const; + QImage currentFrame(); + bool frameReady(); + signals: + void frameReceived(QImage); + private: + int recording; + QImage frameImage; + bool ready; +}; diff --git a/src-qt5/core/libLumina/LVideoSurface.pri b/src-qt5/core/libLumina/LVideoSurface.pri new file mode 100644 index 00000000..469b8c93 --- /dev/null +++ b/src-qt5/core/libLumina/LVideoSurface.pri @@ -0,0 +1,9 @@ +QT *= multimedia + +HEADERS *= $${PWD}/LVideoSurface.h +SOURCES *= $${PWD}/LVideoSurface.cpp + +INCLUDEPATH *= ${PWD} + +#Now the other dependendies of it +#include(LUtils.pri) diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp index d82f09ce..4d695ab4 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp @@ -8,6 +8,7 @@ #include "MainUI.h" #include "ui_MainUI.h" +#include #include #include @@ -22,12 +23,17 @@ MainUI::MainUI() : QDialog(), ui(new Ui::MainUI){ terminate_thread = false; UpdateIcons(); //Set all the icons in the dialog SetupConnections(); + player = new QMediaPlayer(0, QMediaPlayer::VideoSurface); + surface = new LVideoSurface(); + player->setVideoOutput(surface); INFO = 0; } MainUI::~MainUI(){ terminate_thread = true; this->close(); + delete surface; + delete player; } //============= @@ -86,7 +92,15 @@ void MainUI::LoadFile(QString path, QString type){ ui->label_file_icon->setPixmap( pix.scaledToHeight(64) ); ui->label_file_size->setText( ui->label_file_size->text()+" ("+QString::number(pix.width())+" x "+QString::number(pix.height())+" px)" ); //qDebug() << " - done with image"; - }else{ + }/*else if(INFO->isVideo()){ + player->setMedia(QUrl("file://"+INFO->absoluteFilePath())); + player->play(); + player->setPosition(player->duration() / 2); + connect(surface, SIGNAL(frameReceived(QImage)), this, SLOT(stopVideo(QImage))); + //Pixmap set when video is loaded in stopVideo + //ui->label_file_icon->setPixmap( QPixmap::fromImage(surface->frameImage()).scaledToHeight(64) ); + //ui->label_file_size->setText( ui->label_file_size->text()+" ("+QString::number(pix.width())+" x "+QString::number(pix.height())+" px)" ); + }*/else{ ui->label_file_icon->setPixmap( LXDG::findIcon( INFO->iconfile(), "unknown").pixmap(QSize(64,64)) ); } //Now verify the tab is available in the widget @@ -103,7 +117,7 @@ void MainUI::LoadFile(QString path, QString type){ } //Now load the special XDG desktop info qDebug() << "Check XDG Info:" << type; - //qDebug() << INFO->isDesktopFile() << type; + qDebug() << INFO->isDesktopFile() << type; if(INFO->isDesktopFile() || !type.isEmpty()){ if(INFO->XDG()->type == XDGDesktop::APP){ @@ -296,6 +310,13 @@ void MainUI::getXdgCommand(QString prev){ xdgvaluechanged(); } +/*void MainUI::stopVideo(QImage img) { + static bool flag = true; + if(flag) { player->setPosition(player->duration() / 2); flag = false;} + player->pause(); + ui->label_file_icon->setPixmap( QPixmap::fromImage( img.scaledToHeight(64) )); +}*/ + void MainUI::on_tool_xdg_getDir_clicked(){ //Find a directory QString dir = ui->line_xdg_wdir->text(); diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h index cbe23d9e..e1f37425 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h @@ -14,11 +14,11 @@ #define _LUMINA_FILE_INFO_MAIN_UI_H #include - +#include #include +#include -namespace Ui{ - class MainUI; +namespace Ui{ class MainUI; }; class MainUI : public QDialog{ @@ -35,6 +35,8 @@ public slots: private: Ui::MainUI *ui; LFileInfo *INFO; + LVideoSurface *surface; + QMediaPlayer *player; bool canwrite; bool terminate_thread; //flag for terminating the GetDirSize task @@ -51,6 +53,7 @@ private slots: //UI Buttons void on_push_close_clicked(); void on_push_save_clicked(); + //void stopVideo(QImage); void getXdgCommand(QString prev = ""); //void on_tool_xdg_getCommand_clicked(QString prev = ""); void on_tool_xdg_getDir_clicked(); diff --git a/src-qt5/desktop-utils/lumina-fileinfo/lumina-fileinfo.pro b/src-qt5/desktop-utils/lumina-fileinfo/lumina-fileinfo.pro index bbaf842e..b53d8cba 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/lumina-fileinfo.pro +++ b/src-qt5/desktop-utils/lumina-fileinfo/lumina-fileinfo.pro @@ -1,7 +1,7 @@ include("$${PWD}/../../OS-detect.pri") QT += core gui -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets concurrent +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets concurrent multimedia TARGET = lumina-fileinfo @@ -13,6 +13,7 @@ target.path = $${L_BINDIR} include(../../core/libLumina/LUtils.pri) #includes LUtils include(../../core/libLumina/LuminaXDG.pri) #include(../../core/libLumina/LuminaSingleApplication.pri) +include(../../core/libLumina/LVideoSurface.pri) include(../../core/libLumina/LuminaThemes.pri) SOURCES += main.cpp\ diff --git a/src-qt5/desktop-utils/lumina-fm/Browser.cpp b/src-qt5/desktop-utils/lumina-fm/Browser.cpp index f2bdc178..e57b6aed 100644 --- a/src-qt5/desktop-utils/lumina-fm/Browser.cpp +++ b/src-qt5/desktop-utils/lumina-fm/Browser.cpp @@ -16,10 +16,13 @@ Browser::Browser(QObject *parent) : QObject(parent){ watcher = new QFileSystemWatcher(this); connect(watcher, SIGNAL(fileChanged(const QString&)), this, SLOT(fileChanged(QString)) ); - connect(watcher, SIGNAL(directoryChanged(const QString&)), this, SLOT(dirChanged(QString)) ); + connect(watcher, SIGNAL(directoryChanged(const QString&)), this, SLOT(dirChanged(QString)) ); showHidden = false; showThumbs = false; imageFormats = LUtils::imageExtensions(false); //lowercase suffixes + videoFormats = LUtils::videoExtensions(); //lowercase suffixes + //connect(surface, SIGNAL(frameReceived(QImage)), this, SLOT(captureFrame(QImage))); + //connect(player, &QMediaPlayer::mediaStatusChanged, this, [&]{ stopVideo(player, player->mediaStatus()); }); connect(this, SIGNAL(threadDone(QString, QImage)), this, SLOT(futureFinished(QString, QImage))); //will always be between different threads } @@ -60,12 +63,11 @@ void Browser::loadItem(QString info, Browser *obj){ file.close(); pix.loadFromData(bytes); if(pix.width() > 256 || pix.height() > 256 ){ - pix = pix.scaled(256,256, Qt::KeepAspectRatio, Qt::SmoothTransformation); + pix = pix.scaled(256,256, Qt::KeepAspectRatio); } } } - - //qDebug() << " - done with item:" << info; + qDebug() << " - done with item:" << info; obj->emit threadDone(info, pix); } @@ -92,22 +94,60 @@ void Browser::dirChanged(QString dir){ else if(dir.startsWith(currentDir)){ QtConcurrent::run(this, &Browser::loadItem, dir, this ); } } +/*void Browser::stopVideo(QMediaPlayer *player, QMediaPlayer::MediaStatus status) { + qDebug() << status; + if(status == QMediaPlayer::BufferedMedia) { + qDebug() << "stoppingVideo" << player << player->currentMedia().canonicalUrl(); + player->setPosition(player->duration() / 2); + player->pause(); + } +} + +void Browser::captureFrame(QImage pix) { + qDebug() << "grabbing frame"; + videoFrame = pix.scaledToHeight(64); + emit frameChanged(); +}*/ + void Browser::futureFinished(QString name, QImage icon){ //Note: this will be called once for every item that loads QIcon ico; - //LFileInfo info(name); LFileInfo *info = new LFileInfo(name); if(!icon.isNull() && showThumbs){ - //qDebug() << " -- Data:"; QPixmap pix = QPixmap::fromImage(icon); ico.addPixmap(pix); - //}else if(info->isDir()){ - //qDebug() << " -- Folder:"; - //ico = loadIcon("folder"); } if(ico.isNull()){ - //qDebug() << " -- MimeType:" << info.fileName() << info.mimetype(); - ico = loadIcon(info->iconfile()); + if(videoFormats.contains(name.section(".",-1).toLower())) { + qDebug() << "Loading Video for" << name; + qDebug() << "VIDEO" << info; + //qDebug() << obj << this << QThread::currentThread(); + QMediaPlayer *player = new QMediaPlayer(0, QMediaPlayer::VideoSurface); + qDebug() << " - created player"; + LVideoSurface *surface = new LVideoSurface(); + qDebug() << " - Create objects"; + //connect(surface, SIGNAL(frameReceived(QImage)), this, SLOT(captureFrame(QImage))); + //connect(player, &QMediaPlayer::mediaStatusChanged, this, [&]{ stopVideo(player, player->mediaStatus()); }); + player->setVideoOutput(surface); + player->setVolume(0); + player->setMedia(QUrl("file://"+info->absoluteFilePath())); + player->play(); + qDebug() << "Wait for buffer"; + while(player->mediaStatus()!=QMediaPlayer::BufferedMedia){ + QCoreApplication::processEvents(); + } + player->pause(); + player->setPosition(player->duration()/2); + while(!surface->frameReady()) { + QCoreApplication::processEvents(); + } + qDebug() << "Load Frame"; + ico.addPixmap(QPixmap::fromImage(surface->currentFrame())); + delete player; + delete surface; + }else { + ico = loadIcon(info->iconfile()); + } } this->emit itemDataAvailable( ico, info); //qDebug() << " -- done:" << name; diff --git a/src-qt5/desktop-utils/lumina-fm/Browser.h b/src-qt5/desktop-utils/lumina-fm/Browser.h index 94f6ba3f..7ccb5199 100644 --- a/src-qt5/desktop-utils/lumina-fm/Browser.h +++ b/src-qt5/desktop-utils/lumina-fm/Browser.h @@ -15,6 +15,8 @@ #include //#include +#include +#include #include /*class FileItem{ public: @@ -43,8 +45,9 @@ public: private: QString currentDir; QFileSystemWatcher *watcher; + //QImage videoFrame; bool showHidden, showThumbs; - QStringList imageFormats, oldFiles; + QStringList imageFormats, videoFormats, oldFiles; QHash mimeIcons; //cache for quickly re-using QIcons void loadItem(QString info, Browser *obj); //this is the main loader class - multiple instances each run in a separate thread @@ -53,7 +56,8 @@ private: private slots: void fileChanged(QString); //tied into the watcher - for file change notifications void dirChanged(QString); // tied into the watcher - for new/removed files in the current dir - + //void captureFrame(QImage); + //void stopVideo(QMediaPlayer*, QMediaPlayer::MediaStatus); void futureFinished(QString, QImage); public slots: @@ -70,6 +74,8 @@ signals: //Internal signal for the alternate threads void threadDone(QString, QImage); + + //void frameChanged(); }; #endif diff --git a/src-qt5/desktop-utils/lumina-fm/lumina-fm.pro b/src-qt5/desktop-utils/lumina-fm/lumina-fm.pro index 6c340e14..6cb4a537 100644 --- a/src-qt5/desktop-utils/lumina-fm/lumina-fm.pro +++ b/src-qt5/desktop-utils/lumina-fm/lumina-fm.pro @@ -15,6 +15,7 @@ include(../../core/libLumina/LuminaXDG.pri) include(../../core/libLumina/LuminaSingleApplication.pri) include(../../core/libLumina/LuminaThemes.pri) include(../../core/libLumina/ExternalProcess.pri) +include(../../core/libLumina/LVideoSurface.pri) SOURCES += main.cpp \ MainUI.cpp \ diff --git a/src-qt5/src-glwidgets/gltest/colorchange.h b/src-qt5/src-glwidgets/gltest/colorchange.h index d62fcd5c..aad01f05 100644 --- a/src-qt5/src-glwidgets/gltest/colorchange.h +++ b/src-qt5/src-glwidgets/gltest/colorchange.h @@ -13,14 +13,9 @@ private: public slots: void toggle(){ - static int current = 0; - if(current==0){ - base->setBackgroundColor(QColor(Qt::red)); - }else{ - base->setBackgroundColor(QColor(Qt::blue)); - current = -1; - } - current++; + static bool current = false; + base->setBackgroundColor( current ? QColor(Qt::blue) : QColor(Qt::red)); + current = !current; } public: diff --git a/src-qt5/src-glwidgets/gltest/main.cpp b/src-qt5/src-glwidgets/gltest/main.cpp index b303cb6b..efcebea1 100644 --- a/src-qt5/src-glwidgets/gltest/main.cpp +++ b/src-qt5/src-glwidgets/gltest/main.cpp @@ -10,14 +10,14 @@ int main(int argc, char** argv){ - QSurfaceFormat fmt; + QSurfaceFormat fmt; fmt.setRenderableType(QSurfaceFormat::OpenGL); //OpenGL, OpenGLES, OpenVG fmt.setSwapBehavior(QSurfaceFormat::DoubleBuffer); - QSurfaceFormat::setDefaultFormat(fmt); + QSurfaceFormat::setDefaultFormat(fmt); QApplication A(argc,argv); - qDebug() << "Creating base widget"; + qDebug() << "Creating base widget"; GLW_Base base; qDebug() << "Resize base widget"; base.resize(1024,768); @@ -29,7 +29,7 @@ int main(int argc, char** argv){ GLW_Widget wgt(&base); wgt.setGLBase(&base); wgt.setGeometry(75,50,50,50); - QPropertyAnimation anim(&wgt); + QPropertyAnimation anim(&wgt); anim.setTargetObject(&wgt); anim.setPropertyName("geometry"); //anim.setStartValue(QRect(-50,-50,50,50)); @@ -46,6 +46,7 @@ int main(int argc, char** argv){ colorchange CC(&base); qDebug() << "Start Event loop"; base.show(); - A.exec(); - qDebug() << " - Finished"; + int ret = A.exec(); + qDebug() << " - Finished"; + return ret; } diff --git a/src-qt5/src-glwidgets/gltest/test b/src-qt5/src-glwidgets/gltest/test index 85760654..3ba6f8db 100755 Binary files a/src-qt5/src-glwidgets/gltest/test and b/src-qt5/src-glwidgets/gltest/test differ diff --git a/src-qt5/src-glwidgets/glw-base.cpp b/src-qt5/src-glwidgets/glw-base.cpp index ef54606b..4065f70f 100644 --- a/src-qt5/src-glwidgets/glw-base.cpp +++ b/src-qt5/src-glwidgets/glw-base.cpp @@ -67,7 +67,24 @@ void GLW_Base::resizeEvent(QResizeEvent *ev){ }*/ void GLW_Base::paintGL(){ + //Setup the OpenGL stuff + QOpenGLFunctions *f = this->context()->functions(); + f->glViewport(0, 0, width(), height()); + f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + GLfloat vertices[] = { + 0.0f, 0.707f, + -0.5f, -0.5f, + 0.5f, -0.5f + }; + + f->glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices); + f->glEnableVertexAttribArray(0); + f->glDrawArrays(GL_TRIANGLES, 0, 3); + f->glDisableVertexAttribArray(0); + glDrawPixels(bg_img.width(), bg_img.height(), GL_RGBA, GL_UNSIGNED_BYTE, bg_img.bits()); + QRect rect = QRect(QPoint(0,0), this->size()); //Prepare the image to be painted QImage img(this->size(), QImage::Format_RGBA8888); @@ -75,10 +92,6 @@ void GLW_Base::paintGL(){ painter.begin(&img); painter.fillRect(rect, bg_color); painter.end(); - QOpenGLFunctions *f = this->context()->functions(); - //f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - //do native OpenGL commands here - glDrawPixels(bg_img.width(), bg_img.height(), GL_RGBA, GL_UNSIGNED_BYTE, bg_img.bits()); //Now do any QPainter drawing /*QOpenGLPaintDevice device(rect.size()); -- cgit