Commit 199cb6c9 authored by Leander Schulten's avatar Leander Schulten
Browse files

ColorPlot: Cleanup and improve code. Only render visible area. Update only...

ColorPlot: Cleanup and improve code. Only render visible area. Update only when visible for the user.
ColorPlot UX: The user can now zoom the colorplot.
parent ba4b6c46
Pipeline #188613 passed with stage
in 4 minutes and 44 seconds
......@@ -2,96 +2,143 @@
#include "QSGFlatColorMaterial"
#include <QSGGeometryNode>
#include <QSGVertexColorMaterial>
#include <cmath>
namespace GUI{
namespace GUI {
Colorplot::Colorplot():haveNewData(false)
{
setFlag(ItemHasContents);
lastCreated = this;
Colorplot *Colorplot::lastCreated = nullptr;
Colorplot::Colorplot(QQuickItem *parent) : QQuickItem(parent) {
setFlag(ItemHasContents);
lastCreated = this;
startTimer(15);
}
Colorplot::~Colorplot() {
for (const auto &data : dataBlocks) {
delete[] data;
}
if (lastCreated == this) {
lastCreated = nullptr;
}
}
void Colorplot::startBlock() {
mutex.lock();
if (dataBlocks.size() >= MAX_BLOCKS_COUNT) {
currentBlockCounter = 0;
auto data = dataBlocks.front();
dataBlocks.pop_front();
dataBlocks.push_back(data);
} else {
currentBlockCounter = 0;
const auto blockSize = static_cast<size_t>(this->blockSize);
auto data = new float[blockSize];
memset(data, 0, blockSize * sizeof(float));
dataBlocks.push_back(data);
}
}
Colorplot * Colorplot::lastCreated = nullptr;
void Colorplot::endBlock() {
haveNewData = true;
mutex.unlock();
}
void Colorplot::pushDataToBlock(float d) {
if (currentBlockCounter >= 0) {
dataBlocks.back()[currentBlockCounter] = d; //*0.4f;//std::pow(1+d*0.001,3)*20;
++currentBlockCounter;
if (currentBlockCounter >= blockSize) {
currentBlockCounter = -1;
}
} else {
qDebug() << "Error : currentBlockCounter less then 0";
}
}
void Colorplot::setBlockSize(int size) {
Q_ASSERT(size >= 0);
if (size != this->blockSize) {
for (const auto i : dataBlocks) {
delete[] i;
}
dataBlocks.clear();
currentBlockCounter = -1;
blockSize = size;
}
}
QSGNode * Colorplot::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *){
QSGNode *Colorplot::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData * /*transformNode*/) {
QSGNode *node = nullptr;
QSGGeometryNode *lineNode = nullptr;
QSGGeometry *lineGeometry = nullptr;
mutex.lock();
int size2 = dataBlocks.size() * (blockSize+1);
if (!oldNode) {
node = new QSGNode;
/*{
pointNode = new QSGGeometryNode;
pointGeometry = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), size);
pointGeometry->setLineWidth(2);
pointGeometry->setDrawingMode(QSGGeometry::DrawPoints);
pointNode->setGeometry(pointGeometry);
pointNode->setFlag(QSGNode::OwnsGeometry);
pointNode->setMaterial(new QSGVertexColorMaterial);
pointNode->setFlag(QSGNode::OwnsMaterial);
}
node->appendChildNode(pointNode);*/
{
lineNode = new QSGGeometryNode;
lineGeometry = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), size2);
lineGeometry->setLineWidth(1);
lineGeometry->setDrawingMode(QSGGeometry::DrawLineStrip);
lineNode->setGeometry(lineGeometry);
lineNode->setFlag(QSGNode::OwnsGeometry);
lineNode->setMaterial(new QSGVertexColorMaterial);
lineNode->setFlag(QSGNode::OwnsMaterial);
}
node = new QSGNode;
lineNode = new QSGGeometryNode;
lineGeometry = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), 0);
lineGeometry->setLineWidth(1);
lineGeometry->setDrawingMode(QSGGeometry::DrawLineStrip);
lineNode->setGeometry(lineGeometry);
lineNode->setFlag(QSGNode::OwnsGeometry);
lineNode->setMaterial(new QSGVertexColorMaterial);
lineNode->setFlag(QSGNode::OwnsMaterial);
node->appendChildNode(lineNode);
lineNode->setFlag(QSGNode::OwnedByParent);
node->setFlag(QSGNode::OwnedByParent);
} else {
node = static_cast<QSGNode *>(oldNode);
node = oldNode;
lineNode = dynamic_cast<QSGGeometryNode *>(node->childAtIndex(0));
lineGeometry = lineNode->geometry();
}
/*pointNode = static_cast<QSGGeometryNode *>(node->childAtIndex(0));
pointGeometry = pointNode->geometry();
pointGeometry->allocate(size);*/
mutex.lock();
lineNode = static_cast<QSGGeometryNode *>(node->childAtIndex(0));
lineGeometry = lineNode->geometry();
lineGeometry->allocate(size2);
int x = static_cast<int>(width());
const auto height = static_cast<float>(this->height());
const auto lastVisibleBlock = std::min(static_cast<int>(height / zoom), blockSize);
const auto dataBlocksInWidth = std::min(static_cast<int>(dataBlocks.size()), static_cast<int>(width()));
}
lineGeometry->allocate(dataBlocksInWidth * (lastVisibleBlock + 1));
auto *lines = lineGeometry->vertexDataAsColoredPoint2D();
//QSGGeometry::ColoredPoint2D *points = pointGeometry->vertexDataAsColoredPoint2D();
QSGGeometry::ColoredPoint2D *lines = lineGeometry->vertexDataAsColoredPoint2D();
for (auto blockI = dataBlocks.crbegin(); blockI != dataBlocks.crend(); ++blockI) {
const auto block = *blockI;
--x;
if (x == -1) {
break;
}
const auto currentX = static_cast<float>(x);
int counter = 0;
int x = 0;
for(auto block : dataBlocks){
++x;
lines->x = x + 50;
lines->y = height()-(blockSize-1)*2-1;
lines->x = currentX;
lines->y = height - (static_cast<float>(lastVisibleBlock - 1) * zoom) - 1;
++lines;
for (int i = 0; i < static_cast<int>(blockSize); ++i) {
lines->x = x + 50;
// points->x = x*2;
lines->y /*= points->y*/ = height()-i*2-1;
lines->a /*= points->a*/ = 255;
lines->r /*= points->r*/ = (unsigned char)(block[i]*0.5>255.f?255:block[i]*0.5);
lines->g /*= points->g*/ = (unsigned char)std::min(block[i]*0.2f,255.f);
lines->g /*= points->g*/ = (unsigned char)std::min(block[i]/20*255,255.f);
lines->r /*= points->b*/ = (unsigned char)(block[i]/10 * 255);
++lines; //++points;
++counter;
for (int i = 0; i < lastVisibleBlock; ++i) {
lines->x = currentX;
lines->y = height - static_cast<float>(i) * zoom - 1;
lines->a = 255;
lines->r = static_cast<unsigned char>(block[i] * 0.5f > 255.f ? 255 : block[i] * 0.5f);
lines->g = static_cast<unsigned char>(std::min(block[i] / 20 * 255, 255.f));
lines->r = static_cast<unsigned char>(block[i] / 10 * 255);
++lines;
}
}
//qDebug()<<"counter : " << counter << " size : "<< size << " blocks : "<< dataBlocks.size();
mutex.unlock();
haveNewData = false;
//pointNode->markDirty(QSGNode::DirtyGeometry);
// pointNode->markDirty(QSGNode::DirtyGeometry);
lineNode->markDirty(QSGNode::DirtyGeometry);
return node;
}
void Colorplot::timerEvent(QTimerEvent * /*event*/) {
if (visibleForUser && haveNewData) {
update();
}
}
} // namespace GUI
#ifndef COLORPLOT_H
#define COLORPLOT_H
#include <QQuickItem>
#include <list>
#include <mutex>
namespace GUI{
namespace GUI {
class Colorplot : public QQuickItem
{
class Colorplot : public QQuickItem {
Q_OBJECT
unsigned int blockSize = 0;
std::list<volatile float*> dataBlocks;
std::list<float*> freeBlocks;
int blockSize = 0;
int currentBlockCounter = -1;
QColor lineColor = QColor(0,0,0);
Q_PROPERTY(QColor lineColor READ getLineColor WRITE setLineColor NOTIFY lineColorChanged)
static Colorplot * lastCreated;
std::atomic_bool haveNewData;
const static unsigned int MAX_BLOCKS_COUNT = 900;
float zoom = 1;
bool visibleForUser = true;
std::mutex mutex;
std::list<float *> dataBlocks;
Q_PROPERTY(bool visibleForUser MEMBER visibleForUser NOTIFY visibleForUserChanged)
Q_PROPERTY(float zoom MEMBER zoom NOTIFY zoomChanged)
static Colorplot *lastCreated;
std::atomic_bool haveNewData = false;
const static unsigned int MAX_BLOCKS_COUNT = 900;
public:
Colorplot();
~Colorplot(){
if(lastCreated==this)
lastCreated = nullptr;
}
static Colorplot * getLast(){return lastCreated;}
void startBlock(){
mutex.lock();
if (dataBlocks.size()>=MAX_BLOCKS_COUNT) {
currentBlockCounter = 0;
auto data = dataBlocks.front();
dataBlocks.pop_front();
dataBlocks.push_back(data);
}else{
currentBlockCounter = 0;
auto data = new float[blockSize];
memset(data,0,blockSize*sizeof(float));
dataBlocks.push_back(data);
}
}
void endBlock(){
mutex.unlock();
}
void pushDataToBlock(float d){
if (currentBlockCounter>=0) {
dataBlocks.back()[currentBlockCounter] = d;//*0.4f;//std::pow(1+d*0.001,3)*20;
++currentBlockCounter;
if(currentBlockCounter>=static_cast<int>(blockSize))
currentBlockCounter=-1;
}else
qDebug()<<"Error : currentBlockCounter less then 0";
}
void setBlockSize(unsigned int size){
if(size!=this->blockSize){
for(const auto i : dataBlocks)
delete i;
for(const auto i : freeBlocks)
delete i;
dataBlocks.clear();
freeBlocks.clear();
currentBlockCounter = -1;
blockSize=size;
}
}
void setLineColor(QColor c){lineColor=c;update();lineColorChanged();}
QColor getLineColor(){return lineColor;}
explicit Colorplot(QQuickItem *parent = nullptr);
~Colorplot() override;
Q_DISABLE_COPY_MOVE(Colorplot)
static Colorplot *getLast() { return lastCreated; }
void startBlock();
void endBlock();
void pushDataToBlock(float d);
void setBlockSize(int size);
protected:
virtual QSGNode * updatePaintNode(QSGNode *, UpdatePaintNodeData *)override;
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *transformNode) override;
void timerEvent(QTimerEvent *event) override;
signals:
void lineColorChanged();
public slots:
void visibleForUserChanged();
void zoomChanged();
};
} // namespace GUI
......
......@@ -327,17 +327,6 @@ int main(int argc, char *argv[]) {
driver.start();
#endif
QTimer timer;
timer.setInterval(15);
QObject::connect(&timer, &QTimer::timeout, [&]() {
if (Audio::AudioCaptureManager::get().isCapturing()) {
if (Colorplot::getLast()) {
Colorplot::getLast()->update();
}
}
});
timer.start();
qDebug() << "start capturing : " << Audio::AudioCaptureManager::get().startCapturing(settings.getAudioCaptureFilePath());
Modules::ModuleManager::singletone()->controller().start();
......
......@@ -240,7 +240,20 @@ ApplicationWindow {
visibleForUser: SwipeView.isCurrentItem
}
Colorplot{}
Colorplot{
visibleForUser: SwipeView.isCurrentItem
Slider{
anchors.left: parent.left
anchors.top: parent.top
anchors.topMargin: 50
anchors.leftMargin: 20
orientation: Qt.Vertical
from: .5
value: 1
to: 2
onValueChanged: parent.zoom = value
}
}
AudioEventsView{
visibleForUser: SwipeView.isCurrentItem
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment