From: Steinar H. Gunderson Date: Mon, 14 Nov 2022 23:07:06 +0000 (+0100) Subject: Remove the QCustomPlot dependency. X-Git-Tag: 2.2.0~1 X-Git-Url: https://git.sesse.net/?p=nageru;a=commitdiff_plain;h=5e77e932e6a5795882ecba1b3f62a26523863179 Remove the QCustomPlot dependency. This was becoming more a liability than an asset, so replace it with some custom drawing code. It's not 100% as nice, but pretty close. --- diff --git a/README b/README index a565b39..b4a6291 100644 --- a/README +++ b/README @@ -53,8 +53,6 @@ Nageru currently needs: - Qt 5.5 or newer for the GUI. - - QCustomPlot for the histogram display in the frame analyzer. - - libmicrohttpd for the embedded web server. - x264 for encoding high-quality video suitable for streaming to end users. @@ -114,7 +112,7 @@ Futatabi also needs: If on Debian bullsey or something similar, you can install everything you need with: - apt install qtbase5-dev libqt5opengl5-dev qt5-default libqcustomplot-dev \ + apt install qtbase5-dev libqt5opengl5-dev qt5-default \ pkg-config libmicrohttpd-dev libusb-1.0-0-dev libluajit-5.1-dev \ libzita-resampler-dev libva-dev libavcodec-dev libavformat-dev \ libswscale-dev libavresample-dev libmovit-dev libegl1-mesa-dev \ diff --git a/meson.build b/meson.build index a7ea6ae..c41990f 100644 --- a/meson.build +++ b/meson.build @@ -22,7 +22,6 @@ libusbdep = dependency('libusb-1.0') luajitdep = dependency('luajit') movitdep = dependency('movit') protobufdep = dependency('protobuf') -qcustomplotdep = cxx.find_library('qcustomplot') qt5deps = dependency('qt5', modules: ['Core', 'Gui', 'Widgets', 'OpenGLExtensions', 'OpenGL', 'Network']) sdl2_imagedep = dependency('SDL2_image', required: false) sdl2dep = dependency('sdl2', required: false) @@ -78,7 +77,7 @@ nageru_srcs = [] nageru_deps = [shareddep, qt5deps, libjpegdep, movitdep, protobufdep, vax11dep, vadrmdep, x11dep, libavformatdep, libswresampledep, libavcodecdep, libavutildep, libswscaledep, libusbdep, luajitdep, dldep, x264dep, svtav1dep, alsadep, zitaresamplerdep, - qcustomplotdep, threaddep, eigendep, srtdep, libdrmdep] + threaddep, eigendep, srtdep, libdrmdep] nageru_include_dirs = [include_directories('nageru')] nageru_link_with = [] nageru_build_rpath = '' @@ -189,7 +188,7 @@ nageru_link_with += protobuf_lib qt_files = qt5.preprocess( moc_headers: ['nageru/analyzer.h', 'nageru/clickable_label.h', 'nageru/compression_reduction_meter.h', 'nageru/correlation_meter.h', 'nageru/ellipsis_label.h', 'nageru/glwidget.h', 'nageru/input_mapping_dialog.h', 'nageru/lrameter.h', 'nageru/mainwindow.h', 'nageru/midi_mapping_dialog.h', - 'nageru/nonlinear_fader.h', 'nageru/vumeter.h'], + 'nageru/nonlinear_fader.h', 'nageru/vumeter.h', 'nageru/rgb_histogram.h'], ui_files: ['nageru/analyzer.ui', 'nageru/audio_expanded_view.ui', 'nageru/audio_miniview.ui', 'nageru/display.ui', 'nageru/input_mapping.ui', 'nageru/mainwindow.ui', 'nageru/midi_mapping.ui'], dependencies: qt5deps) @@ -197,7 +196,7 @@ qt_files = qt5.preprocess( # Qt objects. nageru_srcs += ['nageru/glwidget.cpp', 'nageru/mainwindow.cpp', 'nageru/vumeter.cpp', 'nageru/lrameter.cpp', 'nageru/compression_reduction_meter.cpp', 'nageru/correlation_meter.cpp', 'nageru/analyzer.cpp', 'nageru/input_mapping_dialog.cpp', 'nageru/midi_mapping_dialog.cpp', - 'nageru/nonlinear_fader.cpp', 'nageru/context_menus.cpp', 'nageru/vu_common.cpp', 'nageru/piecewise_interpolator.cpp', 'nageru/midi_mapper.cpp'] + 'nageru/nonlinear_fader.cpp', 'nageru/context_menus.cpp', 'nageru/vu_common.cpp', 'nageru/piecewise_interpolator.cpp', 'nageru/midi_mapper.cpp', 'nageru/rgb_histogram.cpp'] # Auxiliary objects used for nearly everything. aux_srcs = ['nageru/flags.cpp'] diff --git a/nageru/analyzer.cpp b/nageru/analyzer.cpp index f2d3ae6..d8197cc 100644 --- a/nageru/analyzer.cpp +++ b/nageru/analyzer.cpp @@ -14,21 +14,6 @@ #include "mixer.h" #include "ui_analyzer.h" -// QCustomPlot includes qopenglfunctions.h, which #undefs all of the epoxy -// definitions (ugh) and doesn't put back any others (ugh). Add the ones we -// need back. - -#define glBindBuffer epoxy_glBindBuffer -#define glBindFramebuffer epoxy_glBindFramebuffer -#define glBufferData epoxy_glBufferData -#define glDeleteBuffers epoxy_glDeleteBuffers -#define glDisable epoxy_glDisable -#define glGenBuffers epoxy_glGenBuffers -#define glGetError epoxy_glGetError -#define glReadPixels epoxy_glReadPixels -#define glUnmapBuffer epoxy_glUnmapBuffer -#define glWaitSync epoxy_glWaitSync - using namespace std; Analyzer::Analyzer() @@ -70,10 +55,6 @@ Analyzer::Analyzer() glGenBuffers(1, &pbo); glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo); glBufferData(GL_PIXEL_PACK_BUFFER_ARB, global_flags.width * global_flags.height * 4, nullptr, GL_STREAM_READ); - - ui->histogram->xAxis->setVisible(true); - ui->histogram->yAxis->setVisible(false); - ui->histogram->xAxis->setRange(0, 255); } Analyzer::~Analyzer() @@ -186,38 +167,14 @@ void Analyzer::grab_clicked() glBindFramebuffer(GL_FRAMEBUFFER, 0); check_error(); - QVector r_vec(256), g_vec(256), b_vec(256), x_vec(256); - double max = 0.0; + vector r_vec(256), g_vec(256), b_vec(256); for (unsigned i = 0; i < 256; ++i) { - x_vec[i] = i; r_vec[i] = log(r_hist[i] + 1.0); g_vec[i] = log(g_hist[i] + 1.0); b_vec[i] = log(b_hist[i] + 1.0); - - max = std::max(max, r_vec[i]); - max = std::max(max, g_vec[i]); - max = std::max(max, b_vec[i]); } - ui->histogram->clearGraphs(); - ui->histogram->addGraph(); - ui->histogram->graph(0)->setData(x_vec, r_vec); - ui->histogram->graph(0)->setPen(QPen(Qt::red)); - ui->histogram->graph(0)->setBrush(QBrush(QColor(255, 127, 127, 80))); - ui->histogram->addGraph(); - ui->histogram->graph(1)->setData(x_vec, g_vec); - ui->histogram->graph(1)->setPen(QPen(Qt::green)); - ui->histogram->graph(1)->setBrush(QBrush(QColor(127, 255, 127, 80))); - ui->histogram->addGraph(); - ui->histogram->graph(2)->setData(x_vec, b_vec); - ui->histogram->graph(2)->setPen(QPen(Qt::blue)); - ui->histogram->graph(2)->setBrush(QBrush(QColor(127, 127, 255, 80))); - - ui->histogram->xAxis->setVisible(true); - ui->histogram->yAxis->setVisible(false); - ui->histogram->xAxis->setRange(0, 255); - ui->histogram->yAxis->setRange(0, max); - ui->histogram->replot(); + ui->histogram->set_histograms(std::move(r_vec), std::move(g_vec), std::move(b_vec)); resource_pool->release_2d_texture(fbo_tex); check_error(); diff --git a/nageru/analyzer.ui b/nageru/analyzer.ui index 9cf137e..be467de 100644 --- a/nageru/analyzer.ui +++ b/nageru/analyzer.ui @@ -105,7 +105,7 @@ - + false @@ -355,9 +355,9 @@
glwidget.h
- QCustomPlot + RGBHistogram QWidget -
qcustomplot.h
+
rgb_histogram.h
1
diff --git a/nageru/rgb_histogram.cpp b/nageru/rgb_histogram.cpp new file mode 100644 index 0000000..fb1a0ca --- /dev/null +++ b/nageru/rgb_histogram.cpp @@ -0,0 +1,94 @@ +#include "rgb_histogram.h" + +#include +#include + +class QPaintEvent; +class QResizeEvent; + +using namespace std; + +static constexpr int margin_left = 16; +static constexpr int margin_top = 14; +static constexpr int margin_right = 14; +static constexpr int margin_bottom = 25; + +RGBHistogram::RGBHistogram(QWidget *parent) + : QWidget(parent), red(256, 0.0), green(256, 0.0), blue(256, 0.0) +{ +} + +void RGBHistogram::set_histograms(std::vector red, std::vector green, std::vector blue) +{ + assert(red.size() == 256); + assert(green.size() == 256); + assert(blue.size() == 256); + this->red = std::move(red); + this->green = std::move(green); + this->blue = std::move(blue); + repaint(); +} + +void RGBHistogram::paintEvent(QPaintEvent *event) +{ + QPainter painter(this); + painter.fillRect(0, 0, width(), height(), Qt::white); + painter.setRenderHints(QPainter::Antialiasing); + + double max = 0.0; + for (unsigned i = 0; i < 256; ++i) { + max = std::max(max, red[i]); + max = std::max(max, green[i]); + max = std::max(max, blue[i]); + } + + // Draw the graphs. (We'd like to get rid of the bottom line, but that's just cosmetic.) + painter.setPen(QPen(Qt::red)); + painter.setBrush(QBrush(QColor(255, 127, 127, 80))); + draw(red, max, Qt::GlobalColor::red, &painter); + + painter.setPen(QPen(Qt::green)); + painter.setBrush(QBrush(QColor(127, 255, 127, 80))); + draw(green, max, Qt::GlobalColor::green, &painter); + + painter.setPen(QPen(Qt::blue)); + painter.setBrush(QBrush(QColor(127, 127, 255, 80))); + draw(blue, max, Qt::GlobalColor::blue, &painter); + + // Draw the tick lines. + int w = (width() - 1) - margin_left - margin_right; + painter.setPen(QPen(Qt::black)); + painter.setBrush(QBrush()); + for (int i = 0; i < 256; i += 10) { + int th = (i % 50 == 0) ? 5 : 2; + double x = (i / 255.0) * w + margin_left; + double y = (height() - 1) - margin_top - margin_bottom; + painter.drawLine(QPointF(x, y + margin_top), QPointF(x, y + margin_top - th)); + } + + // And the axis labels. + for (int i = 0; i < 256; i += 50) { + char buf[16]; + snprintf(buf, sizeof(buf), "%d", i); + + double x = (i / 255.0) * w + margin_left; + double y = (height() - 1) - margin_top - margin_bottom; + painter.drawText(QRectF(x - 20, y + margin_top, 40, margin_bottom), Qt::AlignCenter | Qt::AlignTop, QString(buf)); + } +} + +void RGBHistogram::draw(const vector &v, double max, Qt::GlobalColor color, QPainter *painter) +{ + int w = (width() - 1) - margin_left - margin_right; + int h = (height() - 1) - margin_top - margin_bottom; + + QPointF points[258]; + points[0] = QPointF(margin_left, margin_top + h); + for (int i = 0; i < 256; ++i) { + double x = (i / 255.0) * w + margin_left; + double y = (1.0 - (v[i] / max)) * h + margin_top; + points[i + 1] = QPointF(x, y); + } + points[257] = QPointF(margin_left + w, margin_top + h); + painter->drawPolygon(points, 258); +} diff --git a/nageru/rgb_histogram.h b/nageru/rgb_histogram.h new file mode 100644 index 0000000..9dce2e6 --- /dev/null +++ b/nageru/rgb_histogram.h @@ -0,0 +1,30 @@ +#ifndef RGB_HISTOGRAM_H +#define RGB_HISTOGRAM_H + +#include +#include +#include +#include + +#include "vu_common.h" + +class QObject; +class QPaintEvent; +class QResizeEvent; + +class RGBHistogram : public QWidget +{ + Q_OBJECT + +public: + RGBHistogram(QWidget *parent); + void set_histograms(std::vector red, std::vector green, std::vector blue); + +private: + void paintEvent(QPaintEvent *event) override; + void draw(const std::vector &v, double max, Qt::GlobalColor color, QPainter *painter); + + std::vector red, green, blue; +}; + +#endif