Improved controls with menus
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
// Qt includes
|
||||
#include <QIODevice>
|
||||
#include <QAudioInput>
|
||||
#include <QDebug>
|
||||
|
||||
namespace {
|
||||
//! private helper to allow QAudioInput to write to a io device
|
||||
@@ -10,6 +11,7 @@ class AudioDeviceHelper : public QIODevice
|
||||
{
|
||||
public:
|
||||
explicit AudioDeviceHelper(AudioDevice &audioDevice);
|
||||
~AudioDeviceHelper();
|
||||
|
||||
qint64 readData(char *data, qint64 maxlen) override;
|
||||
qint64 writeData(const char *data, qint64 len) override;
|
||||
@@ -17,11 +19,26 @@ public:
|
||||
private:
|
||||
AudioDevice &m_audioDevice;
|
||||
};
|
||||
|
||||
struct AudioDevicePrivate {
|
||||
AudioDevicePrivate(AudioDevice &audioDevice, const QAudioDeviceInfo &audioDeviceInfo, const QAudioFormat &format) :
|
||||
helper(audioDevice), input(audioDeviceInfo, format)
|
||||
{
|
||||
qDebug() << audioDeviceInfo.deviceName();
|
||||
}
|
||||
|
||||
~AudioDevicePrivate()
|
||||
{
|
||||
qDebug() << "called";
|
||||
}
|
||||
|
||||
AudioDeviceHelper helper;
|
||||
QAudioInput input;
|
||||
};
|
||||
}
|
||||
|
||||
AudioDevice::AudioDevice(QObject *parent) :
|
||||
BaseDevice{parent},
|
||||
m_helper(std::make_unique<AudioDeviceHelper>(*this))
|
||||
BaseDevice{parent}
|
||||
{
|
||||
}
|
||||
|
||||
@@ -29,6 +46,8 @@ AudioDevice::~AudioDevice() = default;
|
||||
|
||||
void AudioDevice::start()
|
||||
{
|
||||
qDebug() << m_device.deviceName();
|
||||
|
||||
QAudioFormat format;
|
||||
format.setSampleRate(m_samplerate);
|
||||
format.setChannelCount(2);
|
||||
@@ -37,14 +56,15 @@ void AudioDevice::start()
|
||||
format.setCodec("audio/pcm");
|
||||
format.setByteOrder(QAudioFormat::LittleEndian);
|
||||
|
||||
m_input = std::make_unique<QAudioInput>(m_device, format);
|
||||
m_input->start(m_helper.get());
|
||||
m_input->setBufferSize(m_samplerate/m_framerate*sizeof(qint16)*2);
|
||||
m_private = std::make_unique<AudioDevicePrivate>(*this, m_device, format);
|
||||
m_private->input.start(&m_private->helper);
|
||||
//m_private->input.setBufferSize(m_samplerate/m_framerate*sizeof(qint16)*2);
|
||||
}
|
||||
|
||||
void AudioDevice::stop()
|
||||
{
|
||||
m_input = nullptr;
|
||||
qDebug() << "called";
|
||||
m_private = nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,9 +74,15 @@ AudioDeviceHelper::AudioDeviceHelper(AudioDevice &audioDevice) :
|
||||
QIODevice(&audioDevice),
|
||||
m_audioDevice(audioDevice)
|
||||
{
|
||||
qDebug() << "called";
|
||||
setOpenMode(QIODevice::WriteOnly);
|
||||
}
|
||||
|
||||
AudioDeviceHelper::~AudioDeviceHelper()
|
||||
{
|
||||
qDebug() << "called";
|
||||
}
|
||||
|
||||
qint64 AudioDeviceHelper::readData(char *data, qint64 maxlen)
|
||||
{
|
||||
Q_UNUSED(data)
|
||||
|
@@ -9,7 +9,7 @@
|
||||
#include <memory>
|
||||
|
||||
// forward declares
|
||||
namespace { class AudioDeviceHelper; }
|
||||
namespace { class AudioDevicePrivate; }
|
||||
class QAudioInput;
|
||||
|
||||
class AudioDevice : public BaseDevice
|
||||
@@ -22,24 +22,18 @@ public:
|
||||
|
||||
void start() override;
|
||||
void stop() override;
|
||||
bool running() const override { return m_input != nullptr; }
|
||||
bool running() const override { return m_private != nullptr; }
|
||||
|
||||
int samplerate() const override { return m_samplerate; }
|
||||
void setSamplerate(int samplerate) override { Q_ASSERT(!running()); m_samplerate = samplerate; }
|
||||
|
||||
int framerate() const override { return m_framerate; }
|
||||
void setFramerate(int framerate) override { Q_ASSERT(!running()); m_framerate = framerate; }
|
||||
|
||||
const auto &device() const { return m_device; }
|
||||
void setDevice(const QAudioDeviceInfo &device) { Q_ASSERT(!running()); m_device = device; }
|
||||
|
||||
private:
|
||||
const std::unique_ptr<AudioDeviceHelper> m_helper;
|
||||
|
||||
std::unique_ptr<QAudioInput> m_input;
|
||||
std::unique_ptr<AudioDevicePrivate> m_private;
|
||||
|
||||
int m_samplerate;
|
||||
int m_framerate;
|
||||
|
||||
QAudioDeviceInfo m_device;
|
||||
};
|
||||
|
@@ -18,9 +18,6 @@ public:
|
||||
virtual int samplerate() const = 0;
|
||||
virtual void setSamplerate(int samplerate) = 0;
|
||||
|
||||
virtual int framerate() const = 0;
|
||||
virtual void setFramerate(int framerate) = 0;
|
||||
|
||||
signals:
|
||||
void samplesReceived(const SamplePair *begin, const SamplePair *end);
|
||||
};
|
||||
|
@@ -19,8 +19,8 @@ public:
|
||||
int samplerate() const override { return m_samplerate; }
|
||||
void setSamplerate(int samplerate) override { Q_ASSERT(!running()); m_samplerate = samplerate; }
|
||||
|
||||
int framerate() const override { return m_framerate; }
|
||||
void setFramerate(int framerate) override { Q_ASSERT(!running()); m_framerate = framerate; }
|
||||
int framerate() const { return m_framerate; }
|
||||
void setFramerate(int framerate) { Q_ASSERT(!running()); m_framerate = framerate; }
|
||||
|
||||
protected:
|
||||
void timerEvent(QTimerEvent *event) override;
|
||||
|
170
mainwindow.cpp
170
mainwindow.cpp
@@ -6,88 +6,164 @@
|
||||
#include <QMessageBox>
|
||||
#include <QStringBuilder>
|
||||
#include <QRadioButton>
|
||||
#include <QLabel>
|
||||
#include <QDebug>
|
||||
|
||||
// local includes
|
||||
#include "audiodevice.h"
|
||||
#include "fakedevice.h"
|
||||
|
||||
namespace {
|
||||
constexpr int samplerates[] = { 44100, 48000, 96000, 192000 };
|
||||
|
||||
constexpr int refreshrates[] = { 15, 30, 50, 60 };
|
||||
|
||||
constexpr int zoomlevels[] = { 50, 75, 100, 200, 400, 800 };
|
||||
|
||||
template<typename T>
|
||||
void setActionsEnabled(const T &actions, bool enabled)
|
||||
{
|
||||
for(auto action : actions)
|
||||
action->setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow{parent},
|
||||
m_ui{std::make_unique<Ui::MainWindow>()},
|
||||
m_audioDevices{QAudioDeviceInfo::availableDevices(QAudio::AudioInput)},
|
||||
m_input{std::make_unique<AudioDevice>()}
|
||||
//m_input{std::make_unique<FakeDevice>()}
|
||||
m_statusLabel{*new QLabel}
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
connect(m_input.get(), &BaseDevice::samplesReceived, m_ui->widget, &OsciWidget::renderSamples);
|
||||
m_ui->statusbar->addWidget(&m_statusLabel);
|
||||
|
||||
connect(m_ui->widget, &OsciWidget::statusUpdate, &m_statusLabel, &QLabel::setText);
|
||||
|
||||
// setting up menu File
|
||||
connect(m_ui->actionStart, &QAction::triggered, this, &MainWindow::start);
|
||||
connect(m_ui->actionStop, &QAction::triggered, this, &MainWindow::stop);
|
||||
m_ui->action_Quit->setShortcut(QKeySequence::Quit);
|
||||
|
||||
// setting up menu Devices
|
||||
for (const auto &device : m_audioDevices)
|
||||
{
|
||||
auto name = device.deviceName();
|
||||
m_ui->comboBoxDevices->addItem(name);
|
||||
const auto action = m_ui->menu_Device->addAction(name);
|
||||
action->setCheckable(true);
|
||||
m_deviceGroup.addAction(action);
|
||||
|
||||
// Select last element containing monitor if available
|
||||
if(name.contains("monitor"))
|
||||
{
|
||||
m_ui->comboBoxDevices->setCurrentIndex(m_ui->comboBoxDevices->count()-1);
|
||||
}
|
||||
action->setChecked(true);
|
||||
}
|
||||
|
||||
for (const auto samplerate : { 44100, 48000, 96000, 192000 })
|
||||
m_ui->comboBoxSamplerate->addItem(tr("%0").arg(samplerate), samplerate);
|
||||
|
||||
connect(m_ui->pushButtonToggle, &QAbstractButton::pressed, this, &MainWindow::toggle);
|
||||
|
||||
for (const auto framerate : {15, 30, 50, 60})
|
||||
m_ui->comboBoxFps->addItem(tr("%0 FPS").arg(framerate), framerate);
|
||||
|
||||
connect(m_ui->comboBoxFps, qOverload<int>(&QComboBox::currentIndexChanged), m_ui->widget, [this](){
|
||||
m_ui->widget->setFps(m_ui->comboBoxFps->currentData().toInt());
|
||||
});
|
||||
|
||||
auto buttonGroup = new QButtonGroup;
|
||||
buttonGroup->setExclusive(true);
|
||||
for (auto factor : { .5f, 1.f, 2.f, 4.f, 8.f })
|
||||
// setting up menu Samplerates
|
||||
for (const auto samplerate : samplerates)
|
||||
{
|
||||
auto radioButton = new QRadioButton(QString::number(factor));
|
||||
connect(radioButton, &QRadioButton::pressed, this, [factor,&widget=*m_ui->widget](){
|
||||
widget.setFactor(factor);
|
||||
});
|
||||
m_ui->horizontalLayout->addWidget(radioButton);
|
||||
auto action = m_ui->menu_Samplerate->addAction(tr("%0").arg(samplerate));
|
||||
action->setCheckable(true);
|
||||
m_samplerateGroup.addAction(action);
|
||||
}
|
||||
|
||||
if (m_ui->comboBoxDevices->count())
|
||||
toggle();
|
||||
}
|
||||
m_samplerateGroup.actions().first()->setChecked(true);
|
||||
|
||||
void MainWindow::toggle()
|
||||
{
|
||||
if (!m_ui->comboBoxDevices->count())
|
||||
// setting up menu Refreshrates
|
||||
for (const auto refreshrate : refreshrates)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Failed to start!"), tr("Failed to start!") % "\n\n" % tr("No audio devices available!"));
|
||||
return;
|
||||
auto action = m_ui->menu_Refreshrate->addAction(tr("%0FPS").arg(refreshrate));
|
||||
action->setCheckable(true);
|
||||
m_refreshrateGroup.addAction(action);
|
||||
}
|
||||
|
||||
if (m_input->running())
|
||||
{
|
||||
m_input->stop();
|
||||
m_ui->comboBoxDevices->setEnabled(true);
|
||||
m_ui->comboBoxSamplerate->setEnabled(true);
|
||||
m_ui->pushButtonToggle->setText("▶");
|
||||
const auto index = std::find(std::begin(refreshrates), std::end(refreshrates), m_ui->widget->fps());
|
||||
if (index != std::end(refreshrates))
|
||||
m_refreshrateGroup.actions().at(std::distance(std::begin(refreshrates), index))->setChecked(true);
|
||||
}
|
||||
|
||||
connect(&m_refreshrateGroup, &QActionGroup::triggered, this, &MainWindow::refreshRateChanged);
|
||||
|
||||
// setting up menu Zoom
|
||||
for (const auto zoomlevel : zoomlevels)
|
||||
{
|
||||
auto action = m_ui->menu_Zoom->addAction(tr("%0%").arg(zoomlevel));
|
||||
action->setCheckable(true);
|
||||
m_zoomlevelsGroup.addAction(action);
|
||||
}
|
||||
|
||||
{
|
||||
const auto index = std::find(std::begin(zoomlevels), std::end(zoomlevels), m_ui->widget->factor()*100);
|
||||
if (index != std::end(zoomlevels))
|
||||
m_zoomlevelsGroup.actions().at(std::distance(std::begin(zoomlevels), index))->setChecked(true);
|
||||
}
|
||||
|
||||
connect(&m_zoomlevelsGroup, &QActionGroup::triggered, this, &MainWindow::zoomChanged);
|
||||
|
||||
// autostart
|
||||
if (m_audioDevices.isEmpty())
|
||||
{
|
||||
m_ui->actionStart->setEnabled(false);
|
||||
m_ui->actionStop->setEnabled(false);
|
||||
}
|
||||
else
|
||||
start();
|
||||
}
|
||||
|
||||
void MainWindow::start()
|
||||
{
|
||||
m_input = std::make_unique<AudioDevice>();
|
||||
//m_input = std::make_unique<FakeDevice>();
|
||||
|
||||
{
|
||||
m_input->setSamplerate(m_ui->comboBoxSamplerate->currentData().toInt());
|
||||
m_input->setFramerate(60);
|
||||
auto *checked = m_samplerateGroup.checkedAction();
|
||||
const auto index = m_samplerateGroup.actions().indexOf(checked);
|
||||
const auto samplerate = samplerates[index];
|
||||
qDebug() << "samplerate: checked =" << checked << "index =" << index << "value =" << samplerate;
|
||||
m_input->setSamplerate(samplerate);
|
||||
}
|
||||
|
||||
connect(m_input.get(), &BaseDevice::samplesReceived, m_ui->widget, &OsciWidget::renderSamples);
|
||||
|
||||
if (auto audioDevice = dynamic_cast<AudioDevice*>(m_input.get()))
|
||||
audioDevice->setDevice(m_audioDevices.at(m_ui->comboBoxDevices->currentIndex()));
|
||||
{
|
||||
const auto device = m_audioDevices.at(m_deviceGroup.actions().indexOf(m_deviceGroup.checkedAction()));
|
||||
qDebug() << "setDevice" << device.deviceName();
|
||||
audioDevice->setDevice(device);
|
||||
}
|
||||
m_input->start();
|
||||
|
||||
m_ui->comboBoxDevices->setEnabled(false);
|
||||
m_ui->comboBoxSamplerate->setEnabled(false);
|
||||
m_ui->pushButtonToggle->setText("▮▮");
|
||||
}
|
||||
setActionsEnabled(m_deviceGroup.actions(), false);
|
||||
setActionsEnabled(m_samplerateGroup.actions(), false);
|
||||
m_ui->actionStart->setEnabled(false);
|
||||
m_ui->actionStop->setEnabled(true);
|
||||
}
|
||||
|
||||
void MainWindow::stop()
|
||||
{
|
||||
m_input = nullptr;
|
||||
setActionsEnabled(m_deviceGroup.actions(), true);
|
||||
setActionsEnabled(m_samplerateGroup.actions(), true);
|
||||
m_ui->actionStart->setEnabled(true);
|
||||
m_ui->actionStop->setEnabled(false);
|
||||
}
|
||||
|
||||
void MainWindow::refreshRateChanged()
|
||||
{
|
||||
auto *checked = m_refreshrateGroup.checkedAction();
|
||||
const auto index = m_refreshrateGroup.actions().indexOf(checked);
|
||||
const auto refreshrate = refreshrates[index];
|
||||
qDebug() << "refreshrate: checked =" << checked << "index =" << index << "value =" << refreshrate;
|
||||
m_ui->widget->setFps(refreshrate);
|
||||
}
|
||||
|
||||
void MainWindow::zoomChanged()
|
||||
{
|
||||
auto *checked = m_zoomlevelsGroup.checkedAction();
|
||||
const auto index = m_zoomlevelsGroup.actions().indexOf(checked);
|
||||
const auto zoomlevel = zoomlevels[index];
|
||||
qDebug() << "zoomlevel: checked =" << checked << "index =" << index << "value =" << zoomlevel;
|
||||
m_ui->widget->setFactor(zoomlevel/100.f);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() = default;
|
||||
|
13
mainwindow.h
13
mainwindow.h
@@ -2,12 +2,14 @@
|
||||
|
||||
// Qt includes
|
||||
#include <QMainWindow>
|
||||
#include <QActionGroup>
|
||||
|
||||
// system includes
|
||||
#include <memory>
|
||||
|
||||
// forward declares
|
||||
class QAudioDeviceInfo;
|
||||
class QLabel;
|
||||
namespace Ui { class MainWindow; }
|
||||
class BaseDevice;
|
||||
|
||||
@@ -20,12 +22,19 @@ public:
|
||||
~MainWindow() override;
|
||||
|
||||
private slots:
|
||||
void toggle();
|
||||
void start();
|
||||
void stop();
|
||||
void refreshRateChanged();
|
||||
void zoomChanged();
|
||||
|
||||
private:
|
||||
const std::unique_ptr<Ui::MainWindow> m_ui;
|
||||
|
||||
const QList<QAudioDeviceInfo> m_audioDevices;
|
||||
|
||||
const std::unique_ptr<BaseDevice> m_input;
|
||||
std::unique_ptr<BaseDevice> m_input;
|
||||
|
||||
QActionGroup m_deviceGroup{this}, m_samplerateGroup{this}, m_refreshrateGroup{this}, m_zoomlevelsGroup{this};
|
||||
|
||||
QLabel &m_statusLabel;
|
||||
};
|
||||
|
137
mainwindow.ui
137
mainwindow.ui
@@ -13,65 +13,7 @@
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelDevice">
|
||||
<property name="text">
|
||||
<string>Device:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxDevices"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxSamplerate"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxFps"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonToggle">
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="OsciWidget" name="widget" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="OsciWidget" name="widget"/>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
@@ -81,19 +23,57 @@
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_File">
|
||||
<property name="title">
|
||||
<string>&File</string>
|
||||
</property>
|
||||
<addaction name="actionStart"/>
|
||||
<addaction name="actionStop"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_Quit"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Device">
|
||||
<property name="title">
|
||||
<string>&Device</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Samplerate">
|
||||
<property name="title">
|
||||
<string>&Samplerate</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Refreshrate">
|
||||
<property name="title">
|
||||
<string>&Refreshrate</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Zoom">
|
||||
<property name="title">
|
||||
<string>&Zoom</string>
|
||||
</property>
|
||||
</widget>
|
||||
<addaction name="menu_File"/>
|
||||
<addaction name="menu_Device"/>
|
||||
<addaction name="menu_Samplerate"/>
|
||||
<addaction name="menu_Refreshrate"/>
|
||||
<addaction name="menu_Zoom"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<widget class="QToolBar" name="toolBar">
|
||||
<property name="windowTitle">
|
||||
<string>toolBar</string>
|
||||
<action name="action_Quit">
|
||||
<property name="text">
|
||||
<string>&Quit</string>
|
||||
</property>
|
||||
<attribute name="toolBarArea">
|
||||
<enum>TopToolBarArea</enum>
|
||||
</attribute>
|
||||
<attribute name="toolBarBreak">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</action>
|
||||
<action name="actionStart">
|
||||
<property name="text">
|
||||
<string>Start</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionStop">
|
||||
<property name="text">
|
||||
<string>Stop</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
@@ -104,5 +84,22 @@
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>action_Quit</sender>
|
||||
<signal>triggered()</signal>
|
||||
<receiver>MainWindow</receiver>
|
||||
<slot>close()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>399</x>
|
||||
<y>429</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
@@ -5,6 +5,7 @@
|
||||
|
||||
template<typename T>
|
||||
struct SamplePairT {
|
||||
typedef T Type;
|
||||
T first, second;
|
||||
};
|
||||
|
||||
|
@@ -11,7 +11,7 @@ OsciWidget::OsciWidget(QWidget *parent) :
|
||||
QOpenGLWidget{parent},
|
||||
m_redrawTimerId(startTimer(1000/m_fps))
|
||||
{
|
||||
m_fpsTimer.start();
|
||||
m_statsTimer.start();
|
||||
}
|
||||
|
||||
void OsciWidget::setFps(int fps)
|
||||
@@ -35,30 +35,35 @@ void OsciWidget::paintEvent(QPaintEvent *event)
|
||||
QWidget::paintEvent(event);
|
||||
|
||||
m_frameCounter++;
|
||||
if (m_fpsTimer.hasExpired(1000))
|
||||
if (m_statsTimer.hasExpired(1000))
|
||||
{
|
||||
m_statsDisplay = QString("%0FPS (%1 callbacks)").arg(m_frameCounter).arg(m_callbacksCounter);
|
||||
emit statusUpdate(QString("%0FPS (%1 audio callbacks)").arg(m_frameCounter).arg(m_callbacksCounter));
|
||||
m_frameCounter = 0;
|
||||
m_callbacksCounter = 0;
|
||||
m_fpsTimer.restart();
|
||||
m_statsTimer.restart();
|
||||
}
|
||||
|
||||
QPainter painter;
|
||||
painter.begin(this);
|
||||
if (m_pixmap.size() != size())
|
||||
m_pixmap = QPixmap(size());
|
||||
|
||||
// draw background
|
||||
painter.setBrush(Qt::black);
|
||||
painter.drawRect(rect());
|
||||
QPainter painter;
|
||||
painter.begin(&m_pixmap);
|
||||
|
||||
// darkening last frame
|
||||
painter.setCompositionMode(QPainter::CompositionMode_Multiply);
|
||||
painter.setPen({});
|
||||
painter.setBrush(QColor(150,150,150 ));
|
||||
painter.drawRect(m_pixmap.rect());
|
||||
|
||||
// drawing new lines ontop
|
||||
QPen pen;
|
||||
pen.setWidth(2);
|
||||
pen.setColor(QColor(0, 255, 0));
|
||||
painter.setPen(pen);
|
||||
painter.translate(width()/2, height()/2);
|
||||
painter.translate(m_pixmap.width()/2, m_pixmap.height()/2);
|
||||
painter.setCompositionMode(QPainter::CompositionMode_Plus);
|
||||
|
||||
const auto pointToCoordinates = [width=width()/2,height=height()/2,factor=m_factor](const QPointF &point)
|
||||
const auto pointToCoordinates = [width=m_pixmap.width()/2,height=m_pixmap.height()/2,factor=m_factor](const QPointF &point)
|
||||
{
|
||||
return QPoint{
|
||||
int(point.x() * factor * width),
|
||||
@@ -75,26 +80,23 @@ void OsciWidget::paintEvent(QPaintEvent *event)
|
||||
|
||||
const QLineF line(m_lastPoint, p);
|
||||
|
||||
painter.setOpacity(std::min(1.0, 1. / ((line.length() * 100) + 1)));
|
||||
painter.setOpacity(std::min(1.0, 1. / ((line.length() * 75) + 1)));
|
||||
|
||||
painter.drawLine(pointToCoordinates(m_lastPoint), pointToCoordinates(p));
|
||||
|
||||
m_lastPoint = p;
|
||||
}
|
||||
|
||||
painter.resetTransform();
|
||||
painter.setOpacity(1);
|
||||
|
||||
m_buffer.clear();
|
||||
|
||||
// draw stats
|
||||
painter.setPen(Qt::white);
|
||||
painter.setBrush(Qt::white);
|
||||
QFont font;
|
||||
font.setPixelSize(24);
|
||||
painter.drawText(20, 20, m_statsDisplay);
|
||||
painter.resetTransform();
|
||||
|
||||
painter.end();
|
||||
|
||||
painter.begin(this);
|
||||
painter.drawPixmap(0, 0, m_pixmap);
|
||||
painter.end();
|
||||
|
||||
m_buffer.clear();
|
||||
}
|
||||
|
||||
void OsciWidget::timerEvent(QTimerEvent *event)
|
||||
|
@@ -22,6 +22,9 @@ public:
|
||||
float factor() const { return m_factor; }
|
||||
int fps() const { return m_fps; }
|
||||
|
||||
signals:
|
||||
void statusUpdate(const QString &status);
|
||||
|
||||
public slots:
|
||||
void setFactor(float factor) { m_factor = factor; }
|
||||
void setFps(int fps);
|
||||
@@ -38,11 +41,12 @@ private:
|
||||
QPointF m_lastPoint;
|
||||
|
||||
int m_frameCounter{0}, m_callbacksCounter{0};
|
||||
QString m_statsDisplay;
|
||||
QElapsedTimer m_fpsTimer;
|
||||
QElapsedTimer m_statsTimer;
|
||||
|
||||
int m_fps{15};
|
||||
int m_redrawTimerId;
|
||||
|
||||
std::vector<SamplePair> m_buffer;
|
||||
|
||||
QPixmap m_pixmap;
|
||||
};
|
||||
|
Reference in New Issue
Block a user