Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: simplify waveform combobox #13220

Merged
merged 19 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
d065b8c
feat: simplify waveform combobox
acolombier May 7, 2024
0ace13e
Merge RGB and LRRGB into a single renderer with options
acolombier May 8, 2024
0907c2e
Add option to for signal split waveform
acolombier May 8, 2024
10c4e51
Add waveform option detection and change UI
acolombier May 11, 2024
038c68c
Update the restore slot and remove useless config key
acolombier May 12, 2024
503cd7c
Code style update
acolombier May 20, 2024
10a011a
Merge remote-tracking branch 'upstream/main' into feat/simplify-wavef…
acolombier May 20, 2024
b79a625
Add support for newly introduced filtered waveforms
acolombier May 20, 2024
7bc930a
Reduce the code in macro and use a generic option modifier
acolombier May 20, 2024
4915865
Add TODO for new code
acolombier May 20, 2024
04d9d23
Fix the update path and add tests
acolombier May 21, 2024
9536d13
Don't show VSync if not in developer mode
acolombier May 21, 2024
b4a37b2
Merge remote-tracking branch 'upstream/main' into feat/simplify-wavef…
acolombier May 21, 2024
5c3551d
single waveformwidget class for all allshader waveform widget types, …
May 21, 2024
2155dcc
restored the software renderering (non-opengl) waveforms, deprecated …
May 21, 2024
af24756
Few nits and improve upgrade procedure
acolombier May 22, 2024
f4866ac
Use an enum class for WaveformOption
acolombier May 24, 2024
d414a6e
Bump config version upgrade to 2.6
acolombier May 30, 2024
06c2015
Merge remote-tracking branch 'upstream/main' into feat/simplify-wavef…
acolombier May 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 2 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1521,7 +1521,6 @@ if(QOPENGL)
src/waveform/renderers/allshader/waveformrendererslipmode.cpp
src/waveform/renderers/allshader/waveformrendererfiltered.cpp
src/waveform/renderers/allshader/waveformrendererhsv.cpp
src/waveform/renderers/allshader/waveformrendererlrrgb.cpp
src/waveform/renderers/allshader/waveformrendererpreroll.cpp
src/waveform/renderers/allshader/waveformrendererrgb.cpp
src/waveform/renderers/allshader/waveformrenderertextured.cpp
Expand All @@ -1531,14 +1530,10 @@ if(QOPENGL)
src/waveform/renderers/allshader/waveformrendermarkrange.cpp
src/waveform/widgets/allshader/filteredwaveformwidget.cpp
src/waveform/widgets/allshader/hsvwaveformwidget.cpp
src/waveform/widgets/allshader/lrrgbwaveformwidget.cpp
src/waveform/widgets/allshader/rgbwaveformwidget.cpp
src/waveform/widgets/allshader/rgbstackedwaveformwidget.cpp
src/waveform/widgets/allshader/stackedwaveformwidget.cpp
src/waveform/widgets/allshader/simplewaveformwidget.cpp
src/waveform/widgets/allshader/waveformwidget.cpp
src/waveform/widgets/allshader/waveformwidgettexturedfiltered.cpp
src/waveform/widgets/allshader/waveformwidgettexturedrgb.cpp
src/waveform/widgets/allshader/waveformwidgettexturedstacked.cpp
src/widget/openglwindow.cpp
src/widget/tooltipqopengl.cpp
src/widget/wglwidgetqopengl.cpp
Expand Down Expand Up @@ -2194,6 +2189,7 @@ add_executable(mixxx-test
src/test/wbatterytest.cpp
src/test/wpushbutton_test.cpp
src/test/wwidgetstack_test.cpp
src/test/waveform_upgrade_test.cpp
src/util/moc_included_test.cpp
)
target_precompile_headers(mixxx-test REUSE_FROM mixxx-lib)
Expand Down
7 changes: 4 additions & 3 deletions res/shaders/rgbsignal.frag
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ uniform vec4 axesColor;
uniform vec4 lowColor;
uniform vec4 midColor;
uniform vec4 highColor;
uniform bool splitStereoSignal;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@m0dB do you know what happens if the shader program doesn't bind the uniform? Is there a consistent default value? Just wondering what to do in the deprecated renderer


