• Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Register
    • Login

    Reintegrate projectM Visualizer

    Scheduled Pinned Locked Moved
    Development
    7
    93
    156.5k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Gustavo L ConteG
      Gustavo L Conte @Gustavo L Conte
      last edited by

      this version I posted works MUCH better giving nice results with the cream-of-cream presets,Screenshot from 2024-07-25 05-32-42.png Screenshot from 2024-07-25 05-31-24.png Screenshot from 2024-07-25 05-17-39.png Screenshot from 2024-07-25 05-08-09.png

      Gustavo L ConteG 1 Reply Last reply Reply Quote 0
      • Gustavo L ConteG
        Gustavo L Conte @Gustavo L Conte
        last edited by Gustavo L Conte

        void VisualizationOpenGLWidget::paintGL() {
        
          QPainter p(this);
          p.beginNativePainting();
          
          int w = width(); int h = height();
          this->resize(w*2,h*2);
          if (projectm_visualization_) {
            projectm_visualization_->Resize(w*2, h*2);
            projectm_visualization_->RenderFrame(w*2,h*2);
          }
          update();
          this->resize(w,h);
          if (projectm_visualization_) {
            projectm_visualization_->Resize(w, h);
            projectm_visualization_->RenderFrame(w,h);
          }
          update();
        
           p.endNativePainting();
        
          qLog(Debug) << __PRETTY_FUNCTION__ << glGetError();
        
        }
        

        Its disgusting, but it really makes a HUGE percentage of presets to display instead of black screen.
        Ive done this without wraping the openglwindow into a widget;
        when you resize the window, it displays, several plugins happens that way.. actually the nicer ones like this one:

        😞

        Screenshot from 2024-07-25 09-44-48.png

        1 Reply Last reply Reply Quote 0
        • Gustavo L ConteG
          Gustavo L Conte
          last edited by

          VisualizationContainer::VisualizationContainer(QWidget *parent)
              : QMainWindow(parent),
                projectm_visualization_(new ProjectMVisualization(this)),
                overlay_(new VisualizationOverlay),
                selector_(new VisualizationSelector(this)),
                overlay_proxy_(nullptr),
                engine_(nullptr),
                menu_(new QMenu(this)),
                fps_(kDefaultFps),
                size_(kDefaultTextureSize) {
          
              setWindowTitle(tr("Visualizations"));
              setWindowIcon(IconLoader::Load(QStringLiteral("strawberry")));
              setMinimumSize(64, 64);
          
              {
                  Settings s;
                  s.beginGroup(QLatin1String(kSettingsGroup));
                  if (!restoreGeometry(s.value("geometry").toByteArray())) {
                      resize(kDefaultWidth, kDefaultHeight);
                  }
                  fps_ = s.value("fps", kDefaultFps).toInt();
                  size_ = s.value("size", kDefaultTextureSize).toInt();
                  s.endGroup();
              }
          
              QShortcut *close = new QShortcut(QKeySequence::Close, this);
              QObject::connect(close, &QShortcut::activated, this, &VisualizationContainer::close);
          
              QObject::connect(overlay_, &VisualizationOverlay::OpacityChanged, this, &VisualizationContainer::ChangeOverlayOpacity);
              QObject::connect(overlay_, &VisualizationOverlay::ShowPopupMenu, this, &VisualizationContainer::ShowPopupMenu);
              ChangeOverlayOpacity(1.0);
          
              projectm_visualization_->SetTextureSize(size_);
              SizeChanged();
          
              selector_->SetVisualization(projectm_visualization_);
          
              menu_->addAction(IconLoader::Load(QStringLiteral("view-fullscreen")), tr("Toggle fullscreen"), this, &VisualizationContainer::ToggleFullscreen);
          
              QMenu *fps_menu = menu_->addMenu(tr("Framerate"));
              QActionGroup *fps_group = new QActionGroup(this);
              AddFramerateMenuItem(tr("Low (%1 fps)").arg(kLowFramerate), kLowFramerate, fps_, fps_group);
              AddFramerateMenuItem(tr("Medium (%1 fps)").arg(kMediumFramerate), kMediumFramerate, fps_, fps_group);
              AddFramerateMenuItem(tr("High (%1 fps)").arg(kHighFramerate), kHighFramerate, fps_, fps_group);
              AddFramerateMenuItem(tr("Super high (%1 fps)").arg(kSuperHighFramerate), kSuperHighFramerate, fps_, fps_group);
              fps_menu->addActions(fps_group->actions());
          
              QMenu *quality_menu = menu_->addMenu(tr("Quality", "Visualization quality"));
              QActionGroup *quality_group = new QActionGroup(this);
              AddQualityMenuItem(tr("Low (256x256)"), 256, size_, quality_group);
              AddQualityMenuItem(tr("Medium (512x512)"), 512, size_, quality_group);
              AddQualityMenuItem(tr("High (1024x1024)"), 1024, size_, quality_group);
              AddQualityMenuItem(tr("Super high (2048x2048)"), 2048, size_, quality_group);
              quality_menu->addActions(quality_group->actions());
          
              menu_->addAction(tr("Select visualizations..."), selector_, &VisualizationContainer::show);
              menu_->addSeparator();
              menu_->addAction(IconLoader::Load(QStringLiteral("application-exit")), tr("Close visualization"), this, &VisualizationContainer::hide);
              
          
              // OpenGL
              
              // Create and configure the QSurfaceFormat
              QSurfaceFormat format;
              format.setVersion(3, 3);  // Set OpenGL version to 3.3
              format.setProfile(QSurfaceFormat::CoreProfile);  // Use the core profile
              format.setDepthBufferSize(24);
              format.setStencilBufferSize(8);
          
              // Initialize the primary OpenGL context
              QOpenGLContext *openGLContext = new QOpenGLContext(this);
              openGLContext->setFormat(format);
          
              if (!openGLContext->create()) {
                  qWarning() << "Failed to create OpenGL context";
              } else {
                  qDebug() << "OpenGL context created successfully";
              }
          
              // Create a new shared context
              QOpenGLContext *sharedContext = new QOpenGLContext(this);
              sharedContext->setFormat(format);
          
              if (!sharedContext->create()) {
                  qWarning() << "Failed to create shared OpenGL context";
              } else {
                  qDebug() << "Shared OpenGL context created successfully";
              }
          
              // Set the shared context
              openGLContext->setShareContext(sharedContext);
          
              // Create the OpenGL window using the primary OpenGL context
              openGLWindow_ = new VisualizationOpenGLWidget(projectm_visualization_, openGLContext);
              openGLWindow_->setFormat(format);
          
              // Make the OpenGL context current
              if (!openGLContext->makeCurrent(openGLWindow_)) {
                  qWarning() << "Failed to make OpenGL context current";
              }
          
              // Wrap the QOpenGLWindow in a QWidget container
              glContainer = QWidget::createWindowContainer(openGLWindow_);
              glContainer->setFocusPolicy(Qt::TabFocus);
              glContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
              glContainer->setParent(this);
              glContainer->setVisible(true);
              setCentralWidget(glContainer);
              projectm_visualization_->Resize(width(), height());
          
              // Add the overlay as a child of the container and set its visibility
              overlay_->setParent(glContainer);
              overlay_->resize(glContainer->size());  // Resize the overlay to match the container size
              overlay_->setVisible(true);
              overlay_->raise();
          }
          
          #ifndef VISUALIZATIONOPENGLWIDGET_H
          #define VISUALIZATIONOPENGLWIDGET_H
          
          #include "config.h"
          
          #include <QOpenGLWindow>
          #include <QOpenGLFunctions>
          
          class ProjectMVisualization;
          
          class VisualizationOpenGLWidget : public QOpenGLWindow, protected QOpenGLFunctions {
              Q_OBJECT
          
          public:
              explicit VisualizationOpenGLWidget(ProjectMVisualization* projectm_visualization, QOpenGLContext* sharedContext, QWindow* parent = nullptr);
          
              void initializeGL() override;
          
          protected:
              void paintGL() override;
              void resizeGL(int width, int height) override;
          
          private:
              void Setup(int width, int height);
          
              ProjectMVisualization* projectm_visualization_;
              QOpenGLContext* sharedContext_;
          };
          
          #endif  // VISUALIZATIONOPENGLWIDGET_H
          
          #include "config.h"
          
          #include <QPainter>
          
          #include "core/logging.h"
          #include "visualizationopenglwidget.h"
          #include "projectmvisualization.h"
          
          VisualizationOpenGLWidget::VisualizationOpenGLWidget(ProjectMVisualization* projectm_visualization, QOpenGLContext* sharedContext, QWindow* parent)
              : QOpenGLWindow(NoPartialUpdate, parent),
                projectm_visualization_(projectm_visualization),
                sharedContext_(sharedContext) {
              setFormat(sharedContext_->format());
          }
          
          void VisualizationOpenGLWidget::initializeGL() {
              QOpenGLWindow::initializeGL();
              sharedContext_->makeCurrent(this);
              initializeOpenGLFunctions();
              projectm_visualization_->Init();
          }
          
          void VisualizationOpenGLWidget::paintGL() {
              sharedContext_->makeCurrent(this);
          
              QPainter p(this);
              p.beginNativePainting();
              
              if (projectm_visualization_) {
                  Setup(width(), height());
                  projectm_visualization_->RenderFrame(width(), height());
              }
              
              update();
          
              p.endNativePainting();
          
              GLenum error = glGetError();
              if (error != GL_NO_ERROR) {
                  qWarning() << "OpenGL error in paintGL:" << error;
              }
          
              qLog(Debug) << __PRETTY_FUNCTION__ << "Completed";
          }
          
          void VisualizationOpenGLWidget::resizeGL(int width, int height) {
              sharedContext_->makeCurrent(this);
          
              Setup(width, height);
              projectm_visualization_->Resize(width, height);
          
              GLenum error = glGetError();
              if (error != GL_NO_ERROR) {
                  qWarning() << "OpenGL error in resizeGL:" << error;
              }
          }
          
          void VisualizationOpenGLWidget::Setup(int width, int height) {
              // Ensure the correct OpenGL context is current
              if (!sharedContext_->makeCurrent(this)) {
                  qWarning() << "Failed to make OpenGL context current in Setup";
                  return;
              }
          
              // Initialize OpenGL functions
              initializeOpenGLFunctions();
          
              // Set up OpenGL state
              glShadeModel(GL_SMOOTH);
              glClearColor(0, 0, 0, 0);
              glViewport(0, 0, width, height);
              
              glMatrixMode(GL_TEXTURE);
              glLoadIdentity();
              
              glMatrixMode(GL_PROJECTION);
              glLoadIdentity();
              glOrtho(0, width, height, 0, -1, 1);  // Set an orthographic projection matrix
              
              glMatrixMode(GL_MODELVIEW);
              glLoadIdentity();
              
              glDrawBuffer(GL_BACK);
              glReadBuffer(GL_BACK);
              
              glEnable(GL_BLEND);
              glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
          
              glEnable(GL_LINE_SMOOTH);
              glEnable(GL_POINT_SMOOTH);
              glClearColor(0.0F, 0.0F, 0.0F, 0.0F);
              glLineStipple(2, 0xAAAA);
          
              GLenum error = glGetError();
              if (error != GL_NO_ERROR) {
                  qWarning() << "OpenGL error in Setup:" << error;
              }
          }
          
          1 Reply Last reply Reply Quote 0
          • Gustavo L ConteG
            Gustavo L Conte
            last edited by

            https://forum.qt.io/topic/155554/error-code-1282-when-using-opengl-functions-in-qopenglwindow/2

            1 Reply Last reply Reply Quote 0
            • Gustavo L ConteG
              Gustavo L Conte
              last edited by Gustavo L Conte

              I'm trying lotsa stuff, using FBO and OpenGLWindow, changing profiles (between versions and compatibility/core), I even made an SDL2 window version. Every time I implement a different way, All result are the same: some presets working and the same majority not working.

              But now I've tried bypassing the normal way presets are loaded, and only use this, i.e.

              projectm_playlist_add_path(projectm_playlist_instance_, "/home/guzpido/presets-cream-of-the-crop", true, true);
              

              it appears to make a bit more presets to work. this could be a clue. Maybe the way we are loading presets has some issue; but I've banging my head to figure it out if this makes even sense.

              Screenshot from 2024-08-04 01-37-12.png
              Screenshot from 2024-08-04 01-33-11.png

              edit: also i cant determine if ConsumeBuffer is working

              1 Reply Last reply Reply Quote 0
              • Gustavo L ConteG
                Gustavo L Conte
                last edited by

                I finally understood the mystery of why size_t is accidentally working in ConsumeBuffer: all my FLACs are S24LE, I just tested now one of my own songs which are S16LE and the correct int16 aapproach works for detecting and interacting audio with visuals! Therefore Im trying now to make a ConsumeBuffer with lasers to determine automatically the format and width: (but no luck making S24LE to work)

                #include <QtCore/QtEndian>
                
                void VisualizationSDL2::ConsumeBuffer(GstBuffer *buffer, const int pipeline_id, const QString &format) {
                    Q_UNUSED(pipeline_id);
                
                    GstMapInfo map;
                    gst_buffer_map(buffer, &map, GST_MAP_READ);
                
                    if (projectm_instance_) {
                        unsigned int sample_count = 0;
                        const int16_t *int16_data = nullptr;
                        const float *float_data = nullptr;
                
                        if (format == QStringLiteral("S16LE") || format == QStringLiteral("S16BE")) {
                            sample_count = map.size / sizeof(int16_t) / 2;
                            int16_data = reinterpret_cast<const int16_t *>(map.data);
                            if (format == QStringLiteral("S16BE")) {
                                // Convert big-endian to little-endian if necessary
                                std::vector<int16_t> temp_data(sample_count * 2);
                                for (unsigned int i = 0; i < sample_count * 2; ++i) {
                                    temp_data[i] = qFromBigEndian(int16_data[i]);
                                }
                                int16_data = temp_data.data();
                            }
                            projectm_pcm_add_int16(projectm_instance_, int16_data, sample_count, PROJECTM_STEREO);
                        } else if (format == QStringLiteral("F32LE") || format == QStringLiteral("F32BE")) {
                            sample_count = map.size / sizeof(float) / 2;
                            float_data = reinterpret_cast<const float *>(map.data);
                            if (format == QStringLiteral("F32BE")) {
                                // Convert big-endian to little-endian if necessary
                                std::vector<float> temp_data(sample_count * 2);
                                for (unsigned int i = 0; i < sample_count * 2; ++i) {
                                    temp_data[i] = qFromBigEndian(float_data[i]);
                                }
                                float_data = temp_data.data();
                            }
                            projectm_pcm_add_float(projectm_instance_, float_data, sample_count, PROJECTM_STEREO);
                        } else if (format == QStringLiteral("S24LE")) {
                            // Handle 24-bit audio (3 bytes per sample)
                            sample_count = map.size / 3 / 2;
                            std::vector<int16_t> int16_samples(sample_count * 2);
                            for (unsigned int i = 0; i < sample_count * 2; ++i) {
                                int16_samples[i] = static_cast<int16_t>((map.data[i * 3 + 2] << 8) | map.data[i * 3 + 1]);
                            }
                            projectm_pcm_add_int16(projectm_instance_, int16_samples.data(), sample_count, PROJECTM_STEREO);
                        }
                
                        gst_buffer_unmap(buffer, &map);
                    }
                
                    gst_buffer_unref(buffer);
                }
                
                jonasJ 1 Reply Last reply Reply Quote 0
                • jonasJ
                  jonas @Gustavo L Conte
                  last edited by

                  @Gustavo-L-Conte
                  Are you still working on the projectM integration, or did you give it up?

                  Gustavo L ConteG 1 Reply Last reply Reply Quote 1
                  • Gustavo L ConteG
                    Gustavo L Conte @jonas
                    last edited by Gustavo L Conte

                    @jonas I would not say that I completely gave up, but I just started a new position in a company so I lost that whole free time to mess with this particular thing

                    I went making https://github.com/guprobr/WakkaQt instead to learn a bit more Qt before resuming this task
                    The last ideas we discussed, I never tried... but the last post on projectM made me feel second toughts on the viability of the idea.... anyway, i want to resume this task someday I don't think we should give up but certainly something is missing in the backend inner parts of how Qt works with OpenGL and how projectM works with OpenGL, as it was discussed on the thread on github.

                    But the first thing i would do is trying with latest Qt LTS, before anything.
                    Second thing, to try with the same version on Windows!
                    We have to figure where the problem is. Obviously its a Qt issue, but what made me stop working on it was when SDL window version showed the same issues. That was very disappointing.

                    PS: sorry to take so long to answer, I just saw this today

                    1 Reply Last reply Reply Quote 1
                    • S
                      sami1099
                      last edited by

                      I'm not sure if necrobumping is allowed, but are there any updates regarding this? Would really love to see milkdrop-like visualisations. When I was on Windows I loved watching them with the foobar2k plugin I had for it. 😃

                      jonasJ 1 Reply Last reply Reply Quote 0
                      • jonasJ
                        jonas @sami1099
                        last edited by

                        @sami1099
                        Only a few presets works, this is an underlying issue with projectM and EGL, not specific to Strawberry.

                        1 Reply Last reply Reply Quote 0
                        • First post
                          Last post
                        Powered by NodeBB | Contributors