Refactorings and preperations for loop station
This commit is contained in:
@ -16,6 +16,7 @@ SOURCES += \
|
|||||||
audioplayer.cpp \
|
audioplayer.cpp \
|
||||||
djwidget.cpp \
|
djwidget.cpp \
|
||||||
drummachinesettings.cpp \
|
drummachinesettings.cpp \
|
||||||
|
drumpadwidget.cpp \
|
||||||
filesmodel.cpp \
|
filesmodel.cpp \
|
||||||
graphrenderer.cpp \
|
graphrenderer.cpp \
|
||||||
jsonconverters.cpp \
|
jsonconverters.cpp \
|
||||||
@ -33,6 +34,7 @@ SOURCES += \
|
|||||||
scratchwidget.cpp \
|
scratchwidget.cpp \
|
||||||
sequencerwidget.cpp \
|
sequencerwidget.cpp \
|
||||||
synthisizer.cpp \
|
synthisizer.cpp \
|
||||||
|
synthisizerwidget.cpp \
|
||||||
trackdeck.cpp \
|
trackdeck.cpp \
|
||||||
treetotableproxymodel.cpp
|
treetotableproxymodel.cpp
|
||||||
|
|
||||||
@ -42,6 +44,7 @@ HEADERS += \
|
|||||||
audioplayer.h \
|
audioplayer.h \
|
||||||
djwidget.h \
|
djwidget.h \
|
||||||
drummachinesettings.h \
|
drummachinesettings.h \
|
||||||
|
drumpadwidget.h \
|
||||||
filesmodel.h \
|
filesmodel.h \
|
||||||
graphrenderer.h \
|
graphrenderer.h \
|
||||||
jsonconverters.h \
|
jsonconverters.h \
|
||||||
@ -58,16 +61,19 @@ HEADERS += \
|
|||||||
scratchwidget.h \
|
scratchwidget.h \
|
||||||
sequencerwidget.h \
|
sequencerwidget.h \
|
||||||
synthisizer.h \
|
synthisizer.h \
|
||||||
|
synthisizerwidget.h \
|
||||||
trackdeck.h \
|
trackdeck.h \
|
||||||
treetotableproxymodel.h
|
treetotableproxymodel.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
djwidget.ui \
|
djwidget.ui \
|
||||||
|
drumpadwidget.ui \
|
||||||
mainwindow.ui \
|
mainwindow.ui \
|
||||||
presetdetailwidget.ui \
|
presetdetailwidget.ui \
|
||||||
sampleswidget.ui \
|
sampleswidget.ui \
|
||||||
samplewidget.ui \
|
samplewidget.ui \
|
||||||
sequencerwidget.ui \
|
sequencerwidget.ui \
|
||||||
|
synthisizerwidget.ui \
|
||||||
trackdeck.ui
|
trackdeck.ui
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
|
16
djwidget.cpp
16
djwidget.cpp
@ -75,6 +75,22 @@ void DjWidget::writeSamples(frame_t *begin, frame_t *end)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DjWidget::loadSettings(DrumMachineSettings &settings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DjWidget::unsendColors()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DjWidget::sendColors()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DjWidget::messageReceived(const midi::MidiMessage &message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void DjWidget::directorySelected()
|
void DjWidget::directorySelected()
|
||||||
{
|
{
|
||||||
const auto selected = m_ui->treeViewDirectories->currentIndex();
|
const auto selected = m_ui->treeViewDirectories->currentIndex();
|
||||||
|
12
djwidget.h
12
djwidget.h
@ -7,9 +7,11 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "audioformat.h"
|
#include "audioformat.h"
|
||||||
|
#include "midicontainers.h"
|
||||||
#include "treetotableproxymodel.h"
|
#include "treetotableproxymodel.h"
|
||||||
|
|
||||||
namespace Ui { class DjWidget; }
|
namespace Ui { class DjWidget; }
|
||||||
|
class DrumMachineSettings;
|
||||||
|
|
||||||
class DjWidget : public QWidget
|
class DjWidget : public QWidget
|
||||||
{
|
{
|
||||||
@ -20,8 +22,16 @@ public:
|
|||||||
~DjWidget() override;
|
~DjWidget() override;
|
||||||
|
|
||||||
void injectDecodingThread(QThread &thread);
|
void injectDecodingThread(QThread &thread);
|
||||||
|
|
||||||
void writeSamples(frame_t *begin, frame_t *end);
|
void writeSamples(frame_t *begin, frame_t *end);
|
||||||
|
void loadSettings(DrumMachineSettings &settings);
|
||||||
|
void unsendColors();
|
||||||
|
void sendColors();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void sendMidi(const midi::MidiMessage &midiMsg);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void messageReceived(const midi::MidiMessage &message);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void directorySelected();
|
void directorySelected();
|
||||||
|
152
drumpadwidget.cpp
Normal file
152
drumpadwidget.cpp
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
#include "drumpadwidget.h"
|
||||||
|
#include "ui_drumpadwidget.h"
|
||||||
|
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#include "jsonconverters.h"
|
||||||
|
|
||||||
|
DrumPadWidget::DrumPadWidget(QWidget *parent) :
|
||||||
|
QSplitter{parent},
|
||||||
|
m_ui{std::make_unique<Ui::DrumPadWidget>()}
|
||||||
|
{
|
||||||
|
m_ui->setupUi(this);
|
||||||
|
|
||||||
|
connect(m_ui->samplesWidget, &SamplesWidget::sendMidi, this, &DrumPadWidget::sendMidi);
|
||||||
|
|
||||||
|
connect(m_ui->sequencerWidget, &SequencerWidget::triggerSample, m_ui->samplesWidget, &SamplesWidget::sequencerTriggerSample);
|
||||||
|
|
||||||
|
m_presetsProxyModel.setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||||
|
m_presetsProxyModel.setSortRole(Qt::EditRole);
|
||||||
|
m_presetsProxyModel.setSourceModel(&m_presetsModel);
|
||||||
|
m_ui->presetsView->setModel(&m_presetsProxyModel);
|
||||||
|
|
||||||
|
m_presetsProxyModel.setFilterKeyColumn(1);
|
||||||
|
|
||||||
|
connect(m_ui->lineEdit, &QLineEdit::textChanged, &m_presetsProxyModel, &QSortFilterProxyModel::setFilterFixedString);
|
||||||
|
|
||||||
|
m_ui->filesView->setModel(&m_filesModel);
|
||||||
|
|
||||||
|
connect(m_ui->presetsView->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &DrumPadWidget::currentRowChanged);
|
||||||
|
|
||||||
|
connect(m_ui->pushButtonRefresh, &QAbstractButton::pressed, this, &DrumPadWidget::loadPresets);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrumPadWidget::~DrumPadWidget() = default;
|
||||||
|
|
||||||
|
void DrumPadWidget::selectFirstPreset()
|
||||||
|
{
|
||||||
|
if (!m_presetsProxyModel.rowCount())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto index = m_presetsProxyModel.index(0, 0);
|
||||||
|
if (index.isValid())
|
||||||
|
{
|
||||||
|
m_ui->presetsView->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
|
||||||
|
currentRowChanged(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrumPadWidget::writeSamples(frame_t *begin, frame_t *end)
|
||||||
|
{
|
||||||
|
m_ui->samplesWidget->writeSamples(begin, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrumPadWidget::injectNetworkAccessManager(QNetworkAccessManager &networkAccessManager)
|
||||||
|
{
|
||||||
|
m_networkAccessManager = &networkAccessManager;
|
||||||
|
loadPresets();
|
||||||
|
m_ui->samplesWidget->injectNetworkAccessManager(networkAccessManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrumPadWidget::injectDecodingThread(QThread &thread)
|
||||||
|
{
|
||||||
|
m_ui->samplesWidget->injectDecodingThread(thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrumPadWidget::loadSettings(DrumMachineSettings &settings)
|
||||||
|
{
|
||||||
|
m_ui->samplesWidget->loadSettings(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrumPadWidget::unsendColors()
|
||||||
|
{
|
||||||
|
m_ui->samplesWidget->unsendColors();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrumPadWidget::sendColors()
|
||||||
|
{
|
||||||
|
m_ui->samplesWidget->sendColors();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrumPadWidget::messageReceived(const midi::MidiMessage &message)
|
||||||
|
{
|
||||||
|
m_ui->samplesWidget->messageReceived(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrumPadWidget::currentRowChanged(const QModelIndex ¤t)
|
||||||
|
{
|
||||||
|
if (!current.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto &preset = m_presetsModel.getPreset(m_presetsProxyModel.mapToSource(current));
|
||||||
|
|
||||||
|
m_ui->presetDetailWidget->setPreset(preset);
|
||||||
|
m_filesModel.setPreset(preset);
|
||||||
|
m_ui->sequencerWidget->setPreset(preset);
|
||||||
|
m_ui->samplesWidget->setPreset(preset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrumPadWidget::loadPresets()
|
||||||
|
{
|
||||||
|
if (!m_networkAccessManager)
|
||||||
|
{
|
||||||
|
qWarning() << "no network access manager available";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ui->pushButtonRefresh->setEnabled(false);
|
||||||
|
|
||||||
|
QNetworkRequest request{QUrl{"https://brunner.ninja/komposthaufen/dpm/presets_config_v12.json"}};
|
||||||
|
request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
|
||||||
|
request.setAttribute(QNetworkRequest::CacheSaveControlAttribute, true);
|
||||||
|
|
||||||
|
m_reply = std::unique_ptr<QNetworkReply>(m_networkAccessManager->get(request));
|
||||||
|
connect(m_reply.get(), &QNetworkReply::finished, this, &DrumPadWidget::requestFinished);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrumPadWidget::requestFinished()
|
||||||
|
{
|
||||||
|
qDebug() << "called";
|
||||||
|
|
||||||
|
if (!m_reply)
|
||||||
|
{
|
||||||
|
qWarning() << "no valid reply";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto reply = std::move(m_reply);
|
||||||
|
if (reply->error() != QNetworkReply::NoError)
|
||||||
|
{
|
||||||
|
QMessageBox::warning(this, tr("Could not load presets!"), tr("Could not load presets!") + "\n\n" + reply->errorString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto result = json_converters::parsePresetsConfig(json_converters::loadJson(reply->readAll()));
|
||||||
|
|
||||||
|
if (!result.presets)
|
||||||
|
throw std::runtime_error("presets missing in response");
|
||||||
|
|
||||||
|
m_presetsModel.setPresets(std::move(*std::move(result).presets));
|
||||||
|
|
||||||
|
selectFirstPreset();
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
QMessageBox::warning(this, tr("error"), tr("error") + "\n\n" + QString::fromStdString(e.what()));
|
||||||
|
}
|
||||||
|
}
|
60
drumpadwidget.h
Normal file
60
drumpadwidget.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QSplitter>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "audioformat.h"
|
||||||
|
#include "midicontainers.h"
|
||||||
|
#include "presetsmodel.h"
|
||||||
|
#include "filesmodel.h"
|
||||||
|
|
||||||
|
namespace Ui { class DrumPadWidget; }
|
||||||
|
class SamplesWidget;
|
||||||
|
class SequencerWidget;
|
||||||
|
class QModelIndex;
|
||||||
|
class QNetworkAccessManager;
|
||||||
|
class QThread;
|
||||||
|
class DrumMachineSettings;
|
||||||
|
class QNetworkReply;
|
||||||
|
|
||||||
|
class DrumPadWidget : public QSplitter
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit DrumPadWidget(QWidget *parent = nullptr);
|
||||||
|
~DrumPadWidget() override;
|
||||||
|
|
||||||
|
void selectFirstPreset();
|
||||||
|
void writeSamples(frame_t *begin, frame_t *end);
|
||||||
|
void injectNetworkAccessManager(QNetworkAccessManager &networkAccessManager);
|
||||||
|
void injectDecodingThread(QThread &thread);
|
||||||
|
void loadSettings(DrumMachineSettings &settings);
|
||||||
|
void unsendColors();
|
||||||
|
void sendColors();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void sendMidi(const midi::MidiMessage &midiMsg);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void messageReceived(const midi::MidiMessage &message);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void currentRowChanged(const QModelIndex ¤t);
|
||||||
|
void loadPresets();
|
||||||
|
void requestFinished();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::unique_ptr<Ui::DrumPadWidget> m_ui;
|
||||||
|
|
||||||
|
PresetsModel m_presetsModel;
|
||||||
|
QSortFilterProxyModel m_presetsProxyModel;
|
||||||
|
|
||||||
|
FilesModel m_filesModel;
|
||||||
|
|
||||||
|
QNetworkAccessManager *m_networkAccessManager{};
|
||||||
|
|
||||||
|
std::unique_ptr<QNetworkReply> m_reply;
|
||||||
|
};
|
108
drumpadwidget.ui
Normal file
108
drumpadwidget.ui
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>DrumPadWidget</class>
|
||||||
|
<widget class="QSplitter">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>805</width>
|
||||||
|
<height>525</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="layoutWidget">
|
||||||
|
<layout class="QVBoxLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="lineEdit">
|
||||||
|
<property name="clearButtonEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pushButtonRefresh">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>↻</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTreeView" name="presetsView">
|
||||||
|
<property name="rootIsDecorated">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="sortingEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<widget class="PresetDetailWidget" name="presetDetailWidget">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Properties</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
<widget class="QTreeView" name="filesView">
|
||||||
|
<property name="rootIsDecorated">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Samples</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QSplitter">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="SequencerWidget" name="sequencerWidget" />
|
||||||
|
<widget class="SamplesWidget" name="samplesWidget" />
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>SamplesWidget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>sampleswidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>PresetDetailWidget</class>
|
||||||
|
<extends>QScrollArea</extends>
|
||||||
|
<header>presetdetailwidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>SequencerWidget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>sequencerwidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
48
main.cpp
48
main.cpp
@ -1,17 +1,10 @@
|
|||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QSslSocket>
|
#include <QSslSocket>
|
||||||
#include <QNetworkAccessManager>
|
|
||||||
#include <QNetworkRequest>
|
|
||||||
#include <QNetworkReply>
|
|
||||||
#include <QEventLoop>
|
|
||||||
#include <QSplashScreen>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QNetworkDiskCache>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
#include "portaudio.h"
|
#include "portaudio.h"
|
||||||
|
|
||||||
#include "jsonconverters.h"
|
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -58,7 +51,6 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto helper0 = makeCleanupHelper([](){
|
auto helper0 = makeCleanupHelper([](){
|
||||||
qDebug() << "helper0";
|
|
||||||
if (PaError err = Pa_Terminate(); err != paNoError)
|
if (PaError err = Pa_Terminate(); err != paNoError)
|
||||||
fprintf(stderr, "Could not terminate PortAudio!\n");
|
fprintf(stderr, "Could not terminate PortAudio!\n");
|
||||||
});
|
});
|
||||||
@ -74,39 +66,6 @@ int main(int argc, char *argv[])
|
|||||||
"%{function}(): "
|
"%{function}(): "
|
||||||
"%{message}");
|
"%{message}");
|
||||||
|
|
||||||
presets::PresetsConfig presetsConfig;
|
|
||||||
|
|
||||||
{
|
|
||||||
QSplashScreen splashScreen{QPixmap{":/drummachine/splashscreen.png"}};
|
|
||||||
splashScreen.showMessage(QCoreApplication::translate("main", "Loading list of presets..."));
|
|
||||||
splashScreen.show();
|
|
||||||
|
|
||||||
QEventLoop eventLoop;
|
|
||||||
|
|
||||||
QNetworkAccessManager manager;
|
|
||||||
|
|
||||||
QNetworkDiskCache cache;
|
|
||||||
cache.setCacheDirectory("cache");
|
|
||||||
|
|
||||||
manager.setCache(&cache);
|
|
||||||
|
|
||||||
QNetworkRequest request{QUrl{"https://brunner.ninja/komposthaufen/dpm/presets_config_v12.json"}};
|
|
||||||
request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
|
|
||||||
request.setAttribute(QNetworkRequest::CacheSaveControlAttribute, true);
|
|
||||||
|
|
||||||
const auto reply = std::unique_ptr<QNetworkReply>(manager.get(request));
|
|
||||||
QObject::connect(reply.get(), &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
|
|
||||||
eventLoop.exec();
|
|
||||||
|
|
||||||
if (reply->error() != QNetworkReply::NoError)
|
|
||||||
{
|
|
||||||
QMessageBox::warning(nullptr, QCoreApplication::translate("main", "Could not load presets!"), QCoreApplication::translate("main", "Could not load presets!") + "\n\n" + reply->errorString());
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
presetsConfig = json_converters::parsePresetsConfig(json_converters::loadJson(reply->readAll()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(Q_OS_WIN)
|
#if !defined(Q_OS_WIN)
|
||||||
QPalette darkPalette;
|
QPalette darkPalette;
|
||||||
darkPalette.setColor(QPalette::Window, QColor(53,53,53));
|
darkPalette.setColor(QPalette::Window, QColor(53,53,53));
|
||||||
@ -127,9 +86,8 @@ int main(int argc, char *argv[])
|
|||||||
app.setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
|
app.setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MainWindow mainWindow{presetsConfig};
|
MainWindow mainWindow;
|
||||||
mainWindow.showMaximized();
|
mainWindow.show();
|
||||||
mainWindow.selectFirstPreset();
|
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
204
mainwindow.cpp
204
mainwindow.cpp
@ -12,56 +12,34 @@
|
|||||||
#include "presets.h"
|
#include "presets.h"
|
||||||
#include "midiinwrapper.h"
|
#include "midiinwrapper.h"
|
||||||
#include "midicontainers.h"
|
#include "midicontainers.h"
|
||||||
|
#include "sampleswidget.h"
|
||||||
|
#include "sequencerwidget.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void DummyDeleter(PaStream *stream)
|
void DummyDeleter(PaStream *stream);
|
||||||
{
|
void PaStreamCloser(PaStream *stream);
|
||||||
Q_UNUSED(stream);
|
void PaStreamStopperAndCloser(PaStream *stream);
|
||||||
}
|
void paStreamFinished(void* userData);
|
||||||
void PaStreamCloser(PaStream *stream)
|
|
||||||
{
|
|
||||||
if (PaError err = Pa_CloseStream(stream); err != paNoError)
|
|
||||||
fprintf(stderr, "Could not close stream!\n");
|
|
||||||
}
|
|
||||||
void PaStreamStopperAndCloser(PaStream *stream)
|
|
||||||
{
|
|
||||||
if (PaError err = Pa_StopStream(stream); err != paNoError)
|
|
||||||
fprintf(stderr, "Could not stop stream!\n");
|
|
||||||
PaStreamCloser(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
void paStreamFinished(void* userData)
|
|
||||||
{
|
|
||||||
printf("Stream Completed\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
int paCallback(const void *inputBuffer, void *outputBuffer,
|
int paCallback(const void *inputBuffer, void *outputBuffer,
|
||||||
unsigned long framesPerBuffer,
|
unsigned long framesPerBuffer,
|
||||||
const PaStreamCallbackTimeInfo* timeInfo,
|
const PaStreamCallbackTimeInfo* timeInfo,
|
||||||
PaStreamCallbackFlags statusFlags,
|
PaStreamCallbackFlags statusFlags,
|
||||||
void *userData)
|
void *userData);
|
||||||
{
|
} // namespace
|
||||||
Q_UNUSED(inputBuffer)
|
|
||||||
Q_ASSERT(outputBuffer);
|
|
||||||
Q_ASSERT(framesPerBuffer);
|
|
||||||
Q_UNUSED(timeInfo)
|
|
||||||
Q_UNUSED(statusFlags)
|
|
||||||
Q_ASSERT(userData);
|
|
||||||
|
|
||||||
auto begin = static_cast<frame_t*>(outputBuffer);
|
MainWindow::MainWindow(QWidget *parent) :
|
||||||
|
|
||||||
static_cast<MainWindow*>(userData)->writeSamples(begin, begin+framesPerBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MainWindow::MainWindow(const presets::PresetsConfig &presetsConfig, QWidget *parent) :
|
|
||||||
QMainWindow{parent},
|
QMainWindow{parent},
|
||||||
m_ui{std::make_unique<Ui::MainWindow>()},
|
m_ui{std::make_unique<Ui::MainWindow>()},
|
||||||
m_paStream{nullptr, DummyDeleter},
|
m_paStream{nullptr, DummyDeleter},
|
||||||
m_presetsModel{*presetsConfig.presets}
|
m_midiIn{RtMidi::UNSPECIFIED, "DrumMachine"},
|
||||||
|
m_midiOut{RtMidi::UNSPECIFIED, "DrumMachine"}
|
||||||
{
|
{
|
||||||
m_ui->setupUi(this);
|
m_ui->setupUi(this);
|
||||||
m_ui->splitter->setSizes({99999, 1});
|
|
||||||
|
m_cache.setCacheDirectory("cache");
|
||||||
|
m_networkAccessManager.setCache(&m_cache);
|
||||||
|
|
||||||
|
m_ui->drumPadWidget->injectNetworkAccessManager(m_networkAccessManager);
|
||||||
|
|
||||||
connect(&m_midiIn, &MidiInWrapper::messageReceived, this, &MainWindow::messageReceived);
|
connect(&m_midiIn, &MidiInWrapper::messageReceived, this, &MainWindow::messageReceived);
|
||||||
|
|
||||||
@ -72,11 +50,9 @@ MainWindow::MainWindow(const presets::PresetsConfig &presetsConfig, QWidget *par
|
|||||||
eventLoop.exec();
|
eventLoop.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ui->samplesWidget->injectDecodingThread(m_decoderThread);
|
m_ui->drumPadWidget->injectDecodingThread(m_decoderThread);
|
||||||
m_ui->djWidget->injectDecodingThread(m_decoderThread);
|
m_ui->djWidget->injectDecodingThread(m_decoderThread);
|
||||||
|
|
||||||
connect(m_ui->sequencerWidget, &SequencerWidget::triggerSample, m_ui->samplesWidget, &SamplesWidget::sequencerTriggerSample);
|
|
||||||
|
|
||||||
updateMidiInDevices();
|
updateMidiInDevices();
|
||||||
|
|
||||||
updateMidiOutDevices();
|
updateMidiOutDevices();
|
||||||
@ -92,7 +68,7 @@ MainWindow::MainWindow(const presets::PresetsConfig &presetsConfig, QWidget *par
|
|||||||
{
|
{
|
||||||
const auto index = m_ui->comboBoxMidiIn->currentIndex();
|
const auto index = m_ui->comboBoxMidiIn->currentIndex();
|
||||||
if (index != -1)
|
if (index != -1)
|
||||||
m_midiIn.openPort(index, "DrumMachine");
|
m_midiIn.openPort(index, "Input");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ui->comboBoxMidiIn->setDisabled(m_midiIn.isPortOpen());
|
m_ui->comboBoxMidiIn->setDisabled(m_midiIn.isPortOpen());
|
||||||
@ -103,6 +79,7 @@ MainWindow::MainWindow(const presets::PresetsConfig &presetsConfig, QWidget *par
|
|||||||
if (m_midiOut.isPortOpen())
|
if (m_midiOut.isPortOpen())
|
||||||
{
|
{
|
||||||
qDebug() << "closing port";
|
qDebug() << "closing port";
|
||||||
|
unsendColors(m_ui->tabWidget->currentIndex());
|
||||||
m_midiOut.closePort();
|
m_midiOut.closePort();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -110,8 +87,8 @@ MainWindow::MainWindow(const presets::PresetsConfig &presetsConfig, QWidget *par
|
|||||||
const auto index = m_ui->comboBoxMidiOut->currentIndex();
|
const auto index = m_ui->comboBoxMidiOut->currentIndex();
|
||||||
if (index != -1)
|
if (index != -1)
|
||||||
{
|
{
|
||||||
m_midiOut.openPort(index, "DrumMachine");
|
m_midiOut.openPort(index, "Output");
|
||||||
sendColors();
|
sendColors(m_ui->tabWidget->currentIndex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,22 +104,14 @@ MainWindow::MainWindow(const presets::PresetsConfig &presetsConfig, QWidget *par
|
|||||||
|
|
||||||
connect(m_ui->pushButtonAudioDevice, &QAbstractButton::pressed, this, &MainWindow::openAudioDevice);
|
connect(m_ui->pushButtonAudioDevice, &QAbstractButton::pressed, this, &MainWindow::openAudioDevice);
|
||||||
|
|
||||||
m_presetsProxyModel.setFilterCaseSensitivity(Qt::CaseInsensitive);
|
|
||||||
m_presetsProxyModel.setSortRole(Qt::EditRole);
|
|
||||||
m_presetsProxyModel.setSourceModel(&m_presetsModel);
|
|
||||||
m_ui->presetsView->setModel(&m_presetsProxyModel);
|
|
||||||
|
|
||||||
m_presetsProxyModel.setFilterKeyColumn(1);
|
|
||||||
|
|
||||||
connect(m_ui->lineEdit, &QLineEdit::textChanged, &m_presetsProxyModel, &QSortFilterProxyModel::setFilterFixedString);
|
|
||||||
|
|
||||||
m_ui->filesView->setModel(&m_filesModel);
|
|
||||||
|
|
||||||
connect(m_ui->presetsView->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &MainWindow::currentRowChanged);
|
|
||||||
|
|
||||||
loadSettings();
|
loadSettings();
|
||||||
|
|
||||||
connect(m_ui->samplesWidget, &SamplesWidget::sendMidi, this, &MainWindow::sendMidi);
|
connect(m_ui->drumPadWidget, &DrumPadWidget::sendMidi, this, &MainWindow::sendMidi);
|
||||||
|
connect(m_ui->djWidget, &DjWidget::sendMidi, this, &MainWindow::sendMidi);
|
||||||
|
connect(m_ui->synthisizerWidget, &SynthisizerWidget::sendMidi, this, &MainWindow::sendMidi);
|
||||||
|
|
||||||
|
m_lastIndex = m_ui->tabWidget->currentIndex();
|
||||||
|
connect(m_ui->tabWidget, &QTabWidget::currentChanged, this, &MainWindow::currentChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
@ -151,26 +120,13 @@ MainWindow::~MainWindow()
|
|||||||
m_decoderThread.wait();
|
m_decoderThread.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::selectFirstPreset()
|
int MainWindow::writeSamples(frame_t *begin, frame_t *end)
|
||||||
{
|
|
||||||
if (m_presetsProxyModel.rowCount())
|
|
||||||
{
|
|
||||||
const auto index = m_presetsProxyModel.index(0, 0);
|
|
||||||
if (index.isValid())
|
|
||||||
{
|
|
||||||
m_ui->presetsView->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
|
|
||||||
currentRowChanged(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::writeSamples(frame_t *begin, frame_t *end)
|
|
||||||
{
|
{
|
||||||
std::fill(begin, end, frame_t{0.,0.});
|
std::fill(begin, end, frame_t{0.,0.});
|
||||||
|
|
||||||
m_ui->samplesWidget->writeSamples(begin, end);
|
m_ui->drumPadWidget->writeSamples(begin, end);
|
||||||
m_ui->djWidget->writeSamples(begin, end);
|
m_ui->djWidget->writeSamples(begin, end);
|
||||||
m_synthisizer.writeSamples(begin, end);
|
m_ui->synthisizerWidget->writeSamples(begin, end);
|
||||||
|
|
||||||
std::transform(begin, end, begin, [factor=float(m_ui->horizontalSliderMaster->value())/100.f](frame_t frame){
|
std::transform(begin, end, begin, [factor=float(m_ui->horizontalSliderMaster->value())/100.f](frame_t frame){
|
||||||
std::transform(std::cbegin(frame), std::cend(frame), std::begin(frame), [&factor](const sample_t &sample){
|
std::transform(std::cbegin(frame), std::cend(frame), std::begin(frame), [&factor](const sample_t &sample){
|
||||||
@ -178,6 +134,8 @@ void MainWindow::writeSamples(frame_t *begin, frame_t *end)
|
|||||||
});
|
});
|
||||||
return frame;
|
return frame;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return paContinue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::openAudioDevice()
|
void MainWindow::openAudioDevice()
|
||||||
@ -242,23 +200,12 @@ void MainWindow::messageReceived(const midi::MidiMessage &message)
|
|||||||
.arg(message.flag?"true":"false", QMetaEnum::fromType<midi::Command>().valueToKey(int(message.cmd)))
|
.arg(message.flag?"true":"false", QMetaEnum::fromType<midi::Command>().valueToKey(int(message.cmd)))
|
||||||
.arg(message.channel).arg(message.note).arg(message.velocity), 1000);
|
.arg(message.channel).arg(message.note).arg(message.velocity), 1000);
|
||||||
|
|
||||||
if (m_ui->comboBoxMidiType->currentIndex() == 0)
|
if (m_ui->tabWidget->currentIndex() == 0)
|
||||||
m_ui->samplesWidget->messageReceived(message);
|
m_ui->drumPadWidget->messageReceived(message);
|
||||||
else if (m_ui->comboBoxMidiType->currentIndex() == 1)
|
else if (m_ui->tabWidget->currentIndex() == 1)
|
||||||
m_synthisizer.messageReceived(message);
|
m_ui->djWidget->messageReceived(message);
|
||||||
}
|
else if (m_ui->tabWidget->currentIndex() == 2)
|
||||||
|
m_ui->synthisizerWidget->messageReceived(message);
|
||||||
void MainWindow::currentRowChanged(const QModelIndex ¤t)
|
|
||||||
{
|
|
||||||
if (!current.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
const auto &preset = m_presetsModel.getPreset(m_presetsProxyModel.mapToSource(current));
|
|
||||||
|
|
||||||
m_ui->presetDetailWidget->setPreset(preset);
|
|
||||||
m_filesModel.setPreset(preset);
|
|
||||||
m_ui->sequencerWidget->setPreset(preset);
|
|
||||||
m_ui->samplesWidget->setPreset(preset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::sendMidi(const midi::MidiMessage &midiMsg)
|
void MainWindow::sendMidi(const midi::MidiMessage &midiMsg)
|
||||||
@ -267,6 +214,13 @@ void MainWindow::sendMidi(const midi::MidiMessage &midiMsg)
|
|||||||
m_midiOut.sendMessage(midiMsg);
|
m_midiOut.sendMessage(midiMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::currentChanged(int index)
|
||||||
|
{
|
||||||
|
unsendColors(m_lastIndex);
|
||||||
|
m_lastIndex = index;
|
||||||
|
sendColors(index);
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::updateMidiInDevices()
|
void MainWindow::updateMidiInDevices()
|
||||||
{
|
{
|
||||||
m_ui->comboBoxMidiIn->clear();
|
m_ui->comboBoxMidiIn->clear();
|
||||||
@ -302,15 +256,34 @@ void MainWindow::updateAudioDevices()
|
|||||||
|
|
||||||
void MainWindow::loadSettings()
|
void MainWindow::loadSettings()
|
||||||
{
|
{
|
||||||
m_synthisizer.loadSettings(m_settings);
|
m_ui->drumPadWidget->loadSettings(m_settings);
|
||||||
m_ui->samplesWidget->loadSettings(m_settings);
|
m_ui->djWidget->loadSettings(m_settings);
|
||||||
|
m_ui->synthisizerWidget->loadSettings(m_settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::sendColors()
|
void MainWindow::unsendColors(int index)
|
||||||
{
|
{
|
||||||
m_ui->samplesWidget->sendColors();
|
if (index == 0)
|
||||||
|
m_ui->drumPadWidget->unsendColors();
|
||||||
|
else if (index == 1)
|
||||||
|
m_ui->djWidget->unsendColors();
|
||||||
|
else if (index == 2)
|
||||||
|
m_ui->synthisizerWidget->unsendColors();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::sendColors(int index)
|
||||||
|
{
|
||||||
|
if (index == 0)
|
||||||
|
m_ui->drumPadWidget->sendColors();
|
||||||
|
else if (index == 1)
|
||||||
|
m_ui->djWidget->sendColors();
|
||||||
|
else if (index == 2)
|
||||||
|
m_ui->synthisizerWidget->sendColors();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// this was just for debugging all the available colors on novation launchpad mk1
|
||||||
|
|
||||||
int k{0};
|
int k{0};
|
||||||
for (int j = 0; j < 128; j+= 16)
|
for (int j = 0; j < 128; j+= 16)
|
||||||
{
|
{
|
||||||
@ -327,3 +300,44 @@ void MainWindow::sendColors()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void DummyDeleter(PaStream *stream)
|
||||||
|
{
|
||||||
|
Q_UNUSED(stream);
|
||||||
|
}
|
||||||
|
void PaStreamCloser(PaStream *stream)
|
||||||
|
{
|
||||||
|
if (PaError err = Pa_CloseStream(stream); err != paNoError)
|
||||||
|
fprintf(stderr, "Could not close stream!\n");
|
||||||
|
}
|
||||||
|
void PaStreamStopperAndCloser(PaStream *stream)
|
||||||
|
{
|
||||||
|
if (PaError err = Pa_StopStream(stream); err != paNoError)
|
||||||
|
fprintf(stderr, "Could not stop stream!\n");
|
||||||
|
PaStreamCloser(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void paStreamFinished(void* userData)
|
||||||
|
{
|
||||||
|
printf("Stream Completed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int paCallback(const void *inputBuffer, void *outputBuffer,
|
||||||
|
unsigned long framesPerBuffer,
|
||||||
|
const PaStreamCallbackTimeInfo* timeInfo,
|
||||||
|
PaStreamCallbackFlags statusFlags,
|
||||||
|
void *userData)
|
||||||
|
{
|
||||||
|
Q_UNUSED(inputBuffer)
|
||||||
|
Q_ASSERT(outputBuffer);
|
||||||
|
Q_ASSERT(framesPerBuffer);
|
||||||
|
Q_UNUSED(timeInfo)
|
||||||
|
Q_UNUSED(statusFlags)
|
||||||
|
Q_ASSERT(userData);
|
||||||
|
|
||||||
|
auto begin = static_cast<frame_t*>(outputBuffer);
|
||||||
|
|
||||||
|
return static_cast<MainWindow*>(userData)->writeSamples(begin, begin+framesPerBuffer);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
27
mainwindow.h
27
mainwindow.h
@ -3,17 +3,15 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QSortFilterProxyModel>
|
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QNetworkDiskCache>
|
||||||
|
|
||||||
#include "portaudio.h"
|
#include "portaudio.h"
|
||||||
|
|
||||||
#include "audioformat.h"
|
#include "audioformat.h"
|
||||||
#include "presetsmodel.h"
|
|
||||||
#include "filesmodel.h"
|
|
||||||
#include "midiinwrapper.h"
|
#include "midiinwrapper.h"
|
||||||
#include "midioutwrapper.h"
|
#include "midioutwrapper.h"
|
||||||
#include "synthisizer.h"
|
|
||||||
#include "drummachinesettings.h"
|
#include "drummachinesettings.h"
|
||||||
|
|
||||||
namespace Ui { class MainWindow; }
|
namespace Ui { class MainWindow; }
|
||||||
@ -25,25 +23,24 @@ class MainWindow : public QMainWindow
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit MainWindow(const presets::PresetsConfig &presetsConfig, QWidget *parent = nullptr);
|
explicit MainWindow(QWidget *parent = nullptr);
|
||||||
~MainWindow() override;
|
~MainWindow() override;
|
||||||
|
|
||||||
void selectFirstPreset();
|
int writeSamples(frame_t *begin, frame_t *end);
|
||||||
|
|
||||||
void writeSamples(frame_t *begin, frame_t *end);
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void openAudioDevice();
|
void openAudioDevice();
|
||||||
void messageReceived(const midi::MidiMessage &message);
|
void messageReceived(const midi::MidiMessage &message);
|
||||||
void currentRowChanged(const QModelIndex ¤t);
|
|
||||||
void sendMidi(const midi::MidiMessage &midiMsg);
|
void sendMidi(const midi::MidiMessage &midiMsg);
|
||||||
|
void currentChanged(int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateMidiInDevices();
|
void updateMidiInDevices();
|
||||||
void updateMidiOutDevices();
|
void updateMidiOutDevices();
|
||||||
void updateAudioDevices();
|
void updateAudioDevices();
|
||||||
void loadSettings();
|
void loadSettings();
|
||||||
void sendColors();
|
void unsendColors(int index);
|
||||||
|
void sendColors(int index);
|
||||||
|
|
||||||
const std::unique_ptr<Ui::MainWindow> m_ui;
|
const std::unique_ptr<Ui::MainWindow> m_ui;
|
||||||
|
|
||||||
@ -54,12 +51,10 @@ private:
|
|||||||
MidiInWrapper m_midiIn;
|
MidiInWrapper m_midiIn;
|
||||||
MidiOutWrapper m_midiOut;
|
MidiOutWrapper m_midiOut;
|
||||||
|
|
||||||
|
QNetworkAccessManager m_networkAccessManager;
|
||||||
|
QNetworkDiskCache m_cache;
|
||||||
|
|
||||||
QThread m_decoderThread;
|
QThread m_decoderThread;
|
||||||
|
|
||||||
Synthisizer m_synthisizer;
|
int m_lastIndex;
|
||||||
|
|
||||||
PresetsModel m_presetsModel;
|
|
||||||
QSortFilterProxyModel m_presetsProxyModel;
|
|
||||||
|
|
||||||
FilesModel m_filesModel;
|
|
||||||
};
|
};
|
||||||
|
214
mainwindow.ui
214
mainwindow.ui
@ -14,7 +14,7 @@
|
|||||||
<string>MainWindow</string>
|
<string>MainWindow</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="widget">
|
<widget class="QWidget" name="widget">
|
||||||
<layout class="QVBoxLayout" stretch="0,1">
|
<layout class="QVBoxLayout" stretch="0,0,0">
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
@ -91,6 +91,43 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="comboBoxAudioDevice"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pushButtonRefreshAudioDevices">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>↻</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="spinBoxBufferSize">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>65535</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>32</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pushButtonAudioDevice">
|
||||||
|
<property name="text">
|
||||||
|
<string>Open</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="labelMidiIn">
|
<widget class="QLabel" name="labelMidiIn">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -121,20 +158,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QComboBox" name="comboBoxMidiType">
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Samples</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Synthisizer</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer_2">
|
<spacer name="horizontalSpacer_2">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
@ -178,139 +201,24 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QComboBox" name="comboBoxAudioDevice"/>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="pushButtonRefreshAudioDevices">
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>32</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>↻</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QSpinBox" name="spinBoxBufferSize">
|
|
||||||
<property name="maximum">
|
|
||||||
<number>65535</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>32</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="pushButtonAudioDevice">
|
|
||||||
<property name="text">
|
|
||||||
<string>Open</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSplitter" name="splitter">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<widget class="QSplitter" name="splitter_2">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="layoutWidget">
|
|
||||||
<layout class="QVBoxLayout">
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QLineEdit" name="lineEdit">
|
|
||||||
<property name="clearButtonEnabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="selectRandomPushButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>Select random</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QSplitter" name="splitter">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<widget class="QTreeView" name="presetsView">
|
|
||||||
<property name="rootIsDecorated">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="sortingEnabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<widget class="QTabWidget" name="tabWidget">
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
<widget class="PresetDetailWidget" name="presetDetailWidget">
|
<widget class="DrumPadWidget" name="drumPadWidget">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string>Properties</string>
|
<string>DrumPad</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QTreeView" name="filesView">
|
<widget class="DjWidget" name="djWidget">
|
||||||
<property name="rootIsDecorated">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string>Samples</string>
|
<string>DJ</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
<widget class="SynthisizerWidget" name="synthisizerWidget">
|
||||||
</widget>
|
<attribute name="title">
|
||||||
</item>
|
<string>Synthisizer</string>
|
||||||
</layout>
|
</attribute>
|
||||||
</widget>
|
|
||||||
<widget class="DjWidget" name="djWidget" native="true"/>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="layoutWidget">
|
|
||||||
<layout class="QVBoxLayout" stretch="1,0">
|
|
||||||
<item>
|
|
||||||
<widget class="SequencerWidget" name="sequencerWidget" native="true"/>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="SamplesWidget" name="samplesWidget" native="true"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -329,30 +237,24 @@
|
|||||||
<widget class="QStatusBar" name="statusbar"/>
|
<widget class="QStatusBar" name="statusbar"/>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
|
||||||
<class>SamplesWidget</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>sampleswidget.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>PresetDetailWidget</class>
|
|
||||||
<extends>QScrollArea</extends>
|
|
||||||
<header>presetdetailwidget.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>SequencerWidget</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>sequencerwidget.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>DjWidget</class>
|
<class>DjWidget</class>
|
||||||
<extends>QWidget</extends>
|
<extends>QWidget</extends>
|
||||||
<header>djwidget.h</header>
|
<header>djwidget.h</header>
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>DrumPadWidget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>drumpadwidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>SynthisizerWidget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>synthisizerwidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
@ -32,6 +32,11 @@ enum {
|
|||||||
NumberOfColumns
|
NumberOfColumns
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PresetsModel::PresetsModel(QObject *parent) :
|
||||||
|
QAbstractTableModel{parent}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
PresetsModel::PresetsModel(const std::map<QString, presets::Preset> &presets, QObject *parent) :
|
PresetsModel::PresetsModel(const std::map<QString, presets::Preset> &presets, QObject *parent) :
|
||||||
QAbstractTableModel{parent}
|
QAbstractTableModel{parent}
|
||||||
{
|
{
|
||||||
@ -40,8 +45,44 @@ PresetsModel::PresetsModel(const std::map<QString, presets::Preset> &presets, QO
|
|||||||
m_presets.emplace_back(pair.second);
|
m_presets.emplace_back(pair.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PresetsModel::PresetsModel(std::vector<presets::Preset> &&presets, QObject *parent) :
|
||||||
|
QAbstractTableModel{parent}
|
||||||
|
{
|
||||||
|
m_presets = std::move(presets);
|
||||||
|
}
|
||||||
|
|
||||||
|
PresetsModel::PresetsModel(const std::vector<presets::Preset> &presets, QObject *parent) :
|
||||||
|
QAbstractTableModel{parent}
|
||||||
|
{
|
||||||
|
m_presets = presets;
|
||||||
|
}
|
||||||
|
|
||||||
PresetsModel::~PresetsModel() = default;
|
PresetsModel::~PresetsModel() = default;
|
||||||
|
|
||||||
|
void PresetsModel::setPresets(const std::map<QString, presets::Preset> &presets)
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
m_presets.clear();
|
||||||
|
m_presets.reserve(std::size(presets));
|
||||||
|
for (const auto &pair : presets)
|
||||||
|
m_presets.emplace_back(pair.second);
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PresetsModel::setPresets(std::vector<presets::Preset> &&presets)
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
m_presets = std::move(presets);
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PresetsModel::setPresets(const std::vector<presets::Preset> &presets)
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
m_presets = presets;
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
const presets::Preset &PresetsModel::getPreset(const QModelIndex &index) const
|
const presets::Preset &PresetsModel::getPreset(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
return getPreset(index.row());
|
return getPreset(index.row());
|
||||||
|
@ -11,9 +11,16 @@ class PresetsModel : public QAbstractTableModel
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
PresetsModel(QObject *parent = nullptr);
|
||||||
PresetsModel(const std::map<QString, presets::Preset> &presets, QObject *parent = nullptr);
|
PresetsModel(const std::map<QString, presets::Preset> &presets, QObject *parent = nullptr);
|
||||||
|
PresetsModel(std::vector<presets::Preset> &&presets, QObject *parent = nullptr);
|
||||||
|
PresetsModel(const std::vector<presets::Preset> &presets, QObject *parent = nullptr);
|
||||||
~PresetsModel() override;
|
~PresetsModel() override;
|
||||||
|
|
||||||
|
void setPresets(const std::map<QString, presets::Preset> &presets);
|
||||||
|
void setPresets(std::vector<presets::Preset> &&presets);
|
||||||
|
void setPresets(const std::vector<presets::Preset> &presets);
|
||||||
|
|
||||||
const presets::Preset &getPreset(const QModelIndex &index) const;
|
const presets::Preset &getPreset(const QModelIndex &index) const;
|
||||||
const presets::Preset &getPreset(int row) const;
|
const presets::Preset &getPreset(int row) const;
|
||||||
|
|
||||||
|
@ -13,9 +13,6 @@ SamplesWidget::SamplesWidget(QWidget *parent) :
|
|||||||
{
|
{
|
||||||
m_ui->setupUi(this);
|
m_ui->setupUi(this);
|
||||||
|
|
||||||
m_cache.setCacheDirectory("cache");
|
|
||||||
m_networkAccessManager.setCache(&m_cache);
|
|
||||||
|
|
||||||
connect(m_ui->checkBox, &QCheckBox::toggled, this, &SamplesWidget::updateWidgets);
|
connect(m_ui->checkBox, &QCheckBox::toggled, this, &SamplesWidget::updateWidgets);
|
||||||
|
|
||||||
connect(m_ui->pushButtonStopAll, &QAbstractButton::pressed, this, &SamplesWidget::stopAll);
|
connect(m_ui->pushButtonStopAll, &QAbstractButton::pressed, this, &SamplesWidget::stopAll);
|
||||||
@ -24,7 +21,6 @@ SamplesWidget::SamplesWidget(QWidget *parent) :
|
|||||||
for (SampleWidget &widget : getWidgets())
|
for (SampleWidget &widget : getWidgets())
|
||||||
{
|
{
|
||||||
widget.setPadNr(padNr++);
|
widget.setPadNr(padNr++);
|
||||||
widget.injectNetworkAccessManager(m_networkAccessManager);
|
|
||||||
connect(&widget, &SampleWidget::chokeTriggered, this, &SamplesWidget::chokeTriggered);
|
connect(&widget, &SampleWidget::chokeTriggered, this, &SamplesWidget::chokeTriggered);
|
||||||
connect(&widget, &SampleWidget::sendMidi, this, &SamplesWidget::sendMidi);
|
connect(&widget, &SampleWidget::sendMidi, this, &SamplesWidget::sendMidi);
|
||||||
}
|
}
|
||||||
@ -78,12 +74,24 @@ void SamplesWidget::writeSamples(frame_t *begin, frame_t *end)
|
|||||||
widget.writeSamples(begin, end);
|
widget.writeSamples(begin, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SamplesWidget::injectNetworkAccessManager(QNetworkAccessManager &networkAccessManager)
|
||||||
|
{
|
||||||
|
for (SampleWidget &widget : getWidgets())
|
||||||
|
widget.injectNetworkAccessManager(networkAccessManager);
|
||||||
|
}
|
||||||
|
|
||||||
void SamplesWidget::injectDecodingThread(QThread &thread)
|
void SamplesWidget::injectDecodingThread(QThread &thread)
|
||||||
{
|
{
|
||||||
for (SampleWidget &widget : getWidgets())
|
for (SampleWidget &widget : getWidgets())
|
||||||
widget.injectDecodingThread(thread);
|
widget.injectDecodingThread(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SamplesWidget::unsendColors()
|
||||||
|
{
|
||||||
|
for (SampleWidget &widget : getWidgets())
|
||||||
|
widget.unsendColor();
|
||||||
|
}
|
||||||
|
|
||||||
void SamplesWidget::sendColors()
|
void SamplesWidget::sendColors()
|
||||||
{
|
{
|
||||||
for (SampleWidget &widget : getWidgets())
|
for (SampleWidget &widget : getWidgets())
|
||||||
|
@ -5,14 +5,13 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QNetworkAccessManager>
|
|
||||||
#include <QNetworkDiskCache>
|
|
||||||
|
|
||||||
#include "audioformat.h"
|
#include "audioformat.h"
|
||||||
#include "presets.h"
|
#include "presets.h"
|
||||||
|
|
||||||
namespace Ui { class SamplesWidget; }
|
namespace Ui { class SamplesWidget; }
|
||||||
namespace midi { class MidiMessage; }
|
namespace midi { class MidiMessage; }
|
||||||
|
class QNetworkAccessManager;
|
||||||
class SampleWidget;
|
class SampleWidget;
|
||||||
class DrumMachineSettings;
|
class DrumMachineSettings;
|
||||||
|
|
||||||
@ -32,8 +31,10 @@ public:
|
|||||||
|
|
||||||
void writeSamples(frame_t *begin, frame_t *end);
|
void writeSamples(frame_t *begin, frame_t *end);
|
||||||
|
|
||||||
|
void injectNetworkAccessManager(QNetworkAccessManager &networkAccessManager);
|
||||||
void injectDecodingThread(QThread &thread);
|
void injectDecodingThread(QThread &thread);
|
||||||
|
|
||||||
|
void unsendColors();
|
||||||
void sendColors();
|
void sendColors();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
@ -52,8 +53,5 @@ private:
|
|||||||
|
|
||||||
const std::unique_ptr<Ui::SamplesWidget> m_ui;
|
const std::unique_ptr<Ui::SamplesWidget> m_ui;
|
||||||
|
|
||||||
QNetworkDiskCache m_cache;
|
|
||||||
QNetworkAccessManager m_networkAccessManager;
|
|
||||||
|
|
||||||
presets::Preset m_preset;
|
presets::Preset m_preset;
|
||||||
};
|
};
|
||||||
|
@ -183,6 +183,19 @@ void SampleWidget::learn(quint8 channel, quint8 note)
|
|||||||
learnPressed();
|
learnPressed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SampleWidget::unsendColor()
|
||||||
|
{
|
||||||
|
midi::MidiMessage midiMsg;
|
||||||
|
|
||||||
|
midiMsg.channel = m_ui->channelSpinBox->value();
|
||||||
|
midiMsg.cmd = midi::Command::NoteOn;
|
||||||
|
midiMsg.flag = true;
|
||||||
|
midiMsg.note = m_ui->noteSpinBox->value();
|
||||||
|
midiMsg.velocity = 0;
|
||||||
|
|
||||||
|
emit sendMidi(midiMsg);
|
||||||
|
}
|
||||||
|
|
||||||
void SampleWidget::sendColor()
|
void SampleWidget::sendColor()
|
||||||
{
|
{
|
||||||
midi::MidiMessage midiMsg;
|
midi::MidiMessage midiMsg;
|
||||||
|
@ -58,14 +58,14 @@ public:
|
|||||||
bool isLearning() const { return m_learning; }
|
bool isLearning() const { return m_learning; }
|
||||||
void learn(quint8 channel, quint8 note);
|
void learn(quint8 channel, quint8 note);
|
||||||
|
|
||||||
|
void unsendColor();
|
||||||
|
void sendColor();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void chokeTriggered(int choke);
|
void chokeTriggered(int choke);
|
||||||
void startDecoding(const std::shared_ptr<QIODevice> &device);
|
void startDecoding(const std::shared_ptr<QIODevice> &device);
|
||||||
void sendMidi(const midi::MidiMessage &midiMsg);
|
void sendMidi(const midi::MidiMessage &midiMsg);
|
||||||
|
|
||||||
public slots:
|
|
||||||
void sendColor();
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void updateStatus();
|
void updateStatus();
|
||||||
void requestFinished();
|
void requestFinished();
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>400</width>
|
<width>140</width>
|
||||||
<height>300</height>
|
<height>157</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -63,8 +63,14 @@
|
|||||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="pushButton">
|
<widget class="QPushButton" name="pushButton">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>PushButton</string>
|
<string>▶</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -119,9 +125,6 @@
|
|||||||
<property name="frameShadow">
|
<property name="frameShadow">
|
||||||
<enum>QFrame::Sunken</enum>
|
<enum>QFrame::Sunken</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
|
||||||
<string>TextLabel</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -132,9 +135,6 @@
|
|||||||
<property name="frameShadow">
|
<property name="frameShadow">
|
||||||
<enum>QFrame::Sunken</enum>
|
<enum>QFrame::Sunken</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
|
||||||
<string>TextLabel</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -145,9 +145,6 @@
|
|||||||
<property name="frameShadow">
|
<property name="frameShadow">
|
||||||
<enum>QFrame::Sunken</enum>
|
<enum>QFrame::Sunken</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
|
||||||
<string>TextLabel</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -42,6 +42,6 @@ private:
|
|||||||
|
|
||||||
QTimer m_timer;
|
QTimer m_timer;
|
||||||
|
|
||||||
int m_pos;
|
int m_pos{};
|
||||||
std::array<QLabel*, 24> m_sampleLabels;
|
std::array<QLabel*, 24> m_sampleLabels;
|
||||||
};
|
};
|
||||||
|
@ -6,10 +6,6 @@
|
|||||||
|
|
||||||
constexpr double pi = std::acos(-1);
|
constexpr double pi = std::acos(-1);
|
||||||
|
|
||||||
void Synthisizer::loadSettings(const DrumMachineSettings &settings)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Synthisizer::writeSamples(frame_t *begin, frame_t *end)
|
void Synthisizer::writeSamples(frame_t *begin, frame_t *end)
|
||||||
{
|
{
|
||||||
const auto frequency = m_frequency;
|
const auto frequency = m_frequency;
|
||||||
|
@ -9,14 +9,15 @@ class DrumMachineSettings;
|
|||||||
class Synthisizer
|
class Synthisizer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void loadSettings(const DrumMachineSettings &settings);
|
|
||||||
|
|
||||||
void setFrequency(int16_t frequency) { m_frequency = frequency; }
|
void setFrequency(int16_t frequency) { m_frequency = frequency; }
|
||||||
|
|
||||||
void writeSamples(frame_t *begin, frame_t *end);
|
void writeSamples(frame_t *begin, frame_t *end);
|
||||||
|
|
||||||
void messageReceived(const midi::MidiMessage &message);
|
void messageReceived(const midi::MidiMessage &message);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void sendMidi(const midi::MidiMessage &midiMsg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int16_t m_frequency{};
|
int16_t m_frequency{};
|
||||||
int16_t m_actualFrequency{};
|
int16_t m_actualFrequency{};
|
||||||
|
33
synthisizerwidget.cpp
Normal file
33
synthisizerwidget.cpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include "synthisizerwidget.h"
|
||||||
|
#include "ui_synthisizerwidget.h"
|
||||||
|
|
||||||
|
SynthisizerWidget::SynthisizerWidget(QWidget *parent) :
|
||||||
|
QWidget{parent},
|
||||||
|
m_ui{std::make_unique<Ui::SynthisizerWidget>()}
|
||||||
|
{
|
||||||
|
m_ui->setupUi(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
SynthisizerWidget::~SynthisizerWidget() = default;
|
||||||
|
|
||||||
|
void SynthisizerWidget::writeSamples(frame_t *begin, frame_t *end)
|
||||||
|
{
|
||||||
|
m_synthisizer.writeSamples(begin, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SynthisizerWidget::loadSettings(DrumMachineSettings &settings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SynthisizerWidget::unsendColors()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SynthisizerWidget::sendColors()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SynthisizerWidget::messageReceived(const midi::MidiMessage &message)
|
||||||
|
{
|
||||||
|
m_synthisizer.messageReceived(message);
|
||||||
|
}
|
35
synthisizerwidget.h
Normal file
35
synthisizerwidget.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "synthisizer.h"
|
||||||
|
#include "audioformat.h"
|
||||||
|
|
||||||
|
namespace Ui { class SynthisizerWidget; }
|
||||||
|
class DrumMachineSettings;
|
||||||
|
|
||||||
|
class SynthisizerWidget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SynthisizerWidget(QWidget *parent = nullptr);
|
||||||
|
~SynthisizerWidget() override;
|
||||||
|
|
||||||
|
void writeSamples(frame_t *begin, frame_t *end);
|
||||||
|
void loadSettings(DrumMachineSettings &settings);
|
||||||
|
void unsendColors();
|
||||||
|
void sendColors();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void sendMidi(const midi::MidiMessage &midiMsg);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void messageReceived(const midi::MidiMessage &message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::unique_ptr<Ui::SynthisizerWidget> m_ui;
|
||||||
|
|
||||||
|
Synthisizer m_synthisizer;
|
||||||
|
};
|
32
synthisizerwidget.ui
Normal file
32
synthisizerwidget.ui
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>SynthisizerWidget</class>
|
||||||
|
<widget class="QWidget" name="SynthisizerWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>30</x>
|
||||||
|
<y>60</y>
|
||||||
|
<width>221</width>
|
||||||
|
<height>31</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Hier könnte ihr Synthisizer stehen.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
Reference in New Issue
Block a user