Fixed ordering of loop station samples and lots of other improvements

This commit is contained in:
2022-12-30 13:33:49 +01:00
parent c843b39110
commit d2a931274b
12 changed files with 1068 additions and 220 deletions

View File

@ -6,28 +6,70 @@
<rect>
<x>0</x>
<y>0</y>
<width>660</width>
<height>421</height>
<width>317</width>
<height>159</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,0" columnstretch="0,0,0,0,0,0,0,0,0">
<item row="3" column="3">
<widget class="DrumPadSampleWidget" name="sampleWidget_9" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_9">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="DrumPadSampleWidget" name="sampleWidget_12" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_12">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="DrumPadSampleWidget" name="sampleWidget_13" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_13">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="1" column="7">
<widget class="DrumPadSampleWidget" name="sampleWidget_15" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_15">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="2" column="7">
<widget class="DrumPadSampleWidget" name="sampleWidget_18" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_18">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="4" column="6">
<widget class="DrumPadSampleWidget" name="sampleWidget_23" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_23">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="0" column="0" colspan="9">
<layout class="QHBoxLayout" name="horizontalLayout">
@ -74,10 +116,24 @@
</layout>
</item>
<item row="3" column="2">
<widget class="DrumPadSampleWidget" name="sampleWidget_8" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_8">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="4" column="7">
<widget class="DrumPadSampleWidget" name="sampleWidget_24" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_24">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="1" column="0">
<spacer name="horizontalSpacer_2">
@ -93,13 +149,34 @@
</spacer>
</item>
<item row="1" column="1">
<widget class="DrumPadSampleWidget" name="sampleWidget_1" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_1">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="3" column="5">
<widget class="DrumPadSampleWidget" name="sampleWidget_19" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_19">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="3" column="7">
<widget class="DrumPadSampleWidget" name="sampleWidget_21" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_21">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="1" column="8">
<spacer name="horizontalSpacer_3">
@ -115,16 +192,44 @@
</spacer>
</item>
<item row="2" column="2">
<widget class="DrumPadSampleWidget" name="sampleWidget_5" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_5">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="DrumPadSampleWidget" name="sampleWidget_2" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_2">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="2" column="6">
<widget class="DrumPadSampleWidget" name="sampleWidget_17" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_17">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="3" column="6">
<widget class="DrumPadSampleWidget" name="sampleWidget_20" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_20">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="1" column="4">
<spacer name="horizontalSpacer">
@ -140,38 +245,101 @@
</spacer>
</item>
<item row="2" column="5">
<widget class="DrumPadSampleWidget" name="sampleWidget_16" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_16">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="DrumPadSampleWidget" name="sampleWidget_4" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_4">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="4" column="5">
<widget class="DrumPadSampleWidget" name="sampleWidget_22" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_22">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="DrumPadSampleWidget" name="sampleWidget_11" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_11">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="DrumPadSampleWidget" name="sampleWidget_3" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_3">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="1" column="6">
<widget class="DrumPadSampleWidget" name="sampleWidget_14" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_14">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="DrumPadSampleWidget" name="sampleWidget_10" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_10">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="DrumPadSampleWidget" name="sampleWidget_6" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_6">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="DrumPadSampleWidget" name="sampleWidget_7" native="true"/>
<widget class="DrumPadSampleWidget" name="sampleWidget_7">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>DrumPadSampleWidget</class>
<extends>QWidget</extends>
<extends>QFrame</extends>
<header>widgets/drumpadsamplewidget.h</header>
<container>1</container>
</customwidget>

View File

@ -209,8 +209,7 @@ void DrumPadSampleWidget::sendColor()
void DrumPadSampleWidget::updateStatus()
{
QPalette pal;
QColor newColor;
if (m_file && m_file->color && m_player.buffer().isValid())
{
const auto bright = m_player.playing() ? 255 : 155;
@ -224,19 +223,29 @@ void DrumPadSampleWidget::updateStatus()
const auto &color = *m_file->color;
if (color == "purple")
pal.setColor(QPalette::Window, QColor{bright, dark, bright});
newColor = QColor{bright, dark, bright};
else if (color == "red")
pal.setColor(QPalette::Window, QColor{bright, dark, dark});
newColor = QColor{bright, dark, dark};
else if (color == "yellow")
pal.setColor(QPalette::Window, QColor{bright, bright, dark});
newColor = QColor{bright, bright, dark};
else if (color == "green")
pal.setColor(QPalette::Window, QColor{dark, bright, dark});
newColor = QColor{dark, bright, dark};
else if (color == "blue")
pal.setColor(QPalette::Window, QColor{dark, dark, bright});
newColor = QColor{dark, dark, bright};
else
{
qWarning() << "unknown color:" << color;
newColor = QColor{dark, dark, dark};
}
}
if (newColor.isValid() && (!m_lastColor.isValid() || newColor != m_lastColor))
{
QPalette pal;
pal.setColor(QPalette::Window, newColor);
m_lastColor = newColor;
setPalette(pal);
}
setPalette(pal);
if (m_sendColors)
sendColor();

View File

@ -85,4 +85,6 @@ private:
quint8 m_padNr{};
bool m_sendColors{};
QColor m_lastColor;
};

View File

@ -178,6 +178,12 @@
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimum">
<number>-2147483647</number>
</property>
<property name="maximum">
<number>2147483647</number>
</property>
</widget>
</item>
<item row="5" column="1">
@ -195,6 +201,12 @@
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimum">
<number>-2147483647</number>
</property>
<property name="maximum">
<number>2147483647</number>
</property>
</widget>
</item>
<item row="7" column="1">

View File