uniform int waveformLength;
uniform int textureSize;
Expand All @@ -21,8 +22,8 @@ uniform sampler2D waveformDataTexture;

vec4 getWaveformData(float index) {
vec2 uv_data;
uv_data.y = floor(index / float(textureStride));
uv_data.x = floor(index - uv_data.y * float(textureStride));
uv_data.y = splitStereoSignal ? floor(index / float(textureStride)) : max(floor(index / float(textureStride)), floor((index + 1) / float(textureStride)));
uv_data.x = splitStereoSignal ? floor(index - uv_data.y * float(textureStride)) : max(floor(index - uv_data.y * float(textureStride)), floor((index + 1) - uv_data.y * float(textureStride)));
// Divide again to convert to normalized UV coordinates.
return texture2D(waveformDataTexture, uv_data / float(textureStride));
}
Expand All @@ -36,7 +37,7 @@ void main(void) {

// Texture coordinates put (0,0) at the bottom left, so show the right
// channel if we are in the bottom half.
if (uv.y < 0.5) {
if (uv.y < 0.5 && splitStereoSignal) {
new_currentIndex += 1;
}

Expand Down
222 changes: 209 additions & 13 deletions src/preferences/dialog/dlgprefwaveform.cpp
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking at dlg* code is always too tedious for me. Maybe @ronso0 has energy to do so?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I'm sorry. I have no idea about the waveforms, let alone the latest changes and what the options depend on.

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
#include "waveform/renderers/waveformwidgetrenderer.h"
#include "waveform/waveformwidgetfactory.h"

namespace {
constexpr WaveformWidgetType::Type kDefaultWaveform = WaveformWidgetType::RGB;
} // anonymous namespace
acolombier marked this conversation as resolved.
Show resolved Hide resolved

DlgPrefWaveform::DlgPrefWaveform(
QWidget* pParent,
UserSettingsPointer pConfig,
Expand All @@ -19,17 +23,20 @@ DlgPrefWaveform::DlgPrefWaveform(

// Waveform overview init
waveformOverviewComboBox->addItem(tr("Filtered")); // "0"
waveformOverviewComboBox->addItem(tr("HSV")); // "1"
waveformOverviewComboBox->addItem(tr("RGB")); // "2"
waveformOverviewComboBox->addItem(tr("HSV")); // "1"
waveformOverviewComboBox->addItem(tr("RGB")); // "2"

// Populate waveform options.
WaveformWidgetFactory* factory = WaveformWidgetFactory::instance();
// We assume that the original type list order remains constant.
// We will use the type index later on to set waveform types and to
// update the combobox.
QVector<WaveformWidgetAbstractHandle> handles = factory->getAvailableTypes();
for (int i = 0; i < handles.size(); ++i) {
waveformTypeComboBox->addItem(handles[i].getDisplayName(), i);
QVector<WaveformWidgetAbstractHandle> types = factory->getAvailableTypes();
for (int i = 0; i < types.size(); ++i) {
if (types[i].getType() == WaveformWidgetType::Empty) {
continue;
}
waveformTypeComboBox->addItem(types[i].getDisplayName(), types[i].getType());
acolombier marked this conversation as resolved.
Show resolved Hide resolved
}
// Sort the combobox items alphabetically
waveformTypeComboBox->model()->sort(0);
Expand Down Expand Up @@ -88,10 +95,28 @@ DlgPrefWaveform::DlgPrefWaveform(
beatGridAlphaSlider,
&QSlider::setValue);

connect(useWaveformCheckBox,
&QCheckBox::clicked,
this,
&DlgPrefWaveform::slotSetWaveformEnabled);

connect(waveformTypeComboBox,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this,
&DlgPrefWaveform::slotSetWaveformType);

connect(useAccelerationCheckBox,
&QCheckBox::clicked,
this,
&DlgPrefWaveform::slotSetWaveformAcceleration);
connect(splitLeftRightCheckBox,
&QCheckBox::clicked,
this,
&DlgPrefWaveform::slotSetWaveformOptionSplitStereoSignal);
connect(highDetailCheckBox,
&QCheckBox::clicked,
this,
&DlgPrefWaveform::slotSetWaveformOptionHighDetail);
connect(defaultZoomComboBox,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this,
Expand Down Expand Up @@ -159,21 +184,59 @@ DlgPrefWaveform::DlgPrefWaveform(
DlgPrefWaveform::~DlgPrefWaveform() {
}

void DlgPrefWaveform::slotSetWaveformOptions(
allshader::WaveformRendererSignalBase::Option option, bool enabled) {
int currentOption = m_pConfig->getValue(
ConfigKey("[Waveform]", "waveform_options"),
allshader::WaveformRendererSignalBase::None);
m_pConfig->setValue(ConfigKey("[Waveform]", "waveform_options"),
enabled ? currentOption |
option
: currentOption ^
option);
auto type = static_cast<WaveformWidgetType::Type>(
waveformTypeComboBox->currentData().toInt());
auto* factory = WaveformWidgetFactory::instance();
factory->setWidgetTypeFromHandle(
factory->findHandleIndexFromType(type), true);
}

void DlgPrefWaveform::slotUpdate() {
WaveformWidgetFactory* factory = WaveformWidgetFactory::instance();

bool isAccelerationEnabled = false;
if (factory->isOpenGlAvailable() || factory->isOpenGlesAvailable()) {
openGlStatusData->setText(factory->getOpenGLVersion());
useAccelerationCheckBox->setEnabled(true);
isAccelerationEnabled = m_pConfig->getValue(
ConfigKey("[Waveform]", "use_hardware_acceleration"),
factory->preferredBackend()) !=
WaveformWidgetBackend::None;
acolombier marked this conversation as resolved.
Show resolved Hide resolved
useAccelerationCheckBox->setChecked(isAccelerationEnabled);
} else {
openGlStatusData->setText(tr("OpenGL not available") + ": " + factory->getOpenGLVersion());
useAccelerationCheckBox->setEnabled(false);
useAccelerationCheckBox->setChecked(false);
}

// The combobox holds a list of [handle name, handle index]
int currentIndex = waveformTypeComboBox->findData(factory->getHandleIndex());
int currentIndex = waveformTypeComboBox->findData(factory->getType());
if (currentIndex != -1 && waveformTypeComboBox->currentIndex() != currentIndex) {
waveformTypeComboBox->setCurrentIndex(currentIndex);
}

bool useWaveform = factory->getType() != WaveformWidgetType::Empty;
useWaveformCheckBox->setChecked(useWaveform);

int currentOptions = m_pConfig->getValue(
ConfigKey("[Waveform]", "waveform_options"),
allshader::WaveformRendererSignalBase::None);
WaveformWidgetBackend backend = m_pConfig->getValue(
ConfigKey("[Waveform]", "use_hardware_acceleration"),
factory->preferredBackend());
updateWaveformAcceleration(factory->getType(), backend);
updateWaveformOption(useWaveform, backend, currentOptions);
waveformTypeComboBox->setEnabled(useWaveform);
updateEnableUntilMark();

frameRateSpinBox->setValue(factory->getFrameRate());
Expand Down Expand Up @@ -227,13 +290,23 @@ void DlgPrefWaveform::slotApply() {
void DlgPrefWaveform::slotResetToDefaults() {
WaveformWidgetFactory* factory = WaveformWidgetFactory::instance();

// Get the default we ought to use based on whether the user has OpenGL or not.
// Select the combobox index that holds the default handle's index in data column.
int defaultIndex = waveformTypeComboBox->findData(
factory->findHandleIndexFromType(factory->autoChooseWidgetType()));
kDefaultWaveform);
if (defaultIndex != -1 && waveformTypeComboBox->currentIndex() != defaultIndex) {
waveformTypeComboBox->setCurrentIndex(defaultIndex);
}
auto defaultBackend = factory->preferredBackend();
useWaveformCheckBox->setChecked(true);
waveformTypeComboBox->setEnabled(true);
updateWaveformAcceleration(kDefaultWaveform, defaultBackend);
updateWaveformOption(true, defaultBackend, allshader::WaveformRendererSignalBase::None);

// Restore waveform backend and option setting instantly
m_pConfig->setValue(ConfigKey("[Waveform]", "waveform_options"),
allshader::WaveformRendererSignalBase::None);
m_pConfig->setValue(ConfigKey("[Waveform]", "use_hardware_acceleration"),
defaultBackend);
factory->setWidgetTypeFromHandle(factory->findHandleIndexFromType(kDefaultWaveform), true);

allVisualGain->setValue(1.0);
lowVisualGain->setValue(1.0);
Expand Down Expand Up @@ -280,14 +353,137 @@ void DlgPrefWaveform::slotSetWaveformType(int index) {
if (index < 0) {
return;
}
int handleIndex = waveformTypeComboBox->itemData(index).toInt();
WaveformWidgetFactory::instance()->setWidgetTypeFromHandle(handleIndex);
auto type = static_cast<WaveformWidgetType::Type>(
waveformTypeComboBox->itemData(index).toInt());
auto* factory = WaveformWidgetFactory::instance();
factory->setWidgetTypeFromHandle(factory->findHandleIndexFromType(type));

auto backend = m_pConfig->getValue(
ConfigKey("[Waveform]", "use_hardware_acceleration"),
factory->preferredBackend());
useAccelerationCheckBox->setChecked(backend !=
WaveformWidgetBackend::None);

int currentOptions = m_pConfig->getValue(
ConfigKey("[Waveform]", "waveform_options"),
allshader::WaveformRendererSignalBase::None);
updateWaveformAcceleration(type, backend);
updateWaveformOption(true, backend, currentOptions);
updateEnableUntilMark();
}

void DlgPrefWaveform::slotSetWaveformEnabled(bool checked) {
auto* factory = WaveformWidgetFactory::instance();
if (!checked) {
factory->setWidgetTypeFromHandle(
factory->findHandleIndexFromType(WaveformWidgetType::Empty),
true);
} else {
auto type = static_cast<WaveformWidgetType::Type>(
waveformTypeComboBox->currentData().toInt());
factory->setWidgetTypeFromHandle(factory->findHandleIndexFromType(type), true);
}
slotUpdate();
}

void DlgPrefWaveform::slotSetWaveformAcceleration(bool checked) {
WaveformWidgetBackend backend = WaveformWidgetBackend::None;
if (checked) {
backend =
#ifdef MIXXX_USE_QOPENGL
WaveformWidgetBackend::AllShader
#else
WaveformWidgetBackend::GL
#endif
;
}
m_pConfig->setValue(
ConfigKey("[Waveform]", "use_hardware_acceleration"),
backend);
auto type = static_cast<WaveformWidgetType::Type>(waveformTypeComboBox->currentData().toInt());
auto* factory = WaveformWidgetFactory::instance();
factory->setWidgetTypeFromHandle(factory->findHandleIndexFromType(type), true);
int currentOptions = m_pConfig->getValue(
ConfigKey("[Waveform]", "waveform_options"),
allshader::WaveformRendererSignalBase::None);
updateWaveformOption(true, backend, currentOptions);
updateEnableUntilMark();
}

void DlgPrefWaveform::updateWaveformAcceleration(
WaveformWidgetType::Type type, WaveformWidgetBackend backend) {
auto* factory = WaveformWidgetFactory::instance();
int handleIdx = factory->findHandleIndexFromType(type);

bool supportAcceleration = false, supportSoftware = true;
if (handleIdx != -1) {
const auto& handle = factory->getAvailableTypes()[handleIdx];
supportAcceleration = handle.supportAcceleration();
supportSoftware = handle.supportSoftware();
}
useAccelerationCheckBox->blockSignals(true);

if (type == WaveformWidgetType::Empty) {
useAccelerationCheckBox->setChecked(false);
} else if (supportSoftware ^ supportAcceleration) {
useAccelerationCheckBox->setChecked(!supportSoftware || supportAcceleration);
} else {
useAccelerationCheckBox->setChecked(backend != WaveformWidgetBackend::None);
}

useAccelerationCheckBox->setEnabled(supportAcceleration &&
supportSoftware && type != WaveformWidgetType::Empty);

useAccelerationCheckBox->blockSignals(false);
}
void DlgPrefWaveform::updateWaveformOption(
bool useWaveform, WaveformWidgetBackend backend, int currentOption) {
splitLeftRightCheckBox->blockSignals(true);
highDetailCheckBox->blockSignals(true);

#ifdef MIXXX_USE_QOPENGL
WaveformWidgetFactory* factory = WaveformWidgetFactory::instance();
int supportedOption = allshader::WaveformRendererSignalBase::None;

auto type = static_cast<WaveformWidgetType::Type>(waveformTypeComboBox->currentData().toInt());
int handleIdx = factory->findHandleIndexFromType(type);

if (handleIdx != -1) {
supportedOption = factory->getAvailableTypes()[handleIdx].supportedOptions(backend);
}

splitLeftRightCheckBox->setEnabled(useWaveform &&
supportedOption &
allshader::WaveformRendererSignalBase::SplitStereoSignal);
highDetailCheckBox->setEnabled(useWaveform &&
supportedOption &
allshader::WaveformRendererSignalBase::HighDetail);
splitLeftRightCheckBox->setChecked(splitLeftRightCheckBox->isEnabled() &&
currentOption &
allshader::WaveformRendererSignalBase::SplitStereoSignal);
highDetailCheckBox->setChecked(highDetailCheckBox->isEnabled() &&
currentOption & allshader::WaveformRendererSignalBase::HighDetail);
#else
splitLeftRightCheckBox->setVisible(false);
highDetailCheckBox->setVisible(false);
#endif

splitLeftRightCheckBox->blockSignals(false);
highDetailCheckBox->blockSignals(false);
}

void DlgPrefWaveform::updateEnableUntilMark() {
const bool enabled = WaveformWidgetFactory::instance()->widgetTypeSupportsUntilMark();
#ifndef MIXXX_USE_QOPENGL
const bool enabled = false;
#else
WaveformWidgetFactory* factory = WaveformWidgetFactory::instance();
const bool enabled =
WaveformWidgetFactory::instance()->widgetTypeSupportsUntilMark() &&
m_pConfig->getValue(
ConfigKey("[Waveform]", "use_hardware_acceleration"),
factory->preferredBackend()) !=
WaveformWidgetBackend::None;
#endif
untilMarkShowBeatsCheckBox->setEnabled(enabled);
untilMarkShowTimeCheckBox->setEnabled(enabled);
untilMarkAlignLabel->setEnabled(enabled);
Expand All @@ -298,7 +494,7 @@ void DlgPrefWaveform::updateEnableUntilMark() {
}

void DlgPrefWaveform::slotSetWaveformOverviewType(int index) {
m_pConfig->set(ConfigKey("[Waveform]","WaveformOverviewType"), ConfigValue(index));
m_pConfig->set(ConfigKey("[Waveform]", "WaveformOverviewType"), ConfigValue(index));
emit reloadUserInterface();
}

Expand Down