@ -9,12 +9,45 @@ LoopStationSamplesWidget::LoopStationSamplesWidget(QWidget *parent) :
{
m_ui->setupUi(this);
connect(m_ui->spinBoxBpm, qOverload<int>(&QSpinBox::valueChanged), this, &LoopStationSamplesWidget::tempoChanged);
connect(m_ui->pushButtonPlayPause, &QAbstractButton::pressed, this, &LoopStationSamplesWidget::playPausePressed);
connect(m_ui->pushButtonStop, &QAbstractButton::pressed, this, &LoopStationSamplesWidget::stopPressed);
connect(&m_timer, &QTimer::timeout, this, &LoopStationSamplesWidget::timeout);
m_timer.setTimerType(Qt::PreciseTimer);
quint8 padNr{};
for (LoopStationSampleWidget &widget : getWidgets())
{
widget.setPadNr(padNr++);
connect(&widget, &LoopStationSampleWidget::sendMidi, this, &LoopStationSamplesWidget::sendMidi);
connect(&widget, &LoopStationSampleWidget::loopEnabled, this, &LoopStationSamplesWidget::loopEnabled);
}
constexpr const auto setCategories = [](auto category, auto *widget0, auto *widget1, auto *widget2, auto *widget3, auto *widget4, auto *widget5, auto *widget6, auto *widget7){
widget0->setCategory(category);
widget1->setCategory(category);
widget2->setCategory(category);
widget3->setCategory(category);
widget4->setCategory(category);
widget5->setCategory(category);
widget6->setCategory(category);
widget7->setCategory(category);
};
setCategories(0, m_ui->sampleWidget0, m_ui->sampleWidget1, m_ui->sampleWidget2, m_ui->sampleWidget3,
m_ui->sampleWidget24, m_ui->sampleWidget25, m_ui->sampleWidget26, m_ui->sampleWidget27);
setCategories(1, m_ui->sampleWidget4, m_ui->sampleWidget5, m_ui->sampleWidget6, m_ui->sampleWidget7,
m_ui->sampleWidget28, m_ui->sampleWidget29, m_ui->sampleWidget30, m_ui->sampleWidget31);
setCategories(2, m_ui->sampleWidget8, m_ui->sampleWidget9, m_ui->sampleWidget10, m_ui->sampleWidget11,
m_ui->sampleWidget32, m_ui->sampleWidget33, m_ui->sampleWidget34, m_ui->sampleWidget35);
setCategories(3, m_ui->sampleWidget12, m_ui->sampleWidget13, m_ui->sampleWidget14, m_ui->sampleWidget15,
m_ui->sampleWidget36, m_ui->sampleWidget37, m_ui->sampleWidget38, m_ui->sampleWidget39);
setCategories(4, m_ui->sampleWidget16, m_ui->sampleWidget17, m_ui->sampleWidget18, m_ui->sampleWidget19,
m_ui->sampleWidget40, m_ui->sampleWidget41, m_ui->sampleWidget42, m_ui->sampleWidget43);
setCategories(5, m_ui->sampleWidget20, m_ui->sampleWidget21, m_ui->sampleWidget22, m_ui->sampleWidget23,
m_ui->sampleWidget44, m_ui->sampleWidget45, m_ui->sampleWidget46, m_ui->sampleWidget47);
}
LoopStationSamplesWidget::~LoopStationSamplesWidget() = default;
@ -29,17 +62,22 @@ void LoopStationSamplesWidget::setPreset(const loopstation_presets::Preset &pres
{
assert(preset.id);
assert(preset.pads);
assert(preset.bpm);
const auto &presetId = *preset.id;
const auto &widgets = getWidgets();
const auto &pads = *preset.pads;
stopPressed();
m_ui->spinBoxBpm->setValue(*preset.bpm);
auto iter = std::begin(widgets);
auto iter2 = std::begin(pads);
int i{};
for (; iter != std::end(widgets) && iter2 != std::end(pads); iter++, iter2++)
{
((*iter)).get().setSample(presetId, QString{"%0_%1.wav"}.arg(presetId).arg(++i, 2, 10, QLatin1Char('0')), *iter2);
auto &widget = ((*iter)).get();
widget.setSample(presetId, QString{"%0_%1.wav"}.arg(presetId).arg(++i, 2, 10, QLatin1Char('0')), *iter2);
}
}
@ -79,6 +117,78 @@ void LoopStationSamplesWidget::sendColors()
widget.sendColor();
}
void LoopStationSamplesWidget::timeout()
{
if (m_pos >= 7)
{
for (LoopStationSampleWidget &widget : getWidgets())
widget.timeout();
m_pos = 0;
}
else
{
if (m_pos == 3)
{
for (LoopStationSampleWidget &widget : getWidgets())
widget.timeout();
}
m_pos++;
}
m_ui->horizontalSlider->setValue(m_pos);
}
void LoopStationSamplesWidget::tempoChanged(int tempo)
{
m_timer.setInterval(1000. * 60. / tempo);
}
void LoopStationSamplesWidget::loopEnabled(quint8 category)
{
for (LoopStationSampleWidget &widget : getWidgets())
{
if (widget.category() != category)
continue;
if (&widget == sender())
continue;
widget.setLoopEnabled(false);
}
if (!m_timer.isActive())
{
m_pos = 0;
m_ui->horizontalSlider->setValue(m_pos);
m_timer.start();
for (LoopStationSampleWidget &widget : getWidgets())
widget.timeout();
}
}
void LoopStationSamplesWidget::playPausePressed()
{
if (m_timer.isActive())
m_timer.stop();
else
{
m_timer.start();
if (m_pos == 0)
for (LoopStationSampleWidget &widget : getWidgets())
widget.timeout();
}
}
void LoopStationSamplesWidget::stopPressed()
{
m_timer.stop();
for (LoopStationSampleWidget &widget : getWidgets())
{
widget.setLoopEnabled(false);
widget.stop();
}
m_pos = 0;
m_ui->horizontalSlider->setValue(m_pos);
}
std::array<std::reference_wrapper<LoopStationSampleWidget>, 48> LoopStationSamplesWidget::getWidgets()
{
return {

View File

@ -1,6 +1,7 @@
#pragma once
#include <QWidget>
#include <QTimer>
#include <memory>
#include <array>
@ -40,8 +41,19 @@ public:
signals:
void sendMidi(const midi::MidiMessage &midiMsg);
private slots:
void timeout();
void tempoChanged(int tempo);
void loopEnabled(quint8 category);
void playPausePressed();
void stopPressed();
private:
std::array<std::reference_wrapper<LoopStationSampleWidget>, 48> getWidgets();
const std::unique_ptr<Ui::LoopStationSamplesWidget> m_ui;
QTimer m_timer;
quint8 m_pos{};
};

View File

@ -6,126 +6,42 @@
<rect>
<x>0</x>
<y>0</y>
<width>1254</width>
<height>890</height>
<width>411</width>
<height>273</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="4">
<widget class="LoopStationSampleWidget" name="sampleWidget3" native="true"/>
</item>
<item row="2" column="1">
<widget class="LoopStationSampleWidget" name="sampleWidget4" native="true"/>
</item>
<item row="5" column="3">
<widget class="LoopStationSampleWidget" name="sampleWidget18" native="true"/>
</item>
<item row="4" column="1">
<widget class="LoopStationSampleWidget" name="sampleWidget12" native="true"/>
</item>
<item row="5" column="4">
<widget class="LoopStationSampleWidget" name="sampleWidget19" native="true"/>
</item>
<item row="1" column="9">
<widget class="LoopStationSampleWidget" name="sampleWidget27" native="true"/>
</item>
<item row="4" column="4">
<widget class="LoopStationSampleWidget" name="sampleWidget15" native="true"/>
</item>
<item row="6" column="3">
<widget class="LoopStationSampleWidget" name="sampleWidget22" native="true"/>
</item>
<item row="3" column="3">
<widget class="LoopStationSampleWidget" name="sampleWidget10" native="true"/>
</item>
<item row="2" column="10">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<item row="6" column="8">
<widget class="LoopStationSampleWidget" name="sampleWidget44">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</spacer>
</item>
<item row="3" column="4">
<widget class="LoopStationSampleWidget" name="sampleWidget11" native="true"/>
</item>
<item row="6" column="1">
<widget class="LoopStationSampleWidget" name="sampleWidget20" native="true"/>
</item>
<item row="3" column="1">
<widget class="LoopStationSampleWidget" name="sampleWidget8" native="true"/>
</item>
<item row="4" column="3">
<widget class="LoopStationSampleWidget" name="sampleWidget14" native="true"/>
</item>
<item row="6" column="2">
<widget class="LoopStationSampleWidget" name="sampleWidget21" native="true"/>
</item>
<item row="1" column="2">
<widget class="LoopStationSampleWidget" name="sampleWidget1" native="true"/>
</item>
<item row="5" column="1">
<widget class="LoopStationSampleWidget" name="sampleWidget16" native="true"/>
</item>
<item row="0" column="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<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 row="1" column="7">
<widget class="LoopStationSampleWidget" name="sampleWidget25" native="true"/>
</item>
<item row="4" column="2">
<widget class="LoopStationSampleWidget" name="sampleWidget13" native="true"/>
</item>
<item row="1" column="3">
<widget class="LoopStationSampleWidget" name="sampleWidget2" native="true"/>
</item>
<item row="3" column="2">
<widget class="LoopStationSampleWidget" name="sampleWidget9" native="true"/>
</item>
<item row="1" column="1">
<widget class="LoopStationSampleWidget" name="sampleWidget0" native="true"/>
</item>
<item row="1" column="6">
<widget class="LoopStationSampleWidget" name="sampleWidget24" native="true"/>
</item>
<item row="2" column="2">
<widget class="LoopStationSampleWidget" name="sampleWidget5" native="true"/>
</item>
<item row="6" column="4">
<widget class="LoopStationSampleWidget" name="sampleWidget23" native="true"/>
</item>
<item row="5" column="2">
<widget class="LoopStationSampleWidget" name="sampleWidget17" native="true"/>
</widget>
</item>
<item row="7" column="2">
<widget class="LoopStationSampleWidget" name="sampleWidget11">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="LoopStationSampleWidget" name="sampleWidget5">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="8" column="2">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
@ -138,16 +54,27 @@
</property>
</spacer>
</item>
<item row="2" column="3">
<widget class="LoopStationSampleWidget" name="sampleWidget6" native="true"/>
<item row="4" column="9">
<widget class="LoopStationSampleWidget" name="sampleWidget42">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="LoopStationSampleWidget" name="sampleWidget7" native="true"/>
<item row="6" column="1">
<widget class="LoopStationSampleWidget" name="sampleWidget8">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="1" column="8">
<widget class="LoopStationSampleWidget" name="sampleWidget26" native="true"/>
</item>
<item row="2" column="5">
<item row="3" column="5">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -160,72 +87,545 @@
</property>
</spacer>
</item>
<item row="2" column="6">
<widget class="LoopStationSampleWidget" name="sampleWidget28" native="true"/>
</item>
<item row="2" column="7">
<widget class="LoopStationSampleWidget" name="sampleWidget29" native="true"/>
<item row="3" column="2">
<widget class="LoopStationSampleWidget" name="sampleWidget3">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="2" column="8">
<widget class="LoopStationSampleWidget" name="sampleWidget30" native="true"/>
<widget class="LoopStationSampleWidget" name="sampleWidget36">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="2" column="9">
<widget class="LoopStationSampleWidget" name="sampleWidget31" native="true"/>
</item>
<item row="3" column="6">
<widget class="LoopStationSampleWidget" name="sampleWidget32" native="true"/>
</item>
<item row="3" column="7">
<widget class="LoopStationSampleWidget" name="sampleWidget33" native="true"/>
</item>
<item row="3" column="8">
<widget class="LoopStationSampleWidget" name="sampleWidget34" native="true"/>
</item>
<item row="3" column="9">
<widget class="LoopStationSampleWidget" name="sampleWidget35" native="true"/>
</item>
<item row="4" column="6">
<widget class="LoopStationSampleWidget" name="sampleWidget36" native="true"/>
</item>
<item row="4" column="7">
<widget class="LoopStationSampleWidget" name="sampleWidget37" native="true"/>
<item row="7" column="4">
<widget class="LoopStationSampleWidget" name="sampleWidget23">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="4" column="8">
<widget class="LoopStationSampleWidget" name="sampleWidget38" native="true"/>
<widget class="LoopStationSampleWidget" name="sampleWidget40">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="4" column="9">
<widget class="LoopStationSampleWidget" name="sampleWidget39" native="true"/>
<item row="4" column="3">
<widget class="LoopStationSampleWidget" name="sampleWidget16">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="7" column="7">
<widget class="LoopStationSampleWidget" name="sampleWidget35">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="3" column="7">
<widget class="LoopStationSampleWidget" name="sampleWidget27">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="LoopStationSampleWidget" name="sampleWidget2">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="3" column="8">
<widget class="LoopStationSampleWidget" name="sampleWidget37">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="4" column="6">
<widget class="LoopStationSampleWidget" name="sampleWidget28">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="7" column="6">
<widget class="LoopStationSampleWidget" name="sampleWidget33">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="LoopStationSampleWidget" name="sampleWidget1">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="LoopStationSampleWidget" name="sampleWidget0">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="1" column="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="6" column="3">
<widget class="LoopStationSampleWidget" name="sampleWidget20">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="5" column="6">
<widget class="LoopStationSampleWidget" name="sampleWidget40" native="true"/>
</item>
<item row="5" column="7">
<widget class="LoopStationSampleWidget" name="sampleWidget41" native="true"/>
</item>
<item row="5" column="8">
<widget class="LoopStationSampleWidget" name="sampleWidget42" native="true"/>
<widget class="LoopStationSampleWidget" name="sampleWidget29">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="5" column="9">
<widget class="LoopStationSampleWidget" name="sampleWidget43" native="true"/>
<widget class="LoopStationSampleWidget" name="sampleWidget43">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="6" column="6">
<widget class="LoopStationSampleWidget" name="sampleWidget44" native="true"/>
<item row="5" column="7">
<widget class="LoopStationSampleWidget" name="sampleWidget31">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="LoopStationSampleWidget" name="sampleWidget12">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="LoopStationSampleWidget" name="sampleWidget14">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="6" column="4">
<widget class="LoopStationSampleWidget" name="sampleWidget22">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="LoopStationSampleWidget" name="sampleWidget6">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="4" column="7">
<widget class="LoopStationSampleWidget" name="sampleWidget30">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="LoopStationSampleWidget" name="sampleWidget10">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="3" column="6">
<widget class="LoopStationSampleWidget" name="sampleWidget25">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="5" column="3">
<widget class="LoopStationSampleWidget" name="sampleWidget17">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="LoopStationSampleWidget" name="sampleWidget13">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="6" column="7">
<widget class="LoopStationSampleWidget" name="sampleWidget45" native="true"/>
<widget class="LoopStationSampleWidget" name="sampleWidget34">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="6" column="8">
<widget class="LoopStationSampleWidget" name="sampleWidget46" native="true"/>
<item row="7" column="1">
<widget class="LoopStationSampleWidget" name="sampleWidget9">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="4" column="4">
<widget class="LoopStationSampleWidget" name="sampleWidget18">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="3" column="9">
<widget class="LoopStationSampleWidget" name="sampleWidget39">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="5" column="4">
<widget class="LoopStationSampleWidget" name="sampleWidget19">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="6" column="6">
<widget class="LoopStationSampleWidget" name="sampleWidget32">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="2" column="9">
<widget class="LoopStationSampleWidget" name="sampleWidget38">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="7" column="8">
<widget class="LoopStationSampleWidget" name="sampleWidget45">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<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 row="7" column="9">
<widget class="LoopStationSampleWidget" name="sampleWidget47">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="7" column="3">
<widget class="LoopStationSampleWidget" name="sampleWidget21">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="LoopStationSampleWidget" name="sampleWidget4">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="5" column="8">
<widget class="LoopStationSampleWidget" name="sampleWidget41">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="2" column="7">
<widget class="LoopStationSampleWidget" name="sampleWidget26">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="LoopStationSampleWidget" name="sampleWidget7">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="2" column="6">
<widget class="LoopStationSampleWidget" name="sampleWidget24">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="3" column="4">
<widget class="LoopStationSampleWidget" name="sampleWidget15">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="6" column="9">
<widget class="LoopStationSampleWidget" name="sampleWidget47" native="true"/>
<widget class="LoopStationSampleWidget" name="sampleWidget46">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item row="3" column="10">
<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>
<item row="0" column="0" colspan="12">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="labelBpm">
<property name="text">
<string>Bpm:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBoxBpm">
<property name="suffix">
<string>BPM</string>
</property>
<property name="minimum">
<number>50</number>
</property>
<property name="maximum">
<number>500</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonPlayPause">
<property name="text">
<string>Play/Pause</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonStop">
<property name="text">
<string>Stop</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="horizontalSlider">
<property name="maximum">
<number>8</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<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>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LoopStationSampleWidget</class>
<extends>QWidget</extends>
<extends>QFrame</extends>
<header>widgets/loopstationsamplewidget.h</header>
<container>1</container>
</customwidget>

View File

@ -6,6 +6,7 @@
#include <QNetworkReply>
#include <QNetworkAccessManager>
#include <QMetaEnum>
#include <QPalette>
#include "audioformat.h"
#include "audiodecoder.h"
@ -20,13 +21,24 @@ LoopStationSampleWidget::LoopStationSampleWidget(QWidget *parent) :
connect(&m_player, &AudioPlayer::playingChanged, this, &LoopStationSampleWidget::updateStatus);
connect(m_ui->pushButtonPlay, &QAbstractButton::pressed, this, &LoopStationSampleWidget::pressed);
connect(m_ui->pushButtonPlay, &QAbstractButton::toggled, this, [this](bool toggled){
if (!toggled)
return;
emit loopEnabled(m_category);
});
updateStatus();
}
LoopStationSampleWidget::~LoopStationSampleWidget() = default;
void LoopStationSampleWidget::setCategory(quint8 category)
{
m_category = category;
m_ui->labelCategory->setText(QString::number(category));
updateStatus();
}
void LoopStationSampleWidget::loadSettings(DrumMachineSettings &settings)
{
m_settings = &settings;
@ -55,11 +67,6 @@ void LoopStationSampleWidget::setSample(const QString &presetId, const QString &
m_ui->labelType->setText(type);
}
void LoopStationSampleWidget::pressed()
{
m_player.restart();
}
void LoopStationSampleWidget::injectNetworkAccessManager(QNetworkAccessManager &networkAccessManager)
{
m_networkAccessManager = &networkAccessManager;
@ -111,11 +118,77 @@ void LoopStationSampleWidget::sendColor()
.flag = true,
.note = m_ui->pushButtonPlay->learnSetting().note,
.velocity = uint8_t(m_padNr+1)
});
});
}
void LoopStationSampleWidget::timeout()
{
if (m_ui->pushButtonPlay->isChecked())
{
// if is not playing or position > 90%
if (!m_player.playing() || m_player.position() >= m_player.buffer().frameCount() * 9 / 10)
m_player.restart();
}
else
{
// if is playing and position < 60%
if (m_player.playing() && m_player.position() < m_player.buffer().frameCount() * 6 / 10)
m_player.stop();
}
}
void LoopStationSampleWidget::setLoopEnabled(bool enabled)
{
m_ui->pushButtonPlay->setChecked(enabled);
}
void LoopStationSampleWidget::stop()
{
m_player.stop();
}
void LoopStationSampleWidget::updateStatus()
{
QColor newColor;
if (m_player.buffer().isValid())
{
const auto bright = m_player.playing() ? 255 : 155;
const auto dark = m_player.playing() ?
#if !defined(Q_OS_WIN)
80 : 0
#else
180 : 80
#endif
;
if (m_category == 0)
newColor = QColor{bright, dark, bright};
else if (m_category == 1)
newColor = QColor{bright, dark, dark};
else if (m_category == 2)
newColor = QColor{bright, bright, dark};
else if (m_category == 3)
newColor = QColor{dark, bright, dark};
else if (m_category == 4)
newColor = QColor{dark, dark, bright};
else if (m_category == 5)
newColor = QColor{dark, bright, bright};
else
{
qWarning() << "unknown category:" << m_category;
newColor = QColor{dark, dark, dark};
}
}
if (newColor.isValid() && (!m_lastColor.isValid() || newColor != m_lastColor))
{
QPalette pal;
pal.setColor(QPalette::Window, newColor);
m_lastColor = newColor;
setPalette(pal);
}
if (m_sendColors)
sendColor();

View File

@ -26,12 +26,13 @@ public:
quint8 padNr() const { return m_padNr; }
void setPadNr(quint8 padNr) { m_padNr = padNr; }
quint8 category() const { return m_category; }
void setCategory(quint8 category);
void loadSettings(DrumMachineSettings &settings);
void setSample(const QString &presetId, const QString &filename, const QString &type);
void pressed();
void injectNetworkAccessManager(QNetworkAccessManager &networkAccessManager);
void injectDecodingThread(QThread &thread);
@ -42,9 +43,15 @@ public:
void unsendColor();
void sendColor();
public slots:
void timeout();
void setLoopEnabled(bool enabled);
void stop();
signals:
void startDecoding(std::shared_ptr<QIODevice> device);
void sendMidi(const midi::MidiMessage &midiMsg);
void loopEnabled(quint8 category);
private slots:
void updateStatus();
@ -70,6 +77,9 @@ private:
QNetworkAccessManager *m_networkAccessManager{};
quint8 m_padNr{};
quint8 m_category{};
bool m_sendColors{};
QColor m_lastColor;
};

View File

@ -10,8 +10,8 @@
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
@ -29,6 +29,19 @@
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<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="MidiButton" name="pushButtonPlay">
<property name="maximumSize">
@ -40,8 +53,24 @@
<property name="text">
<string>▶</string>
</property>
<property name="checkable">
<bool>true</bool>
</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>
@ -52,11 +81,25 @@
</widget>
</item>
<item>
<widget class="QLabel" name="labelType">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="labelType">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelCategory">
<property name="text">
<string>TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>

View File

@ -100,7 +100,11 @@ void MidiButton::midiReceived(const midi::MidiMessage &message)
{
case midi::Command::NoteOn:
if (message.velocity != 0)
{
if (isCheckable())
toggle();
emit pressed();
}
else
Q_FALLTHROUGH();
case midi::Command::NoteOff:
@ -113,7 +117,11 @@ void MidiButton::midiReceived(const midi::MidiMessage &message)
else if (m_learnSetting.cmd == message.cmd)
{
if (message.velocity != 0)
{
if (isCheckable())
toggle();
emit pressed();
}
else
emit released();
}

View File

@ -26,9 +26,10 @@ SequencerWidget::SequencerWidget(QWidget *parent) :
connect(m_ui->horizontalSlider, &QSlider::valueChanged, this, [=](int value){ m_pos = value; updateStatusLabel(); });
connect(&m_timer, &QTimer::timeout, this, &SequencerWidget::timeout);
m_timer.setTimerType(Qt::PreciseTimer);
updateStatusLabel();
}
@ -204,8 +205,8 @@ void SequencerWidget::sequenceSelected()
m_ui->pushButtonPlayPause->setEnabled(m_selectedSequence != nullptr);
m_ui->pushButtonStop->setEnabled(m_selectedSequence != nullptr);
m_pos = 0;
m_ui->horizontalSlider->setValue(0);
m_pos = m_selectedSequence ? m_pos % 8 : 0;
m_ui->horizontalSlider->setValue(m_pos);
updateStatusLabel();
}