diff --git a/CMakeLists.txt b/CMakeLists.txt index c5de064a5..e20f13527 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,18 +6,7 @@ SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules" ${CMAKE_MODULE_PATH}) SET(LMMS_BINARY_DIR ${CMAKE_BINARY_DIR}) SET(LMMS_SOURCE_DIR ${CMAKE_SOURCE_DIR}) -IF(COMMAND CMAKE_POLICY) - CMAKE_POLICY(SET CMP0005 NEW) - CMAKE_POLICY(SET CMP0003 NEW) - IF (CMAKE_MAJOR_VERSION GREATER 2) - CMAKE_POLICY(SET CMP0026 NEW) - CMAKE_POLICY(SET CMP0045 NEW) - CMAKE_POLICY(SET CMP0050 OLD) - ENDIF() - CMAKE_POLICY(SET CMP0020 NEW) - CMAKE_POLICY(SET CMP0057 NEW) -ENDIF(COMMAND CMAKE_POLICY) - +# CMAKE_POLICY Section # Import of windows.h breaks min()/max() ADD_DEFINITIONS(-DNOMINMAX) @@ -505,7 +494,11 @@ IF(WANT_SF2) find_package(FluidSynth 1.1.0) if(FluidSynth_FOUND) SET(LMMS_HAVE_FLUIDSYNTH TRUE) - SET(STATUS_FLUIDSYNTH "OK") + if(FluidSynth_VERSION_STRING VERSION_GREATER_EQUAL 2) + set(STATUS_FLUIDSYNTH "OK") + else() + set(STATUS_FLUIDSYNTH "OK (FluidSynth version < 2: per-note panning unsupported)") + endif() else() SET(STATUS_FLUIDSYNTH "not found, libfluidsynth-dev (or similar)" "is highly recommended") @@ -616,7 +609,9 @@ else() set(NOOP_COMMAND "${CMAKE_COMMAND}" "-E" "echo") endif() if(STRIP) - set(STRIP_COMMAND "$,${NOOP_COMMAND},${STRIP}>") + # TODO CMake 3.19: Now that CONFIG generator expressions support testing for + # multiple configurations, combine the OR into a single CONFIG expression. + set(STRIP_COMMAND "$,$>,${NOOP_COMMAND},${STRIP}>") else() set(STRIP_COMMAND "${NOOP_COMMAND}") endif() diff --git a/README.md b/README.md index c64ca0a97..c8324226e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ![LMMS Logo](https://raw.githubusercontent.com/LMMS/artwork/master/Icon%20%26%20Mimetypes/lmms-64x64.svg) LMMS -[![Build status](https://circleci.com/gh/LMMS/lmms.svg?style=shield)](https://circleci.com/gh/LMMS/lmms) +[![Build status](https://github.com/LMMS/lmms/actions/workflows/build.yml/badge.svg)](https://github.com/LMMS/lmms/actions/workflows/build.yml) [![Latest stable release](https://img.shields.io/github/release/LMMS/lmms.svg?maxAge=3600)](https://lmms.io/download) [![Overall downloads on Github](https://img.shields.io/github/downloads/LMMS/lmms/total.svg?maxAge=3600)](https://github.com/LMMS/lmms/releases) [![Join the chat at Discord](https://img.shields.io/badge/chat-on%20discord-7289DA.svg)](https://discord.gg/3sc5su7) diff --git a/cmake/apple/install_apple.sh.in b/cmake/apple/install_apple.sh.in index df9300712..fc27d78b3 100644 --- a/cmake/apple/install_apple.sh.in +++ b/cmake/apple/install_apple.sh.in @@ -35,8 +35,6 @@ cd "$APP" find . -type f -print0 | xargs -0 chmod u+w lmmsbin="MacOS/@CMAKE_PROJECT_NAME@" -zynlib="lib/lmms/libzynaddsubfx.so" -zynfmk="Frameworks/libZynAddSubFxCore.dylib" zynbin="MacOS/RemoteZynAddSubFx" # Move lmms binary @@ -44,15 +42,6 @@ mv "$APP/Contents/bin/@CMAKE_PROJECT_NAME@" "$APP/Contents/$lmmsbin" # Fix zyn linking mv "$APP/Contents/lib/lmms/RemoteZynAddSubFx" "$APP/Contents/$zynbin" -mv "$APP/Contents/lib/lmms/libZynAddSubFxCore.dylib" "$APP/Contents/$zynfmk" - -install_name_tool -change @rpath/libZynAddSubFxCore.dylib \ - @loader_path/../$zynfmk \ - "$APP/Contents/$zynbin" - -install_name_tool -change @rpath/libZynAddSubFxCore.dylib \ - @loader_path/../../$zynfmk \ - "$APP/Contents/$zynlib" # Replace @rpath with @loader_path for Carla # See also plugins/CarlaBase/CMakeLists.txt @@ -67,7 +56,6 @@ install_name_tool -change @rpath/libcarlabase.dylib \ # Link lmms binary _executables="${_executables} -executable=$APP/Contents/$zynbin" -_executables="${_executables} -executable=$APP/Contents/$zynfmk" # Build a list of shared objects in target/lib/lmms for file in "$APP/Contents/lib/lmms/"*.so; do @@ -109,4 +97,8 @@ done # Cleanup rm -rf "$APP/Contents/bin" + +# Codesign +codesign --force --deep --sign - "$APP" + echo -e "\nFinished.\n\n" diff --git a/cmake/install/CMakeLists.txt b/cmake/install/CMakeLists.txt index 5ee731d16..3f6e3624e 100644 --- a/cmake/install/CMakeLists.txt +++ b/cmake/install/CMakeLists.txt @@ -48,5 +48,9 @@ endif() IF(LMMS_BUILD_APPLE) INSTALL(CODE "EXECUTE_PROCESS(COMMAND chmod u+x ${CMAKE_BINARY_DIR}/install_apple.sh)") - INSTALL(CODE "EXECUTE_PROCESS(COMMAND ${CMAKE_BINARY_DIR}/install_apple.sh)") + INSTALL(CODE "EXECUTE_PROCESS(COMMAND ${CMAKE_BINARY_DIR}/install_apple.sh RESULT_VARIABLE EXIT_CODE) + IF(NOT EXIT_CODE EQUAL 0) + MESSAGE(FATAL_ERROR \"Execution of install_apple.sh failed\") + ENDIF() + ") ENDIF() diff --git a/cmake/modules/DefineInstallVar.cmake b/cmake/modules/DefineInstallVar.cmake index b13cb1d52..0ca8fa429 100644 --- a/cmake/modules/DefineInstallVar.cmake +++ b/cmake/modules/DefineInstallVar.cmake @@ -24,7 +24,7 @@ function(DEFINE_INSTALL_VAR) endif() else() if(VAR_GENERATOR_EXPRESSION) - cmake_policy(SET CMP0087 NEW) + cmake_policy(SET CMP0087 NEW) # install(CODE) and install(SCRIPT) support generator expressions. endif() install(CODE "set(\"${VAR_NAME}\" \"${VAR_CONTENT}\")") endif() diff --git a/cmake/modules/InstallDependencies.cmake b/cmake/modules/InstallDependencies.cmake index 791041bb2..167a93f35 100644 --- a/cmake/modules/InstallDependencies.cmake +++ b/cmake/modules/InstallDependencies.cmake @@ -1,8 +1,8 @@ include(GetPrerequisites) include(CMakeParseArguments) -CMAKE_POLICY(SET CMP0011 NEW) -CMAKE_POLICY(SET CMP0057 NEW) +# Project's cmake_minimum_required doesn't always propagate +cmake_policy(SET CMP0057 NEW) # Support new if() IN_LIST operator. function(make_absolute var) get_filename_component(abs "${${var}}" ABSOLUTE BASE_DIR "${CMAKE_INSTALL_PREFIX}") diff --git a/cmake/modules/PluginList.cmake b/cmake/modules/PluginList.cmake index 6b2c7519a..0a4686fb2 100644 --- a/cmake/modules/PluginList.cmake +++ b/cmake/modules/PluginList.cmake @@ -63,6 +63,7 @@ SET(LMMS_PLUGIN_LIST StereoEnhancer StereoMatrix Stk + TapTempo VstBase Vestige VstEffect diff --git a/data/locale/ar.ts b/data/locale/ar.ts index 1f159c42a..0d44c22bf 100644 --- a/data/locale/ar.ts +++ b/data/locale/ar.ts @@ -6361,7 +6361,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/bs.ts b/data/locale/bs.ts index 506b401bd..7abf0baf1 100644 --- a/data/locale/bs.ts +++ b/data/locale/bs.ts @@ -3677,7 +3677,7 @@ You can remove and move mixer channels in the context menu, which is accessed by - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/ca.ts b/data/locale/ca.ts index 765cf3b60..0e27c39db 100644 --- a/data/locale/ca.ts +++ b/data/locale/ca.ts @@ -6360,7 +6360,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/cs.ts b/data/locale/cs.ts index 0ed175022..022f55459 100644 --- a/data/locale/cs.ts +++ b/data/locale/cs.ts @@ -6361,7 +6361,7 @@ Ověřte si prosím, zda máte povolen zápis do souboru a do složky, ve které - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/de.ts b/data/locale/de.ts index 51ca7d562..7817857fd 100644 --- a/data/locale/de.ts +++ b/data/locale/de.ts @@ -6361,7 +6361,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/el.ts b/data/locale/el.ts index 320a6657f..07e61778f 100644 --- a/data/locale/el.ts +++ b/data/locale/el.ts @@ -6360,7 +6360,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/en.ts b/data/locale/en.ts index e52ae39ab..15c3ab1f0 100644 --- a/data/locale/en.ts +++ b/data/locale/en.ts @@ -6362,7 +6362,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/eo.ts b/data/locale/eo.ts index 005ee8100..0dd9c405f 100644 --- a/data/locale/eo.ts +++ b/data/locale/eo.ts @@ -6360,7 +6360,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/es.ts b/data/locale/es.ts index 4fc4951ef..3953ddc11 100644 --- a/data/locale/es.ts +++ b/data/locale/es.ts @@ -6361,7 +6361,7 @@ Asegúrate de tener permisos de escritura tanto del archivo como del directorio - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/eu.ts b/data/locale/eu.ts index 25c165f81..fe6495c0a 100644 --- a/data/locale/eu.ts +++ b/data/locale/eu.ts @@ -6641,7 +6641,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/fa.ts b/data/locale/fa.ts index 181ca0ca1..b376a8424 100644 --- a/data/locale/fa.ts +++ b/data/locale/fa.ts @@ -6360,7 +6360,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/fr.ts b/data/locale/fr.ts index 2c65444a8..4862f4263 100644 --- a/data/locale/fr.ts +++ b/data/locale/fr.ts @@ -6645,7 +6645,7 @@ Veuillez vous assurez que vous avez les droits d'écriture sur le fichier e - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/gl.ts b/data/locale/gl.ts index cf04fd5d4..a1a9e6bf1 100644 --- a/data/locale/gl.ts +++ b/data/locale/gl.ts @@ -6360,7 +6360,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/he.ts b/data/locale/he.ts index ee5a23613..fef0caa91 100644 --- a/data/locale/he.ts +++ b/data/locale/he.ts @@ -6361,7 +6361,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/hi_IN.ts b/data/locale/hi_IN.ts index 15550231f..82cf364e3 100644 --- a/data/locale/hi_IN.ts +++ b/data/locale/hi_IN.ts @@ -6362,7 +6362,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/hu_HU.ts b/data/locale/hu_HU.ts index 836059946..a0f1e4d45 100644 --- a/data/locale/hu_HU.ts +++ b/data/locale/hu_HU.ts @@ -6366,7 +6366,7 @@ Ellenőrizd, hogy rendelkezel-e a szükséges engedélyekkel és próbáld újra - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/id.ts b/data/locale/id.ts index e381ea726..c504740e9 100644 --- a/data/locale/id.ts +++ b/data/locale/id.ts @@ -6362,7 +6362,7 @@ Pastikan Anda memiliki izin menulis ke file dan direktori yang berisi berkas ter - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/it.ts b/data/locale/it.ts index ff146d471..d5a68e6e7 100644 --- a/data/locale/it.ts +++ b/data/locale/it.ts @@ -6366,7 +6366,7 @@ Si prega di controllare i permessi di scrittura sul file e la cartella che lo co - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/ja.ts b/data/locale/ja.ts index e10ca5118..14b38c698 100644 --- a/data/locale/ja.ts +++ b/data/locale/ja.ts @@ -6362,7 +6362,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/ka.ts b/data/locale/ka.ts index 1956d8d04..51eededf2 100644 --- a/data/locale/ka.ts +++ b/data/locale/ka.ts @@ -6360,7 +6360,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/ko.ts b/data/locale/ko.ts index 7373b5ca9..43b99e7f4 100644 --- a/data/locale/ko.ts +++ b/data/locale/ko.ts @@ -6364,7 +6364,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/ms_MY.ts b/data/locale/ms_MY.ts index 209d51d10..ff3478421 100644 --- a/data/locale/ms_MY.ts +++ b/data/locale/ms_MY.ts @@ -6360,7 +6360,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/nb.ts b/data/locale/nb.ts index 3675b7f58..659344d64 100644 --- a/data/locale/nb.ts +++ b/data/locale/nb.ts @@ -6360,7 +6360,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/nl.ts b/data/locale/nl.ts index ad630a249..7ff3e8735 100644 --- a/data/locale/nl.ts +++ b/data/locale/nl.ts @@ -6362,7 +6362,7 @@ Zorg ervoor dat u schrijfbevoegdheid heeft voor het bestand en voor de map die h - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/oc.ts b/data/locale/oc.ts index 58c81c964..045eaf3ad 100644 --- a/data/locale/oc.ts +++ b/data/locale/oc.ts @@ -6360,7 +6360,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/pl.ts b/data/locale/pl.ts index bb0c64ede..ff36a8dac 100644 --- a/data/locale/pl.ts +++ b/data/locale/pl.ts @@ -6646,7 +6646,7 @@ Upewnij się, że masz uprawnienia do zapisu do pliku i katalogu zawierającego - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/pt.ts b/data/locale/pt.ts index b375e289f..f8cfe7618 100644 --- a/data/locale/pt.ts +++ b/data/locale/pt.ts @@ -6363,7 +6363,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/ro.ts b/data/locale/ro.ts index eceb45a64..58abbba99 100644 --- a/data/locale/ro.ts +++ b/data/locale/ro.ts @@ -6361,7 +6361,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/ru.ts b/data/locale/ru.ts index 8235f291f..73b7e06ad 100644 --- a/data/locale/ru.ts +++ b/data/locale/ru.ts @@ -6375,7 +6375,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/sl.ts b/data/locale/sl.ts index 3ad55a4c0..e7bfbc308 100644 --- a/data/locale/sl.ts +++ b/data/locale/sl.ts @@ -6360,7 +6360,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/sr.ts b/data/locale/sr.ts index 9b90164ab..183936bc7 100644 --- a/data/locale/sr.ts +++ b/data/locale/sr.ts @@ -2956,7 +2956,7 @@ You can remove and move mixer channels in the context menu, which is accessed by - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/sv.ts b/data/locale/sv.ts index 4963b07a9..f5d4e0fb4 100644 --- a/data/locale/sv.ts +++ b/data/locale/sv.ts @@ -6644,7 +6644,7 @@ Se till att du har skrivbehörighet till filen och mappen som innehåller filen - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/tr.ts b/data/locale/tr.ts index 387be6d8b..b899337a5 100644 --- a/data/locale/tr.ts +++ b/data/locale/tr.ts @@ -6646,7 +6646,7 @@ Lütfen dosyaya ve dosyayı içeren dizine yazma izniniz olduğundan emin olun v - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/uk.ts b/data/locale/uk.ts index 50df10e4b..9fb6389c9 100644 --- a/data/locale/uk.ts +++ b/data/locale/uk.ts @@ -6361,7 +6361,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/zh_CN.ts b/data/locale/zh_CN.ts index 63b22df99..9b783b963 100644 --- a/data/locale/zh_CN.ts +++ b/data/locale/zh_CN.ts @@ -6370,7 +6370,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/locale/zh_TW.ts b/data/locale/zh_TW.ts index 791a45599..a3a727edb 100644 --- a/data/locale/zh_TW.ts +++ b/data/locale/zh_TW.ts @@ -6361,7 +6361,7 @@ Please make sure you have write permission to the file and the directory contain - InstrumentMiscView + InstrumentTuningView MASTER PITCH diff --git a/data/samples/drums/kick04.ogg b/data/samples/drums/kick04.ogg index 567480abd..8f7dce527 100644 Binary files a/data/samples/drums/kick04.ogg and b/data/samples/drums/kick04.ogg differ diff --git a/data/samples/effects/scratch01.ogg b/data/samples/effects/scratch01.ogg index 9f216038d..0b05505cd 100644 Binary files a/data/samples/effects/scratch01.ogg and b/data/samples/effects/scratch01.ogg differ diff --git a/data/samples/effects/wind_chimes01.ogg b/data/samples/effects/wind_chimes01.ogg index 35d3374a2..7fb3c441a 100644 Binary files a/data/samples/effects/wind_chimes01.ogg and b/data/samples/effects/wind_chimes01.ogg differ diff --git a/data/samples/instruments/harpsichord01.ogg b/data/samples/instruments/harpsichord01.ogg index 028bbd912..c84ffd7df 100644 Binary files a/data/samples/instruments/harpsichord01.ogg and b/data/samples/instruments/harpsichord01.ogg differ diff --git a/data/samples/misc/hit01.ogg b/data/samples/misc/hit01.ogg index d5e93633e..30dd86135 100644 Binary files a/data/samples/misc/hit01.ogg and b/data/samples/misc/hit01.ogg differ diff --git a/data/themes/classic/horizontal_slider.png b/data/themes/classic/horizontal_slider.png new file mode 100644 index 000000000..49d16b9d8 Binary files /dev/null and b/data/themes/classic/horizontal_slider.png differ diff --git a/data/themes/classic/style.css b/data/themes/classic/style.css index a53897c8c..54c119c32 100644 --- a/data/themes/classic/style.css +++ b/data/themes/classic/style.css @@ -209,6 +209,7 @@ lmms--gui--Oscilloscope { lmms--gui--CPULoadWidget { border: none; background: url(resources:cpuload_bg.png); + qproperty-stepSize: 4; } /* scrollbar: trough */ @@ -418,6 +419,25 @@ lmms--gui--AutomatableSlider::handle:vertical { margin: -4px -12px -2px; } +/* main horizontal sliders (zoom) */ + +lmms--gui--AutomatableSlider::groove:horizontal { + background: rgba(0,0,0, 128); + border: 1px inset rgba(100,100,100, 64); + border-radius: 2px; + height: 2px; + margin: 2px; +} + +lmms--gui--AutomatableSlider::handle:horizontal { + background: none; + border-image: url(resources:horizontal_slider.png); + width: 10px; + height: 26px; + border-radius: 2px; + margin: -12px -2px; +} + /* about dialog */ QTabWidget, QTabWidget QWidget { background: #5b6571; diff --git a/data/themes/default/edit_draw_small.png b/data/themes/default/edit_draw_small.png new file mode 100644 index 000000000..9979c8223 Binary files /dev/null and b/data/themes/default/edit_draw_small.png differ diff --git a/data/themes/default/horizontal_slider.png b/data/themes/default/horizontal_slider.png new file mode 100644 index 000000000..24f6098e5 Binary files /dev/null and b/data/themes/default/horizontal_slider.png differ diff --git a/data/themes/default/style.css b/data/themes/default/style.css index a318faacd..addb61a9e 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -241,6 +241,7 @@ lmms--gui--Oscilloscope { lmms--gui--CPULoadWidget { border: none; background: url(resources:cpuload_bg.png); + qproperty-stepSize: 1; } /* scrollbar: trough */ @@ -443,6 +444,25 @@ lmms--gui--AutomatableSlider::handle:vertical { margin: -4px -12px -2px; } +/* main horizontal sliders (zoom) */ + +lmms--gui--AutomatableSlider::groove:horizontal { + background: #040506; + border: none; + border-radius: 2px; + height: 2px; + margin: 2px; +} + +lmms--gui--AutomatableSlider::handle:horizontal { + background: none; + border-image: url(resources:horizontal_slider.png); + width: 10px; + height: 26px; + border-radius: 2px; + margin: -12px -2px; +} + /* window that shows up when you add effects */ lmms--gui--EffectSelectDialog QScrollArea { diff --git a/data/themes/default/tuning_tab.png b/data/themes/default/tuning_tab.png new file mode 100644 index 000000000..41c4f2d9f Binary files /dev/null and b/data/themes/default/tuning_tab.png differ diff --git a/include/ArrayVector.h b/include/ArrayVector.h new file mode 100644 index 000000000..06e09226c --- /dev/null +++ b/include/ArrayVector.h @@ -0,0 +1,388 @@ +/* + * ArrayVector.h + * + * Copyright (c) 2023 Dominic Clark + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LMMS_ARRAY_VECTOR_H +#define LMMS_ARRAY_VECTOR_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace lmms { + +namespace detail { + +template +constexpr bool is_input_iterator_v = false; + +template +constexpr bool is_input_iterator_v::iterator_category>> = + std::is_convertible_v::iterator_category, std::input_iterator_tag>; + +} // namespace detail + +/** + * A container that stores up to a maximum of `N` elements of type `T` directly + * within itself, rather than separately on the heap. Useful when a dynamically + * resizeable container is needed for use in real-time code. Can be thought of + * as a hybrid between `std::array` and `std::vector`. The interface follows + * that of `std::vector` - see standard C++ documentation. + */ +template +class ArrayVector +{ +public: + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using value_type = T; + using reference = T&; + using const_reference = const T&; + using pointer = T*; + using const_pointer = const T*; + using iterator = pointer; + using const_iterator = const_pointer; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + ArrayVector() = default; + + ArrayVector(const ArrayVector& other) noexcept(std::is_nothrow_copy_constructible_v) : + m_size{other.m_size} + { + std::uninitialized_copy(other.begin(), other.end(), begin()); + } + + ArrayVector(ArrayVector&& other) noexcept(std::is_nothrow_move_constructible_v) : + m_size{other.m_size} + { + std::uninitialized_move(other.begin(), other.end(), begin()); + other.clear(); + } + + ArrayVector(size_type count, const T& value) noexcept(std::is_nothrow_copy_constructible_v) : + m_size{count} + { + assert(count <= N); + std::uninitialized_fill_n(begin(), count, value); + } + + explicit ArrayVector(size_type count) noexcept(std::is_nothrow_default_constructible_v) : + m_size{count} + { + assert(count <= N); + std::uninitialized_value_construct_n(begin(), count); + } + + template, int> = 0> + ArrayVector(It first, It last) + { + // Can't check the size first as the iterator may not be multipass + const auto end = std::uninitialized_copy(first, last, begin()); + m_size = end - begin(); + assert(m_size <= N); + } + + ArrayVector(std::initializer_list il) noexcept(std::is_nothrow_copy_constructible_v) : + m_size{il.size()} + { + assert(il.size() <= N); + std::uninitialized_copy(il.begin(), il.end(), begin()); + } + + ~ArrayVector() { std::destroy(begin(), end()); } + + ArrayVector& operator=(const ArrayVector& other) + noexcept(std::is_nothrow_copy_assignable_v && std::is_nothrow_copy_constructible_v) + { + if (this != &other) { + const auto toAssign = std::min(other.size(), size()); + const auto assignedFromEnd = other.begin() + toAssign; + const auto assignedToEnd = std::copy(other.begin(), other.begin() + toAssign, begin()); + std::destroy(assignedToEnd, end()); + std::uninitialized_copy(assignedFromEnd, other.end(), end()); + m_size = other.size(); + } + return *this; + } + + ArrayVector& operator=(ArrayVector&& other) + noexcept(std::is_nothrow_move_assignable_v && std::is_nothrow_move_constructible_v) + { + if (this != &other) { + const auto toAssign = std::min(other.size(), size()); + const auto assignedFromEnd = other.begin() + toAssign; + const auto assignedToEnd = std::move(other.begin(), other.begin() + toAssign, begin()); + std::destroy(assignedToEnd, end()); + std::uninitialized_move(assignedFromEnd, other.end(), end()); + m_size = other.size(); + other.clear(); + } + return *this; + } + + ArrayVector& operator=(std::initializer_list il) + noexcept(std::is_nothrow_copy_assignable_v && std::is_nothrow_copy_constructible_v) + { + assert(il.size() <= N); + const auto toAssign = std::min(il.size(), size()); + const auto assignedFromEnd = il.begin() + toAssign; + const auto assignedToEnd = std::copy(il.begin(), assignedFromEnd, begin()); + std::destroy(assignedToEnd, end()); + std::uninitialized_copy(assignedFromEnd, il.end(), end()); + m_size = il.size(); + return *this; + } + + void assign(size_type count, const T& value) + noexcept(std::is_nothrow_copy_assignable_v && std::is_nothrow_copy_constructible_v) + { + assert(count <= N); + const auto temp = value; + const auto toAssign = std::min(count, size()); + const auto toConstruct = count - toAssign; + const auto assignedToEnd = std::fill_n(begin(), toAssign, temp); + std::destroy(assignedToEnd, end()); + std::uninitialized_fill_n(assignedToEnd, toConstruct, temp); + m_size = count; + } + + template, int> = 0> + void assign(It first, It last) + { + // Can't check the size first as the iterator may not be multipass + auto pos = begin(); + for (; first != last && pos != end(); ++pos, ++first) { + *pos = *first; + } + std::destroy(pos, end()); + pos = std::uninitialized_copy(first, last, pos); + m_size = pos - begin(); + assert(m_size <= N); + } + + reference at(size_type index) + { + if (index >= m_size) { throw std::out_of_range{"index out of range"}; } + return data()[index]; + } + + const_reference at(size_type index) const + { + if (index >= m_size) { throw std::out_of_range{"index out of range"}; } + return data()[index]; + } + + reference operator[](size_type index) noexcept + { + assert(index < m_size); + return data()[index]; + } + + const_reference operator[](size_type index) const noexcept + { + assert(index < m_size); + return data()[index]; + } + + reference front() noexcept { return operator[](0); } + const_reference front() const noexcept { return operator[](0); } + + reference back() noexcept { return operator[](m_size - 1); } + const_reference back() const noexcept { return operator[](m_size - 1); } + + pointer data() noexcept { return *std::launder(reinterpret_cast(m_data)); } + const_pointer data() const noexcept { return *std::launder(reinterpret_cast(m_data)); } + + iterator begin() noexcept { return data(); } + const_iterator begin() const noexcept { return data(); } + const_iterator cbegin() const noexcept { return data(); } + + iterator end() noexcept { return data() + m_size; } + const_iterator end() const noexcept { return data() + m_size; } + const_iterator cend() const noexcept { return data() + m_size; } + + reverse_iterator rbegin() noexcept { return std::reverse_iterator{end()}; } + const_reverse_iterator rbegin() const noexcept { return std::reverse_iterator{end()}; } + const_reverse_iterator crbegin() const noexcept { return std::reverse_iterator{cend()}; } + + reverse_iterator rend() noexcept { return std::reverse_iterator{begin()}; } + const_reverse_iterator rend() const noexcept { return std::reverse_iterator{begin()}; } + const_reverse_iterator crend() const noexcept { return std::reverse_iterator{cbegin()}; } + + bool empty() const noexcept { return m_size == 0; } + bool full() const noexcept { return m_size == N; } + size_type size() const noexcept { return m_size; } + size_type max_size() const noexcept { return N; } + size_type capacity() const noexcept { return N; } + + void clear() noexcept + { + std::destroy(begin(), end()); + m_size = 0; + } + + iterator insert(const_iterator pos, const T& value) { return emplace(pos, value); } + iterator insert(const_iterator pos, T&& value) { return emplace(pos, std::move(value)); } + + iterator insert(const_iterator pos, size_type count, const T& value) + { + assert(m_size + count <= N); + assert(cbegin() <= pos && pos <= cend()); + const auto mutPos = begin() + (pos - cbegin()); + const auto newEnd = std::uninitialized_fill_n(end(), count, value); + std::rotate(mutPos, end(), newEnd); + m_size += count; + return mutPos; + } + + template, int> = 0> + iterator insert(const_iterator pos, It first, It last) + { + // Can't check the size first as the iterator may not be multipass + assert(cbegin() <= pos && pos <= cend()); + const auto mutPos = begin() + (pos - cbegin()); + const auto newEnd = std::uninitialized_copy(first, last, end()); + std::rotate(mutPos, end(), newEnd); + m_size = newEnd - begin(); + assert(m_size <= N); + return mutPos; + } + + iterator insert(const_iterator pos, std::initializer_list il) { return insert(pos, il.begin(), il.end()); } + + template + iterator emplace(const_iterator pos, Args&&... args) + { + assert(cbegin() <= pos && pos <= cend()); + const auto mutPos = begin() + (pos - cbegin()); + emplace_back(std::forward(args)...); + std::rotate(mutPos, end() - 1, end()); + return mutPos; + } + + iterator erase(const_iterator pos) { return erase(pos, pos + 1); } + iterator erase(const_iterator first, const_iterator last) + { + assert(cbegin() <= first && first <= last && last <= cend()); + const auto mutFirst = begin() + (first - cbegin()); + const auto mutLast = begin() + (last - cbegin()); + const auto newEnd = std::move(mutLast, end(), mutFirst); + std::destroy(newEnd, end()); + m_size = newEnd - begin(); + return mutFirst; + } + + void push_back(const T& value) { emplace_back(value); } + void push_back(T&& value) { emplace_back(std::move(value)); } + + template + reference emplace_back(Args&&... args) + { + assert(!full()); + // TODO C++20: Use std::construct_at + const auto result = new(static_cast(end())) T(std::forward(args)...); + ++m_size; + return *result; + } + + void pop_back() + { + assert(!empty()); + --m_size; + std::destroy_at(end()); + } + + void resize(size_type size) + { + if (size > N) { throw std::length_error{"size exceeds maximum size"}; } + if (size < m_size) { + std::destroy(begin() + size, end()); + } else { + std::uninitialized_value_construct(end(), begin() + size); + } + m_size = size; + } + + void resize(size_type size, const value_type& value) + { + if (size > N) { throw std::length_error{"size exceeds maximum size"}; } + if (size < m_size) { + std::destroy(begin() + size, end()); + } else { + std::uninitialized_fill(end(), begin() + size, value); + } + m_size = size; + } + + void swap(ArrayVector& other) + noexcept(std::is_nothrow_swappable_v && std::is_nothrow_move_constructible_v) + { + using std::swap; + swap(*this, other); + } + + friend void swap(ArrayVector& a, ArrayVector& b) + noexcept(std::is_nothrow_swappable_v && std::is_nothrow_move_constructible_v) + { + const auto toSwap = std::min(a.size(), b.size()); + const auto aSwapEnd = a.begin() + toSwap; + const auto bSwapEnd = b.begin() + toSwap; + std::swap_ranges(a.begin(), aSwapEnd, b.begin()); + std::uninitialized_move(aSwapEnd, a.end(), bSwapEnd); + std::uninitialized_move(bSwapEnd, b.end(), aSwapEnd); + std::destroy(aSwapEnd, a.end()); + std::destroy(bSwapEnd, b.end()); + std::swap(a.m_size, b.m_size); + } + + // TODO C++20: Replace with operator<=> + friend bool operator<(const ArrayVector& l, const ArrayVector& r) + { + return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); + } + friend bool operator<=(const ArrayVector& l, const ArrayVector& r) { return !(r < l); } + friend bool operator>(const ArrayVector& l, const ArrayVector& r) { return r < l; } + friend bool operator>=(const ArrayVector& l, const ArrayVector& r) { return !(l < r); } + + friend bool operator==(const ArrayVector& l, const ArrayVector& r) + { + return std::equal(l.begin(), l.end(), r.begin(), r.end()); + } + // TODO C++20: Remove + friend bool operator!=(const ArrayVector& l, const ArrayVector& r) { return !(l == r); } + +private: + alignas(T) std::byte m_data[std::max(N * sizeof(T), std::size_t{1})]; // Intentionally a raw array + size_type m_size = 0; +}; + +} // namespace lmms + +#endif // LMMS_ARRAY_VECTOR_H diff --git a/include/AudioEngine.h b/include/AudioEngine.h index d0f269d87..f056c22e1 100644 --- a/include/AudioEngine.h +++ b/include/AudioEngine.h @@ -32,10 +32,10 @@ #endif #include -#include #include #include +#include #include "lmms_basics.h" #include "LocklessList.h" @@ -109,27 +109,27 @@ public: struct qualitySettings { - enum Mode + enum class Mode { - Mode_Draft, - Mode_HighQuality, - Mode_FinalMix + Draft, + HighQuality, + FinalMix } ; - enum Interpolation + enum class Interpolation { - Interpolation_Linear, - Interpolation_SincFastest, - Interpolation_SincMedium, - Interpolation_SincBest + Linear, + SincFastest, + SincMedium, + SincBest } ; - enum Oversampling + enum class Oversampling { - Oversampling_None, - Oversampling_2x, - Oversampling_4x, - Oversampling_8x + None, + X2, + X4, + X8 } ; Interpolation interpolation; @@ -139,18 +139,18 @@ public: { switch (m) { - case Mode_Draft: - interpolation = Interpolation_Linear; - oversampling = Oversampling_None; + case Mode::Draft: + interpolation = Interpolation::Linear; + oversampling = Oversampling::None; break; - case Mode_HighQuality: + case Mode::HighQuality: interpolation = - Interpolation_SincFastest; - oversampling = Oversampling_2x; + Interpolation::SincFastest; + oversampling = Oversampling::X2; break; - case Mode_FinalMix: - interpolation = Interpolation_SincBest; - oversampling = Oversampling_8x; + case Mode::FinalMix: + interpolation = Interpolation::SincBest; + oversampling = Oversampling::X8; break; } } @@ -165,10 +165,10 @@ public: { switch( oversampling ) { - case Oversampling_None: return 1; - case Oversampling_2x: return 2; - case Oversampling_4x: return 4; - case Oversampling_8x: return 8; + case Oversampling::None: return 1; + case Oversampling::X2: return 2; + case Oversampling::X4: return 4; + case Oversampling::X8: return 8; } return 1; } @@ -177,13 +177,13 @@ public: { switch( interpolation ) { - case Interpolation_Linear: + case Interpolation::Linear: return SRC_ZERO_ORDER_HOLD; - case Interpolation_SincFastest: + case Interpolation::SincFastest: return SRC_SINC_FASTEST; - case Interpolation_SincMedium: + case Interpolation::SincMedium: return SRC_SINC_MEDIUM_QUALITY; - case Interpolation_SincBest: + case Interpolation::SincBest: return SRC_SINC_BEST_QUALITY; } return SRC_LINEAR; @@ -255,7 +255,7 @@ public: return m_playHandles; } - void removePlayHandlesOfTypes(Track * track, const quint8 types); + void removePlayHandlesOfTypes(Track * track, PlayHandle::Types types); // methods providing information for other classes @@ -275,6 +275,11 @@ public: return m_profiler.cpuLoad(); } + int detailLoad(const AudioEngineProfiler::DetailType type) const + { + return m_profiler.detailLoad(type); + } + const qualitySettings & currentQualitySettings() const { return m_qualitySettings; @@ -401,6 +406,10 @@ private: AudioDevice * tryAudioDevices(); MidiClient * tryMidiClients(); + void renderStageNoteSetup(); + void renderStageInstruments(); + void renderStageEffects(); + void renderStageMix(); const surroundSampleFrame * renderNextBuffer(); @@ -416,7 +425,7 @@ private: bool m_renderOnly; - QVector m_audioPorts; + std::vector m_audioPorts; fpp_t m_framesPerPeriod; @@ -430,7 +439,7 @@ private: surroundSampleFrame * m_outputBufferWrite; // worker thread stuff - QVector m_workers; + std::vector m_workers; int m_numWorkers; // playhandle stuff diff --git a/include/AudioEngineProfiler.h b/include/AudioEngineProfiler.h index 7b5191e76..b0d62a1dc 100644 --- a/include/AudioEngineProfiler.h +++ b/include/AudioEngineProfiler.h @@ -25,6 +25,8 @@ #ifndef LMMS_AUDIO_ENGINE_PROFILER_H #define LMMS_AUDIO_ENGINE_PROFILER_H +#include +#include #include #include "lmms_basics.h" @@ -53,11 +55,55 @@ public: void setOutputFile( const QString& outputFile ); + enum class DetailType { + NoteSetup, + Instruments, + Effects, + Mixing, + Count + }; + + constexpr static auto DetailCount = static_cast(DetailType::Count); + + int detailLoad(const DetailType type) const + { + return m_detailLoad[static_cast(type)].load(std::memory_order_relaxed); + } + + class Probe + { + public: + Probe(AudioEngineProfiler& profiler, AudioEngineProfiler::DetailType type) + : m_profiler(profiler) + , m_type(type) + { + profiler.startDetail(type); + } + ~Probe() { m_profiler.finishDetail(m_type); } + Probe& operator=(const Probe&) = delete; + Probe(const Probe&) = delete; + Probe(Probe&&) = delete; + + private: + AudioEngineProfiler &m_profiler; + const AudioEngineProfiler::DetailType m_type; + }; private: + void startDetail(const DetailType type) { m_detailTimer[static_cast(type)].reset(); } + void finishDetail(const DetailType type) + { + m_detailTime[static_cast(type)] = m_detailTimer[static_cast(type)].elapsed(); + } + MicroTimer m_periodTimer; - int m_cpuLoad; + std::atomic m_cpuLoad; QFile m_outputFile; + + // Use arrays to avoid dynamic allocations in realtime code + std::array m_detailTimer; + std::array m_detailTime{0}; + std::array, DetailCount> m_detailLoad{0}; }; } // namespace lmms diff --git a/include/AudioEngineWorkerThread.h b/include/AudioEngineWorkerThread.h index 112930808..b76235aa1 100644 --- a/include/AudioEngineWorkerThread.h +++ b/include/AudioEngineWorkerThread.h @@ -45,7 +45,7 @@ public: class JobQueue { public: - enum OperationMode + enum class OperationMode { Static, // no jobs added while processing queue Dynamic // jobs can be added while processing queue @@ -57,7 +57,7 @@ public: m_items(), m_writeIndex( 0 ), m_itemsDone( 0 ), - m_opMode( Static ) + m_opMode( OperationMode::Static ) { std::fill(m_items, m_items + JOB_QUEUE_SIZE, nullptr); } @@ -83,7 +83,7 @@ public: virtual void quit(); static void resetJobQueue( JobQueue::OperationMode _opMode = - JobQueue::Static ) + JobQueue::OperationMode::Static ) { globalJobQueue.reset( _opMode ); } @@ -97,12 +97,12 @@ public: // to ThreadableJob objects template static void fillJobQueue( const T & _vec, - JobQueue::OperationMode _opMode = JobQueue::Static ) + JobQueue::OperationMode _opMode = JobQueue::OperationMode::Static ) { resetJobQueue( _opMode ); - for( typename T::ConstIterator it = _vec.begin(); it != _vec.end(); ++it ) + for (const auto& job : _vec) { - addJob( *it ); + addJob(job); } } diff --git a/include/AudioJack.h b/include/AudioJack.h index 2ef0f665c..164258e5f 100644 --- a/include/AudioJack.h +++ b/include/AudioJack.h @@ -35,7 +35,7 @@ #endif #include -#include +#include #include "AudioDevice.h" #include "AudioDeviceSetupWidget.h" @@ -117,7 +117,7 @@ private: std::atomic m_stopped; std::atomic m_midiClient; - QVector m_outputPorts; + std::vector m_outputPorts; jack_default_audio_sample_t * * m_tempOutBufs; surroundSampleFrame * m_outBuf; diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index 1e6d5eda3..2264a592e 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -27,6 +27,7 @@ #include #include +#include #include "JournallingObject.h" #include "Model.h" @@ -78,9 +79,9 @@ class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject Q_OBJECT MM_OPERATORS public: - using AutoModelVector = QVector; + using AutoModelVector = std::vector; - enum ScaleType + enum class ScaleType { Linear, Logarithmic, @@ -144,7 +145,7 @@ public: template static bool castValue( const float v ) { - return ( qRound( v ) != 0 ); + return (std::round(v) != 0); } @@ -231,11 +232,11 @@ public: } void setScaleLogarithmic( bool setToTrue = true ) { - setScaleType( setToTrue ? Logarithmic : Linear ); + setScaleType( setToTrue ? ScaleType::Logarithmic : ScaleType::Linear ); } bool isScaleLogarithmic() const { - return m_scaleType == Logarithmic; + return m_scaleType == ScaleType::Logarithmic; } void setStep( const float step ); diff --git a/include/AutomationClip.h b/include/AutomationClip.h index 10c714c3d..ceb5611c9 100644 --- a/include/AutomationClip.h +++ b/include/AutomationClip.h @@ -54,15 +54,15 @@ class LMMS_EXPORT AutomationClip : public Clip { Q_OBJECT public: - enum ProgressionTypes + enum class ProgressionType { - DiscreteProgression, - LinearProgression, - CubicHermiteProgression + Discrete, + Linear, + CubicHermite } ; using timeMap = QMap; - using objectVector = QVector>; + using objectVector = std::vector>; using TimemapIterator = timeMap::const_iterator; @@ -76,11 +76,11 @@ public: const objectVector& objects() const; // progression-type stuff - inline ProgressionTypes progressionType() const + inline ProgressionType progressionType() const { return m_progressionType; } - void setProgressionType( ProgressionTypes _new_progression_type ); + void setProgressionType( ProgressionType _new_progression_type ); inline float getTension() const { @@ -167,7 +167,7 @@ public: static bool isAutomated( const AutomatableModel * _m ); - static QVector clipsForModel( const AutomatableModel * _m ); + static std::vector clipsForModel(const AutomatableModel* _m); static AutomationClip * globalAutomationClip( AutomatableModel * _m ); static void resolveAllIDs(); @@ -190,6 +190,15 @@ private: void generateTangents(timeMap::iterator it, int numToGenerate); float valueAt( timeMap::const_iterator v, int offset ) const; + /** + * @brief + * This function combines the song tracks, pattern store tracks, + * and the global automation track all in one vector. + * + * @return std::vector + */ + static std::vector combineAllTracks(); + // Mutex to make methods involving automation clips thread safe // Mutable so we can lock it from const objects #if (QT_VERSION >= QT_VERSION_CHECK(5,14,0)) @@ -199,13 +208,13 @@ private: #endif AutomationTrack * m_autoTrack; - QVector m_idsToResolve; + std::vector m_idsToResolve; objectVector m_objects; timeMap m_timeMap; // actual values timeMap m_oldTimeMap; // old values for storing the values before setDragValue() is called. float m_tension; bool m_hasAutomation; - ProgressionTypes m_progressionType; + ProgressionType m_progressionType; bool m_dragging; bool m_dragKeepOutValue; // Should we keep the current dragged node's outValue? diff --git a/include/AutomationEditor.h b/include/AutomationEditor.h index c2ab98092..ecefa8b26 100644 --- a/include/AutomationEditor.h +++ b/include/AutomationEditor.h @@ -27,6 +27,7 @@ #define LMMS_GUI_AUTOMATION_EDITOR_H #include +#include #include "Editor.h" @@ -86,11 +87,11 @@ public: return "automationeditor"; } - enum EditModes + enum class EditMode { - DRAW, - ERASE, - DRAW_OUTVALUES + Draw, + Erase, + DrawOutValues }; public slots: @@ -128,10 +129,10 @@ protected slots: void horScrolled( int new_pos ); void verScrolled( int new_pos ); - void setEditMode(AutomationEditor::EditModes mode); + void setEditMode(AutomationEditor::EditMode mode); void setEditMode(int mode); - void setProgressionType(AutomationClip::ProgressionTypes type); + void setProgressionType(AutomationClip::ProgressionType type); void setProgressionType(int type); void setTension(); @@ -145,14 +146,14 @@ protected slots: private: - enum Actions + enum class Action { - NONE, - MOVE_VALUE, - ERASE_VALUES, - MOVE_OUTVALUE, - RESET_OUTVALUES, - DRAW_LINE + None, + MoveValue, + EraseValues, + MoveOutValue, + ResetOutValues, + DrawLine } ; // some constants... @@ -180,7 +181,7 @@ private: ComboBoxModel m_zoomingYModel; ComboBoxModel m_quantizeModel; - static const QVector m_zoomXLevels; + static const std::array m_zoomXLevels; FloatModel * m_tensionModel; @@ -200,7 +201,7 @@ private: TimePos m_currentPosition; - Actions m_action; + Action m_action; int m_moveXOffset; @@ -214,7 +215,7 @@ private: // Time position (key) of automation node whose outValue is being dragged int m_draggedOutValueKey; - EditModes m_editMode; + EditMode m_editMode; bool m_mouseDownLeft; bool m_mouseDownRight; //true if right click is being held down diff --git a/include/BandLimitedWave.h b/include/BandLimitedWave.h index 2a12c62e3..1f402aa6e 100644 --- a/include/BandLimitedWave.h +++ b/include/BandLimitedWave.h @@ -89,14 +89,15 @@ QDataStream& operator>> ( QDataStream &in, WaveMipMap &waveMipMap ); class LMMS_EXPORT BandLimitedWave { public: - enum Waveforms + enum class Waveform { BLSaw, BLSquare, BLTriangle, BLMoog, - NumBLWaveforms + Count }; + constexpr static auto NumWaveforms = static_cast(Waveform::Count); BandLimitedWave() = default; virtual ~BandLimitedWave() = default; @@ -127,7 +128,7 @@ public: * \param _wavelen The wavelength (length of one cycle, ie. the inverse of frequency) of the wanted oscillation, measured in sample frames * \param _wave The wanted waveform. Options currently are saw, triangle, square and moog saw. */ - static inline sample_t oscillate( float _ph, float _wavelen, Waveforms _wave ) + static inline sample_t oscillate( float _ph, float _wavelen, Waveform _wave ) { // get the next higher tlen int t = 0; @@ -139,12 +140,12 @@ public: int lookup = static_cast( lookupf ); const float ip = fraction( lookupf ); - const sample_t s1 = s_waveforms[ _wave ].sampleAt( t, lookup ); - const sample_t s2 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 1 ) % tlen ); + const sample_t s1 = s_waveforms[ static_cast(_wave) ].sampleAt( t, lookup ); + const sample_t s2 = s_waveforms[ static_cast(_wave) ].sampleAt( t, ( lookup + 1 ) % tlen ); const int lm = lookup == 0 ? tlen - 1 : lookup - 1; - const sample_t s0 = s_waveforms[ _wave ].sampleAt( t, lm ); - const sample_t s3 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 2 ) % tlen ); + const sample_t s0 = s_waveforms[ static_cast(_wave) ].sampleAt( t, lm ); + const sample_t s3 = s_waveforms[ static_cast(_wave) ].sampleAt( t, ( lookup + 2 ) % tlen ); const sample_t sr = optimal4pInterpolate( s0, s1, s2, s3, ip ); return sr; @@ -153,8 +154,8 @@ public: lookup = lookup << 1; tlen = tlen << 1; t += 1; - const sample_t s3 = s_waveforms[ _wave ].sampleAt( t, lookup ); - const sample_t s4 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 1 ) % tlen ); + const sample_t s3 = s_waveforms[ static_cast(_wave) ].sampleAt( t, lookup ); + const sample_t s4 = s_waveforms[ static_cast(_wave) ].sampleAt( t, ( lookup + 1 ) % tlen ); const sample_t s34 = linearInterpolate( s3, s4, ip ); const float ip2 = ( ( tlen - _wavelen ) / tlen - 0.5 ) * 2.0; @@ -168,7 +169,7 @@ public: static bool s_wavesGenerated; - static std::array s_waveforms; + static std::array s_waveforms; static QString s_wavetableDir; }; diff --git a/include/BasicFilters.h b/include/BasicFilters.h index c10c47489..9351cbafb 100644 --- a/include/BasicFilters.h +++ b/include/BasicFilters.h @@ -209,7 +209,7 @@ public: inline float update( float s, ch_cnt_t ch ) { - if( qAbs( s ) < 1.0e-10f && qAbs( m_z1[ch] ) < 1.0e-10f ) return 0.0f; + if (std::abs(s) < 1.0e-10f && std::abs(m_z1[ch]) < 1.0e-10f) return 0.0f; return m_z1[ch] = s * m_a0 + m_z1[ch] * m_b1; } @@ -224,7 +224,7 @@ class BasicFilters { MM_OPERATORS public: - enum FilterTypes + enum class FilterType { LowPass, HiPass, @@ -247,8 +247,7 @@ public: Highpass_SV, Notch_SV, FastFormant, - Tripole, - NumFilters + Tripole }; static inline float minFreq() @@ -261,20 +260,20 @@ public: return( 0.01f ); } - inline void setFilterType( const int _idx ) + inline void setFilterType( const FilterType _idx ) { - m_doubleFilter = _idx == DoubleLowPass || _idx == DoubleMoog; + m_doubleFilter = _idx == FilterType::DoubleLowPass || _idx == FilterType::DoubleMoog; if( !m_doubleFilter ) { - m_type = static_cast( _idx ); + m_type = _idx; return; } // Double lowpass mode, backwards-compat for the goofy // Add-NumFilters to signify doubleFilter stuff - m_type = _idx == DoubleLowPass - ? LowPass - : Moog; + m_type = _idx == FilterType::DoubleLowPass + ? FilterType::LowPass + : FilterType::Moog; if( m_subFilter == nullptr ) { m_subFilter = new BasicFilters( @@ -334,28 +333,24 @@ public: sample_t out; switch( m_type ) { - case Moog: + case FilterType::Moog: { sample_t x = _in0 - m_r*m_y4[_chnl]; // four cascaded onepole filters // (bilinear transform) - m_y1[_chnl] = qBound( -10.0f, - ( x + m_oldx[_chnl] ) * m_p - - m_k * m_y1[_chnl], - 10.0f ); - m_y2[_chnl] = qBound( -10.0f, - ( m_y1[_chnl] + m_oldy1[_chnl] ) * m_p - - m_k * m_y2[_chnl], - 10.0f ); - m_y3[_chnl] = qBound( -10.0f, - ( m_y2[_chnl] + m_oldy2[_chnl] ) * m_p - - m_k * m_y3[_chnl], - 10.0f ); - m_y4[_chnl] = qBound( -10.0f, - ( m_y3[_chnl] + m_oldy3[_chnl] ) * m_p - - m_k * m_y4[_chnl], + m_y1[_chnl] = std::clamp((x + m_oldx[_chnl]) * m_p + - m_k * m_y1[_chnl], -10.0f, + 10.0f); + m_y2[_chnl] = std::clamp((m_y1[_chnl] + m_oldy1[_chnl]) * m_p + - m_k * m_y2[_chnl], -10.0f, + 10.0f); + m_y3[_chnl] = std::clamp((m_y2[_chnl] + m_oldy2[_chnl]) * m_p + - m_k * m_y3[_chnl], -10.0f, 10.0f ); + m_y4[_chnl] = std::clamp((m_y3[_chnl] + m_oldy3[_chnl]) * m_p + - m_k * m_y4[_chnl], -10.0f, + 10.0f); m_oldx[_chnl] = x; m_oldy1[_chnl] = m_y1[_chnl]; @@ -368,7 +363,7 @@ public: // 3x onepole filters with 4x oversampling and interpolation of oversampled signal: // input signal is linear-interpolated after oversampling, output signal is averaged from oversampled outputs - case Tripole: + case FilterType::Tripole: { out = 0.0f; float ip = 0.0f; @@ -377,18 +372,15 @@ public: ip += 0.25f; sample_t x = linearInterpolate( m_last[_chnl], _in0, ip ) - m_r * m_y3[_chnl]; - m_y1[_chnl] = qBound( -10.0f, - ( x + m_oldx[_chnl] ) * m_p - - m_k * m_y1[_chnl], - 10.0f ); - m_y2[_chnl] = qBound( -10.0f, - ( m_y1[_chnl] + m_oldy1[_chnl] ) * m_p - - m_k * m_y2[_chnl], - 10.0f ); - m_y3[_chnl] = qBound( -10.0f, - ( m_y2[_chnl] + m_oldy2[_chnl] ) * m_p - - m_k * m_y3[_chnl], - 10.0f ); + m_y1[_chnl] = std::clamp((x + m_oldx[_chnl]) * m_p + - m_k * m_y1[_chnl], -10.0f, + 10.0f); + m_y2[_chnl] = std::clamp((m_y1[_chnl] + m_oldy1[_chnl]) * m_p + - m_k * m_y2[_chnl], -10.0f, + 10.0f); + m_y3[_chnl] = std::clamp((m_y2[_chnl] + m_oldy2[_chnl]) * m_p + - m_k * m_y3[_chnl], -10.0f, + 10.0f); m_oldx[_chnl] = x; m_oldy1[_chnl] = m_y1[_chnl]; m_oldy2[_chnl] = m_y2[_chnl]; @@ -404,8 +396,8 @@ public: // and extended to other SV filter types // /* Hal Chamberlin's state variable filter */ - case Lowpass_SV: - case Bandpass_SV: + case FilterType::Lowpass_SV: + case FilterType::Bandpass_SV: { float highpass; @@ -421,12 +413,12 @@ public: } /* mix filter output into output buffer */ - return m_type == Lowpass_SV + return m_type == FilterType::Lowpass_SV ? m_delay4[_chnl] : m_delay3[_chnl]; } - case Highpass_SV: + case FilterType::Highpass_SV: { float hp; @@ -440,7 +432,7 @@ public: return hp; } - case Notch_SV: + case FilterType::Notch_SV: { float hp1, hp2; @@ -465,22 +457,22 @@ public: // can be driven up to self-oscillation (BTW: do not remove the limits!!!). // (C) 1998 ... 2009 S.Fendt. Released under the GPL v2.0 or any later version. - case Lowpass_RC12: + case FilterType::Lowpass_RC12: { sample_t lp, bp, hp, in; for( int n = 4; n != 0; --n ) { in = _in0 + m_rcbp0[_chnl] * m_rcq; - in = qBound( -1.0f, in, 1.0f ); + in = std::clamp(in, -1.0f, 1.0f); lp = in * m_rcb + m_rclp0[_chnl] * m_rca; - lp = qBound( -1.0f, lp, 1.0f ); + lp = std::clamp(lp, -1.0f, 1.0f); hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] ); - hp = qBound( -1.0f, hp, 1.0f ); + hp = std::clamp(hp, -1.0f, 1.0f); bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca; - bp = qBound( -1.0f, bp, 1.0f ); + bp = std::clamp(bp, -1.0f, 1.0f); m_rclast0[_chnl] = in; m_rclp0[_chnl] = lp; @@ -489,45 +481,45 @@ public: } return lp; } - case Highpass_RC12: - case Bandpass_RC12: + case FilterType::Highpass_RC12: + case FilterType::Bandpass_RC12: { sample_t hp, bp, in; for( int n = 4; n != 0; --n ) { in = _in0 + m_rcbp0[_chnl] * m_rcq; - in = qBound( -1.0f, in, 1.0f ); + in = std::clamp(in, -1.0f, 1.0f); hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] ); - hp = qBound( -1.0f, hp, 1.0f ); + hp = std::clamp(hp, -1.0f, 1.0f); bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca; - bp = qBound( -1.0f, bp, 1.0f ); + bp = std::clamp(bp, -1.0f, 1.0f); m_rclast0[_chnl] = in; m_rchp0[_chnl] = hp; m_rcbp0[_chnl] = bp; } - return m_type == Highpass_RC12 ? hp : bp; + return m_type == FilterType::Highpass_RC12 ? hp : bp; } - case Lowpass_RC24: + case FilterType::Lowpass_RC24: { sample_t lp, bp, hp, in; for( int n = 4; n != 0; --n ) { // first stage is as for the 12dB case... in = _in0 + m_rcbp0[_chnl] * m_rcq; - in = qBound( -1.0f, in, 1.0f ); + in = std::clamp(in, -1.0f, 1.0f); lp = in * m_rcb + m_rclp0[_chnl] * m_rca; - lp = qBound( -1.0f, lp, 1.0f ); + lp = std::clamp(lp, -1.0f, 1.0f); hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] ); - hp = qBound( -1.0f, hp, 1.0f ); + hp = std::clamp(hp, -1.0f, 1.0f); bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca; - bp = qBound( -1.0f, bp, 1.0f ); + bp = std::clamp(bp, -1.0f, 1.0f); m_rclast0[_chnl] = in; m_rclp0[_chnl] = lp; @@ -536,16 +528,16 @@ public: // second stage gets the output of the first stage as input... in = lp + m_rcbp1[_chnl] * m_rcq; - in = qBound( -1.0f, in, 1.0f ); + in = std::clamp(in, -1.0f, 1.0f ); lp = in * m_rcb + m_rclp1[_chnl] * m_rca; - lp = qBound( -1.0f, lp, 1.0f ); + lp = std::clamp(lp, -1.0f, 1.0f); hp = m_rcc * ( m_rchp1[_chnl] + in - m_rclast1[_chnl] ); - hp = qBound( -1.0f, hp, 1.0f ); + hp = std::clamp(hp, -1.0f, 1.0f); bp = hp * m_rcb + m_rcbp1[_chnl] * m_rca; - bp = qBound( -1.0f, bp, 1.0f ); + bp = std::clamp(bp, -1.0f, 1.0f); m_rclast1[_chnl] = in; m_rclp1[_chnl] = lp; @@ -554,91 +546,91 @@ public: } return lp; } - case Highpass_RC24: - case Bandpass_RC24: + case FilterType::Highpass_RC24: + case FilterType::Bandpass_RC24: { sample_t hp, bp, in; for( int n = 4; n != 0; --n ) { // first stage is as for the 12dB case... in = _in0 + m_rcbp0[_chnl] * m_rcq; - in = qBound( -1.0f, in, 1.0f ); + in = std::clamp(in, -1.0f, 1.0f); hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] ); - hp = qBound( -1.0f, hp, 1.0f ); + hp = std::clamp(hp, -1.0f, 1.0f); bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca; - bp = qBound( -1.0f, bp, 1.0f ); + bp = std::clamp(bp, -1.0f, 1.0f); m_rclast0[_chnl] = in; m_rchp0[_chnl] = hp; m_rcbp0[_chnl] = bp; // second stage gets the output of the first stage as input... - in = m_type == Highpass_RC24 + in = m_type == FilterType::Highpass_RC24 ? hp + m_rcbp1[_chnl] * m_rcq : bp + m_rcbp1[_chnl] * m_rcq; - in = qBound( -1.0f, in, 1.0f ); + in = std::clamp(in, -1.0f, 1.0f); hp = m_rcc * ( m_rchp1[_chnl] + in - m_rclast1[_chnl] ); - hp = qBound( -1.0f, hp, 1.0f ); + hp = std::clamp(hp, -1.0f, 1.0f); bp = hp * m_rcb + m_rcbp1[_chnl] * m_rca; - bp = qBound( -1.0f, bp, 1.0f ); + bp = std::clamp(bp, -1.0f, 1.0f); m_rclast1[_chnl] = in; m_rchp1[_chnl] = hp; m_rcbp1[_chnl] = bp; } - return m_type == Highpass_RC24 ? hp : bp; + return m_type == FilterType::Highpass_RC24 ? hp : bp; } - case Formantfilter: - case FastFormant: + case FilterType::Formantfilter: + case FilterType::FastFormant: { - if( qAbs( _in0 ) < 1.0e-10f && qAbs( m_vflast[0][_chnl] ) < 1.0e-10f ) { return 0.0f; } // performance hack - skip processing when the numbers get too small + if (std::abs(_in0) < 1.0e-10f && std::abs(m_vflast[0][_chnl]) < 1.0e-10f) { return 0.0f; } // performance hack - skip processing when the numbers get too small sample_t hp, bp, in; out = 0; - const int os = m_type == FastFormant ? 1 : 4; // no oversampling for fast formant + const int os = m_type == FilterType::FastFormant ? 1 : 4; // no oversampling for fast formant for( int o = 0; o < os; ++o ) { // first formant in = _in0 + m_vfbp[0][_chnl] * m_vfq; - in = qBound( -1.0f, in, 1.0f ); + in = std::clamp(in, -1.0f, 1.0f); hp = m_vfc[0] * ( m_vfhp[0][_chnl] + in - m_vflast[0][_chnl] ); - hp = qBound( -1.0f, hp, 1.0f ); + hp = std::clamp(hp, -1.0f, 1.0f); bp = hp * m_vfb[0] + m_vfbp[0][_chnl] * m_vfa[0]; - bp = qBound( -1.0f, bp, 1.0f ); + bp = std::clamp(bp, -1.0f, 1.0f); m_vflast[0][_chnl] = in; m_vfhp[0][_chnl] = hp; m_vfbp[0][_chnl] = bp; in = bp + m_vfbp[2][_chnl] * m_vfq; - in = qBound( -1.0f, in, 1.0f ); + in = std::clamp(in, -1.0f, 1.0f); hp = m_vfc[0] * ( m_vfhp[2][_chnl] + in - m_vflast[2][_chnl] ); - hp = qBound( -1.0f, hp, 1.0f ); + hp = std::clamp(hp, -1.0f, 1.0f); bp = hp * m_vfb[0] + m_vfbp[2][_chnl] * m_vfa[0]; - bp = qBound( -1.0f, bp, 1.0f ); + bp = std::clamp(bp, -1.0f, 1.0f); m_vflast[2][_chnl] = in; m_vfhp[2][_chnl] = hp; m_vfbp[2][_chnl] = bp; in = bp + m_vfbp[4][_chnl] * m_vfq; - in = qBound( -1.0f, in, 1.0f ); + in = std::clamp(in, -1.0f, 1.0f); hp = m_vfc[0] * ( m_vfhp[4][_chnl] + in - m_vflast[4][_chnl] ); - hp = qBound( -1.0f, hp, 1.0f ); + hp = std::clamp(hp, -1.0f, 1.0f); bp = hp * m_vfb[0] + m_vfbp[4][_chnl] * m_vfa[0]; - bp = qBound( -1.0f, bp, 1.0f ); + bp = std::clamp(bp, -1.0f, 1.0f); m_vflast[4][_chnl] = in; m_vfhp[4][_chnl] = hp; @@ -648,39 +640,39 @@ public: // second formant in = _in0 + m_vfbp[0][_chnl] * m_vfq; - in = qBound( -1.0f, in, 1.0f ); + in = std::clamp(in, -1.0f, 1.0f); hp = m_vfc[1] * ( m_vfhp[1][_chnl] + in - m_vflast[1][_chnl] ); - hp = qBound( -1.0f, hp, 1.0f ); + hp = std::clamp(hp, -1.0f, 1.0f); bp = hp * m_vfb[1] + m_vfbp[1][_chnl] * m_vfa[1]; - bp = qBound( -1.0f, bp, 1.0f ); + bp = std::clamp(bp, -1.0f, 1.0f); m_vflast[1][_chnl] = in; m_vfhp[1][_chnl] = hp; m_vfbp[1][_chnl] = bp; in = bp + m_vfbp[3][_chnl] * m_vfq; - in = qBound( -1.0f, in, 1.0f ); + in = std::clamp(in, -1.0f, 1.0f); hp = m_vfc[1] * ( m_vfhp[3][_chnl] + in - m_vflast[3][_chnl] ); - hp = qBound( -1.0f, hp, 1.0f ); + hp = std::clamp(hp, -1.0f, 1.0f); bp = hp * m_vfb[1] + m_vfbp[3][_chnl] * m_vfa[1]; - bp = qBound( -1.0f, bp, 1.0f ); + bp = std::clamp(bp, -1.0f, 1.0f); m_vflast[3][_chnl] = in; m_vfhp[3][_chnl] = hp; m_vfbp[3][_chnl] = bp; in = bp + m_vfbp[5][_chnl] * m_vfq; - in = qBound( -1.0f, in, 1.0f ); + in = std::clamp(in, -1.0f, 1.0f); hp = m_vfc[1] * ( m_vfhp[5][_chnl] + in - m_vflast[5][_chnl] ); - hp = qBound( -1.0f, hp, 1.0f ); + hp = std::clamp(hp, -1.0f, 1.0f); bp = hp * m_vfb[1] + m_vfbp[5][_chnl] * m_vfa[1]; - bp = qBound( -1.0f, bp, 1.0f ); + bp = std::clamp(bp, -1.0f, 1.0f); m_vflast[5][_chnl] = in; m_vfhp[5][_chnl] = hp; @@ -688,7 +680,7 @@ public: out += bp; } - return m_type == FastFormant ? out * 2.0f : out * 0.5f; + return m_type == FilterType::FastFormant ? out * 2.0f : out * 0.5f; } default: @@ -709,16 +701,16 @@ public: inline void calcFilterCoeffs( float _freq, float _q ) { // temp coef vars - _q = qMax( _q, minQ() ); + _q = std::max(_q, minQ()); - if( m_type == Lowpass_RC12 || - m_type == Bandpass_RC12 || - m_type == Highpass_RC12 || - m_type == Lowpass_RC24 || - m_type == Bandpass_RC24 || - m_type == Highpass_RC24 ) + if( m_type == FilterType::Lowpass_RC12 || + m_type == FilterType::Bandpass_RC12 || + m_type == FilterType::Highpass_RC12 || + m_type == FilterType::Lowpass_RC24 || + m_type == FilterType::Bandpass_RC24 || + m_type == FilterType::Highpass_RC24 ) { - _freq = qBound( 50.0f, _freq, 20000.0f ); + _freq = std::clamp(_freq, 50.0f, 20000.0f); const float sr = m_sampleRatio * 0.25f; const float f = 1.0f / ( _freq * F_2PI ); @@ -731,10 +723,10 @@ public: return; } - if( m_type == Formantfilter || - m_type == FastFormant ) + if( m_type == FilterType::Formantfilter || + m_type == FilterType::FastFormant ) { - _freq = qBound( minFreq(), _freq, 20000.0f ); // limit freq and q for not getting bad noise out of the filter... + _freq = std::clamp(_freq, minFreq(), 20000.0f); // limit freq and q for not getting bad noise out of the filter... // formats for a, e, i, o, u, a static const float _f[6][2] = { { 1000, 1400 }, { 500, 2300 }, @@ -757,7 +749,7 @@ public: const float f1 = 1.0f / ( linearInterpolate( _f[vowel+0][1], _f[vowel+1][1], fract ) * F_2PI ); // samplerate coeff: depends on oversampling - const float sr = m_type == FastFormant ? m_sampleRatio : m_sampleRatio * 0.25f; + const float sr = m_type == FilterType::FastFormant ? m_sampleRatio : m_sampleRatio * 0.25f; m_vfa[0] = 1.0f - sr / ( f0 + sr ); m_vfb[0] = 1.0f - m_vfa[0]; @@ -768,11 +760,11 @@ public: return; } - if( m_type == Moog || - m_type == DoubleMoog ) + if( m_type == FilterType::Moog || + m_type == FilterType::DoubleMoog ) { // [ 0 - 0.5 ] - const float f = qBound( minFreq(), _freq, 20000.0f ) * m_sampleRatio; + const float f = std::clamp(_freq, minFreq(), 20000.0f) * m_sampleRatio; // (Empirical tunning) m_p = ( 3.6f - 3.2f * f ) * f; m_k = 2.0f * m_p - 1; @@ -787,9 +779,9 @@ public: return; } - if( m_type == Tripole ) + if( m_type == FilterType::Tripole ) { - const float f = qBound( 20.0f, _freq, 20000.0f ) * m_sampleRatio * 0.25f; + const float f = std::clamp(_freq, 20.0f, 20000.0f) * m_sampleRatio * 0.25f; m_p = ( 3.6f - 3.2f * f ) * f; m_k = 2.0f * m_p - 1.0f; @@ -798,20 +790,20 @@ public: return; } - if( m_type == Lowpass_SV || - m_type == Bandpass_SV || - m_type == Highpass_SV || - m_type == Notch_SV ) + if( m_type == FilterType::Lowpass_SV || + m_type == FilterType::Bandpass_SV || + m_type == FilterType::Highpass_SV || + m_type == FilterType::Notch_SV ) { - const float f = sinf( qMax( minFreq(), _freq ) * m_sampleRatio * F_PI ); - m_svf1 = qMin( f, 0.825f ); - m_svf2 = qMin( f * 2.0f, 0.825f ); - m_svq = qMax( 0.0001f, 2.0f - ( _q * 0.1995f ) ); + const float f = sinf(std::max(minFreq(), _freq) * m_sampleRatio * F_PI); + m_svf1 = std::min(f, 0.825f); + m_svf2 = std::min(f * 2.0f, 0.825f); + m_svq = std::max(0.0001f, 2.0f - (_q * 0.1995f)); return; } // other filters - _freq = qBound( minFreq(), _freq, 20000.0f ); + _freq = std::clamp(_freq, minFreq(), 20000.0f); const float omega = F_2PI * _freq * m_sampleRatio; const float tsin = sinf( omega ) * 0.5f; const float tcos = cosf( omega ); @@ -825,38 +817,38 @@ public: switch( m_type ) { - case LowPass: + case FilterType::LowPass: { const float b1 = ( 1.0f - tcos ) * a0; const float b0 = b1 * 0.5f; m_biQuad.setCoeffs( a1, a2, b0, b1, b0 ); break; } - case HiPass: + case FilterType::HiPass: { const float b1 = ( -1.0f - tcos ) * a0; const float b0 = b1 * -0.5f; m_biQuad.setCoeffs( a1, a2, b0, b1, b0 ); break; } - case BandPass_CSG: + case FilterType::BandPass_CSG: { const float b0 = tsin * a0; m_biQuad.setCoeffs( a1, a2, b0, 0.0f, -b0 ); break; } - case BandPass_CZPG: + case FilterType::BandPass_CZPG: { const float b0 = alpha * a0; m_biQuad.setCoeffs( a1, a2, b0, 0.0f, -b0 ); break; } - case Notch: + case FilterType::Notch: { m_biQuad.setCoeffs( a1, a2, a0, a1, a0 ); break; } - case AllPass: + case FilterType::AllPass: { m_biQuad.setCoeffs( a1, a2, a2, a1, 1.0f ); break; @@ -905,7 +897,7 @@ private: // in/out history for Lowpass_SV (state-variant lowpass) frame m_delay1, m_delay2, m_delay3, m_delay4; - FilterTypes m_type; + FilterType m_type; bool m_doubleFilter; float m_sampleRate; diff --git a/include/CPULoadWidget.h b/include/CPULoadWidget.h index 904445c67..dfa5bac73 100644 --- a/include/CPULoadWidget.h +++ b/include/CPULoadWidget.h @@ -26,6 +26,7 @@ #ifndef LMMS_GUI_CPU_LOAD_WIDGET_H #define LMMS_GUI_CPU_LOAD_WIDGET_H +#include #include #include #include @@ -40,6 +41,7 @@ namespace lmms::gui class CPULoadWidget : public QWidget { Q_OBJECT + Q_PROPERTY(int stepSize MEMBER m_stepSize) public: CPULoadWidget( QWidget * _parent ); ~CPULoadWidget() override = default; @@ -54,6 +56,8 @@ protected slots: private: + int stepSize() const { return std::max(1, m_stepSize); } + int m_currentLoad; QPixmap m_temp; @@ -64,6 +68,8 @@ private: QTimer m_updateTimer; + int m_stepSize; + } ; diff --git a/include/Clip.h b/include/Clip.h index 8f4162d96..96394602f 100644 --- a/include/Clip.h +++ b/include/Clip.h @@ -164,13 +164,6 @@ signals: private: - enum Actions - { - NoAction, - Move, - Resize - } ; - Track * m_track; QString m_name; diff --git a/include/ClipView.h b/include/ClipView.h index 32c5130b9..942258367 100644 --- a/include/ClipView.h +++ b/include/ClipView.h @@ -140,7 +140,7 @@ public slots: void resetColor(); protected: - enum ContextMenuAction + enum class ContextMenuAction { Remove, Cut, @@ -191,9 +191,9 @@ protected slots: private: - enum Actions + enum class Action { - NoAction, + None, Move, MoveSelection, Resize, @@ -206,7 +206,7 @@ private: static TextFloat * s_textFloat; Clip * m_clip; - Actions m_action; + Action m_action; QPoint m_initialMousePos; QPoint m_initialMouseGlobalPos; QVector m_initialOffsets; diff --git a/include/ComboBoxModel.h b/include/ComboBoxModel.h index 8fd1f49f4..e90d804e2 100644 --- a/include/ComboBoxModel.h +++ b/include/ComboBoxModel.h @@ -72,12 +72,12 @@ public: const QString & itemText( int i ) const { - return m_items[qBound( minValue(), i, maxValue() )].first; + return m_items[std::clamp(i, minValue(), maxValue())].first; } const PixmapLoader* itemPixmap( int i ) const { - return m_items[qBound( minValue(), i, maxValue() )].second.get(); + return m_items[std::clamp(i, minValue(), maxValue())].second.get(); } int size() const diff --git a/include/ConfigManager.h b/include/ConfigManager.h index eee069681..f6239c297 100644 --- a/include/ConfigManager.h +++ b/include/ConfigManager.h @@ -30,9 +30,9 @@ #include #include #include -#include #include +#include #include "lmms_export.h" @@ -239,11 +239,8 @@ public: void addRecentlyOpenedProject(const QString & _file); - const QString & value(const QString & cls, - const QString & attribute) const; - const QString & value(const QString & cls, - const QString & attribute, - const QString & defaultVal) const; + QString value(const QString& cls, const QString& attribute, const QString& defaultVal = "") const; + void setValue(const QString & cls, const QString & attribute, const QString & value); void deleteValue(const QString & cls, const QString & attribute); @@ -302,7 +299,7 @@ private: unsigned int m_configVersion; QStringList m_recentlyOpenedProjects; - using stringPairVector = QVector>; + using stringPairVector = std::vector>; using settingsMap = QMap; settingsMap m_settings; diff --git a/include/Controller.h b/include/Controller.h index 0a5eb0f36..fe78c55cc 100644 --- a/include/Controller.h +++ b/include/Controller.h @@ -45,26 +45,25 @@ class ControllerDialog; } // namespace gui -using ControllerVector = QVector; +using ControllerVector = std::vector; class LMMS_EXPORT Controller : public Model, public JournallingObject { Q_OBJECT public: - enum ControllerTypes + enum class ControllerType { - DummyController, - LfoController, - MidiController, - PeakController, + Dummy, + Lfo, + Midi, + Peak, /* - XYController, - EquationController + XY, + Equation */ - NumControllerTypes } ; - Controller( ControllerTypes _type, Model * _parent, + Controller( ControllerType _type, Model * _parent, const QString & _display_name ); ~Controller() override; @@ -83,7 +82,7 @@ public: m_sampleExact = _exact; } - inline ControllerTypes type() const + inline ControllerType type() const { return( m_type ); } @@ -94,8 +93,8 @@ public: { switch( m_type ) { - case LfoController: return( true ); - case PeakController: return( true ); + case ControllerType::Lfo: return( true ); + case ControllerType::Peak: return( true ); default: break; } @@ -112,13 +111,13 @@ public: void loadSettings( const QDomElement & _this ) override; QString nodeName() const override; - static Controller * create( ControllerTypes _tt, Model * _parent ); + static Controller * create( ControllerType _tt, Model * _parent ); static Controller * create( const QDomElement & _this, Model * _parent ); inline static float fittedValue( float _val ) { - return qBound( 0.0f, _val, 1.0f ); + return std::clamp(_val, 0.0f, 1.0f); } static long runningPeriods() @@ -165,7 +164,7 @@ protected: int m_connectionCount; QString m_name; - ControllerTypes m_type; + ControllerType m_type; static ControllerVector s_controllers; diff --git a/include/ControllerConnection.h b/include/ControllerConnection.h index 4473b68e0..b60687123 100644 --- a/include/ControllerConnection.h +++ b/include/ControllerConnection.h @@ -30,12 +30,13 @@ #define LMMS_CONTROLLER_CONNECTION_H #include -#include #include "Controller.h" #include "JournallingObject.h" #include "ValueBuffer.h" +#include + namespace lmms { @@ -46,7 +47,7 @@ namespace gui class ControllerConnectionDialog; } -using ControllerConnectionVector = QVector; +using ControllerConnectionVector = std::vector; class LMMS_EXPORT ControllerConnection : public QObject, public JournallingObject { diff --git a/include/CustomTextKnob.h b/include/CustomTextKnob.h index 19768ec87..31a58415e 100644 --- a/include/CustomTextKnob.h +++ b/include/CustomTextKnob.h @@ -36,7 +36,7 @@ class LMMS_EXPORT CustomTextKnob : public Knob protected: inline void setHintText( const QString & _txt_before, const QString & _txt_after ) {} // inaccessible public: - CustomTextKnob( knobTypes _knob_num, QWidget * _parent = nullptr, const QString & _name = QString(), const QString & _value_text = QString() ); + CustomTextKnob( KnobType _knob_num, QWidget * _parent = nullptr, const QString & _name = QString(), const QString & _value_text = QString() ); CustomTextKnob( QWidget * _parent = nullptr, const QString & _name = QString(), const QString & _value_text = QString() ); //!< default ctor diff --git a/include/DataFile.h b/include/DataFile.h index a91b37f9b..137f0156f 100644 --- a/include/DataFile.h +++ b/include/DataFile.h @@ -47,9 +47,9 @@ class LMMS_EXPORT DataFile : public QDomDocument using UpgradeMethod = void(DataFile::*)(); public: - enum Types + enum class Type { - UnknownType, + Unknown, SongProject, SongProjectTemplate, InstrumentTrackSettings, @@ -57,10 +57,8 @@ public: ClipboardData, JournalData, EffectSettings, - MidiClip, - TypeCount + MidiClip } ; - using Type = Types; DataFile( const QString& fileName ); DataFile( const QByteArray& data ); diff --git a/include/DspEffectLibrary.h b/include/DspEffectLibrary.h index d8268fd8d..14dbd7ede 100644 --- a/include/DspEffectLibrary.h +++ b/include/DspEffectLibrary.h @@ -187,7 +187,7 @@ namespace lmms::DspEffectLibrary template inline sample_t saturate( sample_t x ) { - return qMin( qMax( -1.0f, x ), 1.0f ); + return std::min(std::max(-1.0f, x), 1.0f); } @@ -198,7 +198,7 @@ namespace lmms::DspEffectLibrary const sample_t _gain, const sample_t _ratio, const FastBassBoost & _orig = FastBassBoost() ) : - m_frequency( qMax( _frequency, 10.0 ) ), + m_frequency(std::max(_frequency, 10.0)), m_gain1( 1.0 / ( m_frequency + 1.0 ) ), m_gain2( _gain ), m_ratio( _ratio ), diff --git a/include/EffectChain.h b/include/EffectChain.h index 57cf8d547..f9482174e 100644 --- a/include/EffectChain.h +++ b/include/EffectChain.h @@ -69,7 +69,7 @@ public: private: - using EffectList = QVector; + using EffectList = std::vector; EffectList m_effects; BoolModel m_enabledModel; diff --git a/include/EnvelopeAndLfoParameters.h b/include/EnvelopeAndLfoParameters.h index a713a90f3..7abc3910e 100644 --- a/include/EnvelopeAndLfoParameters.h +++ b/include/EnvelopeAndLfoParameters.h @@ -25,7 +25,7 @@ #ifndef LMMS_ENVELOPE_AND_LFO_PARAMETERS_H #define LMMS_ENVELOPE_AND_LFO_PARAMETERS_H -#include +#include #include "JournallingObject.h" #include "AutomatableModel.h" @@ -169,7 +169,7 @@ private: bool m_bad_lfoShapeData; SampleBuffer m_userWave; - enum LfoShapes + enum class LfoShape { SineWave, TriangleWave, @@ -177,8 +177,9 @@ private: SquareWave, UserDefinedWave, RandomWave, - NumLfoShapes + Count } ; + constexpr static auto NumLfoShapes = static_cast(LfoShape::Count); sample_t lfoShapeSample( fpp_t _frame_offset ); void updateLfoShapeData(); diff --git a/include/ExportProjectDialog.h b/include/ExportProjectDialog.h index 56a9fc1f5..37f6e0399 100644 --- a/include/ExportProjectDialog.h +++ b/include/ExportProjectDialog.h @@ -62,7 +62,7 @@ private: QString m_fileExtension; bool m_multiExport; - ProjectRenderer::ExportFileFormats m_ft; + ProjectRenderer::ExportFileFormat m_ft; std::unique_ptr m_renderManager; } ; diff --git a/include/FileBrowser.h b/include/FileBrowser.h index 51103b19f..3334a73f6 100644 --- a/include/FileBrowser.h +++ b/include/FileBrowser.h @@ -223,20 +223,19 @@ private: class FileItem : public QTreeWidgetItem { public: - enum FileTypes + enum class FileType { - ProjectFile, - PresetFile, - SampleFile, - SoundFontFile, - PatchFile, - MidiFile, - VstPluginFile, - UnknownFile, - NumFileTypes + Project, + Preset, + Sample, + SoundFont, + Patch, + Midi, + VstPlugin, + Unknown } ; - enum FileHandling + enum class FileHandling { NotSupported, LoadAsProject, @@ -255,7 +254,7 @@ public: return QFileInfo(m_path, text(0)).absoluteFilePath(); } - inline FileTypes type() const + inline FileType type() const { return( m_type ); } @@ -267,7 +266,7 @@ public: inline bool isTrack() const { - return m_handling == LoadAsPreset || m_handling == LoadByPlugin; + return m_handling == FileHandling::LoadAsPreset || m_handling == FileHandling::LoadByPlugin; } QString extension(); @@ -287,7 +286,7 @@ private: static QPixmap * s_unknownFilePixmap; QString m_path; - FileTypes m_type; + FileType m_type; FileHandling m_handling; } ; diff --git a/include/Flags.h b/include/Flags.h new file mode 100644 index 000000000..76106dde6 --- /dev/null +++ b/include/Flags.h @@ -0,0 +1,83 @@ +/* + * Flags.h - class to make flags from enums + * + * Copyright (c) 2023 Dominic Clark + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LMMS_FLAGS_H +#define LMMS_FLAGS_H + +#include + +namespace lmms { + +template +class Flags +{ + static_assert(std::is_enum_v, "lmms::Flags can only be used with enum types"); + +public: + using EnumType = T; + using UnderlyingType = std::underlying_type_t; + + constexpr Flags() = default; + + constexpr Flags(T value) : // Intentionally not explicit + m_value{static_cast(value)} + {} + + constexpr explicit Flags(UnderlyingType value) : + m_value{value} + {} + + constexpr auto testAll(Flags flags) const -> bool { return *this & flags == flags; } + constexpr auto testAny(Flags flags) const -> bool { return *this & flags != Flags{}; } + constexpr auto testFlag(EnumType flag) const -> bool { return static_cast(*this & flag); } + + constexpr auto operator~() const -> Flags { return Flags{~m_value}; } + friend constexpr auto operator&(Flags l, Flags r) -> Flags { return Flags{l.m_value & r.m_value}; } + friend constexpr auto operator|(Flags l, Flags r) -> Flags { return Flags{l.m_value | r.m_value}; } + friend constexpr auto operator^(Flags l, Flags r) -> Flags { return Flags{l.m_value ^ r.m_value}; } + friend constexpr auto operator+(Flags l, Flags r) -> Flags { return Flags{l.m_value | r.m_value}; } + friend constexpr auto operator-(Flags l, Flags r) -> Flags { return Flags{l.m_value & ~r.m_value}; } + + constexpr auto operator&=(Flags f) -> Flags& { m_value &= f.m_value; return *this; } + constexpr auto operator|=(Flags f) -> Flags& { m_value |= f.m_value; return *this; } + constexpr auto operator^=(Flags f) -> Flags& { m_value ^= f.m_value; return *this; } + constexpr auto operator+=(Flags f) -> Flags& { m_value |= f.m_value; return *this; } + constexpr auto operator-=(Flags f) -> Flags& { m_value &= ~f.m_value; return *this; } + + constexpr explicit operator UnderlyingType() const { return m_value; } // TODO C++23: explicit(std::is_scoped_enum) + constexpr explicit operator bool() const { return m_value != 0; } + + friend constexpr auto operator==(Flags l, Flags r) -> bool { return l.m_value == r.m_value; } // TODO C++20: = default + friend constexpr auto operator!=(Flags l, Flags r) -> bool { return l.m_value != r.m_value; } // TODO C++20: Remove + +private: + UnderlyingType m_value = 0; +}; + +#define LMMS_DECLARE_OPERATORS_FOR_FLAGS(type) \ +constexpr inline auto operator|(type l, type r) -> ::lmms::Flags { return ::lmms::Flags{l} | ::lmms::Flags{r}; } + +} // namespace lmms + +#endif // LMMS_FLAGS_H diff --git a/include/Graph.h b/include/Graph.h index f62215ac2..0f5f24524 100644 --- a/include/Graph.h +++ b/include/Graph.h @@ -48,13 +48,12 @@ class LMMS_EXPORT Graph : public QWidget, public ModelView { Q_OBJECT public: - enum graphStyle + enum class Style { - NearestStyle, //!< draw as stairs - LinearStyle, //!< connect each 2 samples with a line, with wrapping - LinearNonCyclicStyle, //!< LinearStyle without wrapping - BarStyle, //!< draw thick bars - NumGraphStyles + Nearest, //!< draw as stairs + Linear, //!< connect each 2 samples with a line, with wrapping + LinearNonCyclic, //!< Linear without wrapping + Bar, //!< draw thick bars }; /** @@ -62,7 +61,7 @@ public: * @param _width Pixel width of widget * @param _height Pixel height of widget */ - Graph( QWidget * _parent, graphStyle _style = Graph::LinearStyle, + Graph( QWidget * _parent, Style _style = Style::Linear, int _width = 132, int _height = 104 ); @@ -78,13 +77,13 @@ public: return castModel(); } - inline graphStyle getGraphStyle() + inline Style getGraphStyle() { return m_graphStyle; } - inline void setGraphStyle( graphStyle _s ) + inline void setGraphStyle( Style _s ) { m_graphStyle = _s; update(); @@ -114,7 +113,7 @@ private: QPixmap m_foreground; QColor m_graphColor; - graphStyle m_graphStyle; + Style m_graphStyle; bool m_mouseDown; int m_lastCursorX; diff --git a/include/Instrument.h b/include/Instrument.h index 1c42c970e..f23e0b401 100644 --- a/include/Instrument.h +++ b/include/Instrument.h @@ -27,6 +27,8 @@ #define LMMS_INSTRUMENT_H #include + +#include "Flags.h" #include "lmms_export.h" #include "lmms_basics.h" #include "MemoryManager.h" @@ -47,7 +49,7 @@ class LMMS_EXPORT Instrument : public Plugin { MM_OPERATORS public: - enum Flag + enum class Flag { NoFlags = 0x00, IsSingleStreamed = 0x01, /*! Instrument provides a single audio stream for all notes */ @@ -55,7 +57,7 @@ public: IsNotBendable = 0x04, /*! Instrument can't react to pitch bend changes */ }; - Q_DECLARE_FLAGS(Flags, Flag); + using Flags = lmms::Flags; Instrument(InstrumentTrack * _instrument_track, const Descriptor * _descriptor, @@ -102,7 +104,7 @@ public: virtual Flags flags() const { - return NoFlags; + return Flag::NoFlags; } // sub-classes can re-implement this for receiving all incoming @@ -149,7 +151,7 @@ private: } ; -Q_DECLARE_OPERATORS_FOR_FLAGS(Instrument::Flags) +LMMS_DECLARE_OPERATORS_FOR_FLAGS(Instrument::Flag) } // namespace lmms diff --git a/include/InstrumentFunctions.h b/include/InstrumentFunctions.h index f62b74e9a..59c651a68 100644 --- a/include/InstrumentFunctions.h +++ b/include/InstrumentFunctions.h @@ -119,7 +119,7 @@ public: }; - struct ChordTable : public QVector + struct ChordTable { private: ChordTable(); @@ -131,6 +131,7 @@ public: }; static std::array s_initTable; + std::vector m_chords; public: static const ChordTable & getInstance() @@ -150,6 +151,11 @@ public: { return getByName( name, false ); } + + const std::vector& chords() const + { + return m_chords; + } }; @@ -170,14 +176,13 @@ class InstrumentFunctionArpeggio : public Model, public JournallingObject { Q_OBJECT public: - enum ArpDirections + enum class ArpDirection { - ArpDirUp, - ArpDirDown, - ArpDirUpAndDown, - ArpDirDownAndUp, - ArpDirRandom, - NumArpDirections + Up, + Down, + UpAndDown, + DownAndUp, + Random } ; InstrumentFunctionArpeggio( Model * _parent ); @@ -196,11 +201,11 @@ public: private: - enum ArpModes + enum class ArpMode { - FreeMode, - SortMode, - SyncMode + Free, + Sort, + Sync } ; BoolModel m_arpEnabledModel; diff --git a/include/InstrumentSoundShaping.h b/include/InstrumentSoundShaping.h index 6db3078ec..fb5f1e8bd 100644 --- a/include/InstrumentSoundShaping.h +++ b/include/InstrumentSoundShaping.h @@ -51,13 +51,14 @@ public: void processAudioBuffer( sampleFrame * _ab, const fpp_t _frames, NotePlayHandle * _n ); - enum Targets + enum class Target { Volume, Cut, Resonance, - NumTargets + Count } ; + constexpr static auto NumTargets = static_cast(Target::Count); f_cnt_t envFrames( const bool _only_vol = false ) const; f_cnt_t releaseFrames() const; @@ -82,7 +83,7 @@ private: FloatModel m_filterCutModel; FloatModel m_filterResModel; - static const char *const targetNames[InstrumentSoundShaping::NumTargets][3]; + static const char *const targetNames[NumTargets][3]; friend class gui::InstrumentSoundShapingView; diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index f21723363..5efafe0c7 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -51,7 +51,7 @@ namespace gui class InstrumentTrackView; class InstrumentTrackWindow; -class InstrumentMiscView; +class InstrumentTuningView; class MidiCCRackView; } // namespace gui @@ -315,7 +315,7 @@ private: friend class gui::InstrumentTrackView; friend class gui::InstrumentTrackWindow; friend class NotePlayHandle; - friend class gui::InstrumentMiscView; + friend class gui::InstrumentTuningView; friend class gui::MidiCCRackView; } ; diff --git a/include/InstrumentTrackView.h b/include/InstrumentTrackView.h index 363f5b3ab..d7d5fb83a 100644 --- a/include/InstrumentTrackView.h +++ b/include/InstrumentTrackView.h @@ -25,6 +25,7 @@ #ifndef LMMS_GUI_INSTRUMENT_TRACK_VIEW_H #define LMMS_GUI_INSTRUMENT_TRACK_VIEW_H +#include "MixerLineLcdSpinBox.h" #include "TrackView.h" #include "InstrumentTrack.h" @@ -72,6 +73,7 @@ public: protected: + void modelChanged() override; void dragEnterEvent( QDragEnterEvent * _dee ) override; void dropEvent( QDropEvent * _de ) override; @@ -97,6 +99,7 @@ private: // widgets in track-settings-widget TrackLabelButton * m_tlb; + MixerLineLcdSpinBox* m_mixerChannelNumber; Knob * m_volumeKnob; Knob * m_panningKnob; FadeButton * m_activityIndicator; diff --git a/include/InstrumentTrackWindow.h b/include/InstrumentTrackWindow.h index d41bbdac8..971c63899 100644 --- a/include/InstrumentTrackWindow.h +++ b/include/InstrumentTrackWindow.h @@ -47,7 +47,7 @@ class MixerLineLcdSpinBox; class InstrumentFunctionArpeggioView; class InstrumentFunctionNoteStackingView; class InstrumentMidiIOView; -class InstrumentMiscView; +class InstrumentTuningView; class InstrumentSoundShapingView; class InstrumentTrackShapingView; class InstrumentTrackView; @@ -154,7 +154,7 @@ private: InstrumentFunctionArpeggioView* m_arpeggioView; InstrumentMidiIOView * m_midiView; EffectRackView * m_effectView; - InstrumentMiscView *m_miscView; + InstrumentTuningView *m_tuningView; // test-piano at the bottom of every instrument-settings-window diff --git a/include/InstrumentMiscView.h b/include/InstrumentTuningView.h similarity index 72% rename from include/InstrumentMiscView.h rename to include/InstrumentTuningView.h index 28f3c6a8e..4ee18dc84 100644 --- a/include/InstrumentMiscView.h +++ b/include/InstrumentTuningView.h @@ -1,9 +1,9 @@ /* - * InstrumentMiscView.h - widget in instrument-track-window for setting up - * miscellaneous options not covered by other tabs + * InstrumentTuningView.h - widget in instrument-track-window for setting up + * tuning and transposition options * * Copyright (c) 2005-2014 Tobias Doerffel - * Copyright (c) 2020 Martin Pavelek + * Copyright (c) 2020-2022 Martin Pavelek * * This file is part of LMMS - https://lmms.io * @@ -24,11 +24,13 @@ * */ -#ifndef LMMS_GUI_INSTRUMENT_MISC_VIEW_H -#define LMMS_GUI_INSTRUMENT_MISC_VIEW_H +#ifndef LMMS_GUI_INSTRUMENT_TUNING_VIEW_H +#define LMMS_GUI_INSTRUMENT_TUNING_VIEW_H #include +class QLabel; + namespace lmms { @@ -42,15 +44,17 @@ class GroupBox; class LedCheckBox; -class InstrumentMiscView : public QWidget +class InstrumentTuningView : public QWidget { Q_OBJECT public: - InstrumentMiscView(InstrumentTrack *it, QWidget *parent); + InstrumentTuningView(InstrumentTrack *it, QWidget *parent); GroupBox *pitchGroupBox() {return m_pitchGroupBox;} GroupBox *microtunerGroupBox() {return m_microtunerGroupBox;} + QLabel *microtunerNotSupportedLabel() {return m_microtunerNotSupportedLabel;} + ComboBox *scaleCombo() {return m_scaleCombo;} ComboBox *keymapCombo() {return m_keymapCombo;} @@ -60,6 +64,8 @@ private: GroupBox *m_pitchGroupBox; GroupBox *m_microtunerGroupBox; + QLabel *m_microtunerNotSupportedLabel; + ComboBox *m_scaleCombo; ComboBox *m_keymapCombo; @@ -71,4 +77,4 @@ private: } // namespace lmms -#endif // LMMS_GUI_INSTRUMENT_MISC_VIEW_H +#endif // LMMS_GUI_INSTRUMENT_TUNING_VIEW_H diff --git a/include/Knob.h b/include/Knob.h index 289af8cd5..d5739bb1c 100644 --- a/include/Knob.h +++ b/include/Knob.h @@ -42,9 +42,9 @@ namespace lmms::gui class SimpleTextFloat; -enum knobTypes +enum class KnobType { - knobDark_28, knobBright_26, knobSmall_17, knobVintage_32, knobStyled + Dark28, Bright26, Small17, Vintage32, Styled } ; @@ -53,7 +53,7 @@ void convertPixmapToGrayScale(QPixmap &pixMap); class LMMS_EXPORT Knob : public QWidget, public FloatModelView { Q_OBJECT - Q_ENUMS( knobTypes ) + Q_ENUMS( KnobType ) Q_PROPERTY(float innerRadius READ innerRadius WRITE setInnerRadius) Q_PROPERTY(float outerRadius READ outerRadius WRITE setOuterRadius) @@ -75,7 +75,7 @@ class LMMS_EXPORT Knob : public QWidget, public FloatModelView mapPropertyFromModel(bool,isVolumeKnob,setVolumeKnob,m_volumeKnob); mapPropertyFromModel(float,volumeRatio,setVolumeRatio,m_volumeRatio); - Q_PROPERTY(knobTypes knobNum READ knobNum WRITE setknobNum) + Q_PROPERTY(KnobType knobNum READ knobNum WRITE setknobNum) Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor) @@ -83,7 +83,7 @@ class LMMS_EXPORT Knob : public QWidget, public FloatModelView void onKnobNumUpdated(); //!< to be called when you updated @a m_knobNum public: - Knob( knobTypes _knob_num, QWidget * _parent = nullptr, const QString & _name = QString() ); + Knob( KnobType _knob_num, QWidget * _parent = nullptr, const QString & _name = QString() ); Knob( QWidget * _parent = nullptr, const QString & _name = QString() ); //!< default ctor Knob( const Knob& other ) = delete; @@ -106,8 +106,8 @@ public: float outerRadius() const; void setOuterRadius( float r ); - knobTypes knobNum() const; - void setknobNum( knobTypes k ); + KnobType knobNum() const; + void setknobNum( KnobType k ); QPointF centerPoint() const; float centerPointX() const; @@ -144,6 +144,9 @@ protected: void wheelEvent( QWheelEvent * _me ) override; void changeEvent(QEvent * ev) override; + void enterEvent(QEvent *event) override; + void leaveEvent(QEvent *event) override; + virtual float getValue( const QPoint & _p ); private slots: @@ -160,6 +163,7 @@ private: float _innerRadius = 1) const; void drawKnob( QPainter * _p ); + void showTextFloat(int msecBeforeDisplay, int msecDisplayTime); void setPosition( const QPoint & _p ); bool updateAngle(); @@ -206,7 +210,7 @@ private: QColor m_textColor; - knobTypes m_knobNum; + KnobType m_knobNum; } ; diff --git a/include/LadspaBase.h b/include/LadspaBase.h index 51c0ca202..6569c5a30 100644 --- a/include/LadspaBase.h +++ b/include/LadspaBase.h @@ -35,16 +35,16 @@ namespace lmms class LadspaControl; -enum buffer_rate_t { - CHANNEL_IN, - CHANNEL_OUT, - AUDIO_RATE_INPUT, - AUDIO_RATE_OUTPUT, - CONTROL_RATE_INPUT, - CONTROL_RATE_OUTPUT +enum class BufferRate { + ChannelIn, + ChannelOut, + AudioRateInput, + AudioRateOutput, + ControlRateInput, + ControlRateOutput }; -enum buffer_data_t { TOGGLED, ENUM, INTEGER, FLOATING, TIME, NONE }; +enum class BufferDataType { Toggled, Enum, Integer, Floating, Time, None }; //! This struct is used to hold port descriptions internally //! which where received from the ladspa plugin @@ -54,8 +54,8 @@ struct port_desc_t ch_cnt_t proc; uint16_t port_id; uint16_t control_id; - buffer_rate_t rate; - buffer_data_t data_type; + BufferRate rate; + BufferDataType data_type; float scale; LADSPA_Data max; LADSPA_Data min; diff --git a/include/LadspaManager.h b/include/LadspaManager.h index 8c00d2604..1a3360231 100644 --- a/include/LadspaManager.h +++ b/include/LadspaManager.h @@ -62,14 +62,14 @@ calls using: as the plug-in key. */ -enum LadspaPluginType +enum class LadspaPluginType { - SOURCE, - TRANSFER, - VALID, - INVALID, - SINK, - OTHER + Source, + Transfer, + Valid, + Invalid, + Sink, + Other }; struct LadspaManagerDescription diff --git a/include/LedCheckBox.h b/include/LedCheckBox.h index ba1b196fa..aaafffaa1 100644 --- a/include/LedCheckBox.h +++ b/include/LedCheckBox.h @@ -38,21 +38,20 @@ class LMMS_EXPORT LedCheckBox : public AutomatableButton { Q_OBJECT public: - enum LedColors + enum class LedColor { Yellow, Green, - Red, - NumColors + Red } ; LedCheckBox( const QString & _txt, QWidget * _parent, const QString & _name = QString(), - LedColors _color = Yellow, + LedColor _color = LedColor::Yellow, bool legacyMode = true); LedCheckBox( QWidget * _parent, const QString & _name = QString(), - LedColors _color = Yellow, + LedColor _color = LedColor::Yellow, bool legacyMode = true); ~LedCheckBox() override; @@ -78,8 +77,9 @@ private: QString m_text; bool m_legacyMode; + + void initUi( LedColor _color ); //!< to be called by ctors - void initUi( LedColors _color ); //!< to be called by ctors void onTextUpdated(); //!< to be called when you updated @a m_text void paintLegacy(QPaintEvent * p); void paintNonLegacy(QPaintEvent * p); diff --git a/include/LmmsStyle.h b/include/LmmsStyle.h index b3be03952..d17bbed98 100644 --- a/include/LmmsStyle.h +++ b/include/LmmsStyle.h @@ -36,34 +36,6 @@ namespace lmms::gui class LmmsStyle : public QProxyStyle { public: - enum ColorRole - { - AutomationBarFill, - AutomationBarValue, - AutomationSelectedBarFill, - AutomationCrosshair, - PianoRollStepNote, - PianoRollSelectedNote, - PianoRollDefaultNote, - PianoRollFrozenNote, - PianoRollMutedNote, - PianoRollEditHandle, - PianoRollVolumeLevel, - PianoRollPanningLevel, - PianoRollSelectedLevel, - TimelineForecolor, - StandardGraphLine, - StandardGraphHandle, - StandardGraphHandleBorder, - StandardGraphCrosshair, - TextFloatForecolor, - TextFloatFill, - VisualizationLevelLow, - VisualizationLevelMid, - VisualizationLevelPeak, - NumColorRoles - }; - LmmsStyle(); ~LmmsStyle() override = default; @@ -88,8 +60,6 @@ public: private: QImage colorizeXpm( const char * const * xpm, const QBrush& fill ) const; void hoverColors( bool sunken, bool hover, bool active, QColor& color, QColor& blend ) const; - QColor m_colors[ LmmsStyle::NumColorRoles ]; - }; diff --git a/include/Lv2ControlBase.h b/include/Lv2ControlBase.h index f5cb0cdb4..2d44f0ecf 100644 --- a/include/Lv2ControlBase.h +++ b/include/Lv2ControlBase.h @@ -74,7 +74,7 @@ class PluginIssue; class LMMS_EXPORT Lv2ControlBase : public LinkedModelGroups { public: - static Plugin::PluginTypes check(const LilvPlugin* m_plugin, + static Plugin::Type check(const LilvPlugin* m_plugin, std::vector &issues); void shutdown(); diff --git a/include/Lv2Manager.h b/include/Lv2Manager.h index 89f6a0efd..909dba560 100644 --- a/include/Lv2Manager.h +++ b/include/Lv2Manager.h @@ -95,18 +95,18 @@ public: //! use only for std::map internals Lv2Info() : m_plugin(nullptr) {} //! ctor used inside Lv2Manager - Lv2Info(const LilvPlugin* plug, Plugin::PluginTypes type, bool valid) : + Lv2Info(const LilvPlugin* plug, Plugin::Type type, bool valid) : m_plugin(plug), m_type(type), m_valid(valid) {} Lv2Info(Lv2Info&& other) = default; Lv2Info& operator=(Lv2Info&& other) = default; const LilvPlugin* plugin() const { return m_plugin; } - Plugin::PluginTypes type() const { return m_type; } + Plugin::Type type() const { return m_type; } bool isValid() const { return m_valid; } private: const LilvPlugin* m_plugin; - Plugin::PluginTypes m_type; + Plugin::Type m_type; bool m_valid = false; }; diff --git a/include/Lv2Ports.h b/include/Lv2Ports.h index 0f0b02913..e4c896ff3 100644 --- a/include/Lv2Ports.h +++ b/include/Lv2Ports.h @@ -33,6 +33,7 @@ #include #include +#include "Flags.h" #include "lmms_basics.h" #include "PluginIssue.h" @@ -210,12 +211,12 @@ private: struct AtomSeq : public VisitablePort { - enum FlagType + enum class FlagType { None = 0, Midi = 1 }; - unsigned flags = FlagType::None; + Flags flags = FlagType::None; struct Lv2EvbufDeleter { diff --git a/include/Lv2Proc.h b/include/Lv2Proc.h index 1be284ced..62070def7 100644 --- a/include/Lv2Proc.h +++ b/include/Lv2Proc.h @@ -64,7 +64,7 @@ namespace Lv2Ports class Lv2Proc : public LinkedModelGroup { public: - static Plugin::PluginTypes check(const LilvPlugin* plugin, + static Plugin::Type check(const LilvPlugin* plugin, std::vector &issues); /* diff --git a/include/Lv2SubPluginFeatures.h b/include/Lv2SubPluginFeatures.h index 57eab8715..eb0bd9900 100644 --- a/include/Lv2SubPluginFeatures.h +++ b/include/Lv2SubPluginFeatures.h @@ -47,7 +47,7 @@ private: static QString pluginName(const LilvPlugin *plug); public: - Lv2SubPluginFeatures(Plugin::PluginTypes type); + Lv2SubPluginFeatures(Plugin::Type type); void fillDescriptionWidget( QWidget *parent, const Key *k) const override; diff --git a/include/MainWindow.h b/include/MainWindow.h index c4bbb6767..30d52ec3a 100644 --- a/include/MainWindow.h +++ b/include/MainWindow.h @@ -113,7 +113,7 @@ public: return m_autoSaveTimer.interval(); } - enum SessionState + enum class SessionState { Normal, Recover diff --git a/include/MidiClient.h b/include/MidiClient.h index 3a64f709c..1eb04402b 100644 --- a/include/MidiClient.h +++ b/include/MidiClient.h @@ -26,7 +26,7 @@ #define LMMS_MIDI_CLIENT_H #include -#include +#include #include "MidiEvent.h" @@ -111,7 +111,7 @@ public: static MidiClient * openMidiClient(); protected: - QVector m_midiPorts; + std::vector m_midiPorts; } ; diff --git a/include/MidiClip.h b/include/MidiClip.h index bbb7d325d..c2287bd00 100644 --- a/include/MidiClip.h +++ b/include/MidiClip.h @@ -46,7 +46,7 @@ class LMMS_EXPORT MidiClip : public Clip { Q_OBJECT public: - enum MidiClipTypes + enum class Type { BeatClip, MelodyClip @@ -79,10 +79,10 @@ public: void setStep( int step, bool enabled ); // Split the list of notes on the given position - void splitNotes(NoteVector notes, TimePos pos); + void splitNotes(const NoteVector& notes, TimePos pos); // clip-type stuff - inline MidiClipTypes type() const + inline Type type() const { return m_clipType; } @@ -129,14 +129,14 @@ protected slots: private: TimePos beatClipLength() const; - void setType( MidiClipTypes _new_clip_type ); + void setType( Type _new_clip_type ); void checkType(); void resizeToFirstTrack(); InstrumentTrack * m_instrumentTrack; - MidiClipTypes m_clipType; + Type m_clipType; // data-stuff NoteVector m_notes; diff --git a/include/MidiPort.h b/include/MidiPort.h index 6f759708e..6078f7a9b 100644 --- a/include/MidiPort.h +++ b/include/MidiPort.h @@ -69,20 +69,19 @@ class MidiPort : public Model, public SerializingObject public: using Map = QMap; - enum Modes + enum class Mode { Disabled, // don't route any MIDI-events (default) Input, // from MIDI-client to MIDI-event-processor Output, // from MIDI-event-processor to MIDI-client Duplex // both directions } ; - using Mode = Modes; MidiPort( const QString& name, MidiClient* client, MidiEventProcessor* eventProcessor, Model* parent = nullptr, - Mode mode = Disabled ); + Mode mode = Mode::Disabled ); ~MidiPort() override; void setName( const QString& name ); @@ -96,12 +95,12 @@ public: bool isInputEnabled() const { - return mode() == Input || mode() == Duplex; + return mode() == Mode::Input || mode() == Mode::Duplex; } bool isOutputEnabled() const { - return mode() == Output || mode() == Duplex; + return mode() == Mode::Output || mode() == Mode::Duplex; } int realOutputChannel() const diff --git a/include/MidiPortMenu.h b/include/MidiPortMenu.h index 0b3fc1b2f..59604969b 100644 --- a/include/MidiPortMenu.h +++ b/include/MidiPortMenu.h @@ -40,7 +40,7 @@ class MidiPortMenu : public QMenu, public ModelView { Q_OBJECT public: - MidiPortMenu( MidiPort::Modes _mode ); + MidiPortMenu( MidiPort::Mode _mode ); ~MidiPortMenu() override = default; @@ -55,7 +55,7 @@ protected slots: private: void modelChanged() override; - MidiPort::Modes m_mode; + MidiPort::Mode m_mode; } ; diff --git a/include/Mixer.h b/include/Mixer.h index 6589836c4..35787a414 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -39,7 +39,7 @@ namespace lmms class MixerRoute; -using MixerRouteVector = QVector; +using MixerRouteVector = std::vector; class MixerChannel : public ThreadableJob { @@ -219,7 +219,7 @@ public: private: // the mixer channels in the mixer. index 0 is always master. - QVector m_mixerChannels; + std::vector m_mixerChannels; // make sure we have at least num channels void allocateChannelsTo(int num); diff --git a/include/Note.h b/include/Note.h index 15aeaa2ce..2df196af2 100644 --- a/include/Note.h +++ b/include/Note.h @@ -27,7 +27,7 @@ #define LMMS_NOTE_H #include -#include +#include #include "volume.h" #include "panning.h" @@ -42,50 +42,56 @@ namespace lmms class DetuningHelper; -enum Keys +enum class Key : int { - Key_C = 0, - Key_CIS = 1, Key_DES = 1, - Key_D = 2, - Key_DIS = 3, Key_ES = 3, - Key_E = 4, Key_FES = 4, - Key_F = 5, - Key_FIS = 6, Key_GES = 6, - Key_G = 7, - Key_GIS = 8, Key_AS = 8, - Key_A = 9, - Key_AIS = 10, Key_B = 10, - Key_H = 11 + C = 0, + Cis = 1, Des = 1, + D = 2, + Dis = 3, Es = 3, + E = 4, Fes = 4, + F = 5, + Fis = 6, Ges = 6, + G = 7, + Gis = 8, As = 8, + A = 9, + Ais = 10, B = 10, + H = 11 } ; -enum Octaves +enum class Octave : int { Octave_m1, // MIDI standard starts at C-1 Octave_0, Octave_1, Octave_2, Octave_3, - Octave_4, DefaultOctave = Octave_4, + Octave_4, Octave_5, Octave_6, Octave_7, Octave_8, Octave_9, // incomplete octave, MIDI only goes up to G9 - NumOctaves }; const int FirstOctave = -1; const int KeysPerOctave = 12; -const int DefaultKey = DefaultOctave * KeysPerOctave + Key_A; + +constexpr inline auto operator+(Octave octave, Key key) -> int +{ + return static_cast(octave) * KeysPerOctave + static_cast(key); +} + +constexpr auto DefaultOctave = Octave::Octave_4; +const int DefaultKey = DefaultOctave + Key::A; //! Number of physical keys, limited to MIDI range (valid for both MIDI 1.0 and 2.0) const int NumKeys = 128; -const int DefaultMiddleKey = Octave_4 * KeysPerOctave + Key_C; -const int DefaultBaseKey = Octave_4 * KeysPerOctave + Key_A; +const int DefaultMiddleKey = Octave::Octave_4 + Key::C; +const int DefaultBaseKey = Octave::Octave_4 + Key::A; const float DefaultBaseFreq = 440.f; -const float MaxDetuning = 4 * 12.0f; +const float MaxDetuning = 5 * 12.0f; @@ -198,7 +204,7 @@ public: int midiVelocity( int midiBaseVelocity ) const { - return qMin( MidiMaxVelocity, getVolume() * midiBaseVelocity / DefaultVolume ); + return std::min(MidiMaxVelocity, getVolume() * midiBaseVelocity / DefaultVolume); } inline panning_t getPanning() const @@ -249,7 +255,7 @@ private: DetuningHelper * m_detuning; }; -using NoteVector = QVector; +using NoteVector = std::vector; struct NoteBounds { diff --git a/include/NotePlayHandle.h b/include/NotePlayHandle.h index 29477705b..7105d6672 100644 --- a/include/NotePlayHandle.h +++ b/include/NotePlayHandle.h @@ -56,15 +56,13 @@ public: fpp_t m_fadeInLength; // specifies origin of NotePlayHandle - enum Origins + enum class Origin { - OriginMidiClip, /*! playback of a note from a MIDI clip */ - OriginMidiInput, /*! playback of a MIDI note input event */ - OriginNoteStacking, /*! created by note stacking instrument function */ - OriginArpeggio, /*! created by arpeggio instrument function */ - OriginCount + MidiClip, /*! playback of a note from a MIDI clip */ + MidiInput, /*! playback of a MIDI note input event */ + NoteStacking, /*! created by note stacking instrument function */ + Arpeggio, /*! created by arpeggio instrument function */ }; - using Origin = Origins; NotePlayHandle( InstrumentTrack* instrumentTrack, const f_cnt_t offset, @@ -72,7 +70,7 @@ public: const Note& noteToPlay, NotePlayHandle* parent = nullptr, int midiEventChannel = -1, - Origin origin = OriginMidiClip ); + Origin origin = Origin::MidiClip ); ~NotePlayHandle() override; void * operator new ( size_t size, void * p ) @@ -110,6 +108,9 @@ public: return m_unpitchedFrequency; } + //! Get the current per-note detuning for this note + float currentDetuning() const { return m_baseDetuning->value(); } + /*! Renders one chunk using the attached instrument into the buffer */ void play( sampleFrame* buffer ) override; @@ -247,7 +248,7 @@ public: } /*! Process note detuning automation */ - void processTimePos( const TimePos& time ); + void processTimePos(const TimePos& time, float pitchValue, bool isRecording); /*! Updates total length (m_frames) depending on a new tempo */ void resize( const bpm_t newTempo ); @@ -349,7 +350,7 @@ public: const Note& noteToPlay, NotePlayHandle* parent = nullptr, int midiEventChannel = -1, - NotePlayHandle::Origin origin = NotePlayHandle::OriginMidiClip ); + NotePlayHandle::Origin origin = NotePlayHandle::Origin::MidiClip ); static void release( NotePlayHandle * nph ); static void extend( int i ); static void free(); diff --git a/include/Oscillator.h b/include/Oscillator.h index 46d858032..dab0b948d 100644 --- a/include/Oscillator.h +++ b/include/Oscillator.h @@ -48,31 +48,34 @@ class LMMS_EXPORT Oscillator { MM_OPERATORS public: - enum WaveShapes + enum class WaveShape { - SineWave, - TriangleWave, - SawWave, - SquareWave, - MoogSawWave, - ExponentialWave, + Sine, + Triangle, + Saw, + Square, + MoogSaw, + Exponential, WhiteNoise, - UserDefinedWave, - NumWaveShapes, //!< Number of all available wave shapes - FirstWaveShapeTable = TriangleWave, //!< First wave shape that has a pre-generated table - NumWaveShapeTables = WhiteNoise - FirstWaveShapeTable, //!< Number of band-limited wave shapes to be generated + UserDefined, + Count //!< Number of all available wave shapes }; + constexpr static auto NumWaveShapes = static_cast(WaveShape::Count); + //! First wave shape that has a pre-generated table + constexpr static auto FirstWaveShapeTable = static_cast(WaveShape::Triangle); + //! Number of band-limited wave shapes to be generated + constexpr static auto NumWaveShapeTables = static_cast(WaveShape::WhiteNoise) - FirstWaveShapeTable; - enum ModulationAlgos + enum class ModulationAlgo { PhaseModulation, AmplitudeModulation, SignalMix, SynchronizedBySubOsc, FrequencyModulation, - NumModulationAlgos + Count } ; - + constexpr static auto NumModulationAlgos = static_cast(ModulationAlgo::Count); Oscillator( const IntModel *wave_shape_model, const IntModel *mod_algo_model, @@ -251,7 +254,7 @@ private: bool m_isModulator; /* Multiband WaveTable */ - static sample_t s_waveTables[WaveShapes::NumWaveShapeTables][OscillatorConstants::WAVE_TABLES_PER_WAVEFORM_COUNT][OscillatorConstants::WAVETABLE_LENGTH]; + static sample_t s_waveTables[NumWaveShapeTables][OscillatorConstants::WAVE_TABLES_PER_WAVEFORM_COUNT][OscillatorConstants::WAVETABLE_LENGTH]; static fftwf_plan s_fftPlan; static fftwf_plan s_ifftPlan; static fftwf_complex * s_specBuf; @@ -284,26 +287,26 @@ private: const ch_cnt_t _chnl ); inline bool syncOk( float _osc_coeff ); - template + template void updateNoSub( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ); - template + template void updatePM( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ); - template + template void updateAM( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ); - template + template void updateMix( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ); - template + template void updateSync( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ); - template + template void updateFM( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ); - template + template inline sample_t getSample( const float _sample ); inline void recalcPhase(); diff --git a/include/OutputSettings.h b/include/OutputSettings.h index 12242e1bb..94de0612c 100644 --- a/include/OutputSettings.h +++ b/include/OutputSettings.h @@ -35,19 +35,18 @@ namespace lmms class OutputSettings { public: - enum BitDepth + enum class BitDepth { - Depth_16Bit, - Depth_24Bit, - Depth_32Bit, - NumDepths + Depth16Bit, + Depth24Bit, + Depth32Bit }; - enum StereoMode + enum class StereoMode { - StereoMode_Stereo, - StereoMode_JointStereo, - StereoMode_Mono + Stereo, + JointStereo, + Mono }; class BitRateSettings @@ -85,7 +84,7 @@ public: OutputSettings( sample_rate_t sampleRate, BitRateSettings const & bitRateSettings, BitDepth bitDepth ) : - OutputSettings(sampleRate, bitRateSettings, bitDepth, StereoMode_Stereo ) + OutputSettings(sampleRate, bitRateSettings, bitDepth, StereoMode::Stereo ) { } diff --git a/include/PeakController.h b/include/PeakController.h index 357e2a95d..de9da3b1c 100644 --- a/include/PeakController.h +++ b/include/PeakController.h @@ -36,7 +36,7 @@ namespace lmms class PeakControllerEffect; -using PeakControllerEffectVector = QVector; +using PeakControllerEffectVector = std::vector; class LMMS_EXPORT PeakController : public Controller { diff --git a/include/Piano.h b/include/Piano.h index 96f374840..698d9c8fe 100644 --- a/include/Piano.h +++ b/include/Piano.h @@ -38,10 +38,10 @@ class MidiEventProcessor; class Piano final : public Model { public: - enum KeyTypes + enum class KeyType { - WhiteKey, - BlackKey + White, + Black } ; Piano(InstrumentTrack* track); diff --git a/include/PianoRoll.h b/include/PianoRoll.h index 6100792d5..38788180f 100644 --- a/include/PianoRoll.h +++ b/include/PianoRoll.h @@ -27,9 +27,10 @@ #ifndef LMMS_GUI_PIANO_ROLL_H #define LMMS_GUI_PIANO_ROLL_H -#include #include +#include + #include "Editor.h" #include "ComboBoxModel.h" #include "SerializingObject.h" @@ -103,13 +104,13 @@ class PianoRoll : public QWidget Q_PROPERTY(QBrush blackKeyActiveBackground MEMBER m_blackKeyActiveBackground) Q_PROPERTY(QBrush blackKeyDisabledBackground MEMBER m_blackKeyDisabledBackground) public: - enum EditModes + enum class EditMode { - ModeDraw, - ModeErase, - ModeSelect, - ModeEditDetuning, - ModeEditKnife + Draw, + Erase, + Select, + Detuning, + Knife }; /*! \brief Resets settings to default when e.g. creating a new project */ @@ -152,16 +153,26 @@ public: int trackOctaveSize() const; - Song::PlayModes desiredPlayModeForAccompany() const; + Song::PlayMode desiredPlayModeForAccompany() const; int quantization() const; protected: - enum QuantizeActions + enum class QuantizeAction { - QuantizeBoth, - QuantizePos, - QuantizeLength + Both, + Pos, + Length + }; + + enum class SemiToneMarkerAction + { + UnmarkAll, + MarkCurrentSemiTone, + MarkAllOctaveSemiTones, + MarkCurrentScale, + MarkCurrentChord, + CopyAllNotesOnKey }; void keyPressEvent( QKeyEvent * ke ) override; @@ -220,12 +231,12 @@ protected slots: void quantizeChanged(); void noteLengthChanged(); void keyChanged(); - void quantizeNotes(lmms::gui::PianoRoll::QuantizeActions mode = QuantizeBoth); + void quantizeNotes(QuantizeAction mode = QuantizeAction::Both); void updateSemiToneMarkerMenu(); void changeNoteEditMode( int i ); - void markSemiTone(int i, bool fromMenu = true); + void markSemiTone(SemiToneMarkerAction i, bool fromMenu = true); void hideMidiClip( lmms::MidiClip* clip ); @@ -247,51 +258,41 @@ signals: private: - enum Actions + enum class Action { - ActionNone, - ActionMoveNote, - ActionResizeNote, - ActionSelectNotes, - ActionChangeNoteProperty, - ActionResizeNoteEditArea, - ActionKnife + None, + MoveNote, + ResizeNote, + SelectNotes, + ChangeNoteProperty, + ResizeNoteEditArea, + Knife }; - enum NoteEditMode + enum class NoteEditMode { - NoteEditVolume, - NoteEditPanning, - NoteEditCount // make sure this one is always last + Volume, + Panning, + Count // make sure this one is always last }; - enum SemiToneMarkerAction + enum class KeyType { - stmaUnmarkAll, - stmaMarkCurrentSemiTone, - stmaMarkAllOctaveSemiTones, - stmaMarkCurrentScale, - stmaMarkCurrentChord, - stmaCopyAllNotesOnKey + WhiteSmall, + WhiteBig, + Black }; - enum PianoRollKeyTypes + enum class GridMode { - PR_WHITE_KEY_SMALL, - PR_WHITE_KEY_BIG, - PR_BLACK_KEY - }; - - enum GridMode - { - gridNudge, - gridSnap - // gridFree + Nudge, + Snap + // Free }; PositionLine * m_positionLine; - QVector m_nemStr; // gui names of each edit mode + std::vector m_nemStr; // gui names of each edit mode QMenu * m_noteEditMenu; // when you right click below the key area QList m_markedSemiTones; @@ -307,9 +308,9 @@ private: TimePos newNoteLen() const; void shiftPos(int amount); - void shiftPos(NoteVector notes, int amount); + void shiftPos(const NoteVector& notes, int amount); void shiftSemiTone(int amount); - void shiftSemiTone(NoteVector notes, int amount); + void shiftSemiTone(const NoteVector& notes, int amount); bool isSelection() const; int selectionCount() const; void testPlayNote( Note * n ); @@ -345,7 +346,7 @@ private: static QPixmap * s_toolOpen; static QPixmap* s_toolKnife; - static std::array prKeyOrder; + static std::array prKeyOrder; static SimpleTextFloat * s_textFloat; @@ -358,8 +359,8 @@ private: ComboBoxModel m_chordModel; ComboBoxModel m_snapModel; - static const QVector m_zoomLevels; - static const QVector m_zoomYLevels; + static const std::vector m_zoomLevels; + static const std::vector m_zoomYLevels; MidiClip* m_midiClip; NoteVector m_ghostNotes; @@ -377,7 +378,7 @@ private: QList m_recordingNotes; Note * m_currentNote; - Actions m_action; + Action m_action; NoteEditMode m_noteEditMode; GridMode m_gridMode; @@ -428,9 +429,9 @@ private: int m_startKey; // first key when drawing int m_lastKey; - EditModes m_editMode; - EditModes m_ctrlMode; // mode they were in before they hit ctrl - EditModes m_knifeMode; // mode they where in before entering knife mode + EditMode m_editMode; + EditMode m_ctrlMode; // mode they were in before they hit ctrl + EditMode m_knifeMode; // mode they where in before entering knife mode bool m_mouseDownRight; //true if right click is being held down diff --git a/include/PlayHandle.h b/include/PlayHandle.h index c64931ac0..8f5d771ed 100644 --- a/include/PlayHandle.h +++ b/include/PlayHandle.h @@ -30,7 +30,7 @@ #include "lmms_export.h" - +#include "Flags.h" #include "ThreadableJob.h" #include "lmms_basics.h" @@ -45,19 +45,16 @@ class AudioPort; class LMMS_EXPORT PlayHandle : public ThreadableJob { public: - enum Types + enum class Type { - TypeNotePlayHandle = 0x01, - TypeInstrumentPlayHandle = 0x02, - TypeSamplePlayHandle = 0x04, - TypePresetPreviewHandle = 0x08 + NotePlayHandle = 0x01, + InstrumentPlayHandle = 0x02, + SamplePlayHandle = 0x04, + PresetPreviewHandle = 0x08 } ; - using Type = Types; + using Types = Flags; - enum - { - MaxNumber = 1024 - } ; + constexpr static std::size_t MaxNumber = 1024; PlayHandle( const Type type, f_cnt_t offset = 0 ); @@ -164,6 +161,8 @@ private: using PlayHandleList = QList; using ConstPlayHandleList = QList; +LMMS_DECLARE_OPERATORS_FOR_FLAGS(PlayHandle::Type) + } // namespace lmms #endif // LMMS_PLAY_HANDLE_H diff --git a/include/Plugin.h b/include/Plugin.h index b1982f98c..439dd95ad 100644 --- a/include/Plugin.h +++ b/include/Plugin.h @@ -74,7 +74,7 @@ class LMMS_EXPORT Plugin : public Model, public JournallingObject MM_OPERATORS Q_OBJECT public: - enum PluginTypes + enum class Type { Instrument, // instrument being used in channel-track Effect, // effect-plugin for effect-board @@ -97,7 +97,7 @@ public: const char * description; const char * author; int version; - PluginTypes type; + Type type; const PixmapLoader * logo; const char * supportedFileTypes; //!< csv list of extensions @@ -181,7 +181,7 @@ public: using KeyList = QList; - SubPluginFeatures( Plugin::PluginTypes type ) : + SubPluginFeatures( Plugin::Type type ) : m_type( type ) { } @@ -227,7 +227,7 @@ public: } protected: - const Plugin::PluginTypes m_type; + const Plugin::Type m_type; } ; SubPluginFeatures * subPluginFeatures; @@ -250,7 +250,7 @@ public: const PixmapLoader *logo() const; //! Return plugin type - inline PluginTypes type() const + inline Type type() const { return m_descriptor->type; } diff --git a/include/PluginFactory.h b/include/PluginFactory.h index 001ea190a..7221f2b09 100644 --- a/include/PluginFactory.h +++ b/include/PluginFactory.h @@ -27,12 +27,12 @@ #include #include +#include #include #include #include #include -#include #include "lmms_export.h" #include "Plugin.h" @@ -55,7 +55,7 @@ public: bool isNull() const {return ! library;} }; using PluginInfoList = QList; - using DescriptorMap = QMultiMap; + using DescriptorMap = QMultiMap; PluginFactory(); ~PluginFactory() = default; @@ -68,7 +68,7 @@ public: /// Returns a list of all found plugins' descriptors. Plugin::DescriptorList descriptors() const; - Plugin::DescriptorList descriptors(Plugin::PluginTypes type) const; + Plugin::DescriptorList descriptors(Plugin::Type type) const; struct PluginInfoAndKey { @@ -99,7 +99,7 @@ private: PluginInfoList m_pluginInfos; QMap m_pluginByExt; - QVector m_garbage; //!< cleaned up at destruction + std::vector m_garbage; //!< cleaned up at destruction QHash m_errors; diff --git a/include/PluginIssue.h b/include/PluginIssue.h index 87e895113..01a4268ec 100644 --- a/include/PluginIssue.h +++ b/include/PluginIssue.h @@ -33,32 +33,32 @@ namespace lmms //! Types of issues that can cause LMMS to not load a plugin //! LMMS Plugins should use this to indicate errors -enum PluginIssueType +enum class PluginIssueType { // port flow & type - unknownPortFlow, - unknownPortType, + UnknownPortFlow, + UnknownPortType, // channel count - tooManyInputChannels, - tooManyOutputChannels, - tooManyMidiInputChannels, - tooManyMidiOutputChannels, - noOutputChannel, + TooManyInputChannels, + TooManyOutputChannels, + TooManyMidiInputChannels, + TooManyMidiOutputChannels, + NoOutputChannel, // port metadata - portHasNoDef, - portHasNoMin, - portHasNoMax, - minGreaterMax, - defaultValueNotInRange, - logScaleMinMissing, - logScaleMaxMissing, - logScaleMinMaxDifferentSigns, + PortHasNoDef, + PortHasNoMin, + PortHasNoMax, + MinGreaterMax, + DefaultValueNotInRange, + LogScaleMinMissing, + LogScaleMaxMissing, + LogScaleMinMaxDifferentSigns, // features - featureNotSupported, //!< plugin requires functionality LMMS can't offer + FeatureNotSupported, //!< plugin requires functionality LMMS can't offer // misc - badPortType, //!< port type not supported - blacklisted, - noIssue + BadPortType, //!< port type not supported + Blacklisted, + NoIssue }; //! Issue type bundled with informational string diff --git a/include/ProjectJournal.h b/include/ProjectJournal.h index a4a263078..841bbf094 100644 --- a/include/ProjectJournal.h +++ b/include/ProjectJournal.h @@ -104,7 +104,7 @@ private: struct CheckPoint { - CheckPoint( jo_id_t initID = 0, const DataFile& initData = DataFile( DataFile::JournalData ) ) : + CheckPoint( jo_id_t initID = 0, const DataFile& initData = DataFile( DataFile::Type::JournalData ) ) : joID( initID ), data( initData ) { diff --git a/include/ProjectRenderer.h b/include/ProjectRenderer.h index 95a1f53ed..14c584a2e 100644 --- a/include/ProjectRenderer.h +++ b/include/ProjectRenderer.h @@ -40,20 +40,21 @@ class LMMS_EXPORT ProjectRenderer : public QThread { Q_OBJECT public: - enum ExportFileFormats: int + enum class ExportFileFormat : int { - WaveFile, - FlacFile, - OggFile, - MP3File, - NumFileFormats + Wave, + Flac, + Ogg, + MP3, + Count } ; + constexpr static auto NumFileFormats = static_cast(ExportFileFormat::Count); struct FileEncodeDevice { bool isAvailable() const { return m_getDevInst != nullptr; } - ExportFileFormats m_fileFormat; + ExportFileFormat m_fileFormat; const char * m_description; const char * m_extension; AudioFileDeviceInstantiaton m_getDevInst; @@ -62,7 +63,7 @@ public: ProjectRenderer( const AudioEngine::qualitySettings & _qs, const OutputSettings & _os, - ExportFileFormats _file_format, + ExportFileFormat _file_format, const QString & _out_file ); ~ProjectRenderer() override = default; @@ -71,10 +72,10 @@ public: return m_fileDev != nullptr; } - static ExportFileFormats getFileFormatFromExtension( + static ExportFileFormat getFileFormatFromExtension( const QString & _ext ); - static QString getFileExtensionFromFormat( ExportFileFormats fmt ); + static QString getFileExtensionFromFormat( ExportFileFormat fmt ); static const std::array fileEncodeDevices; diff --git a/include/ProjectVersion.h b/include/ProjectVersion.h index d9a459a43..20b32d1c9 100644 --- a/include/ProjectVersion.h +++ b/include/ProjectVersion.h @@ -42,11 +42,11 @@ namespace lmms class ProjectVersion { public: - enum CompareType : int { None = 0, Major=1, Minor=2, Release=3, Stage=4, Build=5, All = std::numeric_limits::max() }; + enum class CompareType : int { None = 0, Major=1, Minor=2, Release=3, Stage=4, Build=5, All = std::numeric_limits::max() }; - ProjectVersion(QString version, CompareType c = All); - ProjectVersion(const char * version, CompareType c = All); + ProjectVersion(QString version, CompareType c = CompareType::All); + ProjectVersion(const char * version, CompareType c = CompareType::All); const QString& getVersion() const { return m_version; } int getMajor() const { return m_major; } diff --git a/include/RenderManager.h b/include/RenderManager.h index 5240e96a8..686522778 100644 --- a/include/RenderManager.h +++ b/include/RenderManager.h @@ -43,7 +43,7 @@ public: RenderManager( const AudioEngine::qualitySettings & qualitySettings, const OutputSettings & outputSettings, - ProjectRenderer::ExportFileFormats fmt, + ProjectRenderer::ExportFileFormat fmt, QString outputPath); ~RenderManager() override; @@ -73,13 +73,13 @@ private: const AudioEngine::qualitySettings m_qualitySettings; const AudioEngine::qualitySettings m_oldQualitySettings; const OutputSettings m_outputSettings; - ProjectRenderer::ExportFileFormats m_format; + ProjectRenderer::ExportFileFormat m_format; QString m_outputPath; std::unique_ptr m_activeRenderer; - QVector m_tracksToRender; - QVector m_unmuted; + std::vector m_tracksToRender; + std::vector m_unmuted; } ; diff --git a/include/SampleBuffer.h b/include/SampleBuffer.h index e2ed24b81..3d1013baa 100644 --- a/include/SampleBuffer.h +++ b/include/SampleBuffer.h @@ -57,10 +57,10 @@ class LMMS_EXPORT SampleBuffer : public QObject, public sharedObject Q_OBJECT MM_OPERATORS public: - enum LoopMode { - LoopOff = 0, - LoopOn, - LoopPingPong + enum class LoopMode { + Off = 0, + On, + PingPong }; class LMMS_EXPORT handleState { @@ -125,7 +125,7 @@ public: handleState * state, const fpp_t frames, const float freq, - const LoopMode loopMode = LoopOff + const LoopMode loopMode = LoopMode::Off ); void visualize( diff --git a/include/SamplePlayHandle.h b/include/SamplePlayHandle.h index d016fcf0b..31b4f0bd5 100644 --- a/include/SamplePlayHandle.h +++ b/include/SamplePlayHandle.h @@ -40,7 +40,7 @@ class Track; class AudioPort; -class SamplePlayHandle : public PlayHandle +class LMMS_EXPORT SamplePlayHandle : public PlayHandle { public: SamplePlayHandle( SampleBuffer* sampleBuffer , bool ownAudioPort = true ); diff --git a/include/SampleTrackView.h b/include/SampleTrackView.h index b586df15e..3ccb97aea 100644 --- a/include/SampleTrackView.h +++ b/include/SampleTrackView.h @@ -26,6 +26,7 @@ #define LMMS_GUI_SAMPLE_TRACK_VIEW_H +#include "MixerLineLcdSpinBox.h" #include "TrackView.h" namespace lmms @@ -90,6 +91,7 @@ private slots: private: SampleTrackWindow * m_window; + MixerLineLcdSpinBox* m_mixerChannelNumber; Knob * m_volumeKnob; Knob * m_panningKnob; FadeButton * m_activityIndicator; diff --git a/include/SetupDialog.h b/include/SetupDialog.h index 27a4ce4f9..de4cdd9dd 100644 --- a/include/SetupDialog.h +++ b/include/SetupDialog.h @@ -53,7 +53,7 @@ class SetupDialog : public QDialog Q_OBJECT public: - enum ConfigTabs + enum class ConfigTab { GeneralSettings, PerformanceSettings, @@ -62,7 +62,7 @@ public: PathsSettings }; - SetupDialog(ConfigTabs tab_to_open = GeneralSettings); + SetupDialog(ConfigTab tab_to_open = ConfigTab::GeneralSettings); ~SetupDialog() override; diff --git a/include/SimpleTextFloat.h b/include/SimpleTextFloat.h index f720d0b3e..bde6c84fa 100644 --- a/include/SimpleTextFloat.h +++ b/include/SimpleTextFloat.h @@ -31,6 +31,7 @@ #include "lmms_export.h" class QLabel; +class QTimer; namespace lmms::gui { @@ -44,6 +45,8 @@ public: void setText(const QString & text); + void showWithDelay(int msecBeforeDisplay, int msecDisplayTime); + void setVisibilityTimeOut(int msecs); void moveGlobal(QWidget * w, const QPoint & offset) @@ -51,11 +54,14 @@ public: move(w->mapToGlobal(QPoint(0, 0)) + offset); } + void hide(); + private: QLabel * m_textLabel; + QTimer * m_showTimer; + QTimer * m_hideTimer; }; - } // namespace lmms::gui #endif diff --git a/include/Song.h b/include/Song.h index c13fe0e96..02714d8ac 100644 --- a/include/Song.h +++ b/include/Song.h @@ -68,15 +68,16 @@ class LMMS_EXPORT Song : public TrackContainer mapPropertyFromModel( int,masterPitch,setMasterPitch,m_masterPitchModel ); mapPropertyFromModel( int,masterVolume,setMasterVolume, m_masterVolumeModel ); public: - enum PlayModes + enum class PlayMode { - Mode_None, - Mode_PlaySong, - Mode_PlayPattern, - Mode_PlayMidiClip, - Mode_PlayAutomationClip, - Mode_Count + None, + Song, + Pattern, + MidiClip, + AutomationClip, + Count } ; + constexpr static auto PlayModeCount = static_cast(PlayMode::Count); struct SaveOptions { /** @@ -141,36 +142,34 @@ public: inline int getMilliseconds() const { - return m_elapsedMilliSeconds[m_playMode]; + return getMilliseconds(m_playMode); } - inline int getMilliseconds(PlayModes playMode) const + inline int getMilliseconds(PlayMode playMode) const { - return m_elapsedMilliSeconds[playMode]; + return m_elapsedMilliSeconds[static_cast(playMode)]; } inline void setToTime(TimePos const & pos) { - m_elapsedMilliSeconds[m_playMode] = pos.getTimeInMilliseconds(getTempo()); - m_playPos[m_playMode].setTicks(pos.getTicks()); + setToTime(pos, m_playMode); } - inline void setToTime(TimePos const & pos, PlayModes playMode) + inline void setToTime(TimePos const & pos, PlayMode playMode) { - m_elapsedMilliSeconds[playMode] = pos.getTimeInMilliseconds(getTempo()); - m_playPos[playMode].setTicks(pos.getTicks()); + m_elapsedMilliSeconds[static_cast(playMode)] = pos.getTimeInMilliseconds(getTempo()); + getPlayPos(playMode).setTicks(pos.getTicks()); } inline void setToTimeByTicks(tick_t ticks) { - m_elapsedMilliSeconds[m_playMode] = TimePos::ticksToMilliseconds(ticks, getTempo()); - m_playPos[m_playMode].setTicks(ticks); + setToTimeByTicks(ticks, m_playMode); } - inline void setToTimeByTicks(tick_t ticks, PlayModes playMode) + inline void setToTimeByTicks(tick_t ticks, PlayMode playMode) { - m_elapsedMilliSeconds[playMode] = TimePos::ticksToMilliseconds(ticks, getTempo()); - m_playPos[playMode].setTicks(ticks); + m_elapsedMilliSeconds[static_cast(playMode)] = TimePos::ticksToMilliseconds(ticks, getTempo()); + getPlayPos(playMode).setTicks(ticks); } inline int getBars() const @@ -253,18 +252,18 @@ public: m_renderBetweenMarkers = renderBetweenMarkers; } - inline PlayModes playMode() const + inline PlayMode playMode() const { return m_playMode; } - inline PlayPos & getPlayPos( PlayModes pm ) + inline PlayPos & getPlayPos( PlayMode pm ) { - return m_playPos[pm]; + return m_playPos[static_cast(pm)]; } - inline const PlayPos & getPlayPos( PlayModes pm ) const + inline const PlayPos & getPlayPos( PlayMode pm ) const { - return m_playPos[pm]; + return m_playPos[static_cast(pm)]; } inline PlayPos & getPlayPos() { @@ -417,21 +416,21 @@ private: inline bar_t currentBar() const { - return m_playPos[m_playMode].getBar(); + return getPlayPos(m_playMode).getBar(); } inline tick_t currentTick() const { - return m_playPos[m_playMode].getTicks(); + return getPlayPos(m_playMode).getTicks(); } inline f_cnt_t currentFrame() const { - return m_playPos[m_playMode].getTicks() * Engine::framesPerTick() + - m_playPos[m_playMode].currentFrame(); + return getPlayPos(m_playMode).getTicks() * Engine::framesPerTick() + + getPlayPos(m_playMode).currentFrame(); } - void setPlayPos( tick_t ticks, PlayModes playMode ); + void setPlayPos( tick_t ticks, PlayMode playMode ); void saveControllerStates( QDomDocument & doc, QDomElement & element ); void restoreControllerStates( const QDomElement & element ); @@ -482,14 +481,14 @@ private: QHash m_errors; - PlayModes m_playMode; - PlayPos m_playPos[Mode_Count]; + PlayMode m_playMode; + PlayPos m_playPos[PlayModeCount]; bar_t m_length; const MidiClip* m_midiClipToPlay; bool m_loopMidiClip; - double m_elapsedMilliSeconds[Mode_Count]; + double m_elapsedMilliSeconds[PlayModeCount]; tick_t m_elapsedTicks; bar_t m_elapsedBars; diff --git a/include/SongEditor.h b/include/SongEditor.h index 081b2cb61..ee9e83f44 100644 --- a/include/SongEditor.h +++ b/include/SongEditor.h @@ -26,6 +26,7 @@ #ifndef LMMS_GUI_SONG_EDITOR_H #define LMMS_GUI_SONG_EDITOR_H +#include "AutomatableModel.h" #include "Editor.h" #include "TrackContainerView.h" @@ -56,11 +57,11 @@ class SongEditor : public TrackContainerView { Q_OBJECT public: - enum EditMode + enum class EditMode { - DrawMode, - KnifeMode, - SelectMode + Draw, + Knife, + Select }; SongEditor( Song * song ); @@ -69,7 +70,6 @@ public: void saveSettings( QDomDocument& doc, QDomElement& element ) override; void loadSettings( const QDomElement& element ) override; - ComboBoxModel *zoomingModel() const; ComboBoxModel *snappingModel() const; float getSnapSize() const; QString getSnapSizeString() const; @@ -120,10 +120,12 @@ private: bool allowRubberband() const override; bool knifeMode() const override; + int calculatePixelsPerBar() const; + int calculateZoomSliderValue(int pixelsPerBar) const; + int trackIndexFromSelectionPoint(int yPos); int indexOfTrackView(const TrackView* tv); - Song * m_song; QScrollBar * m_leftRightScroll; @@ -141,12 +143,10 @@ private: PositionLine * m_positionLine; - ComboBoxModel* m_zoomingModel; + IntModel* m_zoomingModel; ComboBoxModel* m_snappingModel; bool m_proportionalSnap; - static const QVector m_zoomLevels; - bool m_scrollBack; bool m_smoothScroll; @@ -158,14 +158,14 @@ private: QPoint m_mousePos; int m_rubberBandStartTrackview; TimePos m_rubberbandStartTimePos; - int m_currentZoomingValue; + int m_rubberbandPixelsPerBar; //!< pixels per bar when selection starts int m_trackHeadWidth; bool m_selectRegion; friend class SongEditorWindow; signals: - void zoomingValueChanged( float ); + void pixelsPerBarChanged(float); } ; @@ -213,7 +213,7 @@ private: QAction* m_selectModeAction; QAction* m_crtlAction; - ComboBox * m_zoomingComboBox; + AutomatableSlider * m_zoomingSlider; ComboBox * m_snappingComboBox; QLabel* m_snapSizeLabel; @@ -221,7 +221,6 @@ private: QAction* m_removeBarAction; }; - } // namespace gui } // namespace lmms diff --git a/include/StepRecorder.h b/include/StepRecorder.h index 456e69a69..55435617c 100644 --- a/include/StepRecorder.h +++ b/include/StepRecorder.h @@ -59,7 +59,7 @@ class StepRecorder : public QObject void setCurrentMidiClip(MidiClip* newMidiClip); void setStepsLength(const TimePos& newLength); - QVector getCurStepNotes(); + std::vector getCurStepNotes(); bool isRecording() const { @@ -142,7 +142,7 @@ class StepRecorder : public QObject QElapsedTimer releasedTimer; } ; - QVector m_curStepNotes; // contains the current recorded step notes (i.e. while user still press the notes; before they are applied to the clip) + std::vector m_curStepNotes; // contains the current recorded step notes (i.e. while user still press the notes; before they are applied to the clip) StepNote* findCurStepNote(const int key); diff --git a/include/TempoSyncKnob.h b/include/TempoSyncKnob.h index a8e2eeb7e..b86320d13 100644 --- a/include/TempoSyncKnob.h +++ b/include/TempoSyncKnob.h @@ -41,7 +41,7 @@ class LMMS_EXPORT TempoSyncKnob : public Knob { Q_OBJECT public: - TempoSyncKnob( knobTypes knobNum, QWidget* parent = nullptr, const QString& name = QString() ); + TempoSyncKnob( KnobType knobNum, QWidget* parent = nullptr, const QString& name = QString() ); ~TempoSyncKnob() override; const QString & syncDescription(); diff --git a/include/TempoSyncKnobModel.h b/include/TempoSyncKnobModel.h index 59d7b5dc8..5cd2db067 100644 --- a/include/TempoSyncKnobModel.h +++ b/include/TempoSyncKnobModel.h @@ -46,17 +46,17 @@ class LMMS_EXPORT TempoSyncKnobModel : public FloatModel Q_OBJECT MODEL_IS_VISITABLE public: - enum TempoSyncMode + enum class SyncMode { - SyncNone, - SyncDoubleWholeNote, - SyncWholeNote, - SyncHalfNote, - SyncQuarterNote, - SyncEighthNote, - SyncSixteenthNote, - SyncThirtysecondNote, - SyncCustom + None, + DoubleWholeNote, + WholeNote, + HalfNote, + QuarterNote, + EighthNote, + SixteenthNote, + ThirtysecondNote, + Custom } ; TempoSyncKnobModel( const float _val, const float _min, @@ -68,12 +68,12 @@ public: void saveSettings( QDomDocument & _doc, QDomElement & _this, const QString& name ) override; void loadSettings( const QDomElement & _this, const QString& name ) override; - TempoSyncMode syncMode() const + SyncMode syncMode() const { return m_tempoSyncMode; } - void setSyncMode( TempoSyncMode _new_mode ); + void setSyncMode( SyncMode _new_mode ); float scale() const { @@ -83,16 +83,16 @@ public: void setScale( float _new_scale ); signals: - void syncModeChanged( lmms::TempoSyncKnobModel::TempoSyncMode _new_mode ); + void syncModeChanged( lmms::TempoSyncKnobModel::SyncMode _new_mode ); void scaleChanged( float _new_scale ); public slots: inline void disableSync() { - setTempoSync( SyncNone ); + setTempoSync( SyncMode::None ); } - void setTempoSync( int _note_type ); + void setTempoSync( SyncMode _note_type ); void setTempoSync( QAction * _item ); @@ -102,8 +102,8 @@ protected slots: private: - TempoSyncMode m_tempoSyncMode; - TempoSyncMode m_tempoLastSyncMode; + SyncMode m_tempoSyncMode; + SyncMode m_tempoLastSyncMode; float m_scale; MeterModel m_custom; diff --git a/include/TimeDisplayWidget.h b/include/TimeDisplayWidget.h index 9e74b57aa..287b4ee7e 100644 --- a/include/TimeDisplayWidget.h +++ b/include/TimeDisplayWidget.h @@ -51,13 +51,11 @@ private slots: private: - enum DisplayModes + enum class DisplayMode { MinutesSeconds, - BarsTicks, - DisplayModeCount + BarsTicks }; - using DisplayMode = DisplayModes; void setDisplayMode( DisplayMode displayMode ); diff --git a/include/TimeLineWidget.h b/include/TimeLineWidget.h index 061a31081..2e4ba6a97 100644 --- a/include/TimeLineWidget.h +++ b/include/TimeLineWidget.h @@ -55,19 +55,19 @@ public: Q_PROPERTY( QColor activeLoopInnerColor READ getActiveLoopInnerColor WRITE setActiveLoopInnerColor ) Q_PROPERTY( int loopRectangleVerticalPadding READ getLoopRectangleVerticalPadding WRITE setLoopRectangleVerticalPadding ) - enum AutoScrollStates + enum class AutoScrollState { - AutoScrollEnabled, - AutoScrollDisabled + Enabled, + Disabled } ; - enum LoopPointStates + enum class LoopPointState { - LoopPointsDisabled, - LoopPointsEnabled + Disabled, + Enabled } ; - enum BehaviourAtStopStates + enum class BehaviourAtStopState { BackToZero, BackToStart, @@ -76,7 +76,7 @@ public: TimeLineWidget(int xoff, int yoff, float ppb, Song::PlayPos & pos, - const TimePos & begin, Song::PlayModes mode, QWidget * parent); + const TimePos & begin, Song::PlayMode mode, QWidget * parent); ~TimeLineWidget() override; inline QColor const & getBarLineColor() const { return m_barLineColor; } @@ -111,12 +111,12 @@ public: return( m_pos ); } - AutoScrollStates autoScroll() const + AutoScrollState autoScroll() const { return m_autoScroll; } - BehaviourAtStopStates behaviourAtStop() const + BehaviourAtStopState behaviourAtStop() const { return m_behaviourAtStop; } @@ -128,7 +128,7 @@ public: bool loopPointsEnabled() const { - return m_loopPoints == LoopPointsEnabled; + return m_loopPoints == LoopPointState::Enabled; } inline const TimePos & loopBegin() const @@ -220,9 +220,9 @@ private: QColor m_barLineColor; QColor m_barNumberColor; - AutoScrollStates m_autoScroll; - LoopPointStates m_loopPoints; - BehaviourAtStopStates m_behaviourAtStop; + AutoScrollState m_autoScroll; + LoopPointState m_loopPoints; + BehaviourAtStopState m_behaviourAtStop; bool m_changedPosition; @@ -232,7 +232,7 @@ private: float m_snapSize; Song::PlayPos & m_pos; const TimePos & m_begin; - const Song::PlayModes m_mode; + const Song::PlayMode m_mode; TimePos m_loopPos[2]; TimePos m_savedPos; @@ -242,7 +242,7 @@ private: int m_initalXSelect; - enum actions + enum class Action { NoAction, MovePositionMarker, diff --git a/include/Track.h b/include/Track.h index ff3c1ae00..33d1ad233 100644 --- a/include/Track.h +++ b/include/Track.h @@ -25,7 +25,8 @@ #ifndef LMMS_TRACK_H #define LMMS_TRACK_H -#include +#include + #include #include "AutomatableModel.h" @@ -69,31 +70,31 @@ class LMMS_EXPORT Track : public Model, public JournallingObject mapPropertyFromModel(bool,isMuted,setMuted,m_mutedModel); mapPropertyFromModel(bool,isSolo,setSolo,m_soloModel); public: - using clipVector = QVector; + using clipVector = std::vector; - enum TrackTypes + enum class Type { - InstrumentTrack, - PatternTrack, - SampleTrack, - EventTrack, - VideoTrack, - AutomationTrack, - HiddenAutomationTrack, - NumTrackTypes + Instrument, + Pattern, + Sample, + Event, + Video, + Automation, + HiddenAutomation, + Count } ; - Track( TrackTypes type, TrackContainer * tc ); + Track( Type type, TrackContainer * tc ); ~Track() override; - static Track * create( TrackTypes tt, TrackContainer * tc ); + static Track * create( Type tt, TrackContainer * tc ); static Track * create( const QDomElement & element, TrackContainer * tc ); Track * clone(); // pure virtual functions - TrackTypes type() const + Type type() const { return m_type; } @@ -223,7 +224,7 @@ public slots: private: TrackContainer* m_trackContainer; - TrackTypes m_type; + Type m_type; QString m_name; int m_height; diff --git a/include/TrackContainer.h b/include/TrackContainer.h index f99273ba2..01e94df54 100644 --- a/include/TrackContainer.h +++ b/include/TrackContainer.h @@ -49,11 +49,11 @@ class LMMS_EXPORT TrackContainer : public Model, public JournallingObject { Q_OBJECT public: - using TrackList = QVector; - enum TrackContainerTypes + using TrackList = std::vector; + enum class Type { - PatternContainer, - SongContainer + Pattern, + Song } ; TrackContainer(); @@ -63,7 +63,7 @@ public: void loadSettings( const QDomElement & _this ) override; - int countTracks( Track::TrackTypes _tt = Track::NumTrackTypes ) const; + int countTracks( Track::Type _tt = Track::Type::Count ) const; void addTrack( Track * _track ); @@ -85,12 +85,12 @@ public: return "trackcontainer"; } - inline void setType( TrackContainerTypes newType ) + inline void setType( Type newType ) { m_TrackContainerType = newType; } - inline TrackContainerTypes type() const + inline Type type() const { return m_TrackContainerType; } @@ -108,7 +108,7 @@ protected: private: TrackList m_tracks; - TrackContainerTypes m_TrackContainerType; + Type m_TrackContainerType; friend class gui::TrackContainerView; diff --git a/include/TrackContainerView.h b/include/TrackContainerView.h index d53291c33..82d6f993b 100644 --- a/include/TrackContainerView.h +++ b/include/TrackContainerView.h @@ -174,12 +174,6 @@ protected: private: - enum Actions - { - AddTrack, - RemoveTrack - } ; - class scrollArea : public QScrollArea { public: diff --git a/include/TrackContentWidget.h b/include/TrackContentWidget.h index 1a3e14a0e..7cf236323 100644 --- a/include/TrackContentWidget.h +++ b/include/TrackContentWidget.h @@ -95,7 +95,7 @@ public slots: void changePosition( const lmms::TimePos & newPos = TimePos( -1 ) ); protected: - enum ContextMenuAction + enum class ContextMenuAction { Paste }; diff --git a/include/TrackView.h b/include/TrackView.h index efa4f4a0a..f697d9ea8 100644 --- a/include/TrackView.h +++ b/include/TrackView.h @@ -48,11 +48,11 @@ class FadeButton; class TrackContainerView; -const int DEFAULT_SETTINGS_WIDGET_WIDTH = 224; +const int DEFAULT_SETTINGS_WIDGET_WIDTH = 256; const int TRACK_OP_WIDTH = 78; // This shaves 150-ish pixels off track buttons, // ruled from config: ui.compacttrackbuttons -const int DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT = 96; +const int DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT = 128; const int TRACK_OP_WIDTH_COMPACT = 62; @@ -95,7 +95,7 @@ public: bool isMovingTrack() const { - return m_action == MoveTrack; + return m_action == Action::Move; } virtual void update(); @@ -139,11 +139,11 @@ protected: private: - enum Actions + enum class Action { - NoAction, - MoveTrack, - ResizeTrack + None, + Move, + Resize } ; Track * m_track; @@ -153,7 +153,7 @@ private: QWidget m_trackSettingsWidget; TrackContentWidget m_trackContentWidget; - Actions m_action; + Action m_action; virtual FadeButton * getActivityIndicator() { diff --git a/include/fft_helpers.h b/include/fft_helpers.h index 2d2a8d19e..cd4e5f88d 100644 --- a/include/fft_helpers.h +++ b/include/fft_helpers.h @@ -44,12 +44,12 @@ const unsigned int FFT_BUFFER_SIZE = 2048; const std::vector FFT_BLOCK_SIZES = {256, 512, 1024, 2048, 4096, 8192, 16384}; // List of FFT window functions supported by precomputeWindow() -enum FFT_WINDOWS +enum class FFTWindow { - RECTANGULAR = 0, - BLACKMAN_HARRIS, - HAMMING, - HANNING + Rectangular = 0, + BlackmanHarris, + Hamming, + Hanning }; @@ -83,7 +83,7 @@ int LMMS_EXPORT notEmpty(const std::vector &spectrum); * * @return -1 on error */ -int LMMS_EXPORT precomputeWindow(float *window, unsigned int length, FFT_WINDOWS type, bool normalized = true); +int LMMS_EXPORT precomputeWindow(float *window, unsigned int length, FFTWindow type, bool normalized = true); /** Compute absolute values of complex_buffer, save to absspec_buffer. diff --git a/include/lmms_constants.h b/include/lmms_constants.h index e6fce9f4d..c6452d6c6 100644 --- a/include/lmms_constants.h +++ b/include/lmms_constants.h @@ -62,13 +62,13 @@ constexpr unsigned int MaxKeymapCount = 10; //!< number of keyboard mappings per constexpr int LOWEST_LOG_FREQ = 5; // Full range is defined by LOWEST_LOG_FREQ and current sample rate. -enum FREQUENCY_RANGES +enum class FrequencyRange { - FRANGE_FULL = 0, - FRANGE_AUDIBLE, - FRANGE_BASS, - FRANGE_MIDS, - FRANGE_HIGH + Full = 0, + Audible, + Bass, + Mids, + High }; constexpr int FRANGE_AUDIBLE_START = 20; @@ -83,12 +83,12 @@ constexpr int FRANGE_HIGH_END = 20000; // Amplitude ranges (in dBFS). // Reference: full scale sine wave (-1.0 to 1.0) is 0 dB. // Doubling or halving the amplitude produces 3 dB difference. -enum AMPLITUDE_RANGES +enum class AmplitudeRange { - ARANGE_EXTENDED = 0, - ARANGE_AUDIBLE, - ARANGE_LOUD, - ARANGE_SILENT + Extended = 0, + Audible, + Loud, + Silent }; constexpr int ARANGE_EXTENDED_START = -80; diff --git a/include/lmms_math.h b/include/lmms_math.h index 1f896a683..b62da81c2 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -214,7 +214,7 @@ static inline float logToLinearScale( float min, float max, float value ) { if( min < 0 ) { - const float mmax = qMax( qAbs( min ), qAbs( max ) ); + const float mmax = std::max(std::abs(min), std::abs(max)); const float val = value * ( max - min ) + min; float result = signedPowf( val / mmax, F_E ) * mmax; return std::isnan( result ) ? 0 : result; @@ -228,11 +228,11 @@ static inline float logToLinearScale( float min, float max, float value ) static inline float linearToLogScale( float min, float max, float value ) { static const float EXP = 1.0f / F_E; - const float valueLimited = qBound( min, value, max); + const float valueLimited = std::clamp(value, min, max); const float val = ( valueLimited - min ) / ( max - min ); if( min < 0 ) { - const float mmax = qMax( qAbs( min ), qAbs( max ) ); + const float mmax = std::max(std::abs(min), std::abs(max)); float result = signedPowf( valueLimited / mmax, EXP ) * mmax; return std::isnan( result ) ? 0 : result; } @@ -315,14 +315,14 @@ static inline float fastSqrt( float n ) template static inline T absMax( T a, T b ) { - return qAbs(a) > qAbs(b) ? a : b; + return std::abs(a) > std::abs(b) ? a : b; } //! returns value nearest to zero template static inline T absMin( T a, T b ) { - return qAbs(a) < qAbs(b) ? a : b; + return std::abs(a) < std::abs(b) ? a : b; } diff --git a/include/panning.h b/include/panning.h index 56ca04eee..0fd74d1cc 100644 --- a/include/panning.h +++ b/include/panning.h @@ -31,6 +31,8 @@ #include "Midi.h" #include "volume.h" +#include + namespace lmms { @@ -40,7 +42,7 @@ inline StereoVolumeVector panningToVolumeVector( panning_t _p, { StereoVolumeVector v = { { _scale, _scale } }; const float pf = _p / 100.0f; - v.vol[_p >= PanningCenter ? 0 : 1] *= 1.0f - qAbs( pf ); + v.vol[_p >= PanningCenter ? 0 : 1] *= 1.0f - std::abs(pf); return v; } diff --git a/include/versioninfo.h b/include/versioninfo.h index f224b62c5..7495299c2 100644 --- a/include/versioninfo.h +++ b/include/versioninfo.h @@ -3,15 +3,17 @@ #include "lmms_basics.h" -#ifdef __GNUC__ +#if defined(__GNUC__) constexpr const char* LMMS_BUILDCONF_COMPILER_VERSION = "GCC " __VERSION__; +#elif defined(__clang__) +constexpr const char* LMMS_BUILDCONF_COMPILER_VERSION = "Clang " __clang_version__; #elif defined(_MSC_VER) constexpr const char* LMMS_BUILDCONF_COMPILER_VERSION = "MSVC " LMMS_STRINGIFY(_MSC_FULL_VER); #else constexpr const char* LMMS_BUILDCONF_COMPILER_VERSION = "unknown compiler"; #endif -#ifdef LMMS_HOST_X86 +#if defined(LMMS_HOST_X86) constexpr const char* LMMS_BUILDCONF_MACHINE = "i386"; #elif defined(LMMS_HOST_X86_64) constexpr const char* LMMS_BUILDCONF_MACHINE = "x86_64"; @@ -23,32 +25,28 @@ constexpr const char* LMMS_BUILDCONF_MACHINE = "arm64"; constexpr const char* LMMS_BUILDCONF_MACHINE = "riscv32"; #elif defined(LMMS_HOST_RISCV64) constexpr const char* LMMS_BUILDCONF_MACHINE = "riscv64"; +#elif defined(LMMS_HOST_PPC32) +constexpr const char* LMMS_BUILDCONF_MACHINE = "ppc"; +#elif defined(LMMS_HOST_PPC64) +constexpr const char* LMMS_BUILDCONF_MACHINE = "ppc64"; #else constexpr const char* LMMS_BUILDCONF_MACHINE = "unknown processor"; #endif -#ifdef LMMS_BUILD_LINUX +#if defined(LMMS_BUILD_LINUX) constexpr const char* LMMS_BUILDCONF_PLATFORM = "Linux"; -#endif - -#ifdef LMMS_BUILD_APPLE +#elif defined(LMMS_BUILD_APPLE) constexpr const char* LMMS_BUILDCONF_PLATFORM = "OS X"; -#endif - -#ifdef LMMS_BUILD_OPENBSD +#elif defined(LMMS_BUILD_OPENBSD) constexpr const char* LMMS_BUILDCONF_PLATFORM = "OpenBSD"; -#endif - -#ifdef LMMS_BUILD_FREEBSD +#elif defined(LMMS_BUILD_FREEBSD) constexpr const char* LMMS_BUILDCONF_PLATFORM = "FreeBSD"; -#endif - -#ifdef LMMS_BUILD_WIN32 +#elif defined(LMMS_BUILD_WIN32) constexpr const char* LMMS_BUILDCONF_PLATFORM = "win32"; -#endif - -#ifdef LMMS_BUILD_HAIKU +#elif defined(LMMS_BUILD_HAIKU) constexpr const char* LMMS_BUILDCONF_PLATFORM = "Haiku"; +#else +constexpr const char* LMMS_BUILDCONF_PLATFORM = "unknown platform"; #endif #endif // LMMS_VERSION_INFO_H diff --git a/plugins/Amplifier/Amplifier.cpp b/plugins/Amplifier/Amplifier.cpp index 9344807c4..7de8fb180 100644 --- a/plugins/Amplifier/Amplifier.cpp +++ b/plugins/Amplifier/Amplifier.cpp @@ -41,7 +41,7 @@ Plugin::Descriptor PLUGIN_EXPORT amplifier_plugin_descriptor = QT_TRANSLATE_NOOP( "PluginBrowser", "A native amplifier plugin" ), "Vesa Kivimäki ", 0x0100, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader("logo"), nullptr, nullptr, diff --git a/plugins/Amplifier/AmplifierControlDialog.cpp b/plugins/Amplifier/AmplifierControlDialog.cpp index 226130fcd..ed9e98f29 100644 --- a/plugins/Amplifier/AmplifierControlDialog.cpp +++ b/plugins/Amplifier/AmplifierControlDialog.cpp @@ -43,27 +43,27 @@ AmplifierControlDialog::AmplifierControlDialog( AmplifierControls* controls ) : setPalette( pal ); setFixedSize( 100, 110 ); - auto volumeKnob = new Knob(knobBright_26, this); + auto volumeKnob = new Knob(KnobType::Bright26, this); volumeKnob -> move( 16, 10 ); volumeKnob -> setVolumeKnob( true ); volumeKnob->setModel( &controls->m_volumeModel ); volumeKnob->setLabel( tr( "VOL" ) ); volumeKnob->setHintText( tr( "Volume:" ) , "%" ); - auto panKnob = new Knob(knobBright_26, this); + auto panKnob = new Knob(KnobType::Bright26, this); panKnob -> move( 57, 10 ); panKnob->setModel( &controls->m_panModel ); panKnob->setLabel( tr( "PAN" ) ); panKnob->setHintText( tr( "Panning:" ) , "" ); - auto leftKnob = new Knob(knobBright_26, this); + auto leftKnob = new Knob(KnobType::Bright26, this); leftKnob -> move( 16, 65 ); leftKnob -> setVolumeKnob( true ); leftKnob->setModel( &controls->m_leftModel ); leftKnob->setLabel( tr( "LEFT" ) ); leftKnob->setHintText( tr( "Left gain:" ) , "%" ); - auto rightKnob = new Knob(knobBright_26, this); + auto rightKnob = new Knob(KnobType::Bright26, this); rightKnob -> move( 57, 65 ); rightKnob -> setVolumeKnob( true ); rightKnob->setModel( &controls->m_rightModel ); diff --git a/plugins/AudioFileProcessor/AudioFileProcessor.cpp b/plugins/AudioFileProcessor/AudioFileProcessor.cpp index 2e2d7163b..a941e773f 100644 --- a/plugins/AudioFileProcessor/AudioFileProcessor.cpp +++ b/plugins/AudioFileProcessor/AudioFileProcessor.cpp @@ -1,5 +1,5 @@ /* - * AudioFileProcessor.cpp - instrument for using audio-files + * AudioFileProcessor.cpp - instrument for using audio files * * Copyright (c) 2004-2014 Tobias Doerffel * @@ -47,7 +47,6 @@ #include "embed.h" #include "plugin_export.h" - namespace lmms { @@ -65,7 +64,7 @@ Plugin::Descriptor PLUGIN_EXPORT audiofileprocessor_plugin_descriptor = "instrument-track" ), "Tobias Doerffel ", 0x0100, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader( "logo" ), "wav,ogg,ds,spx,au,voc,aif,aiff,flac,raw", nullptr, @@ -205,74 +204,70 @@ void AudioFileProcessor::deleteNotePluginData( NotePlayHandle * _n ) -void AudioFileProcessor::saveSettings( QDomDocument & _doc, - QDomElement & _this ) +void AudioFileProcessor::saveSettings(QDomDocument& doc, QDomElement& elem) { - _this.setAttribute( "src", m_sampleBuffer.audioFile() ); - if( m_sampleBuffer.audioFile() == "" ) + elem.setAttribute("src", m_sampleBuffer.audioFile()); + if (m_sampleBuffer.audioFile().isEmpty()) { QString s; - _this.setAttribute( "sampledata", - m_sampleBuffer.toBase64( s ) ); + elem.setAttribute("sampledata", m_sampleBuffer.toBase64(s)); } - m_reverseModel.saveSettings( _doc, _this, "reversed" ); - m_loopModel.saveSettings( _doc, _this, "looped" ); - m_ampModel.saveSettings( _doc, _this, "amp" ); - m_startPointModel.saveSettings( _doc, _this, "sframe" ); - m_endPointModel.saveSettings( _doc, _this, "eframe" ); - m_loopPointModel.saveSettings( _doc, _this, "lframe" ); - m_stutterModel.saveSettings( _doc, _this, "stutter" ); - m_interpolationModel.saveSettings( _doc, _this, "interp" ); - + m_reverseModel.saveSettings(doc, elem, "reversed"); + m_loopModel.saveSettings(doc, elem, "looped"); + m_ampModel.saveSettings(doc, elem, "amp"); + m_startPointModel.saveSettings(doc, elem, "sframe"); + m_endPointModel.saveSettings(doc, elem, "eframe"); + m_loopPointModel.saveSettings(doc, elem, "lframe"); + m_stutterModel.saveSettings(doc, elem, "stutter"); + m_interpolationModel.saveSettings(doc, elem, "interp"); } -void AudioFileProcessor::loadSettings( const QDomElement & _this ) +void AudioFileProcessor::loadSettings(const QDomElement& elem) { - if( _this.attribute( "src" ) != "" ) + if (!elem.attribute("src").isEmpty()) { - setAudioFile( _this.attribute( "src" ), false ); + setAudioFile(elem.attribute("src"), false); - QString absolutePath = PathUtil::toAbsolute( m_sampleBuffer.audioFile() ); - if ( !QFileInfo( absolutePath ).exists() ) + QString absolutePath = PathUtil::toAbsolute(m_sampleBuffer.audioFile()); + if (!QFileInfo(absolutePath).exists()) { - QString message = tr( "Sample not found: %1" ).arg( m_sampleBuffer.audioFile() ); - - Engine::getSong()->collectError( message ); + QString message = tr("Sample not found: %1").arg(m_sampleBuffer.audioFile()); + Engine::getSong()->collectError(message); } } - else if( _this.attribute( "sampledata" ) != "" ) + else if (!elem.attribute("sampledata").isEmpty()) { - m_sampleBuffer.loadFromBase64( _this.attribute( "srcdata" ) ); + m_sampleBuffer.loadFromBase64(elem.attribute("srcdata")); } - m_loopModel.loadSettings( _this, "looped" ); - m_ampModel.loadSettings( _this, "amp" ); - m_endPointModel.loadSettings( _this, "eframe" ); - m_startPointModel.loadSettings( _this, "sframe" ); + m_loopModel.loadSettings(elem, "looped"); + m_ampModel.loadSettings(elem, "amp"); + m_endPointModel.loadSettings(elem, "eframe"); + m_startPointModel.loadSettings(elem, "sframe"); // compat code for not having a separate loopback point - if (_this.hasAttribute("lframe") || !(_this.firstChildElement("lframe").isNull())) + if (elem.hasAttribute("lframe") || !elem.firstChildElement("lframe").isNull()) { - m_loopPointModel.loadSettings( _this, "lframe" ); + m_loopPointModel.loadSettings(elem, "lframe"); } else { - m_loopPointModel.loadSettings( _this, "sframe" ); + m_loopPointModel.loadSettings(elem, "sframe"); } - m_reverseModel.loadSettings( _this, "reversed" ); + m_reverseModel.loadSettings(elem, "reversed"); - m_stutterModel.loadSettings( _this, "stutter" ); - if( _this.hasAttribute( "interp" ) ) + m_stutterModel.loadSettings(elem, "stutter"); + if (elem.hasAttribute("interp") || !elem.firstChildElement("interp").isNull()) { - m_interpolationModel.loadSettings( _this, "interp" ); + m_interpolationModel.loadSettings(elem, "interp"); } else { - m_interpolationModel.setValue( 1 ); //linear by default + m_interpolationModel.setValue(1.0f); // linear by default } pointChanged(); @@ -521,7 +516,7 @@ AudioFileProcessorView::AudioFileProcessorView( Instrument * _instrument, m_stutterButton->setToolTip( tr( "Continue sample playback across notes" ) ); - m_ampKnob = new Knob( knobBright_26, this ); + m_ampKnob = new Knob( KnobType::Bright26, this ); m_ampKnob->setVolumeKnob( true ); m_ampKnob->move( 5, 108 ); m_ampKnob->setHintText( tr( "Amplify:" ), "%" ); @@ -572,7 +567,7 @@ void AudioFileProcessorView::dragEnterEvent( QDragEnterEvent * _dee ) QString txt = _dee->mimeData()->data( mimeType( MimeType::StringPair ) ); if( txt.section( ':', 0, 0 ) == QString( "clip_%1" ).arg( - Track::SampleTrack ) ) + static_cast(Track::Type::Sample) ) ) { _dee->acceptProposedAction(); } @@ -624,7 +619,7 @@ void AudioFileProcessorView::dropEvent( QDropEvent * _de ) newWaveView(); return; } - else if( type == QString( "clip_%1" ).arg( Track::SampleTrack ) ) + else if( type == QString( "clip_%1" ).arg( static_cast(Track::Type::Sample) ) ) { DataFile dataFile( value.toUtf8() ); castModel()->setAudioFile( dataFile.content().firstChild().toElement().attribute( "src" ) ); @@ -686,14 +681,12 @@ void AudioFileProcessorView::sampleUpdated() void AudioFileProcessorView::openAudioFile() { - QString af = castModel()->m_sampleBuffer. - openAudioFile(); - if( af != "" ) - { - castModel()->setAudioFile( af ); - Engine::getSong()->setModified(); - m_waveView->updateSampleRange(); - } + QString af = castModel()->m_sampleBuffer.openAudioFile(); + if (af.isEmpty()) { return; } + + castModel()->setAudioFile(af); + Engine::getSong()->setModified(); + m_waveView->updateSampleRange(); } @@ -794,9 +787,9 @@ void AudioFileProcessorWaveView::mousePressEvent( QMouseEvent * _me ) const int end_dist = qAbs( m_endFrameX - x ); const int loop_dist = qAbs( m_loopFrameX - x ); - draggingType dt = sample_loop; int md = loop_dist; - if( start_dist < loop_dist ) { dt = sample_start; md = start_dist; } - else if( end_dist < loop_dist ) { dt = sample_end; md = end_dist; } + DraggingType dt = DraggingType::SampleLoop; int md = loop_dist; + if( start_dist < loop_dist ) { dt = DraggingType::SampleStart; md = start_dist; } + else if( end_dist < loop_dist ) { dt = DraggingType::SampleEnd; md = end_dist; } if( md < 4 ) { @@ -804,7 +797,7 @@ void AudioFileProcessorWaveView::mousePressEvent( QMouseEvent * _me ) } else { - m_draggingType = wave; + m_draggingType = DraggingType::Wave; updateCursor(_me); } } @@ -815,7 +808,7 @@ void AudioFileProcessorWaveView::mousePressEvent( QMouseEvent * _me ) void AudioFileProcessorWaveView::mouseReleaseEvent( QMouseEvent * _me ) { m_isDragging = false; - if( m_draggingType == wave ) + if( m_draggingType == DraggingType::Wave ) { updateCursor(_me); } @@ -835,16 +828,16 @@ void AudioFileProcessorWaveView::mouseMoveEvent( QMouseEvent * _me ) const int step = _me->x() - m_draggingLastPoint.x(); switch( m_draggingType ) { - case sample_start: - slideSamplePointByPx( start, step ); + case DraggingType::SampleStart: + slideSamplePointByPx( Point::Start, step ); break; - case sample_end: - slideSamplePointByPx( end, step ); + case DraggingType::SampleEnd: + slideSamplePointByPx( Point::End, step ); break; - case sample_loop: - slideSamplePointByPx( loop, step ); + case DraggingType::SampleLoop: + slideSamplePointByPx( Point::Loop, step ); break; - case wave: + case DraggingType::Wave: default: if( qAbs( _me->y() - m_draggingLastPoint.y() ) < 2 * qAbs( _me->x() - m_draggingLastPoint.x() ) ) @@ -990,7 +983,7 @@ void AudioFileProcessorWaveView::updateGraph() if( m_to == 1 ) { m_to = m_sampleBuffer.frames() * 0.7; - slideSamplePointToFrames( end, m_to * 0.7 ); + slideSamplePointToFrames( Point::End, m_to * 0.7 ); } if( m_from > m_sampleBuffer.startFrame() ) @@ -1117,7 +1110,7 @@ void AudioFileProcessorWaveView::setKnobs( knob * _start, knob * _end, knob * _l -void AudioFileProcessorWaveView::slideSamplePointByPx( knobType _point, int _px ) +void AudioFileProcessorWaveView::slideSamplePointByPx( Point _point, int _px ) { slideSamplePointByFrames( _point, @@ -1128,18 +1121,18 @@ void AudioFileProcessorWaveView::slideSamplePointByPx( knobType _point, int _px -void AudioFileProcessorWaveView::slideSamplePointByFrames( knobType _point, f_cnt_t _frames, bool _slide_to ) +void AudioFileProcessorWaveView::slideSamplePointByFrames( Point _point, f_cnt_t _frames, bool _slide_to ) { knob * a_knob = m_startKnob; switch( _point ) { - case end: + case Point::End: a_knob = m_endKnob; break; - case loop: + case Point::Loop: a_knob = m_loopKnob; break; - case start: + case Point::Start: break; } if( a_knob == nullptr ) @@ -1203,7 +1196,7 @@ void AudioFileProcessorWaveView::reverse() void AudioFileProcessorWaveView::updateCursor( QMouseEvent * _me ) { - bool const waveIsDragged = m_isDragging && (m_draggingType == wave); + bool const waveIsDragged = m_isDragging && (m_draggingType == DraggingType::Wave); bool const pointerCloseToStartEndOrLoop = (_me != nullptr ) && ( isCloseTo( _me->x(), m_startFrameX ) || isCloseTo( _me->x(), m_endFrameX ) || diff --git a/plugins/AudioFileProcessor/AudioFileProcessor.h b/plugins/AudioFileProcessor/AudioFileProcessor.h index b80954577..5fed10862 100644 --- a/plugins/AudioFileProcessor/AudioFileProcessor.h +++ b/plugins/AudioFileProcessor/AudioFileProcessor.h @@ -23,9 +23,8 @@ * */ - -#ifndef AUDIO_FILE_PROCESSOR_H -#define AUDIO_FILE_PROCESSOR_H +#ifndef LMMS_AUDIO_FILE_PROCESSOR_H +#define LMMS_AUDIO_FILE_PROCESSOR_H #include @@ -61,9 +60,8 @@ public: sampleFrame * _working_buffer ) override; void deleteNotePluginData( NotePlayHandle * _n ) override; - void saveSettings( QDomDocument & _doc, - QDomElement & _parent ) override; - void loadSettings( const QDomElement & _this ) override; + void saveSettings(QDomDocument& doc, QDomElement& elem) override; + void loadSettings(const QDomElement& elem) override; void loadFile( const QString & _file ) override; @@ -179,11 +177,11 @@ protected: public: - enum knobType + enum class Point { - start, - end, - loop + Start, + End, + Loop } ; class knob : public Knob @@ -194,7 +192,7 @@ public: public: knob( QWidget * _parent ) : - Knob( knobBright_26, _parent ), + Knob( KnobType::Bright26, _parent ), m_waveView( 0 ), m_relatedKnob( 0 ) { @@ -241,12 +239,12 @@ public slots: private: static const int s_padding = 2; - enum draggingType + enum class DraggingType { - wave, - sample_start, - sample_end, - sample_loop + Wave, + SampleStart, + SampleEnd, + SampleLoop } ; SampleBuffer& m_sampleBuffer; @@ -264,7 +262,7 @@ private: f_cnt_t m_loopFrameX; bool m_isDragging; QPoint m_draggingLastPoint; - draggingType m_draggingType; + DraggingType m_draggingType; bool m_reversed; f_cnt_t m_framesPlayed; bool m_animation; @@ -278,11 +276,11 @@ public: private: void zoom( const bool _out = false ); void slide( int _px ); - void slideSamplePointByPx( knobType _point, int _px ); - void slideSamplePointByFrames( knobType _point, f_cnt_t _frames, bool _slide_to = false ); + void slideSamplePointByPx( Point _point, int _px ); + void slideSamplePointByFrames( Point _point, f_cnt_t _frames, bool _slide_to = false ); void slideSampleByFrames( f_cnt_t _frames ); - void slideSamplePointToFrames( knobType _point, f_cnt_t _frames ) + void slideSamplePointToFrames( Point _point, f_cnt_t _frames ) { slideSamplePointByFrames( _point, _frames, true ); } @@ -303,4 +301,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_AUDIO_FILE_PROCESSOR_H diff --git a/plugins/BassBooster/BassBooster.cpp b/plugins/BassBooster/BassBooster.cpp index 48e265911..e6b25b0d1 100644 --- a/plugins/BassBooster/BassBooster.cpp +++ b/plugins/BassBooster/BassBooster.cpp @@ -41,7 +41,7 @@ Plugin::Descriptor PLUGIN_EXPORT bassbooster_plugin_descriptor = QT_TRANSLATE_NOOP( "PluginBrowser", "Boost your bass the fast and simple way" ), "Tobias Doerffel ", 0x0100, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader("logo"), nullptr, nullptr, diff --git a/plugins/BassBooster/BassBoosterControlDialog.cpp b/plugins/BassBooster/BassBoosterControlDialog.cpp index 21aacb0f2..9efa07c0d 100644 --- a/plugins/BassBooster/BassBoosterControlDialog.cpp +++ b/plugins/BassBooster/BassBoosterControlDialog.cpp @@ -50,17 +50,17 @@ BassBoosterControlDialog::BassBoosterControlDialog( BassBoosterControls* control auto l = new QHBoxLayout; - auto freqKnob = new Knob(knobBright_26, this); + auto freqKnob = new Knob(KnobType::Bright26, this); freqKnob->setModel( &controls->m_freqModel ); freqKnob->setLabel( tr( "FREQ" ) ); freqKnob->setHintText( tr( "Frequency:" ) , "Hz" ); - auto gainKnob = new Knob(knobBright_26, this); + auto gainKnob = new Knob(KnobType::Bright26, this); gainKnob->setModel( &controls->m_gainModel ); gainKnob->setLabel( tr( "GAIN" ) ); gainKnob->setHintText( tr( "Gain:" ) , "" ); - auto ratioKnob = new Knob(knobBright_26, this); + auto ratioKnob = new Knob(KnobType::Bright26, this); ratioKnob->setModel( &controls->m_ratioModel ); ratioKnob->setLabel( tr( "RATIO" ) ); ratioKnob->setHintText( tr( "Ratio:" ) , "" ); diff --git a/plugins/BitInvader/BitInvader.cpp b/plugins/BitInvader/BitInvader.cpp index 947c6f5d6..98ef1e97c 100644 --- a/plugins/BitInvader/BitInvader.cpp +++ b/plugins/BitInvader/BitInvader.cpp @@ -60,7 +60,7 @@ Plugin::Descriptor PLUGIN_EXPORT bitinvader_plugin_descriptor = "Customizable wavetable synthesizer" ), "Andreas Brandmaier ", 0x0100, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader( "logo" ), nullptr, nullptr, @@ -274,9 +274,8 @@ QString BitInvader::nodeName() const void BitInvader::playNote( NotePlayHandle * _n, sampleFrame * _working_buffer ) { - if ( _n->totalFramesPlayed() == 0 || _n->m_pluginData == nullptr ) + if (!_n->m_pluginData) { - float factor; if( !m_normalize.value() ) { @@ -346,11 +345,11 @@ BitInvaderView::BitInvaderView( Instrument * _instrument, "artwork" ) ); setPalette( pal ); - m_sampleLengthKnob = new Knob( knobDark_28, this ); + m_sampleLengthKnob = new Knob( KnobType::Dark28, this ); m_sampleLengthKnob->move( 6, 201 ); m_sampleLengthKnob->setHintText( tr( "Sample length" ), "" ); - m_graph = new Graph( this, Graph::NearestStyle, 204, 134 ); + m_graph = new Graph( this, Graph::Style::Nearest, 204, 134 ); m_graph->move(23,59); // 55,120 - 2px border m_graph->setAutoFillBackground( true ); m_graph->setGraphColor( QColor( 255, 255, 255 ) ); @@ -432,12 +431,12 @@ BitInvaderView::BitInvaderView( Instrument * _instrument, m_interpolationToggle = new LedCheckBox( "Interpolation", this, - tr( "Interpolation" ), LedCheckBox::Yellow ); + tr( "Interpolation" ), LedCheckBox::LedColor::Yellow ); m_interpolationToggle->move( 131, 221 ); m_normalizeToggle = new LedCheckBox( "Normalize", this, - tr( "Normalize" ), LedCheckBox::Green ); + tr( "Normalize" ), LedCheckBox::LedColor::Green ); m_normalizeToggle->move( 131, 236 ); @@ -557,7 +556,7 @@ void BitInvaderView::smoothClicked() void BitInvaderView::interpolationToggled( bool value ) { - m_graph->setGraphStyle( value ? Graph::LinearStyle : Graph::NearestStyle); + m_graph->setGraphStyle( value ? Graph::Style::Linear : Graph::Style::Nearest); Engine::getSong()->setModified(); } diff --git a/plugins/Bitcrush/Bitcrush.cpp b/plugins/Bitcrush/Bitcrush.cpp index 963e970db..8d29186b5 100644 --- a/plugins/Bitcrush/Bitcrush.cpp +++ b/plugins/Bitcrush/Bitcrush.cpp @@ -48,7 +48,7 @@ Plugin::Descriptor PLUGIN_EXPORT bitcrush_plugin_descriptor = QT_TRANSLATE_NOOP( "PluginBrowser", "An oversampling bitcrusher" ), "Vesa Kivimäki ", 0x0100, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader( "logo" ), nullptr, nullptr, diff --git a/plugins/Bitcrush/BitcrushControlDialog.cpp b/plugins/Bitcrush/BitcrushControlDialog.cpp index f3dc85470..64c9b6361 100644 --- a/plugins/Bitcrush/BitcrushControlDialog.cpp +++ b/plugins/Bitcrush/BitcrushControlDialog.cpp @@ -53,13 +53,13 @@ BitcrushControlDialog::BitcrushControlDialog( BitcrushControls * controls ) : outLabel->move( 139, 15 ); // input knobs - auto inGain = new Knob(knobBright_26, this); + auto inGain = new Knob(KnobType::Bright26, this); inGain->move( 16, 32 ); inGain->setModel( & controls->m_inGain ); inGain->setLabel( tr( "GAIN" ) ); inGain->setHintText( tr( "Input gain:" ) , " dBFS" ); - auto inNoise = new Knob(knobBright_26, this); + auto inNoise = new Knob(KnobType::Bright26, this); inNoise->move( 14, 76 ); inNoise->setModel( & controls->m_inNoise ); inNoise->setLabel( tr( "NOISE" ) ); @@ -67,13 +67,13 @@ BitcrushControlDialog::BitcrushControlDialog( BitcrushControls * controls ) : // output knobs - auto outGain = new Knob(knobBright_26, this); + auto outGain = new Knob(KnobType::Bright26, this); outGain->move( 138, 32 ); outGain->setModel( & controls->m_outGain ); outGain->setLabel( tr( "GAIN" ) ); outGain->setHintText( tr( "Output gain:" ) , " dBFS" ); - auto outClip = new Knob(knobBright_26, this); + auto outClip = new Knob(KnobType::Bright26, this); outClip->move( 138, 76 ); outClip->setModel( & controls->m_outClip ); outClip->setLabel( tr( "CLIP" ) ); @@ -82,25 +82,25 @@ BitcrushControlDialog::BitcrushControlDialog( BitcrushControls * controls ) : // leds - auto rateEnabled = new LedCheckBox("", this, tr("Rate enabled"), LedCheckBox::Green); + auto rateEnabled = new LedCheckBox("", this, tr("Rate enabled"), LedCheckBox::LedColor::Green); rateEnabled->move( 64, 14 ); rateEnabled->setModel( & controls->m_rateEnabled ); rateEnabled->setToolTip(tr("Enable sample-rate crushing")); - auto depthEnabled = new LedCheckBox("", this, tr("Depth enabled"), LedCheckBox::Green); + auto depthEnabled = new LedCheckBox("", this, tr("Depth enabled"), LedCheckBox::LedColor::Green); depthEnabled->move( 101, 14 ); depthEnabled->setModel( & controls->m_depthEnabled ); depthEnabled->setToolTip(tr("Enable bit-depth crushing")); // rate crushing knobs - auto rate = new Knob(knobBright_26, this); + auto rate = new Knob(KnobType::Bright26, this); rate->move( 59, 32 ); rate->setModel( & controls->m_rate ); rate->setLabel( tr( "FREQ" ) ); rate->setHintText( tr( "Sample rate:" ) , " Hz" ); - auto stereoDiff = new Knob(knobBright_26, this); + auto stereoDiff = new Knob(KnobType::Bright26, this); stereoDiff->move( 72, 76 ); stereoDiff->setModel( & controls->m_stereoDiff ); stereoDiff->setLabel( tr( "STEREO" ) ); @@ -108,7 +108,7 @@ BitcrushControlDialog::BitcrushControlDialog( BitcrushControls * controls ) : // depth crushing knob - auto levels = new Knob(knobBright_26, this); + auto levels = new Knob(KnobType::Bright26, this); levels->move( 92, 32 ); levels->setModel( & controls->m_levels ); levels->setLabel( tr( "QUANT" ) ); diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index cad7c00b4..9a71be4b8 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -5,7 +5,7 @@ SET(CMAKE_DEBUG_POSTFIX "") # Enable C++17 SET(CMAKE_CXX_STANDARD 17) -IF(LMMS_BUILD_APPLE) +IF(LMMS_BUILD_APPLE AND CMAKE_CXX_COMPILER_ID MATCHES "Clang") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") ENDIF() diff --git a/plugins/CarlaBase/CMakeLists.txt b/plugins/CarlaBase/CMakeLists.txt index d4f7939c9..8f9e14dd1 100644 --- a/plugins/CarlaBase/CMakeLists.txt +++ b/plugins/CarlaBase/CMakeLists.txt @@ -1,11 +1,3 @@ -# For MacOS, use "OLD" RPATH install_name behavior -# This can be changed to "NEW" safely if install_apple.sh.in -# is updated to relink libcarlabase.dylib. MacOS 10.8 uses -# cmake 3.9.6, so this can be done at any time. -IF(NOT CMAKE_VERSION VERSION_LESS 3.9) - CMAKE_POLICY(SET CMP0068 OLD) -ENDIF() - # If Carla was not provided by the system, make a dummy library instead if(LMMS_HAVE_WEAKCARLA) SET(CARLA_INCLUDE_DIRS diff --git a/plugins/CarlaBase/Carla.cpp b/plugins/CarlaBase/Carla.cpp index ef14b7aa4..faff94b57 100644 --- a/plugins/CarlaBase/Carla.cpp +++ b/plugins/CarlaBase/Carla.cpp @@ -220,7 +220,7 @@ CarlaInstrument::CarlaInstrument(InstrumentTrack* const instrumentTrack, const D CarlaInstrument::~CarlaInstrument() { - Engine::audioEngine()->removePlayHandlesOfTypes(instrumentTrack(), PlayHandle::TypeNotePlayHandle | PlayHandle::TypeInstrumentPlayHandle); + Engine::audioEngine()->removePlayHandlesOfTypes(instrumentTrack(), PlayHandle::Type::NotePlayHandle | PlayHandle::Type::InstrumentPlayHandle); if (fHost.resourceDir != nullptr) { @@ -345,7 +345,7 @@ intptr_t CarlaInstrument::handleDispatcher(const NativeHostDispatcherOpcode opco Instrument::Flags CarlaInstrument::flags() const { - return IsSingleStreamed|IsMidiBased|IsNotBendable; + return Flag::IsSingleStreamed | Flag::IsMidiBased | Flag::IsNotBendable; } QString CarlaInstrument::nodeName() const @@ -1015,7 +1015,7 @@ void CarlaParamsView::refreshKnobs() for (uint32_t i=0; i < m_carlaInstrument->m_paramModels.count(); ++i) { bool enabled = m_carlaInstrument->m_paramModels[i]->enabled(); - m_knobs.push_back(new Knob(knobDark_28, m_inputScrollAreaWidgetContent)); + m_knobs.push_back(new Knob(KnobType::Dark28, m_inputScrollAreaWidgetContent)); QString name = (*m_carlaInstrument->m_paramModels[i]).displayName(); m_knobs[i]->setHintText(name, ""); m_knobs[i]->setLabel(name); diff --git a/plugins/CarlaBase/DummyCarla.cpp b/plugins/CarlaBase/DummyCarla.cpp index 8fd9ef6d7..572bdf4bc 100644 --- a/plugins/CarlaBase/DummyCarla.cpp +++ b/plugins/CarlaBase/DummyCarla.cpp @@ -2,12 +2,16 @@ #define BUILDING_CARLA #include "CarlaNativePlugin.h" -CARLA_EXPORT const char* carla_get_library_filename() { return nullptr; } -CARLA_EXPORT const char* carla_get_library_folder() { return nullptr; } -CARLA_EXPORT const NativePluginDescriptor* carla_get_native_rack_plugin() { return nullptr; } -CARLA_EXPORT const NativePluginDescriptor* carla_get_native_patchbay_plugin() { return nullptr; } -CARLA_EXPORT const NativePluginDescriptor* carla_get_native_patchbay16_plugin() { return nullptr; } -CARLA_EXPORT const NativePluginDescriptor* carla_get_native_patchbay32_plugin() { return nullptr; } -CARLA_EXPORT const NativePluginDescriptor* carla_get_native_patchbay64_plugin() { return nullptr; } -CARLA_EXPORT const NativePluginDescriptor* carla_get_native_patchbay_cv_plugin() { return nullptr; } -CARLA_EXPORT CarlaBackend::CarlaEngine* carla_get_native_plugin_engine(const NativePluginDescriptor* desc, NativePluginHandle handle) { return nullptr; } +#ifndef CARLA_PLUGIN_EXPORT +#define CARLA_PLUGIN_EXPORT CARLA_EXPORT +#endif + +CARLA_PLUGIN_EXPORT const char* carla_get_library_filename() { return nullptr; } +CARLA_PLUGIN_EXPORT const char* carla_get_library_folder() { return nullptr; } +CARLA_PLUGIN_EXPORT const NativePluginDescriptor* carla_get_native_rack_plugin() { return nullptr; } +CARLA_PLUGIN_EXPORT const NativePluginDescriptor* carla_get_native_patchbay_plugin() { return nullptr; } +CARLA_PLUGIN_EXPORT const NativePluginDescriptor* carla_get_native_patchbay16_plugin() { return nullptr; } +CARLA_PLUGIN_EXPORT const NativePluginDescriptor* carla_get_native_patchbay32_plugin() { return nullptr; } +CARLA_PLUGIN_EXPORT const NativePluginDescriptor* carla_get_native_patchbay64_plugin() { return nullptr; } +CARLA_PLUGIN_EXPORT const NativePluginDescriptor* carla_get_native_patchbay_cv_plugin() { return nullptr; } +CARLA_PLUGIN_EXPORT CarlaBackend::CarlaEngine* carla_get_native_plugin_engine(const NativePluginDescriptor* desc, NativePluginHandle handle) { return nullptr; } diff --git a/plugins/CarlaPatchbay/CarlaPatchbay.cpp b/plugins/CarlaPatchbay/CarlaPatchbay.cpp index e440d4e3f..ae22e30d1 100644 --- a/plugins/CarlaPatchbay/CarlaPatchbay.cpp +++ b/plugins/CarlaPatchbay/CarlaPatchbay.cpp @@ -43,7 +43,7 @@ Plugin::Descriptor PLUGIN_EXPORT carlapatchbay_plugin_descriptor = "Carla Patchbay Instrument" ), "falkTX ", CARLA_VERSION_HEX, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader( "logo" ), nullptr, nullptr, diff --git a/plugins/CarlaRack/CarlaRack.cpp b/plugins/CarlaRack/CarlaRack.cpp index 5360baf96..8be5e40b3 100644 --- a/plugins/CarlaRack/CarlaRack.cpp +++ b/plugins/CarlaRack/CarlaRack.cpp @@ -43,7 +43,7 @@ Plugin::Descriptor PLUGIN_EXPORT carlarack_plugin_descriptor = "Carla Rack Instrument" ), "falkTX ", CARLA_VERSION_HEX, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader( "logo" ), nullptr, nullptr, diff --git a/plugins/Compressor/Compressor.cpp b/plugins/Compressor/Compressor.cpp index 92123ffd9..3c5ad6157 100755 --- a/plugins/Compressor/Compressor.cpp +++ b/plugins/Compressor/Compressor.cpp @@ -43,7 +43,7 @@ Plugin::Descriptor PLUGIN_EXPORT compressor_plugin_descriptor = QT_TRANSLATE_NOOP("PluginBrowser", "A dynamic range compressor."), "Lost Robot ", 0x0100, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader("logo"), nullptr, nullptr, @@ -442,28 +442,28 @@ bool CompressorEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames) m_gainResult[i] = qMax(m_rangeVal, m_gainResult[i]); } - switch (stereoLink) + switch (static_cast(stereoLink)) { - case Unlinked: + case StereoLinkMode::Unlinked: { break; } - case Maximum: + case StereoLinkMode::Maximum: { m_gainResult[0] = m_gainResult[1] = qMin(m_gainResult[0], m_gainResult[1]); break; } - case Average: + case StereoLinkMode::Average: { m_gainResult[0] = m_gainResult[1] = (m_gainResult[0] + m_gainResult[1]) * 0.5f; break; } - case Minimum: + case StereoLinkMode::Minimum: { m_gainResult[0] = m_gainResult[1] = qMax(m_gainResult[0], m_gainResult[1]); break; } - case Blend: + case StereoLinkMode::Blend: { if (blend > 0)// 0 is unlinked { diff --git a/plugins/Compressor/Compressor.h b/plugins/Compressor/Compressor.h index 121e0b88f..da6ab52bc 100755 --- a/plugins/Compressor/Compressor.h +++ b/plugins/Compressor/Compressor.h @@ -79,7 +79,7 @@ private: inline int realmod(int k, int n); inline float realfmod(float k, float n); - enum StereoLinkModes { Unlinked, Maximum, Average, Minimum, Blend }; + enum class StereoLinkMode { Unlinked, Maximum, Average, Minimum, Blend }; std::vector m_preLookaheadBuf[2]; int m_preLookaheadBufLoc[2] = {0}; diff --git a/plugins/Compressor/CompressorControlDialog.cpp b/plugins/Compressor/CompressorControlDialog.cpp index 8c6f61bec..114980a7d 100755 --- a/plugins/Compressor/CompressorControlDialog.cpp +++ b/plugins/Compressor/CompressorControlDialog.cpp @@ -95,92 +95,92 @@ CompressorControlDialog::CompressorControlDialog(CompressorControls* controls) : m_ratioEnabledLabel->setPixmap(PLUGIN_NAME::getIconPixmap("knob_enabled_large")); m_ratioEnabledLabel->setAttribute(Qt::WA_TransparentForMouseEvents); - m_thresholdKnob = new Knob(knobStyled, this); + m_thresholdKnob = new Knob(KnobType::Styled, this); makeLargeKnob(m_thresholdKnob, tr("Threshold:") , " dBFS"); m_thresholdKnob->setModel(&controls->m_thresholdModel); m_thresholdKnob->setToolTip(tr("Volume at which the compression begins to take place")); - m_ratioKnob = new Knob(knobStyled, this); + m_ratioKnob = new Knob(KnobType::Styled, this); makeLargeKnob(m_ratioKnob, tr("Ratio:") , ":1"); m_ratioKnob->setModel(&controls->m_ratioModel); m_ratioKnob->setToolTip(tr("How far the compressor must turn the volume down after crossing the threshold")); - m_attackKnob = new Knob(knobStyled, this); + m_attackKnob = new Knob(KnobType::Styled, this); makeLargeKnob(m_attackKnob, tr("Attack:") , " ms"); m_attackKnob->setModel(&controls->m_attackModel); m_attackKnob->setToolTip(tr("Speed at which the compressor starts to compress the audio")); - m_releaseKnob = new Knob(knobStyled, this); + m_releaseKnob = new Knob(KnobType::Styled, this); makeLargeKnob(m_releaseKnob, tr("Release:") , " ms"); m_releaseKnob->setModel(&controls->m_releaseModel); m_releaseKnob->setToolTip(tr("Speed at which the compressor ceases to compress the audio")); - m_kneeKnob = new Knob(knobStyled, this); + m_kneeKnob = new Knob(KnobType::Styled, this); makeSmallKnob(m_kneeKnob, tr("Knee:") , " dB"); m_kneeKnob->setModel(&controls->m_kneeModel); m_kneeKnob->setToolTip(tr("Smooth out the gain reduction curve around the threshold")); - m_rangeKnob = new Knob(knobStyled, this); + m_rangeKnob = new Knob(KnobType::Styled, this); makeSmallKnob(m_rangeKnob, tr("Range:") , " dBFS"); m_rangeKnob->setModel(&controls->m_rangeModel); m_rangeKnob->setToolTip(tr("Maximum gain reduction")); - m_lookaheadLengthKnob = new Knob(knobStyled, this); + m_lookaheadLengthKnob = new Knob(KnobType::Styled, this); makeSmallKnob(m_lookaheadLengthKnob, tr("Lookahead Length:") , " ms"); m_lookaheadLengthKnob->setModel(&controls->m_lookaheadLengthModel); m_lookaheadLengthKnob->setToolTip(tr("How long the compressor has to react to the sidechain signal ahead of time")); - m_holdKnob = new Knob(knobStyled, this); + m_holdKnob = new Knob(KnobType::Styled, this); makeSmallKnob(m_holdKnob, tr("Hold:") , " ms"); m_holdKnob->setModel(&controls->m_holdModel); m_holdKnob->setToolTip(tr("Delay between attack and release stages")); - m_rmsKnob = new Knob(knobStyled, this); + m_rmsKnob = new Knob(KnobType::Styled, this); makeSmallKnob(m_rmsKnob, tr("RMS Size:") , ""); m_rmsKnob->setModel(&controls->m_rmsModel); m_rmsKnob->setToolTip(tr("Size of the RMS buffer")); - m_inBalanceKnob = new Knob(knobStyled, this); + m_inBalanceKnob = new Knob(KnobType::Styled, this); makeSmallKnob(m_inBalanceKnob, tr("Input Balance:") , ""); m_inBalanceKnob->setModel(&controls->m_inBalanceModel); m_inBalanceKnob->setToolTip(tr("Bias the input audio to the left/right or mid/side")); - m_outBalanceKnob = new Knob(knobStyled, this); + m_outBalanceKnob = new Knob(KnobType::Styled, this); makeSmallKnob(m_outBalanceKnob, tr("Output Balance:") , ""); m_outBalanceKnob->setModel(&controls->m_outBalanceModel); m_outBalanceKnob->setToolTip(tr("Bias the output audio to the left/right or mid/side")); - m_stereoBalanceKnob = new Knob(knobStyled, this); + m_stereoBalanceKnob = new Knob(KnobType::Styled, this); makeSmallKnob(m_stereoBalanceKnob, tr("Stereo Balance:") , ""); m_stereoBalanceKnob->setModel(&controls->m_stereoBalanceModel); m_stereoBalanceKnob->setToolTip(tr("Bias the sidechain signal to the left/right or mid/side")); - m_blendKnob = new Knob(knobStyled, this); + m_blendKnob = new Knob(KnobType::Styled, this); makeSmallKnob(m_blendKnob, tr("Stereo Link Blend:") , ""); m_blendKnob->setModel(&controls->m_blendModel); m_blendKnob->setToolTip(tr("Blend between unlinked/maximum/average/minimum stereo linking modes")); - m_tiltKnob = new Knob(knobStyled, this); + m_tiltKnob = new Knob(KnobType::Styled, this); makeSmallKnob(m_tiltKnob, tr("Tilt Gain:") , " dB"); m_tiltKnob->setModel(&controls->m_tiltModel); m_tiltKnob->setToolTip(tr("Bias the sidechain signal to the low or high frequencies. -6 db is lowpass, 6 db is highpass.")); - m_tiltFreqKnob = new Knob(knobStyled, this); + m_tiltFreqKnob = new Knob(KnobType::Styled, this); makeSmallKnob(m_tiltFreqKnob, tr("Tilt Frequency:") , " Hz"); m_tiltFreqKnob->setModel(&controls->m_tiltFreqModel); m_tiltFreqKnob->setToolTip(tr("Center frequency of sidechain tilt filter")); - m_mixKnob = new Knob(knobStyled, this); + m_mixKnob = new Knob(KnobType::Styled, this); makeSmallKnob(m_mixKnob, tr("Mix:") , "%"); m_mixKnob->setModel(&controls->m_mixModel); m_mixKnob->setToolTip(tr("Balance between wet and dry signals")); - m_autoAttackKnob = new Knob(knobStyled, this); + m_autoAttackKnob = new Knob(KnobType::Styled, this); makeSmallKnob(m_autoAttackKnob, tr("Auto Attack:") , "%"); m_autoAttackKnob->setModel(&controls->m_autoAttackModel); m_autoAttackKnob->setToolTip(tr("Automatically control attack value depending on crest factor")); - m_autoReleaseKnob = new Knob(knobStyled, this); + m_autoReleaseKnob = new Knob(KnobType::Styled, this); makeSmallKnob(m_autoReleaseKnob, tr("Auto Release:") , "%"); m_autoReleaseKnob->setModel(&controls->m_autoReleaseModel); m_autoReleaseKnob->setToolTip(tr("Automatically control release value depending on crest factor")); diff --git a/plugins/CrossoverEQ/CrossoverEQ.cpp b/plugins/CrossoverEQ/CrossoverEQ.cpp index 641e06b4e..c4334677c 100644 --- a/plugins/CrossoverEQ/CrossoverEQ.cpp +++ b/plugins/CrossoverEQ/CrossoverEQ.cpp @@ -43,7 +43,7 @@ Plugin::Descriptor PLUGIN_EXPORT crossovereq_plugin_descriptor = QT_TRANSLATE_NOOP( "PluginBrowser", "A 4-band Crossover Equalizer" ), "Vesa Kivimäki ", 0x0100, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader( "logo" ), nullptr, nullptr, diff --git a/plugins/CrossoverEQ/CrossoverEQControlDialog.cpp b/plugins/CrossoverEQ/CrossoverEQControlDialog.cpp index ba32e9dfc..12b560b23 100644 --- a/plugins/CrossoverEQ/CrossoverEQControlDialog.cpp +++ b/plugins/CrossoverEQ/CrossoverEQControlDialog.cpp @@ -46,19 +46,19 @@ CrossoverEQControlDialog::CrossoverEQControlDialog( CrossoverEQControls * contro setFixedSize( 167, 178 ); // knobs - auto xover12 = new Knob(knobBright_26, this); + auto xover12 = new Knob(KnobType::Bright26, this); xover12->move( 29, 11 ); xover12->setModel( & controls->m_xover12 ); xover12->setLabel( "1/2" ); xover12->setHintText( tr( "Band 1/2 crossover:" ), " Hz" ); - auto xover23 = new Knob(knobBright_26, this); + auto xover23 = new Knob(KnobType::Bright26, this); xover23->move( 69, 11 ); xover23->setModel( & controls->m_xover23 ); xover23->setLabel( "2/3" ); xover23->setHintText( tr( "Band 2/3 crossover:" ), " Hz" ); - auto xover34 = new Knob(knobBright_26, this); + auto xover34 = new Knob(KnobType::Bright26, this); xover34->move( 109, 11 ); xover34->setModel( & controls->m_xover34 ); xover34->setLabel( "3/4" ); @@ -90,22 +90,22 @@ CrossoverEQControlDialog::CrossoverEQControlDialog( CrossoverEQControls * contro gain4->setHintText( tr( "Band 4 gain:" ), " dBFS" ); // leds - auto mute1 = new LedCheckBox("", this, tr("Band 1 mute"), LedCheckBox::Green); + auto mute1 = new LedCheckBox("", this, tr("Band 1 mute"), LedCheckBox::LedColor::Green); mute1->move( 15, 154 ); mute1->setModel( & controls->m_mute1 ); mute1->setToolTip(tr("Mute band 1")); - auto mute2 = new LedCheckBox("", this, tr("Band 2 mute"), LedCheckBox::Green); + auto mute2 = new LedCheckBox("", this, tr("Band 2 mute"), LedCheckBox::LedColor::Green); mute2->move( 55, 154 ); mute2->setModel( & controls->m_mute2 ); mute2->setToolTip(tr("Mute band 2")); - auto mute3 = new LedCheckBox("", this, tr("Band 3 mute"), LedCheckBox::Green); + auto mute3 = new LedCheckBox("", this, tr("Band 3 mute"), LedCheckBox::LedColor::Green); mute3->move( 95, 154 ); mute3->setModel( & controls->m_mute3 ); mute3->setToolTip(tr("Mute band 3")); - auto mute4 = new LedCheckBox("", this, tr("Band 4 mute"), LedCheckBox::Green); + auto mute4 = new LedCheckBox("", this, tr("Band 4 mute"), LedCheckBox::LedColor::Green); mute4->move( 135, 154 ); mute4->setModel( & controls->m_mute4 ); mute4->setToolTip(tr("Mute band 4")); diff --git a/plugins/Delay/DelayControlsDialog.cpp b/plugins/Delay/DelayControlsDialog.cpp index 9a9dea0d4..065b3d1e4 100644 --- a/plugins/Delay/DelayControlsDialog.cpp +++ b/plugins/Delay/DelayControlsDialog.cpp @@ -44,28 +44,28 @@ DelayControlsDialog::DelayControlsDialog( DelayControls *controls ) : setPalette( pal ); setFixedSize( 300, 208 ); - auto sampleDelayKnob = new TempoSyncKnob(knobBright_26, this); + auto sampleDelayKnob = new TempoSyncKnob(KnobType::Bright26, this); sampleDelayKnob->move( 10,14 ); sampleDelayKnob->setVolumeKnob( false ); sampleDelayKnob->setModel( &controls->m_delayTimeModel ); sampleDelayKnob->setLabel( tr( "DELAY" ) ); sampleDelayKnob->setHintText( tr( "Delay time" ) + " ", " s" ); - auto feedbackKnob = new Knob(knobBright_26, this); + auto feedbackKnob = new Knob(KnobType::Bright26, this); feedbackKnob->move( 11, 58 ); feedbackKnob->setVolumeKnob( true) ; feedbackKnob->setModel( &controls->m_feedbackModel); feedbackKnob->setLabel( tr( "FDBK" ) ); feedbackKnob->setHintText( tr ( "Feedback amount" ) + " " , "" ); - auto lfoFreqKnob = new TempoSyncKnob(knobBright_26, this); + auto lfoFreqKnob = new TempoSyncKnob(KnobType::Bright26, this); lfoFreqKnob->move( 11, 119 ); lfoFreqKnob->setVolumeKnob( false ); lfoFreqKnob->setModel( &controls->m_lfoTimeModel ); lfoFreqKnob->setLabel( tr( "RATE" ) ); lfoFreqKnob->setHintText( tr ( "LFO frequency") + " ", " s" ); - auto lfoAmtKnob = new TempoSyncKnob(knobBright_26, this); + auto lfoAmtKnob = new TempoSyncKnob(KnobType::Bright26, this); lfoAmtKnob->move( 11, 159 ); lfoAmtKnob->setVolumeKnob( false ); lfoAmtKnob->setModel( &controls->m_lfoAmountModel ); diff --git a/plugins/Delay/DelayEffect.cpp b/plugins/Delay/DelayEffect.cpp index 6db2f38e3..05204f355 100644 --- a/plugins/Delay/DelayEffect.cpp +++ b/plugins/Delay/DelayEffect.cpp @@ -44,7 +44,7 @@ Plugin::Descriptor PLUGIN_EXPORT delay_plugin_descriptor = QT_TRANSLATE_NOOP( "PluginBrowser", "A native delay plugin" ), "Dave French ", 0x0100, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader("logo"), nullptr, nullptr, diff --git a/plugins/Dispersion/Dispersion.cpp b/plugins/Dispersion/Dispersion.cpp index 9b98877e5..fb28e1f47 100644 --- a/plugins/Dispersion/Dispersion.cpp +++ b/plugins/Dispersion/Dispersion.cpp @@ -40,7 +40,7 @@ Plugin::Descriptor PLUGIN_EXPORT dispersion_plugin_descriptor = QT_TRANSLATE_NOOP("PluginBrowser", "An all-pass filter allowing for extremely high orders."), "Lost Robot ", 0x0100, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader("logo"), nullptr, nullptr diff --git a/plugins/Dispersion/DispersionControlDialog.cpp b/plugins/Dispersion/DispersionControlDialog.cpp index b9f04baa2..2879e7613 100644 --- a/plugins/Dispersion/DispersionControlDialog.cpp +++ b/plugins/Dispersion/DispersionControlDialog.cpp @@ -51,19 +51,19 @@ DispersionControlDialog::DispersionControlDialog(DispersionControls* controls) : m_amountBox->setLabel(tr("AMOUNT")); m_amountBox->setToolTip(tr("Number of all-pass filters")); - Knob * freqKnob = new Knob(knobBright_26, this); + Knob * freqKnob = new Knob(KnobType::Bright26, this); freqKnob->move(59, 8); freqKnob->setModel(&controls->m_freqModel); freqKnob->setLabel(tr("FREQ")); freqKnob->setHintText(tr("Frequency:") , " Hz"); - Knob * resoKnob = new Knob(knobBright_26, this); + Knob * resoKnob = new Knob(KnobType::Bright26, this); resoKnob->move(99, 8); resoKnob->setModel(&controls->m_resoModel); resoKnob->setLabel(tr("RESO")); resoKnob->setHintText(tr("Resonance:") , " octaves"); - Knob * feedbackKnob = new Knob(knobBright_26, this); + Knob * feedbackKnob = new Knob(KnobType::Bright26, this); feedbackKnob->move(139, 8); feedbackKnob->setModel(&controls->m_feedbackModel); feedbackKnob->setLabel(tr("FEED")); diff --git a/plugins/DualFilter/DualFilter.cpp b/plugins/DualFilter/DualFilter.cpp index e510109e9..4e66db988 100644 --- a/plugins/DualFilter/DualFilter.cpp +++ b/plugins/DualFilter/DualFilter.cpp @@ -43,7 +43,7 @@ Plugin::Descriptor PLUGIN_EXPORT dualfilter_plugin_descriptor = QT_TRANSLATE_NOOP( "PluginBrowser", "A Dual filter plugin" ), "Vesa Kivimäki ", 0x0100, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader( "logo" ), nullptr, nullptr, @@ -90,12 +90,12 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames if( m_dfControls.m_filter1Model.isValueChanged() || m_filter1changed ) { - m_filter1->setFilterType( m_dfControls.m_filter1Model.value() ); + m_filter1->setFilterType( static_cast::FilterType>(m_dfControls.m_filter1Model.value()) ); m_filter1changed = true; } if( m_dfControls.m_filter2Model.isValueChanged() || m_filter2changed ) { - m_filter2->setFilterType( m_dfControls.m_filter2Model.value() ); + m_filter2->setFilterType( static_cast::FilterType>(m_dfControls.m_filter2Model.value()) ); m_filter2changed = true; } diff --git a/plugins/DualFilter/DualFilterControlDialog.cpp b/plugins/DualFilter/DualFilterControlDialog.cpp index 81a835901..d316e3372 100644 --- a/plugins/DualFilter/DualFilterControlDialog.cpp +++ b/plugins/DualFilter/DualFilterControlDialog.cpp @@ -36,7 +36,7 @@ namespace lmms::gui #define makeknob( name, x, y, model, label, hint, unit ) \ - Knob * name = new Knob( knobBright_26, this); \ + Knob * name = new Knob( KnobType::Bright26, this); \ (name) -> move( x, y ); \ (name) ->setModel( &controls-> model ); \ (name) ->setLabel( label ); \ @@ -64,8 +64,8 @@ DualFilterControlDialog::DualFilterControlDialog( DualFilterControls* controls ) gain1Knob-> setVolumeKnob( true ); gain2Knob-> setVolumeKnob( true ); - auto enabled1Toggle = new LedCheckBox("", this, tr("Filter 1 enabled"), LedCheckBox::Green); - auto enabled2Toggle = new LedCheckBox("", this, tr("Filter 2 enabled"), LedCheckBox::Green); + auto enabled1Toggle = new LedCheckBox("", this, tr("Filter 1 enabled"), LedCheckBox::LedColor::Green); + auto enabled2Toggle = new LedCheckBox("", this, tr("Filter 2 enabled"), LedCheckBox::LedColor::Green); enabled1Toggle -> move( 12, 11 ); enabled1Toggle -> setModel( &controls -> m_enabled1Model ); diff --git a/plugins/DynamicsProcessor/DynamicsProcessor.cpp b/plugins/DynamicsProcessor/DynamicsProcessor.cpp index 54f1f0c50..6bdf41eee 100644 --- a/plugins/DynamicsProcessor/DynamicsProcessor.cpp +++ b/plugins/DynamicsProcessor/DynamicsProcessor.cpp @@ -47,7 +47,7 @@ Plugin::Descriptor PLUGIN_EXPORT dynamicsprocessor_plugin_descriptor = "plugin for processing dynamics in a flexible way" ), "Vesa Kivimäki ", 0x0100, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader("logo"), nullptr, nullptr, @@ -167,19 +167,19 @@ bool DynProcEffect::processAudioBuffer( sampleFrame * _buf, } // account for stereo mode - switch( stereoMode ) + switch( static_cast(stereoMode) ) { - case DynProcControls::SM_Maximum: + case DynProcControls::StereoMode::Maximum: { sm_peak[0] = sm_peak[1] = qMax( m_currentPeak[0], m_currentPeak[1] ); break; } - case DynProcControls::SM_Average: + case DynProcControls::StereoMode::Average: { sm_peak[0] = sm_peak[1] = ( m_currentPeak[0] + m_currentPeak[1] ) * 0.5; break; } - case DynProcControls::SM_Unlinked: + case DynProcControls::StereoMode::Unlinked: { sm_peak[0] = m_currentPeak[0]; sm_peak[1] = m_currentPeak[1]; diff --git a/plugins/DynamicsProcessor/DynamicsProcessorControlDialog.cpp b/plugins/DynamicsProcessor/DynamicsProcessorControlDialog.cpp index 4d8758e03..bd076b946 100644 --- a/plugins/DynamicsProcessor/DynamicsProcessorControlDialog.cpp +++ b/plugins/DynamicsProcessor/DynamicsProcessorControlDialog.cpp @@ -47,7 +47,7 @@ DynProcControlDialog::DynProcControlDialog( setPalette( pal ); setFixedSize( 224, 319 ); - auto waveGraph = new Graph(this, Graph::LinearNonCyclicStyle, 204, 205); + auto waveGraph = new Graph(this, Graph::Style::LinearNonCyclic, 204, 205); waveGraph -> move( 10, 6 ); waveGraph -> setModel( &_controls -> m_wavegraphModel ); waveGraph -> setAutoFillBackground( true ); @@ -58,7 +58,7 @@ DynProcControlDialog::DynProcControlDialog( waveGraph->setGraphColor( QColor( 85, 204, 145 ) ); waveGraph -> setMaximumSize( 204, 205 ); - auto inputKnob = new Knob(knobBright_26, this); + auto inputKnob = new Knob(KnobType::Bright26, this); inputKnob -> setVolumeKnob( true ); inputKnob -> setVolumeRatio( 1.0 ); inputKnob -> move( 26, 223 ); @@ -66,7 +66,7 @@ DynProcControlDialog::DynProcControlDialog( inputKnob->setLabel( tr( "INPUT" ) ); inputKnob->setHintText( tr( "Input gain:" ) , "" ); - auto outputKnob = new Knob(knobBright_26, this); + auto outputKnob = new Knob(KnobType::Bright26, this); outputKnob -> setVolumeKnob( true ); outputKnob -> setVolumeRatio( 1.0 ); outputKnob -> move( 76, 223 ); @@ -74,13 +74,13 @@ DynProcControlDialog::DynProcControlDialog( outputKnob->setLabel( tr( "OUTPUT" ) ); outputKnob->setHintText( tr( "Output gain:" ) , "" ); - auto attackKnob = new Knob(knobBright_26, this); + auto attackKnob = new Knob(KnobType::Bright26, this); attackKnob -> move( 24, 268 ); attackKnob->setModel( &_controls->m_attackModel ); attackKnob->setLabel( tr( "ATTACK" ) ); attackKnob->setHintText( tr( "Peak attack time:" ) , "ms" ); - auto releaseKnob = new Knob(knobBright_26, this); + auto releaseKnob = new Knob(KnobType::Bright26, this); releaseKnob -> move( 74, 268 ); releaseKnob->setModel( &_controls->m_releaseModel ); releaseKnob->setLabel( tr( "RELEASE" ) ); diff --git a/plugins/DynamicsProcessor/DynamicsProcessorControls.h b/plugins/DynamicsProcessor/DynamicsProcessorControls.h index cbe109eaf..8fb66fee3 100644 --- a/plugins/DynamicsProcessor/DynamicsProcessorControls.h +++ b/plugins/DynamicsProcessor/DynamicsProcessorControls.h @@ -41,12 +41,11 @@ class DynProcControls : public EffectControls { Q_OBJECT public: - enum StereoModes + enum class StereoMode { - SM_Maximum, - SM_Average, - SM_Unlinked, - NumStereoModes + Maximum, + Average, + Unlinked }; DynProcControls( DynProcEffect * _eff ); ~DynProcControls() override = default; diff --git a/plugins/Eq/EqControlsDialog.cpp b/plugins/Eq/EqControlsDialog.cpp index 6535b61f3..a26fa0db9 100644 --- a/plugins/Eq/EqControlsDialog.cpp +++ b/plugins/Eq/EqControlsDialog.cpp @@ -106,14 +106,14 @@ EqControlsDialog::EqControlsDialog( EqControls *controls ) : distance = 81; for( int i = 0; i < m_parameterWidget->bandCount() ; i++ ) { - auto resKnob = new Knob(knobBright_26, this); + auto resKnob = new Knob(KnobType::Bright26, this); resKnob->move( distance, 440 ); resKnob->setVolumeKnob(false); resKnob->setModel( m_parameterWidget->getBandModels( i )->res ); if(i > 1 && i < 6) { resKnob->setHintText( tr( "Bandwidth: " ) , tr( " Octave" ) ); } else { resKnob->setHintText( tr( "Resonance : " ) , "" ); } - auto freqKnob = new Knob(knobBright_26, this); + auto freqKnob = new Knob(KnobType::Bright26, this); freqKnob->move( distance, 396 ); freqKnob->setVolumeKnob( false ); freqKnob->setModel( m_parameterWidget->getBandModels( i )->freq ); diff --git a/plugins/Eq/EqCurve.cpp b/plugins/Eq/EqCurve.cpp index b9fa3f519..10213bfa9 100644 --- a/plugins/Eq/EqCurve.cpp +++ b/plugins/Eq/EqCurve.cpp @@ -137,7 +137,7 @@ void EqHandle::paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QRectF textRect2 = QRectF ( rectX+1, rectY+1, 80, 30 ); QString freq = QString::number( xPixelToFreq( EqHandle::x(), m_width ) ); QString res; - if ( getType() != para ) + if ( getType() != EqHandleType::Para ) { res = tr( "Reso: ") + QString::number( getResonance() ); } @@ -171,11 +171,11 @@ QPainterPath EqHandle::getCurvePath() float y = m_heigth * 0.5; for ( float x = 0 ; x < m_width; x++ ) { - if ( m_type == highpass ) y = getLowCutCurve( x ); - if ( m_type == lowshelf ) y = getLowShelfCurve( x ); - if ( m_type == para ) y = getPeakCurve( x ); - if ( m_type == highshelf ) y = getHighShelfCurve( x ); - if ( m_type == lowpass ) y = getHighCutCurve( x ); + if ( m_type == EqHandleType::HighPass ) y = getLowCutCurve( x ); + if ( m_type == EqHandleType::LowShelf ) y = getLowShelfCurve( x ); + if ( m_type == EqHandleType::Para ) y = getPeakCurve( x ); + if ( m_type == EqHandleType::HighShelf ) y = getHighShelfCurve( x ); + if ( m_type == EqHandleType::LowPass ) y = getHighCutCurve( x ); if ( x == 0 ) path.moveTo( x, y ); // sets the begin of Path path.lineTo( x, y ); } @@ -410,7 +410,7 @@ int EqHandle::getNum() -void EqHandle::setType( int t ) +void EqHandle::setType( EqHandleType t ) { EqHandle::m_type = t; } @@ -442,7 +442,7 @@ void EqHandle::setMouseHover( bool d ) -int EqHandle::getType() +EqHandleType EqHandle::getType() { return m_type; } @@ -569,7 +569,7 @@ void EqHandle::mouseReleaseEvent( QGraphicsSceneMouseEvent *event ) void EqHandle::wheelEvent( QGraphicsSceneWheelEvent *wevent ) { float highestBandwich; - if( m_type != para ) + if( m_type != EqHandleType::Para ) { highestBandwich = 10; } @@ -631,7 +631,7 @@ QVariant EqHandle::itemChange( QGraphicsItem::GraphicsItemChange change, const Q if( change == ItemPositionChange ) { // pass filter don't move in y direction - if ( m_type == highpass || m_type == lowpass ) + if ( m_type == EqHandleType::HighPass || m_type == EqHandleType::LowPass ) { float newX = value.toPointF().x(); if( newX < 0 ) @@ -714,23 +714,23 @@ void EqCurve::paint( QPainter *painter, const QStyleOptionGraphicsItem *option, { for ( int x = 0; x < m_width ; x=x+1 ) { - if ( m_handle->at( thatHandle )->getType() == highpass ) + if ( m_handle->at( thatHandle )->getType() == EqHandleType::HighPass ) { mainCurve[x]= ( mainCurve[x] + ( m_handle->at( thatHandle )->getLowCutCurve( x ) * ( activeHandles ) ) - ( ( activeHandles * ( m_heigth/2 ) ) - m_heigth ) ); } - if ( m_handle->at(thatHandle)->getType() == lowshelf ) + if ( m_handle->at(thatHandle)->getType() == EqHandleType::LowShelf ) { mainCurve[x]= ( mainCurve[x] + ( m_handle->at( thatHandle )->getLowShelfCurve( x ) * ( activeHandles ) ) - ( ( activeHandles * ( m_heigth/2 ) ) - m_heigth ) ); } - if ( m_handle->at( thatHandle )->getType() == para ) + if ( m_handle->at( thatHandle )->getType() == EqHandleType::Para ) { mainCurve[x]= ( mainCurve[x] + ( m_handle->at( thatHandle )->getPeakCurve( x ) * ( activeHandles ) ) - ( ( activeHandles * ( m_heigth/2 ) ) - m_heigth ) ); } - if ( m_handle->at( thatHandle )->getType() == highshelf ) + if ( m_handle->at( thatHandle )->getType() == EqHandleType::HighShelf ) { mainCurve[x]= ( mainCurve[x] + ( m_handle->at( thatHandle )->getHighShelfCurve( x ) * ( activeHandles ) ) - ( ( activeHandles * ( m_heigth/2 ) ) - m_heigth ) ); } - if ( m_handle->at(thatHandle)->getType() == lowpass ) + if ( m_handle->at(thatHandle)->getType() == EqHandleType::LowPass ) { mainCurve[x]= ( mainCurve[x] + ( m_handle->at( thatHandle )->getHighCutCurve( x ) * ( activeHandles ) ) - ( ( activeHandles * ( m_heigth/2 ) ) - m_heigth ) ); } diff --git a/plugins/Eq/EqCurve.h b/plugins/Eq/EqCurve.h index e01e30841..27236aabb 100644 --- a/plugins/Eq/EqCurve.h +++ b/plugins/Eq/EqCurve.h @@ -32,12 +32,12 @@ namespace lmms::gui { -enum{ - highpass=1, - lowshelf, - para, - highshelf, - lowpass +enum class EqHandleType { + HighPass=1, + LowShelf, + Para, + HighShelf, + LowPass }; @@ -64,8 +64,8 @@ public: float getHighCutCurve( float x ); float getResonance(); int getNum(); - int getType(); - void setType( int t ); + EqHandleType getType(); + void setType( EqHandleType t ); void setResonance( float r ); bool isMouseHover(); void setMouseHover( bool d ); @@ -104,7 +104,8 @@ private: bool m_lp24; bool m_lp48; bool m_mouseHover; - int m_type, m_numb; + EqHandleType m_type; + int m_numb; float m_width, m_heigth; float m_resonance; bool m_mousePressed; diff --git a/plugins/Eq/EqEffect.cpp b/plugins/Eq/EqEffect.cpp index eb168a9f9..8a7954144 100644 --- a/plugins/Eq/EqEffect.cpp +++ b/plugins/Eq/EqEffect.cpp @@ -44,7 +44,7 @@ Plugin::Descriptor PLUGIN_EXPORT eq_plugin_descriptor = QT_TRANSLATE_NOOP( "PluginBrowser", "A native eq plugin" ), "Dave French ", 0x0100, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader("logo"), nullptr, nullptr, diff --git a/plugins/Eq/EqParameterWidget.cpp b/plugins/Eq/EqParameterWidget.cpp index fb60322a1..b48f0f317 100644 --- a/plugins/Eq/EqParameterWidget.cpp +++ b/plugins/Eq/EqParameterWidget.cpp @@ -164,35 +164,35 @@ void EqParameterWidget::changeHandle( int i ) switch ( i ) { case 0 : - m_handleList->at( i )->setType( highpass ); + m_handleList->at( i )->setType( EqHandleType::HighPass ); m_handleList->at( i )->setPos( x, m_displayHeigth / 2 ); break; case 1: - m_handleList->at( i )->setType( lowshelf ); + m_handleList->at( i )->setType( EqHandleType::LowShelf ); m_handleList->at( i )->setPos( x, y ); break; case 2: - m_handleList->at( i )->setType( para ); + m_handleList->at( i )->setType( EqHandleType::Para ); m_handleList->at( i )->setPos( x, y ); break; case 3: - m_handleList->at( i )->setType( para ); + m_handleList->at( i )->setType( EqHandleType::Para ); m_handleList->at( i )->setPos( x, y ); break; case 4: - m_handleList->at( i )->setType( para ); + m_handleList->at( i )->setType( EqHandleType::Para ); m_handleList->at( i )->setPos( x, y ); break; case 5: - m_handleList->at( i )->setType( para ); + m_handleList->at( i )->setType( EqHandleType::Para ); m_handleList->at( i )->setPos( x, y ); break; case 6: - m_handleList->at( i )->setType( highshelf ); + m_handleList->at( i )->setType( EqHandleType::HighShelf ); m_handleList->at( i )->setPos( x, y ); break; case 7: - m_handleList->at( i )->setType( lowpass ); + m_handleList->at( i )->setType( EqHandleType::LowPass ); m_handleList->at( i )->setPos( QPointF( x, m_displayHeigth / 2 ) ); break; } diff --git a/plugins/Flanger/FlangerControlsDialog.cpp b/plugins/Flanger/FlangerControlsDialog.cpp index f35aabfd4..3ac5dc9c6 100644 --- a/plugins/Flanger/FlangerControlsDialog.cpp +++ b/plugins/Flanger/FlangerControlsDialog.cpp @@ -42,42 +42,42 @@ FlangerControlsDialog::FlangerControlsDialog( FlangerControls *controls ) : setPalette( pal ); setFixedSize( 233, 75 ); - auto delayKnob = new Knob(knobBright_26, this); + auto delayKnob = new Knob(KnobType::Bright26, this); delayKnob->move( 10,10 ); delayKnob->setVolumeKnob( false ); delayKnob->setModel( &controls->m_delayTimeModel ); delayKnob->setLabel( tr( "DELAY" ) ); delayKnob->setHintText( tr( "Delay time:" ) + " ", "s" ); - auto lfoFreqKnob = new TempoSyncKnob(knobBright_26, this); + auto lfoFreqKnob = new TempoSyncKnob(KnobType::Bright26, this); lfoFreqKnob->move( 48,10 ); lfoFreqKnob->setVolumeKnob( false ); lfoFreqKnob->setModel( &controls->m_lfoFrequencyModel ); lfoFreqKnob->setLabel( tr( "RATE" ) ); lfoFreqKnob->setHintText( tr( "Period:" ) , " Sec" ); - auto lfoAmtKnob = new Knob(knobBright_26, this); + auto lfoAmtKnob = new Knob(KnobType::Bright26, this); lfoAmtKnob->move( 85,10 ); lfoAmtKnob->setVolumeKnob( false ); lfoAmtKnob->setModel( &controls->m_lfoAmountModel ); lfoAmtKnob->setLabel( tr( "AMNT" ) ); lfoAmtKnob->setHintText( tr( "Amount:" ) , "" ); - auto lfoPhaseKnob = new Knob(knobBright_26, this); + auto lfoPhaseKnob = new Knob(KnobType::Bright26, this); lfoPhaseKnob->move( 123,10 ); lfoPhaseKnob->setVolumeKnob( false ); lfoPhaseKnob->setModel( &controls->m_lfoPhaseModel ); lfoPhaseKnob->setLabel( tr( "PHASE" ) ); lfoPhaseKnob->setHintText( tr( "Phase:" ) , " degrees" ); - auto feedbackKnob = new Knob(knobBright_26, this); + auto feedbackKnob = new Knob(KnobType::Bright26, this); feedbackKnob->move( 160,10 ); feedbackKnob->setVolumeKnob( true) ; feedbackKnob->setModel( &controls->m_feedbackModel ); feedbackKnob->setLabel( tr( "FDBK" ) ); feedbackKnob->setHintText( tr( "Feedback amount:" ) , "" ); - auto whiteNoiseKnob = new Knob(knobBright_26, this); + auto whiteNoiseKnob = new Knob(KnobType::Bright26, this); whiteNoiseKnob->move( 196,10 ); whiteNoiseKnob->setVolumeKnob( true) ; whiteNoiseKnob->setModel( &controls->m_whiteNoiseAmountModel ); diff --git a/plugins/Flanger/FlangerEffect.cpp b/plugins/Flanger/FlangerEffect.cpp index 9f7200f0e..60b5df67b 100644 --- a/plugins/Flanger/FlangerEffect.cpp +++ b/plugins/Flanger/FlangerEffect.cpp @@ -45,7 +45,7 @@ Plugin::Descriptor PLUGIN_EXPORT flanger_plugin_descriptor = QT_TRANSLATE_NOOP( "PluginBrowser", "A native flanger plugin" ), "Dave French ", 0x0100, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader("logo"), nullptr, nullptr, diff --git a/plugins/FreeBoy/FreeBoy.cpp b/plugins/FreeBoy/FreeBoy.cpp index 1fd3f2513..6450253ee 100644 --- a/plugins/FreeBoy/FreeBoy.cpp +++ b/plugins/FreeBoy/FreeBoy.cpp @@ -63,7 +63,7 @@ Plugin::Descriptor PLUGIN_EXPORT freeboy_plugin_descriptor = "Attila Herman " "Csaba Hruska ", 0x0100, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader( "logo" ), nullptr, } ; @@ -250,7 +250,7 @@ void FreeBoyInstrument::playNote(NotePlayHandle* nph, sampleFrame* workingBuffer int data = 0; int freq = nph->frequency(); - if ( tfp == 0 ) + if (!nph->m_pluginData) { auto papu = new GbApuWrapper{}; papu->setSampleRate(samplerate, CLOCK_RATE); @@ -446,7 +446,7 @@ class FreeBoyKnob : public Knob { public: FreeBoyKnob( QWidget * _parent ) : - Knob( knobStyled, _parent ) + Knob( KnobType::Styled, _parent ) { setFixedSize( 30, 30 ); setCenterPointX( 15.0 ); @@ -677,7 +677,7 @@ FreeBoyInstrumentView::FreeBoyInstrumentView( Instrument * _instrument, m_graph = new Graph( this ); - m_graph->setGraphStyle( Graph::NearestStyle ); + m_graph->setGraphStyle( Graph::Style::Nearest ); m_graph->setGraphColor( QColor(0x4E, 0x83, 0x2B) ); m_graph->move( 37, 199 ); m_graph->resize(208, 47); diff --git a/plugins/GigPlayer/GigPlayer.cpp b/plugins/GigPlayer/GigPlayer.cpp index 24073ceea..c2e155a20 100644 --- a/plugins/GigPlayer/GigPlayer.cpp +++ b/plugins/GigPlayer/GigPlayer.cpp @@ -69,7 +69,7 @@ Plugin::Descriptor PLUGIN_EXPORT gigplayer_plugin_descriptor = QT_TRANSLATE_NOOP( "PluginBrowser", "Player for GIG files" ), "Garrett Wilson ", 0x0100, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader( "logo" ), "gig", nullptr, @@ -108,8 +108,8 @@ GigInstrument::GigInstrument( InstrumentTrack * _instrument_track ) : GigInstrument::~GigInstrument() { Engine::audioEngine()->removePlayHandlesOfTypes( instrumentTrack(), - PlayHandle::TypeNotePlayHandle - | PlayHandle::TypeInstrumentPlayHandle ); + PlayHandle::Type::NotePlayHandle + | PlayHandle::Type::InstrumentPlayHandle ); freeInstance(); } @@ -293,8 +293,6 @@ void GigInstrument::playNote( NotePlayHandle * _n, sampleFrame * ) { const float LOG440 = 2.643452676f; - const f_cnt_t tfp = _n->totalFramesPlayed(); - int midiNote = (int) floor( 12.0 * ( log2( _n->unpitchedFrequency() ) - LOG440 ) - 4.0 ); // out of range? @@ -303,7 +301,7 @@ void GigInstrument::playNote( NotePlayHandle * _n, sampleFrame * ) return; } - if( tfp == 0 ) + if (!_n->m_pluginData) { auto pluginData = new GIGPluginData; pluginData->midiNote = midiNote; @@ -343,16 +341,16 @@ void GigInstrument::play( sampleFrame * _working_buffer ) for( QList::iterator it = m_notes.begin(); it != m_notes.end(); ++it ) { // Process notes in the KeyUp state, adding release samples if desired - if( it->state == KeyUp ) + if( it->state == GigState::KeyUp ) { // If there are no samples, we're done if( it->samples.empty() ) { - it->state = Completed; + it->state = GigState::Completed; } else { - it->state = PlayingKeyUp; + it->state = GigState::PlayingKeyUp; // Notify each sample that the key has been released for (auto& sample : it->samples) @@ -368,9 +366,9 @@ void GigInstrument::play( sampleFrame * _working_buffer ) } } // Process notes in the KeyDown state, adding samples for the notes - else if( it->state == KeyDown ) + else if( it->state == GigState::KeyDown ) { - it->state = PlayingKeyDown; + it->state = GigState::PlayingKeyDown; addSamples( *it, false ); } @@ -395,7 +393,7 @@ void GigInstrument::play( sampleFrame * _working_buffer ) } // Delete ended notes (either in the completed state or all the samples ended) - if( it->state == Completed || it->samples.empty() ) + if( it->state == GigState::Completed || it->samples.empty() ) { it = m_notes.erase( it ); @@ -410,7 +408,7 @@ void GigInstrument::play( sampleFrame * _working_buffer ) for (auto& note : m_notes) { // Only process the notes if we're in a playing state - if (!(note.state == PlayingKeyDown || note.state == PlayingKeyUp )) + if (!(note.state == GigState::PlayingKeyDown || note.state == GigState::PlayingKeyUp )) { continue; } @@ -682,9 +680,9 @@ void GigInstrument::deleteNotePluginData( NotePlayHandle * _n ) for (auto& note : m_notes) { // Find the note by matching pointers to the plugin data - if (note.handle == pluginData && (note.state == KeyDown || note.state == PlayingKeyDown)) + if (note.handle == pluginData && (note.state == GigState::KeyDown || note.state == GigState::PlayingKeyDown)) { - note.state = KeyUp; + note.state = GigState::KeyUp; } } @@ -908,7 +906,7 @@ class gigKnob : public Knob { public: gigKnob( QWidget * _parent ) : - Knob( knobBright_26, _parent ) + Knob( KnobType::Bright26, _parent ) { setFixedSize( 31, 38 ); } diff --git a/plugins/GigPlayer/GigPlayer.h b/plugins/GigPlayer/GigPlayer.h index 20058424b..e5039f109 100644 --- a/plugins/GigPlayer/GigPlayer.h +++ b/plugins/GigPlayer/GigPlayer.h @@ -187,7 +187,7 @@ public: // What portion of a note are we in? -enum GigState +enum class GigState { // We just pressed the key KeyDown, @@ -224,7 +224,7 @@ public: GigNote( int midiNote, int velocity, float frequency, GIGPluginData * handle ) : midiNote( midiNote ), velocity( velocity ), - release( false ), isRelease( false ), state( KeyDown ), + release( false ), isRelease( false ), state( GigState::KeyDown ), frequency( frequency ), handle( handle ) { } @@ -268,7 +268,7 @@ public: Flags flags() const override { - return IsSingleStreamed|IsNotBendable; + return Flag::IsSingleStreamed | Flag::IsNotBendable; } gui::PluginView* instantiateView( QWidget * _parent ) override; diff --git a/plugins/HydrogenImport/HydrogenImport.cpp b/plugins/HydrogenImport/HydrogenImport.cpp index d8f76071a..144a2f5e7 100644 --- a/plugins/HydrogenImport/HydrogenImport.cpp +++ b/plugins/HydrogenImport/HydrogenImport.cpp @@ -30,7 +30,7 @@ Plugin::Descriptor PLUGIN_EXPORT hydrogenimport_plugin_descriptor = "Filter for importing Hydrogen files into LMMS" ), "frank mather", 0x0100, - Plugin::ImportFilter, + Plugin::Type::ImportFilter, nullptr, nullptr, nullptr, @@ -42,7 +42,7 @@ QString filename; class NoteKey { public: - enum Key { + enum class Key { C = 0, Cs, D, @@ -59,7 +59,7 @@ public: static int stringToNoteKey( const QString& str ) { - int m_key = NoteKey::C; + auto m_key = Key::C; QString sKey = str.left( str.length() - 1 ); @@ -74,54 +74,54 @@ public: if ( sKey == "C" ) { - m_key = NoteKey::C; + m_key = Key::C; } else if ( sKey == "Cs" ) { - m_key = NoteKey::Cs; + m_key = Key::Cs; } else if ( sKey == "D" ) { - m_key = NoteKey::D; + m_key = Key::D; } else if ( sKey == "Ef" ) { - m_key = NoteKey::Ef; + m_key = Key::Ef; } else if ( sKey == "E" ) { - m_key = NoteKey::E; + m_key = Key::E; } else if ( sKey == "F" ) { - m_key = NoteKey::F; + m_key = Key::F; } else if ( sKey == "Fs" ) { - m_key = NoteKey::Fs; + m_key = Key::Fs; } else if ( sKey == "G" ) { - m_key = NoteKey::G; + m_key = Key::G; } else if ( sKey == "Af" ) { - m_key = NoteKey::Af; + m_key = Key::Af; } else if ( sKey == "A" ) { - m_key = NoteKey::A; + m_key = Key::A; } else if ( sKey == "Bf" ) { - m_key = NoteKey::Bf; + m_key = Key::Bf; } else if ( sKey == "B" ) { - m_key = NoteKey::B; + m_key = Key::B; } // Hydrogen records MIDI notes from C-1 to B5, and exports them as a number ranging from -3 to 3 - return m_key + ((nOctave + 3) * 12); + return static_cast(m_key) + ((nOctave + 3) * 12); } }; @@ -218,7 +218,7 @@ bool HydrogenImport::readSong() if ( nLayer == 0 ) { drum_track[sId] = static_cast( - Track::create(Track::InstrumentTrack, Engine::patternStore()) + Track::create(Track::Type::Instrument, Engine::patternStore()) ); drum_track[sId]->volumeModel()->setValue( fVolume * 100 ); drum_track[sId]->panningModel()->setValue( ( fPan_R - fPan_L ) * 100 ); diff --git a/plugins/Kicker/Kicker.cpp b/plugins/Kicker/Kicker.cpp index 7d4c6fbb0..ef1d623c1 100644 --- a/plugins/Kicker/Kicker.cpp +++ b/plugins/Kicker/Kicker.cpp @@ -23,11 +23,10 @@ * */ - +#include "Kicker.h" #include -#include "Kicker.h" #include "AudioEngine.h" #include "Engine.h" #include "InstrumentTrack.h" @@ -55,7 +54,7 @@ Plugin::Descriptor PLUGIN_EXPORT kicker_plugin_descriptor = "Versatile drum synthesizer" ), "Tobias Doerffel ", 0x0100, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader( "logo" ), nullptr, nullptr, @@ -85,65 +84,64 @@ KickerInstrument::KickerInstrument( InstrumentTrack * _instrument_track ) : -void KickerInstrument::saveSettings( QDomDocument & _doc, - QDomElement & _this ) +void KickerInstrument::saveSettings(QDomDocument& doc, QDomElement& elem) { - m_startFreqModel.saveSettings( _doc, _this, "startfreq" ); - m_endFreqModel.saveSettings( _doc, _this, "endfreq" ); - m_decayModel.saveSettings( _doc, _this, "decay" ); - m_distModel.saveSettings( _doc, _this, "dist" ); - m_distEndModel.saveSettings( _doc, _this, "distend" ); - m_gainModel.saveSettings( _doc, _this, "gain" ); - m_envModel.saveSettings( _doc, _this, "env" ); - m_noiseModel.saveSettings( _doc, _this, "noise" ); - m_clickModel.saveSettings( _doc, _this, "click" ); - m_slopeModel.saveSettings( _doc, _this, "slope" ); - m_startNoteModel.saveSettings( _doc, _this, "startnote" ); - m_endNoteModel.saveSettings( _doc, _this, "endnote" ); - m_versionModel.saveSettings( _doc, _this, "version" ); + m_startFreqModel.saveSettings(doc, elem, "startfreq"); + m_endFreqModel.saveSettings(doc, elem, "endfreq"); + m_decayModel.saveSettings(doc, elem, "decay"); + m_distModel.saveSettings(doc, elem, "dist"); + m_distEndModel.saveSettings(doc, elem, "distend"); + m_gainModel.saveSettings(doc, elem, "gain"); + m_envModel.saveSettings(doc, elem, "env"); + m_noiseModel.saveSettings(doc, elem, "noise"); + m_clickModel.saveSettings(doc, elem, "click"); + m_slopeModel.saveSettings(doc, elem, "slope"); + m_startNoteModel.saveSettings(doc, elem, "startnote"); + m_endNoteModel.saveSettings(doc, elem, "endnote"); + m_versionModel.saveSettings(doc, elem, "version"); } -void KickerInstrument::loadSettings( const QDomElement & _this ) +void KickerInstrument::loadSettings(const QDomElement& elem) { - m_versionModel.loadSettings( _this, "version" ); + m_versionModel.loadSettings(elem, "version"); - m_startFreqModel.loadSettings( _this, "startfreq" ); - m_endFreqModel.loadSettings( _this, "endfreq" ); - m_decayModel.loadSettings( _this, "decay" ); - m_distModel.loadSettings( _this, "dist" ); - if( _this.hasAttribute( "distend" ) ) + m_startFreqModel.loadSettings(elem, "startfreq"); + m_endFreqModel.loadSettings(elem, "endfreq"); + m_decayModel.loadSettings(elem, "decay"); + m_distModel.loadSettings(elem, "dist"); + if (elem.hasAttribute("distend") || !elem.firstChildElement("distend").isNull()) { - m_distEndModel.loadSettings( _this, "distend" ); + m_distEndModel.loadSettings(elem, "distend"); } else { - m_distEndModel.setValue( m_distModel.value() ); + m_distEndModel.setValue(m_distModel.value()); } - m_gainModel.loadSettings( _this, "gain" ); - m_envModel.loadSettings( _this, "env" ); - m_noiseModel.loadSettings( _this, "noise" ); - m_clickModel.loadSettings( _this, "click" ); - m_slopeModel.loadSettings( _this, "slope" ); - m_startNoteModel.loadSettings( _this, "startnote" ); - if( m_versionModel.value() < 1 ) + m_gainModel.loadSettings(elem, "gain"); + m_envModel.loadSettings(elem, "env"); + m_noiseModel.loadSettings(elem, "noise"); + m_clickModel.loadSettings(elem, "click"); + m_slopeModel.loadSettings(elem, "slope"); + m_startNoteModel.loadSettings(elem, "startnote"); + if (m_versionModel.value() < 1) { - m_startNoteModel.setValue( false ); + m_startNoteModel.setValue(false); } - m_endNoteModel.loadSettings( _this, "endnote" ); + m_endNoteModel.loadSettings(elem, "endnote"); // Try to maintain backwards compatibility - if( !_this.hasAttribute( "version" ) ) + if (!elem.hasAttribute("version")) { - m_startNoteModel.setValue( false ); - m_decayModel.setValue( m_decayModel.value() * 1.33f ); - m_envModel.setValue( 1.0f ); - m_slopeModel.setValue( 1.0f ); - m_clickModel.setValue( 0.0f ); + m_startNoteModel.setValue(false); + m_decayModel.setValue(m_decayModel.value() * 1.33f); + m_envModel.setValue(1.0f); + m_slopeModel.setValue(1.0f); + m_clickModel.setValue(0.0f); } - m_versionModel.setValue( KICKER_PRESET_VERSION ); + m_versionModel.setValue(KICKER_PRESET_VERSION); } @@ -165,7 +163,7 @@ void KickerInstrument::playNote( NotePlayHandle * _n, const float decfr = m_decayModel.value() * Engine::audioEngine()->processingSampleRate() / 1000.0f; const f_cnt_t tfp = _n->totalFramesPlayed(); - if ( tfp == 0 ) + if (!_n->m_pluginData) { _n->m_pluginData = new SweepOsc( DistFX( m_distModel.value(), @@ -228,7 +226,7 @@ class KickerKnob : public Knob { public: KickerKnob( QWidget * _parent ) : - Knob( knobStyled, _parent ) + Knob( KnobType::Styled, _parent ) { setFixedSize( 29, 29 ); setObjectName( "smallKnob" ); @@ -240,7 +238,7 @@ class KickerEnvKnob : public TempoSyncKnob { public: KickerEnvKnob( QWidget * _parent ) : - TempoSyncKnob( knobStyled, _parent ) + TempoSyncKnob( KnobType::Styled, _parent ) { setFixedSize( 29, 29 ); setObjectName( "smallKnob" ); @@ -252,7 +250,7 @@ class KickerLargeKnob : public Knob { public: KickerLargeKnob( QWidget * _parent ) : - Knob( knobStyled, _parent ) + Knob( KnobType::Styled, _parent ) { setFixedSize( 34, 34 ); setObjectName( "largeKnob" ); @@ -317,10 +315,10 @@ KickerInstrumentView::KickerInstrumentView( Instrument * _instrument, m_distEndKnob->setHintText( tr( "End distortion:" ), "" ); m_distEndKnob->move( COL5, ROW2 ); - m_startNoteToggle = new LedCheckBox( "", this, "", LedCheckBox::Green ); + m_startNoteToggle = new LedCheckBox( "", this, "", LedCheckBox::LedColor::Green ); m_startNoteToggle->move( COL1 + 8, LED_ROW ); - m_endNoteToggle = new LedCheckBox( "", this, "", LedCheckBox::Green ); + m_endNoteToggle = new LedCheckBox( "", this, "", LedCheckBox::LedColor::Green ); m_endNoteToggle->move( END_COL + 8, LED_ROW ); setAutoFillBackground( true ); diff --git a/plugins/Kicker/Kicker.h b/plugins/Kicker/Kicker.h index 22413c4db..b5d065598 100644 --- a/plugins/Kicker/Kicker.h +++ b/plugins/Kicker/Kicker.h @@ -23,9 +23,8 @@ * */ - -#ifndef KICKER_H -#define KICKER_H +#ifndef LMMS_KICKER_H +#define LMMS_KICKER_H #include "AutomatableModel.h" #include "Instrument.h" @@ -60,14 +59,14 @@ public: sampleFrame * _working_buffer ) override; void deleteNotePluginData( NotePlayHandle * _n ) override; - void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; - void loadSettings( const QDomElement & _this ) override; + void saveSettings(QDomDocument& doc, QDomElement& elem) override; + void loadSettings(const QDomElement& elem) override; QString nodeName() const override; Flags flags() const override { - return IsNotBendable; + return Flag::IsNotBendable; } f_cnt_t desiredReleaseFrames() const override @@ -135,4 +134,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_KICKER_H diff --git a/plugins/LadspaBrowser/LadspaBrowser.cpp b/plugins/LadspaBrowser/LadspaBrowser.cpp index 09f83ab4e..31be64056 100644 --- a/plugins/LadspaBrowser/LadspaBrowser.cpp +++ b/plugins/LadspaBrowser/LadspaBrowser.cpp @@ -56,7 +56,7 @@ Plugin::Descriptor PLUGIN_EXPORT ladspabrowser_plugin_descriptor = "List installed LADSPA plugins" ), "Danny McRae ", 0x0100, - Plugin::Tool, + Plugin::Type::Tool, new PluginPixmapLoader("logo"), nullptr, nullptr, @@ -107,12 +107,12 @@ LadspaBrowserView::LadspaBrowserView( ToolPlugin * _tool ) : auto ws = new QWidget(this); ws->setFixedSize( 500, 480 ); - QWidget * available = createTab( ws, tr( "Available Effects" ), VALID ); + QWidget * available = createTab( ws, tr( "Available Effects" ), LadspaPluginType::Valid ); QWidget * unavailable = createTab( ws, tr( "Unavailable Effects" ), - INVALID ); - QWidget * instruments = createTab( ws, tr( "Instruments" ), SOURCE ); - QWidget * analysis = createTab( ws, tr( "Analysis Tools" ), SINK ); - QWidget * other = createTab( ws, tr( "Don't know" ), OTHER ); + LadspaPluginType::Invalid ); + QWidget * instruments = createTab( ws, tr( "Instruments" ), LadspaPluginType::Source ); + QWidget * analysis = createTab( ws, tr( "Analysis Tools" ), LadspaPluginType::Sink ); + QWidget * other = createTab( ws, tr( "Don't know" ), LadspaPluginType::Other ); m_tabBar->addTab( available, tr( "Available Effects" ), diff --git a/plugins/LadspaBrowser/LadspaDescription.cpp b/plugins/LadspaBrowser/LadspaDescription.cpp index 004505d66..fbcd6c25d 100644 --- a/plugins/LadspaBrowser/LadspaDescription.cpp +++ b/plugins/LadspaBrowser/LadspaDescription.cpp @@ -49,22 +49,22 @@ LadspaDescription::LadspaDescription( QWidget * _parent, l_sortable_plugin_t plugins; switch( _type ) { - case SOURCE: + case LadspaPluginType::Source: plugins = manager->getInstruments(); break; - case TRANSFER: + case LadspaPluginType::Transfer: plugins = manager->getValidEffects(); break; - case VALID: + case LadspaPluginType::Valid: plugins = manager->getValidEffects(); break; - case INVALID: + case LadspaPluginType::Invalid: plugins = manager->getInvalidEffects(); break; - case SINK: + case LadspaPluginType::Sink: plugins = manager->getAnalysisTools(); break; - case OTHER: + case LadspaPluginType::Other: plugins = manager->getOthers(); break; default: @@ -75,7 +75,7 @@ LadspaDescription::LadspaDescription( QWidget * _parent, for (const auto& plugin : plugins) { ch_cnt_t audioDeviceChannels = Engine::audioEngine()->audioDev()->channels(); - if (_type != VALID || manager->getDescription(plugin.second)->inputChannels <= audioDeviceChannels) + if (_type != LadspaPluginType::Valid || manager->getDescription(plugin.second)->inputChannels <= audioDeviceChannels) { pluginNames.push_back(plugin.first); m_pluginKeys.push_back(plugin.second); diff --git a/plugins/LadspaEffect/LadspaControlDialog.cpp b/plugins/LadspaEffect/LadspaControlDialog.cpp index 571dbd454..2a5437fb1 100644 --- a/plugins/LadspaEffect/LadspaControlDialog.cpp +++ b/plugins/LadspaEffect/LadspaControlDialog.cpp @@ -86,7 +86,7 @@ void LadspaControlDialog::updateEffectView( LadspaControls * _ctl ) control_list_t & controls = _ctl->m_controls[proc]; int row = 0; int col = 0; - buffer_data_t last_port = NONE; + BufferDataType last_port = BufferDataType::None; QGroupBox * grouper; if( _ctl->m_processors > 1 ) @@ -108,10 +108,10 @@ void LadspaControlDialog::updateEffectView( LadspaControls * _ctl ) { if (control->port()->proc == proc) { - buffer_data_t this_port = control->port()->data_type; - if( last_port != NONE && - ( this_port == TOGGLED || this_port == ENUM ) && - ( last_port != TOGGLED && last_port != ENUM ) ) + BufferDataType this_port = control->port()->data_type; + if( last_port != BufferDataType::None && + ( this_port == BufferDataType::Toggled || this_port == BufferDataType::Enum ) && + ( last_port != BufferDataType::Toggled && last_port != BufferDataType::Enum ) ) { ++row; col = 0; diff --git a/plugins/LadspaEffect/LadspaEffect.cpp b/plugins/LadspaEffect/LadspaEffect.cpp index e5d1c5d69..cc754a829 100644 --- a/plugins/LadspaEffect/LadspaEffect.cpp +++ b/plugins/LadspaEffect/LadspaEffect.cpp @@ -60,10 +60,10 @@ Plugin::Descriptor PLUGIN_EXPORT ladspaeffect_plugin_descriptor = "inside LMMS." ), "Danny McRae ", 0x0100, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader("logo"), nullptr, - new LadspaSubPluginFeatures( Plugin::Effect ) + new LadspaSubPluginFeatures( Plugin::Type::Effect ) } ; } @@ -106,7 +106,7 @@ LadspaEffect::~LadspaEffect() void LadspaEffect::changeSampleRate() { - DataFile dataFile( DataFile::EffectSettings ); + DataFile dataFile( DataFile::Type::EffectSettings ); m_controls->saveState( dataFile, dataFile.content() ); LadspaControls * controls = m_controls; @@ -163,7 +163,7 @@ bool LadspaEffect::processAudioBuffer( sampleFrame * _buf, port_desc_t * pp = m_ports.at( proc ).at( port ); switch( pp->rate ) { - case CHANNEL_IN: + case BufferRate::ChannelIn: for( fpp_t frame = 0; frame < frames; ++frame ) { @@ -172,7 +172,7 @@ bool LadspaEffect::processAudioBuffer( sampleFrame * _buf, } ++channel; break; - case AUDIO_RATE_INPUT: + case BufferRate::AudioRateInput: { ValueBuffer * vb = pp->control->valueBuffer(); if( vb ) @@ -195,7 +195,7 @@ bool LadspaEffect::processAudioBuffer( sampleFrame * _buf, } break; } - case CONTROL_RATE_INPUT: + case BufferRate::ControlRateInput: if( pp->control == nullptr ) { break; @@ -205,9 +205,9 @@ bool LadspaEffect::processAudioBuffer( sampleFrame * _buf, pp->buffer[0] = pp->value; break; - case CHANNEL_OUT: - case AUDIO_RATE_OUTPUT: - case CONTROL_RATE_OUTPUT: + case BufferRate::ChannelOut: + case BufferRate::AudioRateOutput: + case BufferRate::ControlRateOutput: break; default: break; @@ -234,11 +234,11 @@ bool LadspaEffect::processAudioBuffer( sampleFrame * _buf, port_desc_t * pp = m_ports.at( proc ).at( port ); switch( pp->rate ) { - case CHANNEL_IN: - case AUDIO_RATE_INPUT: - case CONTROL_RATE_INPUT: + case BufferRate::ChannelIn: + case BufferRate::AudioRateInput: + case BufferRate::ControlRateInput: break; - case CHANNEL_OUT: + case BufferRate::ChannelOut: for( fpp_t frame = 0; frame < frames; ++frame ) { @@ -247,8 +247,8 @@ bool LadspaEffect::processAudioBuffer( sampleFrame * _buf, } ++channel; break; - case AUDIO_RATE_OUTPUT: - case CONTROL_RATE_OUTPUT: + case BufferRate::AudioRateOutput: + case BufferRate::ControlRateOutput: break; default: break; @@ -325,7 +325,7 @@ void LadspaEffect::pluginInstantiation() if( p->name.toUpper().contains( "IN" ) && manager->isPortInput( m_key, port ) ) { - p->rate = CHANNEL_IN; + p->rate = BufferRate::ChannelIn; p->buffer = MM_ALLOC( Engine::audioEngine()->framesPerPeriod() ); inbuf[ inputch ] = p->buffer; inputch++; @@ -333,7 +333,7 @@ void LadspaEffect::pluginInstantiation() else if( p->name.toUpper().contains( "OUT" ) && manager->isPortOutput( m_key, port ) ) { - p->rate = CHANNEL_OUT; + p->rate = BufferRate::ChannelOut; if( ! m_inPlaceBroken && inbuf[ outputch ] ) { p->buffer = inbuf[ outputch ]; @@ -347,12 +347,12 @@ void LadspaEffect::pluginInstantiation() } else if( manager->isPortInput( m_key, port ) ) { - p->rate = AUDIO_RATE_INPUT; + p->rate = BufferRate::AudioRateInput; p->buffer = MM_ALLOC( Engine::audioEngine()->framesPerPeriod() ); } else { - p->rate = AUDIO_RATE_OUTPUT; + p->rate = BufferRate::AudioRateOutput; p->buffer = MM_ALLOC( Engine::audioEngine()->framesPerPeriod() ); } } @@ -362,30 +362,30 @@ void LadspaEffect::pluginInstantiation() if( manager->isPortInput( m_key, port ) ) { - p->rate = CONTROL_RATE_INPUT; + p->rate = BufferRate::ControlRateInput; } else { - p->rate = CONTROL_RATE_OUTPUT; + p->rate = BufferRate::ControlRateOutput; } } p->scale = 1.0f; if( manager->isEnum( m_key, port ) ) { - p->data_type = ENUM; + p->data_type = BufferDataType::Enum; } else if( manager->isPortToggled( m_key, port ) ) { - p->data_type = TOGGLED; + p->data_type = BufferDataType::Toggled; } else if( manager->isInteger( m_key, port ) ) { - p->data_type = INTEGER; + p->data_type = BufferDataType::Integer; } else if( p->name.toUpper().contains( "(SECONDS)" ) ) { - p->data_type = TIME; + p->data_type = BufferDataType::Time; p->scale = 1000.0f; int loc = p->name.toUpper().indexOf( "(SECONDS)" ); @@ -393,20 +393,20 @@ void LadspaEffect::pluginInstantiation() } else if( p->name.toUpper().contains( "(S)" ) ) { - p->data_type = TIME; + p->data_type = BufferDataType::Time; p->scale = 1000.0f; int loc = p->name.toUpper().indexOf( "(S)" ); p->name.replace( loc, 3, "(ms)" ); } else if( p->name.toUpper().contains( "(MS)" ) ) { - p->data_type = TIME; + p->data_type = BufferDataType::Time; int loc = p->name.toUpper().indexOf( "(MS)" ); p->name.replace( loc, 4, "(ms)" ); } else { - p->data_type = FLOATING; + p->data_type = BufferDataType::Floating; } // Get the range and default values. @@ -438,7 +438,7 @@ void LadspaEffect::pluginInstantiation() p->def = manager->getDefaultSetting( m_key, port ); if( p->def == NOHINT ) { - if( p->data_type != TOGGLED ) + if( p->data_type != BufferDataType::Toggled ) { p->def = ( p->min + p->max ) / 2.0f; } @@ -465,8 +465,8 @@ void LadspaEffect::pluginInstantiation() // For convenience, keep a separate list of the ports that are used // to control the processors. - if( p->rate == AUDIO_RATE_INPUT || - p->rate == CONTROL_RATE_INPUT ) + if( p->rate == BufferRate::AudioRateInput || + p->rate == BufferRate::ControlRateInput ) { p->control_id = m_portControls.count(); m_portControls.append( p ); @@ -555,7 +555,7 @@ void LadspaEffect::pluginDestruction() for( int port = 0; port < m_portCount; port++ ) { port_desc_t * pp = m_ports.at( proc ).at( port ); - if( m_inPlaceBroken || pp->rate != CHANNEL_OUT ) + if( m_inPlaceBroken || pp->rate != BufferRate::ChannelOut ) { if( pp->buffer) MM_FREE( pp->buffer ); } diff --git a/plugins/LadspaEffect/LadspaSubPluginFeatures.cpp b/plugins/LadspaEffect/LadspaSubPluginFeatures.cpp index 1522d7187..46a211f9f 100644 --- a/plugins/LadspaEffect/LadspaSubPluginFeatures.cpp +++ b/plugins/LadspaEffect/LadspaSubPluginFeatures.cpp @@ -39,7 +39,7 @@ namespace lmms { -LadspaSubPluginFeatures::LadspaSubPluginFeatures( Plugin::PluginTypes _type ) : +LadspaSubPluginFeatures::LadspaSubPluginFeatures( Plugin::Type _type ) : SubPluginFeatures( _type ) { } @@ -137,17 +137,17 @@ void LadspaSubPluginFeatures::listSubPluginKeys( l_sortable_plugin_t plugins; switch( m_type ) { - case Plugin::Instrument: + case Plugin::Type::Instrument: plugins = lm->getInstruments(); break; - case Plugin::Effect: + case Plugin::Type::Effect: plugins = lm->getValidEffects(); //plugins += lm->getInvalidEffects(); break; - case Plugin::Tool: + case Plugin::Type::Tool: plugins = lm->getAnalysisTools(); break; - case Plugin::Other: + case Plugin::Type::Other: plugins = lm->getOthers(); break; default: diff --git a/plugins/LadspaEffect/LadspaSubPluginFeatures.h b/plugins/LadspaEffect/LadspaSubPluginFeatures.h index c65dce9fe..7747127b8 100644 --- a/plugins/LadspaEffect/LadspaSubPluginFeatures.h +++ b/plugins/LadspaEffect/LadspaSubPluginFeatures.h @@ -38,7 +38,7 @@ namespace lmms class LadspaSubPluginFeatures : public Plugin::Descriptor::SubPluginFeatures { public: - LadspaSubPluginFeatures( Plugin::PluginTypes _type ); + LadspaSubPluginFeatures( Plugin::Type _type ); QString displayName(const Key& k) const override; void fillDescriptionWidget( QWidget * _parent, diff --git a/plugins/LadspaEffect/caps/Descriptor.h b/plugins/LadspaEffect/caps/Descriptor.h index 12c5d1c88..c3e1c325e 100644 --- a/plugins/LadspaEffect/caps/Descriptor.h +++ b/plugins/LadspaEffect/caps/Descriptor.h @@ -53,7 +53,7 @@ class DescriptorStub PortCount = 0; } - ~DescriptorStub() + virtual ~DescriptorStub() { if (PortCount) { @@ -87,6 +87,7 @@ class Descriptor public: Descriptor() { setup(); } + ~Descriptor() override = default; void setup(); void autogen() diff --git a/plugins/LadspaEffect/cmt/cmt b/plugins/LadspaEffect/cmt/cmt index f7c25ed4e..6e6e291fb 160000 --- a/plugins/LadspaEffect/cmt/cmt +++ b/plugins/LadspaEffect/cmt/cmt @@ -1 +1 @@ -Subproject commit f7c25ed4ef7f4d7efb1bcd4229d25595d4f1ce55 +Subproject commit 6e6e291fbad1138c808860ba3f140a963b52fa58 diff --git a/plugins/Lb302/Lb302.cpp b/plugins/Lb302/Lb302.cpp index 140b84189..b8fff2c0b 100644 --- a/plugins/Lb302/Lb302.cpp +++ b/plugins/Lb302/Lb302.cpp @@ -86,7 +86,7 @@ Plugin::Descriptor PLUGIN_EXPORT lb302_plugin_descriptor = "Incomplete monophonic imitation TB-303" ), "Paul Giblock ", 0x0100, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader( "logo" ), nullptr, nullptr, @@ -290,7 +290,7 @@ Lb302Synth::Lb302Synth( InstrumentTrack * _instrumentTrack ) : vca_decay(0.99897516), vca_a0(0.5), vca_a(0.), - vca_mode(never_played) + vca_mode(VcaMode::NeverPlayed) { connect( Engine::audioEngine(), SIGNAL( sampleRateChanged() ), @@ -332,7 +332,7 @@ Lb302Synth::Lb302Synth( InstrumentTrack * _instrumentTrack ) : vcf_envpos = ENVINC; - vco_shape = BL_SAWTOOTH; + vco_shape = VcoShape::BLSawtooth; vcfs[0] = new Lb302FilterIIR2(&fs); vcfs[1] = new Lb302Filter3Pole(&fs); @@ -469,7 +469,7 @@ int Lb302Synth::process(sampleFrame *outbuf, const int size) if( release_frame == 0 || ! m_playingNote ) { - vca_mode = decay; + vca_mode = VcaMode::Decay; } if( new_freq ) @@ -493,7 +493,7 @@ int Lb302Synth::process(sampleFrame *outbuf, const int size) // start decay if we're past release if( i >= release_frame ) { - vca_mode = decay; + vca_mode = VcaMode::Decay; } // update vcf @@ -523,43 +523,43 @@ int Lb302Synth::process(sampleFrame *outbuf, const int size) vco_c -= 1.0; switch(int(rint(wave_shape.value()))) { - case 0: vco_shape = SAWTOOTH; break; - case 1: vco_shape = TRIANGLE; break; - case 2: vco_shape = SQUARE; break; - case 3: vco_shape = ROUND_SQUARE; break; - case 4: vco_shape = MOOG; break; - case 5: vco_shape = SINE; break; - case 6: vco_shape = EXPONENTIAL; break; - case 7: vco_shape = WHITE_NOISE; break; - case 8: vco_shape = BL_SAWTOOTH; break; - case 9: vco_shape = BL_SQUARE; break; - case 10: vco_shape = BL_TRIANGLE; break; - case 11: vco_shape = BL_MOOG; break; - default: vco_shape = SAWTOOTH; break; + case 0: vco_shape = VcoShape::Sawtooth; break; + case 1: vco_shape = VcoShape::Triangle; break; + case 2: vco_shape = VcoShape::Square; break; + case 3: vco_shape = VcoShape::RoundSquare; break; + case 4: vco_shape = VcoShape::Moog; break; + case 5: vco_shape = VcoShape::Sine; break; + case 6: vco_shape = VcoShape::Exponential; break; + case 7: vco_shape = VcoShape::WhiteNoise; break; + case 8: vco_shape = VcoShape::BLSawtooth; break; + case 9: vco_shape = VcoShape::BLSquare; break; + case 10: vco_shape = VcoShape::BLTriangle; break; + case 11: vco_shape = VcoShape::BLMoog; break; + default: vco_shape = VcoShape::Sawtooth; break; } // add vco_shape_param the changes the shape of each curve. // merge sawtooths with triangle and square with round square? switch (vco_shape) { - case SAWTOOTH: // p0: curviness of line + case VcoShape::Sawtooth: // p0: curviness of line vco_k = vco_c; // Is this sawtooth backwards? break; - case TRIANGLE: // p0: duty rev.saw<->triangle<->saw p1: curviness + case VcoShape::Triangle: // p0: duty rev.saw<->triangle<->saw p1: curviness vco_k = (vco_c*2.0)+0.5; if (vco_k>0.5) vco_k = 1.0- vco_k; break; - case SQUARE: // p0: slope of top + case VcoShape::Square: // p0: slope of top vco_k = (vco_c<0)?0.5:-0.5; break; - case ROUND_SQUARE: // p0: width of round + case VcoShape::RoundSquare: // p0: width of round vco_k = (vco_c<0)?(sqrtf(1-(vco_c*vco_c*4))-0.5):-0.5; break; - case MOOG: // Maybe the fall should be exponential/sinsoidal instead of quadric. + case VcoShape::Moog: // Maybe the fall should be exponential/sinsoidal instead of quadric. // [-0.5, 0]: Rise, [0,0.25]: Slope down, [0.25,0.5]: Low vco_k = (vco_c*2.0)+0.5; if (vco_k>1.0) { @@ -572,33 +572,33 @@ int Lb302Synth::process(sampleFrame *outbuf, const int size) vco_k *= 2.0; // MOOG wave gets filtered away break; - case SINE: + case VcoShape::Sine: // [-0.5, 0.5] : [-pi, pi] vco_k = 0.5f * Oscillator::sinSample( vco_c ); break; - case EXPONENTIAL: + case VcoShape::Exponential: vco_k = 0.5 * Oscillator::expSample( vco_c ); break; - case WHITE_NOISE: + case VcoShape::WhiteNoise: vco_k = 0.5 * Oscillator::noiseSample( vco_c ); break; - case BL_SAWTOOTH: - vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::BLSaw ) * 0.5f; + case VcoShape::BLSawtooth: + vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::Waveform::BLSaw ) * 0.5f; break; - case BL_SQUARE: - vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::BLSquare ) * 0.5f; + case VcoShape::BLSquare: + vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::Waveform::BLSquare ) * 0.5f; break; - case BL_TRIANGLE: - vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::BLTriangle ) * 0.5f; + case VcoShape::BLTriangle: + vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::Waveform::BLTriangle ) * 0.5f; break; - case BL_MOOG: - vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::BLMoog ); + case VcoShape::BLMoog: + vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::Waveform::BLMoog ); break; } @@ -633,18 +633,18 @@ int Lb302Synth::process(sampleFrame *outbuf, const int size) } // Handle Envelope - if(vca_mode==attack) { + if(vca_mode==VcaMode::Attack) { vca_a+=(vca_a0-vca_a)*vca_attack; if(sample_cnt>=0.5*Engine::audioEngine()->processingSampleRate()) - vca_mode = idle; + vca_mode = VcaMode::Idle; } - else if(vca_mode == decay) { + else if(vca_mode == VcaMode::Decay) { vca_a *= vca_decay; // the following line actually speeds up processing if(vca_a < (1/65536.0)) { vca_a = 0; - vca_mode = never_played; + vca_mode = VcaMode::NeverPlayed; } } @@ -666,15 +666,15 @@ void Lb302Synth::initNote( Lb302Note *n) // Always reset vca on non-dead notes, and // Only reset vca on decaying(decayed) and never-played - if(n->dead == 0 || (vca_mode == decay || vca_mode == never_played)) { + if(n->dead == 0 || (vca_mode == VcaMode::Decay || vca_mode == VcaMode::NeverPlayed)) { //printf(" good\n"); sample_cnt = 0; - vca_mode = attack; + vca_mode = VcaMode::Attack; // LB303: //vca_a = 0; } else { - vca_mode = idle; + vca_mode = VcaMode::Idle; } initSlide(); @@ -746,7 +746,7 @@ void Lb302Synth::playNote( NotePlayHandle * _n, sampleFrame * _working_buffer ) void Lb302Synth::processNote( NotePlayHandle * _n ) { /// Start a new note. - if( _n->m_pluginData != this ) + if (_n->m_pluginData != this) { m_playingNote = _n; new_freq = true; @@ -819,22 +819,22 @@ Lb302SynthView::Lb302SynthView( Instrument * _instrument, QWidget * _parent ) : InstrumentViewFixedSize( _instrument, _parent ) { // GUI - m_vcfCutKnob = new Knob( knobBright_26, this ); + m_vcfCutKnob = new Knob( KnobType::Bright26, this ); m_vcfCutKnob->move( 75, 130 ); m_vcfCutKnob->setHintText( tr( "Cutoff Freq:" ), "" ); m_vcfCutKnob->setLabel( "" ); - m_vcfResKnob = new Knob( knobBright_26, this ); + m_vcfResKnob = new Knob( KnobType::Bright26, this ); m_vcfResKnob->move( 120, 130 ); m_vcfResKnob->setHintText( tr( "Resonance:" ), "" ); m_vcfResKnob->setLabel( "" ); - m_vcfModKnob = new Knob( knobBright_26, this ); + m_vcfModKnob = new Knob( KnobType::Bright26, this ); m_vcfModKnob->move( 165, 130 ); m_vcfModKnob->setHintText( tr( "Env Mod:" ), "" ); m_vcfModKnob->setLabel( "" ); - m_vcfDecKnob = new Knob( knobBright_26, this ); + m_vcfDecKnob = new Knob( KnobType::Bright26, this ); m_vcfDecKnob->move( 210, 130 ); m_vcfDecKnob->setHintText( tr( "Decay:" ), "" ); m_vcfDecKnob->setLabel( "" ); @@ -855,12 +855,12 @@ Lb302SynthView::Lb302SynthView( Instrument * _instrument, QWidget * _parent ) : tr( "303-es-que, 24dB/octave, 3 pole filter" ) ); - m_slideDecKnob = new Knob( knobBright_26, this ); + m_slideDecKnob = new Knob( KnobType::Bright26, this ); m_slideDecKnob->move( 210, 75 ); m_slideDecKnob->setHintText( tr( "Slide Decay:" ), "" ); m_slideDecKnob->setLabel( ""); - m_distKnob = new Knob( knobBright_26, this ); + m_distKnob = new Knob( KnobType::Bright26, this ); m_distKnob->move( 210, 190 ); m_distKnob->setHintText( tr( "DIST:" ), "" ); m_distKnob->setLabel( tr( "")); diff --git a/plugins/Lb302/Lb302.h b/plugins/Lb302/Lb302.h index 3abece98f..237a3f3f8 100644 --- a/plugins/Lb302/Lb302.h +++ b/plugins/Lb302/Lb302.h @@ -165,7 +165,7 @@ public: Flags flags() const override { - return IsSingleStreamed; + return Flag::IsSingleStreamed; } f_cnt_t desiredReleaseFrames() const override @@ -213,9 +213,9 @@ private: vco_slideinc, //* Slide base to use in next node. Nonzero=slide next note vco_slidebase; //* The base vco_inc while sliding. - enum vco_shape_t { SAWTOOTH, SQUARE, TRIANGLE, MOOG, ROUND_SQUARE, SINE, EXPONENTIAL, WHITE_NOISE, - BL_SAWTOOTH, BL_SQUARE, BL_TRIANGLE, BL_MOOG }; - vco_shape_t vco_shape; + enum class VcoShape { Sawtooth, Square, Triangle, Moog, RoundSquare, Sine, Exponential, WhiteNoise, + BLSawtooth, BLSquare, BLTriangle, BLMoog }; + VcoShape vco_shape; // Filters (just keep both loaded and switch) Lb302Filter* vcfs[NUM_FILTERS]; @@ -235,14 +235,14 @@ private: vca_a; // Amplifier coefficient. // Envelope State - enum VCA_Mode + enum class VcaMode { - attack = 0, - decay = 1, - idle = 2, - never_played = 3 + Attack = 0, + Decay = 1, + Idle = 2, + NeverPlayed = 3 }; - VCA_Mode vca_mode; + VcaMode vca_mode; // My hacks int sample_cnt; diff --git a/plugins/Lv2Effect/Lv2Effect.cpp b/plugins/Lv2Effect/Lv2Effect.cpp index ec2dc1f48..9c21b3f2a 100644 --- a/plugins/Lv2Effect/Lv2Effect.cpp +++ b/plugins/Lv2Effect/Lv2Effect.cpp @@ -46,10 +46,10 @@ Plugin::Descriptor PLUGIN_EXPORT lv2effect_plugin_descriptor = "plugin for using arbitrary LV2-effects inside LMMS."), "Johannes Lorenz ", 0x0100, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader("logo"), nullptr, - new Lv2SubPluginFeatures(Plugin::Effect) + new Lv2SubPluginFeatures(Plugin::Type::Effect) }; } diff --git a/plugins/Lv2Instrument/Lv2Instrument.cpp b/plugins/Lv2Instrument/Lv2Instrument.cpp index 052445844..1e45f4e91 100644 --- a/plugins/Lv2Instrument/Lv2Instrument.cpp +++ b/plugins/Lv2Instrument/Lv2Instrument.cpp @@ -55,10 +55,10 @@ Plugin::Descriptor PLUGIN_EXPORT lv2instrument_plugin_descriptor = "plugin for using arbitrary LV2 instruments inside LMMS."), "Johannes Lorenz ", 0x0100, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader("logo"), nullptr, - new Lv2SubPluginFeatures(Plugin::Instrument) + new Lv2SubPluginFeatures(Plugin::Type::Instrument) }; } @@ -97,7 +97,7 @@ Lv2Instrument::Lv2Instrument(InstrumentTrack *instrumentTrackArg, Lv2Instrument::~Lv2Instrument() { Engine::audioEngine()->removePlayHandlesOfTypes(instrumentTrack(), - PlayHandle::TypeNotePlayHandle | PlayHandle::TypeInstrumentPlayHandle); + PlayHandle::Type::NotePlayHandle | PlayHandle::Type::InstrumentPlayHandle); } diff --git a/plugins/Lv2Instrument/Lv2Instrument.h b/plugins/Lv2Instrument/Lv2Instrument.h index 7b521e1b0..2cd73632d 100644 --- a/plugins/Lv2Instrument/Lv2Instrument.h +++ b/plugins/Lv2Instrument/Lv2Instrument.h @@ -89,9 +89,9 @@ public: Flags flags() const override { #ifdef LV2_INSTRUMENT_USE_MIDI - return IsSingleStreamed | IsMidiBased; + return Flag::IsSingleStreamed | Flag::IsMidiBased; #else - return IsSingleStreamed; + return Flag::IsSingleStreamed; #endif } gui::PluginView* instantiateView(QWidget *parent) override; diff --git a/plugins/MidiExport/MidiExport.cpp b/plugins/MidiExport/MidiExport.cpp index 0d18d8ae1..df968e36a 100644 --- a/plugins/MidiExport/MidiExport.cpp +++ b/plugins/MidiExport/MidiExport.cpp @@ -51,7 +51,7 @@ Plugin::Descriptor PLUGIN_EXPORT midiexport_plugin_descriptor = "Mohamed Abdel Maksoud and " "Hyunjin Song ", 0x0100, - Plugin::ExportFilter, + Plugin::Type::ExportFilter, nullptr, nullptr, nullptr, @@ -84,8 +84,8 @@ bool MidiExport::tryExport(const TrackContainer::TrackList &tracks, auto buffer = std::array{}; uint32_t size; - for (const Track* track : tracks) if (track->type() == Track::InstrumentTrack) nTracks++; - for (const Track* track : patternStoreTracks) if (track->type() == Track::InstrumentTrack) nTracks++; + for (const Track* track : tracks) if (track->type() == Track::Type::Instrument) nTracks++; + for (const Track* track : patternStoreTracks) if (track->type() == Track::Type::Instrument) nTracks++; // midi header MidiFile::MIDIHeader header(nTracks); @@ -97,10 +97,10 @@ bool MidiExport::tryExport(const TrackContainer::TrackList &tracks, // midi tracks for (Track* track : tracks) { - DataFile dataFile(DataFile::SongProject); + DataFile dataFile(DataFile::Type::SongProject); MTrack mtrack; - if (track->type() == Track::InstrumentTrack) + if (track->type() == Track::Type::Instrument) { mtrack.addName(track->name().toStdString(), 0); @@ -143,7 +143,7 @@ bool MidiExport::tryExport(const TrackContainer::TrackList &tracks, midiout.writeRawData((char *)buffer.data(), size); } - if (track->type() == Track::PatternTrack) + if (track->type() == Track::Type::Pattern) { patternTrack = dynamic_cast(track); element = patternTrack->saveState(dataFile, dataFile.content()); @@ -169,7 +169,7 @@ bool MidiExport::tryExport(const TrackContainer::TrackList &tracks, // for each instrument in the pattern editor for (Track* track : patternStoreTracks) { - DataFile dataFile(DataFile::SongProject); + DataFile dataFile(DataFile::Type::SongProject); MTrack mtrack; // begin at the first pattern track (first pattern) @@ -177,7 +177,7 @@ bool MidiExport::tryExport(const TrackContainer::TrackList &tracks, std::vector> st; - if (track->type() != Track::InstrumentTrack) continue; + if (track->type() != Track::Type::Instrument) continue; mtrack.addName(track->name().toStdString(), 0); //mtrack.addProgramChange(0, 0); diff --git a/plugins/MidiImport/MidiImport.cpp b/plugins/MidiImport/MidiImport.cpp index 6836060f3..785cd079a 100644 --- a/plugins/MidiImport/MidiImport.cpp +++ b/plugins/MidiImport/MidiImport.cpp @@ -71,7 +71,7 @@ Plugin::Descriptor PLUGIN_EXPORT midiimport_plugin_descriptor = "Filter for importing MIDI-files into LMMS" ), "Tobias Doerffel ", 0x0100, - Plugin::ImportFilter, + Plugin::Type::ImportFilter, nullptr, nullptr, nullptr, @@ -165,7 +165,7 @@ public: // in the main thread. This should probably be // removed if that ever changes. qApp->processEvents(); - at = dynamic_cast( Track::create( Track::AutomationTrack, tc ) ); + at = dynamic_cast( Track::create( Track::Type::Automation, tc ) ); } if( tn != "") { at->setName( tn ); @@ -227,7 +227,7 @@ public: if( !it ) { // Keep LMMS responsive qApp->processEvents(); - it = dynamic_cast( Track::create( Track::InstrumentTrack, tc ) ); + it = dynamic_cast( Track::create( Track::Type::Instrument, tc ) ); #ifdef LMMS_HAVE_FLUIDSYNTH it_inst = it->loadInstrument( "sf2player" ); @@ -328,9 +328,9 @@ bool MidiImport::readSMF( TrackContainer* tc ) // NOTE: unordered_map::operator[] creates a new element if none exists MeterModel & timeSigMM = Engine::getSong()->getTimeSigModel(); - auto nt = dynamic_cast(Track::create(Track::AutomationTrack, Engine::getSong())); + auto nt = dynamic_cast(Track::create(Track::Type::Automation, Engine::getSong())); nt->setName(tr("MIDI Time Signature Numerator")); - auto dt = dynamic_cast(Track::create(Track::AutomationTrack, Engine::getSong())); + auto dt = dynamic_cast(Track::create(Track::Type::Automation, Engine::getSong())); dt->setName(tr("MIDI Time Signature Denominator")); auto timeSigNumeratorPat = new AutomationClip(nt); timeSigNumeratorPat->setDisplayName(tr("Numerator")); @@ -358,7 +358,7 @@ bool MidiImport::readSMF( TrackContainer* tc ) pd.setValue( 2 ); // Tempo stuff - auto tt = dynamic_cast(Track::create(Track::AutomationTrack, Engine::getSong())); + auto tt = dynamic_cast(Track::create(Track::Type::Automation, Engine::getSong())); tt->setName(tr("Tempo")); auto tap = new AutomationClip(tt); tap->setDisplayName(tr("Tempo")); diff --git a/plugins/Monstro/Monstro.cpp b/plugins/Monstro/Monstro.cpp index 3a9737fdb..f588d6b78 100644 --- a/plugins/Monstro/Monstro.cpp +++ b/plugins/Monstro/Monstro.cpp @@ -53,7 +53,7 @@ Plugin::Descriptor PLUGIN_EXPORT monstro_plugin_descriptor = "Monstrous 3-oscillator synth with modulation matrix" ), "Vesa Kivimäki ", 0x0100, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader( "logo" ), nullptr, nullptr, @@ -1030,7 +1030,7 @@ void MonstroInstrument::playNote( NotePlayHandle * _n, const fpp_t frames = _n->framesLeftForCurrentPeriod(); const f_cnt_t offset = _n->noteOffset(); - if ( _n->totalFramesPlayed() == 0 || _n->m_pluginData == nullptr ) + if (!_n->m_pluginData) { _n->m_pluginData = new MonstroSynth( this, _n ); } diff --git a/plugins/Monstro/Monstro.h b/plugins/Monstro/Monstro.h index 319b7e000..21efedaf3 100644 --- a/plugins/Monstro/Monstro.h +++ b/plugins/Monstro/Monstro.h @@ -43,14 +43,14 @@ // #define makeknob( name, x, y, hint, unit, oname ) \ - name = new Knob( knobStyled, view ); \ + name = new Knob( KnobType::Styled, view ); \ name ->move( x, y ); \ name ->setHintText( hint, unit ); \ name ->setObjectName( oname ); \ name ->setFixedSize( 20, 20 ); #define maketsknob( name, x, y, hint, unit, oname ) \ - name = new TempoSyncKnob( knobStyled, view ); \ + name = new TempoSyncKnob( KnobType::Styled, view ); \ name ->move( x, y ); \ name ->setHintText( hint, unit ); \ name ->setObjectName( oname ); \ @@ -211,19 +211,19 @@ private: break; case WAVE_TRI: //return Oscillator::triangleSample( _ph ); - return BandLimitedWave::oscillate( _ph, _wavelen, BandLimitedWave::BLTriangle ); + return BandLimitedWave::oscillate( _ph, _wavelen, BandLimitedWave::Waveform::BLTriangle ); break; case WAVE_SAW: //return Oscillator::sawSample( _ph ); - return BandLimitedWave::oscillate( _ph, _wavelen, BandLimitedWave::BLSaw ); + return BandLimitedWave::oscillate( _ph, _wavelen, BandLimitedWave::Waveform::BLSaw ); break; case WAVE_RAMP: //return Oscillator::sawSample( _ph ) * -1.0; - return BandLimitedWave::oscillate( _ph, _wavelen, BandLimitedWave::BLSaw ) * -1.0; + return BandLimitedWave::oscillate( _ph, _wavelen, BandLimitedWave::Waveform::BLSaw ) * -1.0; break; case WAVE_SQR: //return Oscillator::squareSample( _ph ); - return BandLimitedWave::oscillate( _ph, _wavelen, BandLimitedWave::BLSquare ); + return BandLimitedWave::oscillate( _ph, _wavelen, BandLimitedWave::Waveform::BLSquare ); break; case WAVE_SQRSOFT: { @@ -236,7 +236,7 @@ private: } case WAVE_MOOG: //return Oscillator::moogSawSample( _ph ); - return BandLimitedWave::oscillate( _ph, _wavelen, BandLimitedWave::BLMoog ); + return BandLimitedWave::oscillate( _ph, _wavelen, BandLimitedWave::Waveform::BLMoog ); break; case WAVE_SINABS: return qAbs( Oscillator::sinSample( _ph ) ); diff --git a/plugins/MultitapEcho/MultitapEcho.cpp b/plugins/MultitapEcho/MultitapEcho.cpp index 05c3f30fe..4f5e9fdf8 100644 --- a/plugins/MultitapEcho/MultitapEcho.cpp +++ b/plugins/MultitapEcho/MultitapEcho.cpp @@ -41,7 +41,7 @@ Plugin::Descriptor PLUGIN_EXPORT multitapecho_plugin_descriptor = QT_TRANSLATE_NOOP( "PluginBrowser", "A multitap echo delay plugin" ), "Vesa Kivimäki ", 0x0100, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader( "logo" ), nullptr, nullptr, diff --git a/plugins/MultitapEcho/MultitapEchoControlDialog.cpp b/plugins/MultitapEcho/MultitapEchoControlDialog.cpp index dbf428e5f..e89137bf0 100644 --- a/plugins/MultitapEcho/MultitapEchoControlDialog.cpp +++ b/plugins/MultitapEcho/MultitapEchoControlDialog.cpp @@ -48,8 +48,8 @@ MultitapEchoControlDialog::MultitapEchoControlDialog( MultitapEchoControls * con // graph widgets - auto ampGraph = new Graph(this, Graph::BarStyle, 204, 105); - auto lpGraph = new Graph(this, Graph::BarStyle, 204, 105); + auto ampGraph = new Graph(this, Graph::Style::Bar, 204, 105); + auto lpGraph = new Graph(this, Graph::Style::Bar, 204, 105); ampGraph->move( 30, 10 ); lpGraph->move( 30, 125 ); @@ -78,26 +78,26 @@ MultitapEchoControlDialog::MultitapEchoControlDialog( MultitapEchoControls * con // knobs - auto stepLength = new TempoSyncKnob(knobBright_26, this); + auto stepLength = new TempoSyncKnob(KnobType::Bright26, this); stepLength->move( 100, 245 ); stepLength->setModel( & controls->m_stepLength ); stepLength->setLabel( tr( "Length" ) ); stepLength->setHintText( tr( "Step length:" ) , " ms" ); - auto dryGain = new Knob(knobBright_26, this); + auto dryGain = new Knob(KnobType::Bright26, this); dryGain->move( 150, 245 ); dryGain->setModel( & controls->m_dryGain ); dryGain->setLabel( tr( "Dry" ) ); dryGain->setHintText( tr( "Dry gain:" ) , " dBFS" ); - auto stages = new Knob(knobBright_26, this); + auto stages = new Knob(KnobType::Bright26, this); stages->move( 200, 245 ); stages->setModel( & controls->m_stages ); stages->setLabel( tr( "Stages" ) ); stages->setHintText( tr( "Low-pass stages:" ) , "x" ); // switch led - auto swapInputs = new LedCheckBox("Swap inputs", this, tr("Swap inputs"), LedCheckBox::Green); + auto swapInputs = new LedCheckBox("Swap inputs", this, tr("Swap inputs"), LedCheckBox::LedColor::Green); swapInputs->move( 20, 275 ); swapInputs->setModel( & controls->m_swapInputs ); swapInputs->setToolTip(tr("Swap left and right input channels for reflections")); diff --git a/plugins/Nes/Nes.cpp b/plugins/Nes/Nes.cpp index d47ebd728..a530ac19b 100644 --- a/plugins/Nes/Nes.cpp +++ b/plugins/Nes/Nes.cpp @@ -51,7 +51,7 @@ Plugin::Descriptor PLUGIN_EXPORT nes_plugin_descriptor = "A NES-like synthesizer" ), "Vesa Kivimäki ", 0x0100, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader( "logo" ), nullptr, nullptr, @@ -550,7 +550,7 @@ void NesInstrument::playNote( NotePlayHandle * n, sampleFrame * workingBuffer ) const fpp_t frames = n->framesLeftForCurrentPeriod(); const f_cnt_t offset = n->noteOffset(); - if ( n->totalFramesPlayed() == 0 || n->m_pluginData == nullptr ) + if (!n->m_pluginData) { auto nes = new NesObject(this, Engine::audioEngine()->processingSampleRate(), n); n->m_pluginData = nes; diff --git a/plugins/Nes/Nes.h b/plugins/Nes/Nes.h index 91e5e556c..3ddf0fc9a 100644 --- a/plugins/Nes/Nes.h +++ b/plugins/Nes/Nes.h @@ -35,7 +35,7 @@ #define makeknob( name, x, y, hint, unit, oname ) \ - name = new Knob( knobStyled, this ); \ + name = new Knob( KnobType::Styled, this ); \ name ->move( x, y ); \ name ->setHintText( hint, unit ); \ name ->setObjectName( oname ); \ diff --git a/plugins/OpulenZ/OpulenZ.cpp b/plugins/OpulenZ/OpulenZ.cpp index 3a18c1e3f..64f609995 100644 --- a/plugins/OpulenZ/OpulenZ.cpp +++ b/plugins/OpulenZ/OpulenZ.cpp @@ -73,7 +73,7 @@ Plugin::Descriptor PLUGIN_EXPORT opulenz_plugin_descriptor = "2-operator FM Synth" ), "Raine M. Ekman ", 0x0100, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader( "logo" ), "sbi", nullptr, @@ -222,8 +222,8 @@ OpulenzInstrument::OpulenzInstrument( InstrumentTrack * _instrument_track ) : OpulenzInstrument::~OpulenzInstrument() { delete theEmulator; Engine::audioEngine()->removePlayHandlesOfTypes( instrumentTrack(), - PlayHandle::TypeNotePlayHandle - | PlayHandle::TypeInstrumentPlayHandle ); + PlayHandle::Type::NotePlayHandle + | PlayHandle::Type::InstrumentPlayHandle ); delete [] renderbuffer; } @@ -686,7 +686,7 @@ OpulenzInstrumentView::OpulenzInstrumentView( Instrument * _instrument, { #define KNOB_GEN(knobname, hinttext, hintunit,xpos,ypos) \ - knobname = new Knob( knobStyled, this );\ + knobname = new Knob( KnobType::Styled, this );\ knobname->setHintText( tr(hinttext), hintunit );\ knobname->setFixedSize(22,22);\ knobname->setCenterPointX(11.0);\ diff --git a/plugins/OpulenZ/OpulenZ.h b/plugins/OpulenZ/OpulenZ.h index 1f999252f..a3e11a6c0 100644 --- a/plugins/OpulenZ/OpulenZ.h +++ b/plugins/OpulenZ/OpulenZ.h @@ -66,7 +66,7 @@ public: Flags flags() const override { - return IsSingleStreamed | IsMidiBased; + return Flag::IsSingleStreamed | Flag::IsMidiBased; } bool handleMidiEvent( const MidiEvent& event, const TimePos& time, f_cnt_t offset = 0 ) override; diff --git a/plugins/Organic/Organic.cpp b/plugins/Organic/Organic.cpp index 6c2cde773..f8a2b0d13 100644 --- a/plugins/Organic/Organic.cpp +++ b/plugins/Organic/Organic.cpp @@ -22,13 +22,10 @@ * */ - #include "Organic.h" - #include - #include "Engine.h" #include "AudioEngine.h" #include "InstrumentTrack.h" @@ -38,7 +35,6 @@ #include "PixmapButton.h" #include "embed.h" - #include "plugin_export.h" namespace lmms @@ -56,7 +52,7 @@ Plugin::Descriptor PLUGIN_EXPORT organic_plugin_descriptor = "Additive Synthesizer for organ-like sounds" ), "Andreas Brandmaier ", 0x0100, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader( "logo" ), nullptr, nullptr, @@ -78,7 +74,9 @@ float * OrganicInstrument::s_harmonics = nullptr; OrganicInstrument::OrganicInstrument( InstrumentTrack * _instrument_track ) : Instrument( _instrument_track, &organic_plugin_descriptor ), - m_modulationAlgo( Oscillator::SignalMix, Oscillator::SignalMix, Oscillator::SignalMix), + m_modulationAlgo(static_cast(Oscillator::ModulationAlgo::SignalMix), + static_cast(Oscillator::ModulationAlgo::SignalMix), + static_cast(Oscillator::ModulationAlgo::SignalMix)), m_fx1Model( 0.0f, 0.0f, 0.99f, 0.01f , this, tr( "Distortion" ) ), m_volModel( 100.0f, 0.0f, 200.0f, 1.0f, this, tr( "Volume" ) ) { @@ -159,61 +157,59 @@ OrganicInstrument::~OrganicInstrument() -void OrganicInstrument::saveSettings( QDomDocument & _doc, QDomElement & _this ) +void OrganicInstrument::saveSettings(QDomDocument& doc, QDomElement& elem) { - _this.setAttribute( "num_osc", QString::number( m_numOscillators ) ); - m_fx1Model.saveSettings( _doc, _this, "foldback" ); - m_volModel.saveSettings( _doc, _this, "vol" ); + elem.setAttribute("num_osc", QString::number(m_numOscillators)); + m_fx1Model.saveSettings(doc, elem, "foldback"); + m_volModel.saveSettings(doc, elem, "vol"); - for( int i = 0; i < m_numOscillators; ++i ) + for (int i = 0; i < m_numOscillators; ++i) { - QString is = QString::number( i ); - m_osc[i]->m_volModel.saveSettings( _doc, _this, "vol" + is ); - m_osc[i]->m_panModel.saveSettings( _doc, _this, "pan" + is ); - m_osc[i]->m_harmModel.saveSettings( _doc, _this, "newharmonic" + is ); - - m_osc[i]->m_detuneModel.saveSettings( _doc, _this, "newdetune" - + is ); - m_osc[i]->m_oscModel.saveSettings( _doc, _this, "wavetype" - + is ); + const auto is = QString::number(i); + m_osc[i]->m_volModel.saveSettings(doc, elem, "vol" + is); + m_osc[i]->m_panModel.saveSettings(doc, elem, "pan" + is); + m_osc[i]->m_harmModel.saveSettings(doc, elem, "newharmonic" + is); + m_osc[i]->m_detuneModel.saveSettings(doc, elem, "newdetune" + is); + m_osc[i]->m_oscModel.saveSettings(doc, elem, "wavetype" + is); } } -void OrganicInstrument::loadSettings( const QDomElement & _this ) +void OrganicInstrument::loadSettings(const QDomElement& elem) { -// m_numOscillators = _this.attribute( "num_osc" ). - // toInt(); - - for( int i = 0; i < m_numOscillators; ++i ) + for (int i = 0; i < m_numOscillators; ++i) { - QString is = QString::number( i ); - m_osc[i]->m_volModel.loadSettings( _this, "vol" + is ); - if( _this.hasAttribute( "detune" + is ) ) - { - m_osc[i]->m_detuneModel.setValue( _this.attribute( "detune" ).toInt() * 12 ); - } - else - { - m_osc[i]->m_detuneModel.loadSettings( _this, "newdetune" + is ); - } - m_osc[i]->m_panModel.loadSettings( _this, "pan" + is ); - m_osc[i]->m_oscModel.loadSettings( _this, "wavetype" + is ); + const auto is = QString::number(i); - if( _this.hasAttribute( "newharmonic" + is ) ) + m_osc[i]->m_volModel.loadSettings(elem, "vol" + is); + + if (elem.hasAttribute("detune" + is) || !elem.firstChildElement("detune" + is).isNull()) { - m_osc[i]->m_harmModel.loadSettings( _this, "newharmonic" + is ); + m_osc[i]->m_detuneModel.loadSettings(elem, "detune" + is); + m_osc[i]->m_detuneModel.setValue(m_osc[i]->m_detuneModel.value() * 12); // compat } else { - m_osc[i]->m_harmModel.setValue( static_cast( i ) ); + m_osc[i]->m_detuneModel.loadSettings(elem, "newdetune" + is); + } + + m_osc[i]->m_panModel.loadSettings(elem, "pan" + is); + m_osc[i]->m_oscModel.loadSettings(elem, "wavetype" + is); + + if (elem.hasAttribute("newharmonic" + is) || !elem.firstChildElement("newharmonic" + is).isNull()) + { + m_osc[i]->m_harmModel.loadSettings(elem, "newharmonic" + is); + } + else + { + m_osc[i]->m_harmModel.setValue(static_cast(i)); } } - m_volModel.loadSettings( _this, "vol" ); - m_fx1Model.loadSettings( _this, "foldback" ); + m_volModel.loadSettings(elem, "vol"); + m_fx1Model.loadSettings(elem, "foldback"); } @@ -231,7 +227,7 @@ void OrganicInstrument::playNote( NotePlayHandle * _n, const fpp_t frames = _n->framesLeftForCurrentPeriod(); const f_cnt_t offset = _n->noteOffset(); - if( _n->totalFramesPlayed() == 0 || _n->m_pluginData == nullptr ) + if (!_n->m_pluginData) { auto oscs_l = std::array{}; auto oscs_r = std::array{}; @@ -409,7 +405,7 @@ class OrganicKnob : public Knob { public: OrganicKnob( QWidget * _parent ) : - Knob( knobStyled, _parent ) + Knob( KnobType::Styled, _parent ) { setFixedSize( 21, 21 ); } @@ -512,7 +508,7 @@ void OrganicInstrumentView::modelChanged() oscKnob->setHintText( tr( "Osc %1 waveform:" ).arg( i + 1 ), QString() ); // setup volume-knob - auto volKnob = new Knob(knobStyled, this); + auto volKnob = new Knob(KnobType::Styled, this); volKnob->setVolumeKnob( true ); volKnob->move( x + i * colWidth, y + rowHeight*1 ); volKnob->setFixedSize( 21, 21 ); @@ -566,7 +562,7 @@ void OrganicInstrumentView::updateKnobHint() OscillatorObject::OscillatorObject( Model * _parent, int _index ) : Model( _parent ), - m_waveShape( Oscillator::SineWave, 0, Oscillator::NumWaveShapes-1, this ), + m_waveShape( static_cast(Oscillator::WaveShape::Sine), 0, Oscillator::NumWaveShapes-1, this ), m_oscModel( 0.0f, 0.0f, 5.0f, 1.0f, this, tr( "Osc %1 waveform" ).arg( _index + 1 ) ), m_harmModel( static_cast( _index ), 0.0f, 17.0f, 1.0f, @@ -588,15 +584,15 @@ void OscillatorObject::oscButtonChanged() static auto shapes = std::array { - Oscillator::SineWave, - Oscillator::SawWave, - Oscillator::SquareWave, - Oscillator::TriangleWave, - Oscillator::MoogSawWave, - Oscillator::ExponentialWave + Oscillator::WaveShape::Sine, + Oscillator::WaveShape::Saw, + Oscillator::WaveShape::Square, + Oscillator::WaveShape::Triangle, + Oscillator::WaveShape::MoogSaw, + Oscillator::WaveShape::Exponential } ; - m_waveShape.setValue( shapes[(int)roundf( m_oscModel.value() )] ); + m_waveShape.setValue( static_cast(shapes[(int)roundf( m_oscModel.value() )]) ); } diff --git a/plugins/Organic/Organic.h b/plugins/Organic/Organic.h index 057a4a5b4..6c53e84ec 100644 --- a/plugins/Organic/Organic.h +++ b/plugins/Organic/Organic.h @@ -22,9 +22,8 @@ * */ - -#ifndef ORGANIC_H -#define ORGANIC_H +#ifndef LMMS_ORGANIC_H +#define LMMS_ORGANIC_H #include @@ -131,8 +130,8 @@ public: void deleteNotePluginData( NotePlayHandle * _n ) override; - void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; - void loadSettings( const QDomElement & _this ) override; + void saveSettings(QDomDocument& doc, QDomElement& elem) override; + void loadSettings(const QDomElement& elem) override; QString nodeName() const override; @@ -239,4 +238,4 @@ protected slots: } // namespace lmms -#endif +#endif // LMMS_ORGANIC_H diff --git a/plugins/Patman/Patman.cpp b/plugins/Patman/Patman.cpp index a8f75db60..a2b829940 100644 --- a/plugins/Patman/Patman.cpp +++ b/plugins/Patman/Patman.cpp @@ -61,7 +61,7 @@ Plugin::Descriptor PLUGIN_EXPORT patman_plugin_descriptor = "GUS-compatible patch instrument" ), "Javier Serrano Polo ", 0x0100, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader( "logo" ), "pat", nullptr, @@ -144,7 +144,7 @@ void PatmanInstrument::playNote( NotePlayHandle * _n, const fpp_t frames = _n->framesLeftForCurrentPeriod(); const f_cnt_t offset = _n->noteOffset(); - if( !_n->m_pluginData ) + if (!_n->m_pluginData) { selectSample( _n ); } @@ -154,7 +154,7 @@ void PatmanInstrument::playNote( NotePlayHandle * _n, hdata->sample->frequency(); if( hdata->sample->play( _working_buffer + offset, hdata->state, frames, - play_freq, m_loopedModel.value() ? SampleBuffer::LoopOn : SampleBuffer::LoopOff ) ) + play_freq, m_loopedModel.value() ? SampleBuffer::LoopMode::On : SampleBuffer::LoopMode::Off ) ) { applyRelease( _working_buffer, _n ); instrumentTrack()->processAudioBuffer( _working_buffer, @@ -201,8 +201,8 @@ void PatmanInstrument::setFile( const QString & _patch_file, bool _rename ) // named it self m_patchFile = PathUtil::toShortestRelative( _patch_file ); - LoadErrors error = loadPatch( PathUtil::toAbsolute( _patch_file ) ); - if( error ) + LoadError error = loadPatch( PathUtil::toAbsolute( _patch_file ) ); + if( error != LoadError::OK ) { printf("Load error\n"); } @@ -213,7 +213,7 @@ void PatmanInstrument::setFile( const QString & _patch_file, bool _rename ) -PatmanInstrument::LoadErrors PatmanInstrument::loadPatch( +PatmanInstrument::LoadError PatmanInstrument::loadPatch( const QString & _filename ) { unloadCurrentPatch(); @@ -222,7 +222,7 @@ PatmanInstrument::LoadErrors PatmanInstrument::loadPatch( if( !fd ) { perror( "fopen" ); - return( LoadOpen ); + return( LoadError::Open ); } auto header = std::array{}; @@ -232,19 +232,19 @@ PatmanInstrument::LoadErrors PatmanInstrument::loadPatch( && memcmp(header.data(), "GF1PATCH100\0ID#000002", 22))) { fclose( fd ); - return( LoadNotGUS ); + return( LoadError::NotGUS ); } if( header[82] != 1 && header[82] != 0 ) { fclose( fd ); - return( LoadInstruments ); + return( LoadError::Instruments ); } if( header[151] != 1 && header[151] != 0 ) { fclose( fd ); - return( LoadLayers ); + return( LoadError::Layers ); } int sample_count = header[198]; @@ -256,14 +256,14 @@ PatmanInstrument::LoadErrors PatmanInstrument::loadPatch( if ( fseek( fd, x, SEEK_CUR ) == -1 ) \ { \ fclose( fd ); \ - return( LoadIO ); \ + return( LoadError::IO ); \ } #define READ_SHORT( x ) \ if ( fread( &tmpshort, 2, 1, fd ) != 1 ) \ { \ fclose( fd ); \ - return( LoadIO ); \ + return( LoadError::IO ); \ } \ x = (unsigned short)swap16IfBE( tmpshort ); @@ -271,7 +271,7 @@ PatmanInstrument::LoadErrors PatmanInstrument::loadPatch( if ( fread( &x, 4, 1, fd ) != 1 ) \ { \ fclose( fd ); \ - return( LoadIO ); \ + return( LoadError::IO ); \ } \ x = (unsigned)swap32IfBE( x ); @@ -295,7 +295,7 @@ PatmanInstrument::LoadErrors PatmanInstrument::loadPatch( if ( fread( &modes, 1, 1, fd ) != 1 ) { fclose( fd ); - return( LoadIO ); + return( LoadError::IO ); } // skip scale frequency, scale factor, reserved space SKIP_BYTES( 2 + 2 + 36 ); @@ -313,7 +313,7 @@ PatmanInstrument::LoadErrors PatmanInstrument::loadPatch( { delete[] wave_samples; fclose( fd ); - return( LoadIO ); + return( LoadError::IO ); } sample = swap16IfBE( sample ); if( modes & MODES_UNSIGNED ) @@ -337,7 +337,7 @@ PatmanInstrument::LoadErrors PatmanInstrument::loadPatch( { delete[] wave_samples; fclose( fd ); - return( LoadIO ); + return( LoadError::IO ); } if( modes & MODES_UNSIGNED ) { @@ -374,7 +374,7 @@ PatmanInstrument::LoadErrors PatmanInstrument::loadPatch( delete[] data; } fclose( fd ); - return( LoadOK ); + return( LoadError::OK ); } diff --git a/plugins/Patman/Patman.h b/plugins/Patman/Patman.h index acdf4f7ef..3a15db5f3 100644 --- a/plugins/Patman/Patman.h +++ b/plugins/Patman/Patman.h @@ -98,17 +98,17 @@ private: BoolModel m_tunedModel; - enum LoadErrors + enum class LoadError { - LoadOK, - LoadOpen, - LoadNotGUS, - LoadInstruments, - LoadLayers, - LoadIO + OK, + Open, + NotGUS, + Instruments, + Layers, + IO } ; - LoadErrors loadPatch( const QString & _filename ); + LoadError loadPatch( const QString & _filename ); void unloadCurrentPatch(); void selectSample( NotePlayHandle * _n ); diff --git a/plugins/PeakControllerEffect/PeakControllerEffect.cpp b/plugins/PeakControllerEffect/PeakControllerEffect.cpp index d32a22320..7aff6f803 100644 --- a/plugins/PeakControllerEffect/PeakControllerEffect.cpp +++ b/plugins/PeakControllerEffect/PeakControllerEffect.cpp @@ -48,7 +48,7 @@ Plugin::Descriptor PLUGIN_EXPORT peakcontrollereffect_plugin_descriptor = "Plugin for controlling knobs with sound peaks" ), "Paul Giblock ", 0x0100, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader("logo"), nullptr, nullptr, @@ -76,7 +76,7 @@ PeakControllerEffect::PeakControllerEffect( { Engine::getSong()->addController( m_autoController ); } - PeakController::s_effects.append( this ); + PeakController::s_effects.push_back(this); } @@ -84,11 +84,11 @@ PeakControllerEffect::PeakControllerEffect( PeakControllerEffect::~PeakControllerEffect() { - int idx = PeakController::s_effects.indexOf( this ); - if( idx >= 0 ) + auto it = std::find(PeakController::s_effects.begin(), PeakController::s_effects.end(), this); + if (it != PeakController::s_effects.end()) { - PeakController::s_effects.remove( idx ); - Engine::getSong()->removeController( m_autoController ); + PeakController::s_effects.erase(it); + Engine::getSong()->removeController(m_autoController); } } diff --git a/plugins/PeakControllerEffect/PeakControllerEffectControlDialog.cpp b/plugins/PeakControllerEffect/PeakControllerEffectControlDialog.cpp index 69566a86c..e44d5bcc2 100644 --- a/plugins/PeakControllerEffect/PeakControllerEffectControlDialog.cpp +++ b/plugins/PeakControllerEffect/PeakControllerEffectControlDialog.cpp @@ -49,32 +49,32 @@ PeakControllerEffectControlDialog::PeakControllerEffectControlDialog( setPalette( pal ); setFixedSize( 240, 80 ); - m_baseKnob = new Knob( knobBright_26, this ); + m_baseKnob = new Knob( KnobType::Bright26, this ); m_baseKnob->setLabel( tr( "BASE" ) ); m_baseKnob->setModel( &_controls->m_baseModel ); m_baseKnob->setHintText( tr( "Base:" ) , "" ); - m_amountKnob = new Knob( knobBright_26, this ); + m_amountKnob = new Knob( KnobType::Bright26, this ); m_amountKnob->setLabel( tr( "AMNT" ) ); m_amountKnob->setModel( &_controls->m_amountModel ); m_amountKnob->setHintText( tr( "Modulation amount:" ) , "" ); - m_amountMultKnob = new Knob( knobBright_26, this ); + m_amountMultKnob = new Knob( KnobType::Bright26, this ); m_amountMultKnob->setLabel( tr( "MULT" ) ); m_amountMultKnob->setModel( &_controls->m_amountMultModel ); m_amountMultKnob->setHintText( tr( "Amount multiplicator:" ) , "" ); - m_attackKnob = new Knob( knobBright_26, this ); + m_attackKnob = new Knob( KnobType::Bright26, this ); m_attackKnob->setLabel( tr( "ATCK" ) ); m_attackKnob->setModel( &_controls->m_attackModel ); m_attackKnob->setHintText( tr( "Attack:" ) , "" ); - m_decayKnob = new Knob( knobBright_26, this ); + m_decayKnob = new Knob( KnobType::Bright26, this ); m_decayKnob->setLabel( tr( "DCAY" ) ); m_decayKnob->setModel( &_controls->m_decayModel ); m_decayKnob->setHintText( tr( "Release:" ) , "" ); - m_tresholdKnob = new Knob( knobBright_26, this ); + m_tresholdKnob = new Knob( KnobType::Bright26, this ); m_tresholdKnob->setLabel( tr( "TRSH" ) ); m_tresholdKnob->setModel( &_controls->m_tresholdModel ); m_tresholdKnob->setHintText( tr( "Treshold:" ) , "" ); diff --git a/plugins/ReverbSC/ReverbSC.cpp b/plugins/ReverbSC/ReverbSC.cpp index e8dec8fd7..9006f8c9f 100644 --- a/plugins/ReverbSC/ReverbSC.cpp +++ b/plugins/ReverbSC/ReverbSC.cpp @@ -42,7 +42,7 @@ Plugin::Descriptor PLUGIN_EXPORT reverbsc_plugin_descriptor = QT_TRANSLATE_NOOP( "PluginBrowser", "Reverb algorithm by Sean Costello" ), "Paul Batchelor", 0x0123, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader( "logo" ), nullptr, nullptr, diff --git a/plugins/ReverbSC/ReverbSCControlDialog.cpp b/plugins/ReverbSC/ReverbSCControlDialog.cpp index c9ddef384..615d3823e 100644 --- a/plugins/ReverbSC/ReverbSCControlDialog.cpp +++ b/plugins/ReverbSC/ReverbSCControlDialog.cpp @@ -42,25 +42,25 @@ ReverbSCControlDialog::ReverbSCControlDialog( ReverbSCControls* controls ) : setPalette( pal ); setFixedSize( 185, 55 ); - auto inputGainKnob = new Knob(knobBright_26, this); + auto inputGainKnob = new Knob(KnobType::Bright26, this); inputGainKnob -> move( 16, 10 ); inputGainKnob->setModel( &controls->m_inputGainModel ); inputGainKnob->setLabel( tr( "Input" ) ); inputGainKnob->setHintText( tr( "Input gain:" ) , "dB" ); - auto sizeKnob = new Knob(knobBright_26, this); + auto sizeKnob = new Knob(KnobType::Bright26, this); sizeKnob -> move( 57, 10 ); sizeKnob->setModel( &controls->m_sizeModel ); sizeKnob->setLabel( tr( "Size" ) ); sizeKnob->setHintText( tr( "Size:" ) , "" ); - auto colorKnob = new Knob(knobBright_26, this); + auto colorKnob = new Knob(KnobType::Bright26, this); colorKnob -> move( 98, 10 ); colorKnob->setModel( &controls->m_colorModel ); colorKnob->setLabel( tr( "Color" ) ); colorKnob->setHintText( tr( "Color:" ) , "" ); - auto outputGainKnob = new Knob(knobBright_26, this); + auto outputGainKnob = new Knob(KnobType::Bright26, this); outputGainKnob -> move( 139, 10 ); outputGainKnob->setModel( &controls->m_outputGainModel ); outputGainKnob->setLabel( tr( "Output" ) ); diff --git a/plugins/Sf2Player/Sf2Player.cpp b/plugins/Sf2Player/Sf2Player.cpp index ab3729f7d..d46af5e4f 100644 --- a/plugins/Sf2Player/Sf2Player.cpp +++ b/plugins/Sf2Player/Sf2Player.cpp @@ -30,6 +30,7 @@ #include #include +#include "ArrayVector.h" #include "AudioEngine.h" #include "ConfigManager.h" #include "FileDialog.h" @@ -63,7 +64,7 @@ Plugin::Descriptor PLUGIN_EXPORT sf2player_plugin_descriptor = QT_TRANSLATE_NOOP( "PluginBrowser", "Player for SoundFont files" ), "Paul Giblock ", 0x0100, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader( "logo" ), "sf2,sf3", nullptr, @@ -71,17 +72,47 @@ Plugin::Descriptor PLUGIN_EXPORT sf2player_plugin_descriptor = } +/** + * A non-owning reference to a single FluidSynth voice, for tracking whether the + * referenced voice is still the same voice that was passed to the constructor. + */ +class FluidVoice +{ +public: + //! Create a reference to the voice currently pointed at by `voice`. + explicit FluidVoice(fluid_voice_t* voice) : + m_voice{voice}, + m_id{fluid_voice_get_id(voice)} + { } + + //! Get a pointer to the referenced voice. + fluid_voice_t* get() const noexcept { return m_voice; } + + //! Test whether this object still refers to the original voice. + bool isValid() const + { + return fluid_voice_get_id(m_voice) == m_id && fluid_voice_is_playing(m_voice); + } + +private: + fluid_voice_t* m_voice; + unsigned int m_id; +}; struct Sf2PluginData { int midiNote; int lastPanning; float lastVelocity; - fluid_voice_t * fluidVoice; + // The soundfonts I checked used at most two voices per note, so space for + // four should be safe. This may need to be increased if a soundfont with + // more voices per note is found. + ArrayVector fluidVoices; bool isNew; f_cnt_t offset; bool noteOffSent; -} ; + panning_t panning; +}; @@ -200,8 +231,8 @@ Sf2Instrument::Sf2Instrument( InstrumentTrack * _instrument_track ) : Sf2Instrument::~Sf2Instrument() { Engine::audioEngine()->removePlayHandlesOfTypes( instrumentTrack(), - PlayHandle::TypeNotePlayHandle - | PlayHandle::TypeInstrumentPlayHandle ); + PlayHandle::Type::NotePlayHandle + | PlayHandle::Type::InstrumentPlayHandle ); freeFont(); delete_fluid_synth( m_synth ); delete_fluid_settings( m_settings ); @@ -616,7 +647,7 @@ void Sf2Instrument::reloadSynth() m_synthMutex.lock(); if( Engine::audioEngine()->currentQualitySettings().interpolation >= - AudioEngine::qualitySettings::Interpolation_SincFastest ) + AudioEngine::qualitySettings::Interpolation::SincFastest ) { fluid_synth_set_interp_method( m_synth, -1, FLUID_INTERP_7THORDER ); } @@ -663,8 +694,6 @@ void Sf2Instrument::playNote( NotePlayHandle * _n, sampleFrame * ) return; } - const f_cnt_t tfp = _n->totalFramesPlayed(); - int masterPitch = instrumentTrack()->useMasterPitchModel()->value() ? Engine::getSong()->masterPitch() : 0; int baseNote = instrumentTrack()->baseNoteModel()->value(); int midiNote = _n->midiKey() - baseNote + DefaultBaseKey + masterPitch; @@ -675,7 +704,7 @@ void Sf2Instrument::playNote( NotePlayHandle * _n, sampleFrame * ) return; } - if (tfp == 0) + if (!_n->m_pluginData) { const int baseVelocity = instrumentTrack()->midiPort()->baseVelocity(); @@ -683,10 +712,10 @@ void Sf2Instrument::playNote( NotePlayHandle * _n, sampleFrame * ) pluginData->midiNote = midiNote; pluginData->lastPanning = 0; pluginData->lastVelocity = _n->midiVelocity( baseVelocity ); - pluginData->fluidVoice = nullptr; pluginData->isNew = true; pluginData->offset = _n->offset(); pluginData->noteOffSent = false; + pluginData->panning = _n->getPanning(); _n->m_pluginData = pluginData; @@ -705,6 +734,17 @@ void Sf2Instrument::playNote( NotePlayHandle * _n, sampleFrame * ) m_playingNotes.append( _n ); m_playingNotesMutex.unlock(); } + + // Update the pitch of all the voices + if (const auto data = static_cast(_n->m_pluginData)) { + const auto detuning = _n->currentDetuning(); + for (const auto& voice : data->fluidVoices) { + if (voice.isValid()) { + fluid_voice_gen_set(voice.get(), GEN_COARSETUNE, detuning); + fluid_voice_update_param(voice.get(), GEN_COARSETUNE); + } + } + } } @@ -717,35 +757,47 @@ void Sf2Instrument::noteOn( Sf2PluginData * n ) const int poly = fluid_synth_get_polyphony( m_synth ); #ifndef _MSC_VER fluid_voice_t* voices[poly]; - unsigned int id[poly]; #else const auto voices = static_cast(_alloca(poly * sizeof(fluid_voice_t*))); - const auto id = static_cast(_alloca(poly * sizeof(unsigned int))); #endif - fluid_synth_get_voicelist( m_synth, voices, poly, -1 ); - for( int i = 0; i < poly; ++i ) - { - id[i] = 0; - } - for( int i = 0; i < poly && voices[i]; ++i ) - { - id[i] = fluid_voice_get_id( voices[i] ); - } fluid_synth_noteon( m_synth, m_channel, n->midiNote, n->lastVelocity ); - // get new voice and save it - fluid_synth_get_voicelist( m_synth, voices, poly, -1 ); - for( int i = 0; i < poly && voices[i]; ++i ) + // Get any new voices and store them in the plugin data + fluid_synth_get_voicelist(m_synth, voices, poly, -1); + for (int i = 0; i < poly && voices[i] && !n->fluidVoices.full(); ++i) { - const unsigned int newID = fluid_voice_get_id( voices[i] ); - if( id[i] != newID || newID == 0 ) - { - n->fluidVoice = voices[i]; - break; + const auto voice = voices[i]; + // FluidSynth stops voices with the same channel and pitch upon note-on, + // so voices with the current channel and pitch are playing this note. + if (fluid_voice_get_channel(voice) == m_channel + && fluid_voice_get_key(voice) == n->midiNote + && fluid_voice_is_on(voice) + ) { + n->fluidVoices.emplace_back(voices[i]); } } +#if FLUIDSYNTH_VERSION_MAJOR >= 2 + // Smallest balance value that results in full attenuation of one channel. + // Corresponds to internal FluidSynth macro `FLUID_CB_AMP_SIZE`. + constexpr static auto maxBalance = 1441.f; + // Convert panning from linear to exponential for FluidSynth + const auto panning = n->panning; + const auto factor = 1.f - std::abs(panning) / static_cast(PanningRight); + const auto balance = std::copysign( + factor <= 0 ? maxBalance : std::min(-200.f * std::log10(factor), maxBalance), + panning + ); + // Set note panning on all the voices + for (const auto& voice : n->fluidVoices) { + if (voice.isValid()) { + fluid_voice_gen_set(voice.get(), GEN_CUSTOM_BALANCE, balance); + fluid_voice_update_param(voice.get(), GEN_CUSTOM_BALANCE); + } + } +#endif + m_synthMutex.unlock(); m_notesRunningMutex.lock(); @@ -861,6 +913,7 @@ void Sf2Instrument::play( sampleFrame * _working_buffer ) void Sf2Instrument::renderFrames( f_cnt_t frames, sampleFrame * buf ) { m_synthMutex.lock(); + fluid_synth_get_gain(m_synth); // This flushes voice updates as a side effect if( m_internalSampleRate < Engine::audioEngine()->processingSampleRate() && m_srcState != nullptr ) { @@ -938,7 +991,7 @@ class Sf2Knob : public Knob { public: Sf2Knob( QWidget * _parent ) : - Knob( knobStyled, _parent ) + Knob( KnobType::Styled, _parent ) { setFixedSize( 31, 38 ); } diff --git a/plugins/Sf2Player/Sf2Player.h b/plugins/Sf2Player/Sf2Player.h index 5a88d0f95..bd7fa1b81 100644 --- a/plugins/Sf2Player/Sf2Player.h +++ b/plugins/Sf2Player/Sf2Player.h @@ -88,7 +88,7 @@ public: Flags flags() const override { - return IsSingleStreamed; + return Flag::IsSingleStreamed; } gui::PluginView* instantiateView( QWidget * _parent ) override; diff --git a/plugins/Sfxr/Sfxr.cpp b/plugins/Sfxr/Sfxr.cpp index d97217446..fc39ea0fa 100644 --- a/plugins/Sfxr/Sfxr.cpp +++ b/plugins/Sfxr/Sfxr.cpp @@ -67,7 +67,7 @@ Plugin::Descriptor PLUGIN_EXPORT sfxr_plugin_descriptor = "LMMS port of sfxr" ), "Wong Cho Ching", 0x0100, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader( "logo" ), nullptr, nullptr, @@ -350,7 +350,7 @@ SfxrInstrument::SfxrInstrument( InstrumentTrack * _instrument_track ) : m_lpFilResoModel(0.0f, this, "LP Filter Resonance"), m_hpFilCutModel(0.0f, this, "HP Filter Cutoff"), m_hpFilCutSweepModel(0.0f, this, "HP Filter Cutoff Sweep"), - m_waveFormModel( SQR_WAVE, 0, WAVES_NUM-1, this, tr( "Wave" ) ) + m_waveFormModel( static_cast(SfxrWave::Square), 0, NumSfxrWaves-1, this, tr( "Wave" ) ) { } @@ -446,9 +446,9 @@ void SfxrInstrument::playNote( NotePlayHandle * _n, sampleFrame * _working_buffe { float currentSampleRate = Engine::audioEngine()->processingSampleRate(); - fpp_t frameNum = _n->framesLeftForCurrentPeriod(); - const f_cnt_t offset = _n->noteOffset(); - if ( _n->totalFramesPlayed() == 0 || _n->m_pluginData == nullptr ) + fpp_t frameNum = _n->framesLeftForCurrentPeriod(); + const f_cnt_t offset = _n->noteOffset(); + if (!_n->m_pluginData) { _n->m_pluginData = new SfxrSynth( this ); } @@ -549,7 +549,7 @@ class SfxrKnob : public Knob { public: SfxrKnob( QWidget * _parent ) : - Knob( knobStyled, _parent ) + Knob( KnobType::Styled, _parent ) { setFixedSize( 20, 20 ); setCenterPointX( 10.0 ); diff --git a/plugins/Sfxr/Sfxr.h b/plugins/Sfxr/Sfxr.h index 632ccfebd..edec0ba6f 100644 --- a/plugins/Sfxr/Sfxr.h +++ b/plugins/Sfxr/Sfxr.h @@ -37,10 +37,11 @@ namespace lmms { -enum SfxrWaves +enum class SfxrWave { - SQR_WAVE, SAW_WAVE, SINE_WAVE, NOISE_WAVE, WAVES_NUM + Square, Saw, Sine, Noise, Count }; +constexpr auto NumSfxrWaves = static_cast(SfxrWave::Count); const int WAVEFORM_BASE_X = 20; const int WAVEFORM_BASE_Y = 15; diff --git a/plugins/Sid/SidInstrument.cpp b/plugins/Sid/SidInstrument.cpp index 6e7473492..f663c3b69 100644 --- a/plugins/Sid/SidInstrument.cpp +++ b/plugins/Sid/SidInstrument.cpp @@ -83,7 +83,7 @@ Plugin::Descriptor PLUGIN_EXPORT sid_plugin_descriptor = "Csaba Hruska " "Attila Herman ", 0x0100, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader( "logo" ), nullptr, nullptr, @@ -105,7 +105,7 @@ VoiceObject::VoiceObject( Model * _parent, int _idx ) : tr( "Voice %1 release" ).arg( _idx+1 ) ), m_coarseModel( 0.0f, -24.0, 24.0, 1.0f, this, tr( "Voice %1 coarse detuning" ).arg( _idx+1 ) ), - m_waveFormModel( TriangleWave, 0, NumWaveShapes-1, this, + m_waveFormModel( static_cast(WaveForm::Triangle), 0, NumWaveShapes-1, this, tr( "Voice %1 wave shape" ).arg( _idx+1 ) ), m_syncModel( false, this, tr( "Voice %1 sync" ).arg( _idx+1 ) ), @@ -121,12 +121,12 @@ SidInstrument::SidInstrument( InstrumentTrack * _instrument_track ) : // filter m_filterFCModel( 1024.0f, 0.0f, 2047.0f, 1.0f, this, tr( "Cutoff frequency" ) ), m_filterResonanceModel( 8.0f, 0.0f, 15.0f, 1.0f, this, tr( "Resonance" ) ), - m_filterModeModel( LowPass, 0, NumFilterTypes-1, this, tr( "Filter type" )), + m_filterModeModel( static_cast(FilterType::LowPass), 0, NumFilterTypes-1, this, tr( "Filter type" )), // misc m_voice3OffModel( false, this, tr( "Voice 3 off" ) ), m_volumeModel( 15.0f, 0.0f, 15.0f, 1.0f, this, tr( "Volume" ) ), - m_chipModel( sidMOS8580, 0, NumChipModels-1, this, tr( "Chip model" ) ) + m_chipModel( static_cast(ChipModel::MOS8580), 0, NumChipModels-1, this, tr( "Chip model" ) ) { for( int i = 0; i < 3; ++i ) { @@ -297,12 +297,10 @@ static int sid_fillbuffer(unsigned char* sidreg, SID *sid, int tdelta, short *pt void SidInstrument::playNote( NotePlayHandle * _n, sampleFrame * _working_buffer ) { - const f_cnt_t tfp = _n->totalFramesPlayed(); - const int clockrate = C64_PAL_CYCLES_PER_SEC; const int samplerate = Engine::audioEngine()->processingSampleRate(); - if ( tfp == 0 ) + if (!_n->m_pluginData) { SID *sid = new SID(); sid->set_sampling_parameters( clockrate, SAMPLE_FAST, samplerate ); @@ -325,7 +323,7 @@ void SidInstrument::playNote( NotePlayHandle * _n, reg = 0x00; } - if( (ChipModel)m_chipModel.value() == sidMOS6581 ) + if( (ChipModel)m_chipModel.value() == ChipModel::MOS6581 ) { sid->set_chip_model( MOS6581 ); } @@ -362,13 +360,13 @@ void SidInstrument::playNote( NotePlayHandle * _n, data8 += m_voice[i]->m_syncModel.value()?2:0; data8 += m_voice[i]->m_ringModModel.value()?4:0; data8 += m_voice[i]->m_testModel.value()?8:0; - switch( m_voice[i]->m_waveFormModel.value() ) + switch( static_cast(m_voice[i]->m_waveFormModel.value()) ) { default: break; - case VoiceObject::NoiseWave: data8 += 128; break; - case VoiceObject::SquareWave: data8 += 64; break; - case VoiceObject::SawWave: data8 += 32; break; - case VoiceObject::TriangleWave: data8 += 16; break; + case VoiceObject::WaveForm::Noise: data8 += 128; break; + case VoiceObject::WaveForm::Square: data8 += 64; break; + case VoiceObject::WaveForm::Saw: data8 += 32; break; + case VoiceObject::WaveForm::Triangle: data8 += 16; break; } sidreg[base+4] = data8&0x00FF; // ad @@ -408,12 +406,12 @@ void SidInstrument::playNote( NotePlayHandle * _n, data8 = data16&0x000F; data8 += m_voice3OffModel.value()?128:0; - switch( m_filterModeModel.value() ) + switch( static_cast(m_filterModeModel.value()) ) { default: break; - case LowPass: data8 += 16; break; - case BandPass: data8 += 32; break; - case HighPass: data8 += 64; break; + case FilterType::LowPass: data8 += 16; break; + case FilterType::BandPass: data8 += 32; break; + case FilterType::HighPass: data8 += 64; break; } sidreg[24] = data8&0x00FF; @@ -461,7 +459,7 @@ class sidKnob : public Knob { public: sidKnob( QWidget * _parent ) : - Knob( knobStyled, _parent ) + Knob( KnobType::Styled, _parent ) { setFixedSize( 16, 16 ); setCenterPointX( 7.5 ); diff --git a/plugins/Sid/SidInstrument.h b/plugins/Sid/SidInstrument.h index 203e52e7b..53efa8942 100644 --- a/plugins/Sid/SidInstrument.h +++ b/plugins/Sid/SidInstrument.h @@ -50,13 +50,15 @@ class VoiceObject : public Model Q_OBJECT MM_OPERATORS public: - enum WaveForm { - SquareWave = 0, - TriangleWave, - SawWave, - NoiseWave, - NumWaveShapes + enum class WaveForm { + Square = 0, + Triangle, + Saw, + Noise, + Count }; + constexpr static auto NumWaveShapes = static_cast(WaveForm::Count); + VoiceObject( Model * _parent, int _idx ); ~VoiceObject() override = default; @@ -82,19 +84,20 @@ class SidInstrument : public Instrument { Q_OBJECT public: - enum FilerType { + enum class FilterType { HighPass = 0, BandPass, LowPass, - NumFilterTypes + Count }; + constexpr static auto NumFilterTypes = static_cast(FilterType::Count); - enum ChipModel { - sidMOS6581 = 0, - sidMOS8580, - NumChipModels + enum class ChipModel { + MOS6581 = 0, + MOS8580, + Count }; - + constexpr static auto NumChipModels = static_cast(ChipModel::Count); SidInstrument( InstrumentTrack * _instrument_track ); ~SidInstrument() override = default; diff --git a/plugins/SpectrumAnalyzer/Analyzer.cpp b/plugins/SpectrumAnalyzer/Analyzer.cpp index de4ac8c68..0bbada7db 100644 --- a/plugins/SpectrumAnalyzer/Analyzer.cpp +++ b/plugins/SpectrumAnalyzer/Analyzer.cpp @@ -48,7 +48,7 @@ extern "C" { QT_TRANSLATE_NOOP("PluginBrowser", "A graphical spectrum analyzer."), "Martin Pavelek ", 0x0112, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader("logo"), nullptr, nullptr, diff --git a/plugins/SpectrumAnalyzer/SaControls.cpp b/plugins/SpectrumAnalyzer/SaControls.cpp index 1ebfcdca3..d14176ed3 100644 --- a/plugins/SpectrumAnalyzer/SaControls.cpp +++ b/plugins/SpectrumAnalyzer/SaControls.cpp @@ -66,7 +66,7 @@ SaControls::SaControls(Analyzer *effect) : m_zeroPaddingModel(2.0f, 0.0f, 4.0f, 1.0f, this, tr("FFT zero padding")) { // Frequency and amplitude ranges; order must match - // FREQUENCY_RANGES and AMPLITUDE_RANGES defined in SaControls.h + // FrequencyRange and AmplitudeRange defined in SaControls.h m_freqRangeModel.addItem(tr("Full (auto)")); m_freqRangeModel.addItem(tr("Audible")); m_freqRangeModel.addItem(tr("Bass")); @@ -99,7 +99,7 @@ SaControls::SaControls(Analyzer *effect) : } m_blockSizeModel.setValue(m_blockSizeModel.findText("2048")); - // Window type order must match FFT_WINDOWS defined in fft_helpers.h + // Window type order must match FFTWindow defined in fft_helpers.h m_windowModel.addItem(tr("Rectangular (Off)")); m_windowModel.addItem(tr("Blackman-Harris (Default)")); m_windowModel.addItem(tr("Hamming")); diff --git a/plugins/SpectrumAnalyzer/SaControlsDialog.cpp b/plugins/SpectrumAnalyzer/SaControlsDialog.cpp index c4fc431b1..eb09c793a 100644 --- a/plugins/SpectrumAnalyzer/SaControlsDialog.cpp +++ b/plugins/SpectrumAnalyzer/SaControlsDialog.cpp @@ -236,7 +236,7 @@ SaControlsDialog::SaControlsDialog(SaControls *controls, SaProcessor *processor) controls_layout->setStretchFactor(advanced_widget, 10); // Peak envelope resolution - auto envelopeResolutionKnob = new Knob(knobSmall_17, this); + auto envelopeResolutionKnob = new Knob(KnobType::Small17, this); envelopeResolutionKnob->setModel(&controls->m_envelopeResolutionModel); envelopeResolutionKnob->setLabel(tr("Envelope res.")); envelopeResolutionKnob->setToolTip(tr("Increase envelope resolution for better details, decrease for better GUI performance.")); @@ -244,7 +244,7 @@ SaControlsDialog::SaControlsDialog(SaControls *controls, SaProcessor *processor) advanced_layout->addWidget(envelopeResolutionKnob, 0, 0, 1, 1, Qt::AlignCenter); // Spectrum graph resolution - auto spectrumResolutionKnob = new Knob(knobSmall_17, this); + auto spectrumResolutionKnob = new Knob(KnobType::Small17, this); spectrumResolutionKnob->setModel(&controls->m_spectrumResolutionModel); spectrumResolutionKnob->setLabel(tr("Spectrum res.")); spectrumResolutionKnob->setToolTip(tr("Increase spectrum resolution for better details, decrease for better GUI performance.")); @@ -252,7 +252,7 @@ SaControlsDialog::SaControlsDialog(SaControls *controls, SaProcessor *processor) advanced_layout->addWidget(spectrumResolutionKnob, 1, 0, 1, 1, Qt::AlignCenter); // Peak falloff speed - auto peakDecayFactorKnob = new Knob(knobSmall_17, this); + auto peakDecayFactorKnob = new Knob(KnobType::Small17, this); peakDecayFactorKnob->setModel(&controls->m_peakDecayFactorModel); peakDecayFactorKnob->setLabel(tr("Falloff factor")); peakDecayFactorKnob->setToolTip(tr("Decrease to make peaks fall faster.")); @@ -260,7 +260,7 @@ SaControlsDialog::SaControlsDialog(SaControls *controls, SaProcessor *processor) advanced_layout->addWidget(peakDecayFactorKnob, 0, 1, 1, 1, Qt::AlignCenter); // Averaging weight - auto averagingWeightKnob = new Knob(knobSmall_17, this); + auto averagingWeightKnob = new Knob(KnobType::Small17, this); averagingWeightKnob->setModel(&controls->m_averagingWeightModel); averagingWeightKnob->setLabel(tr("Averaging weight")); averagingWeightKnob->setToolTip(tr("Decrease to make averaging slower and smoother.")); @@ -268,7 +268,7 @@ SaControlsDialog::SaControlsDialog(SaControls *controls, SaProcessor *processor) advanced_layout->addWidget(averagingWeightKnob, 1, 1, 1, 1, Qt::AlignCenter); // Waterfall history size - auto waterfallHeightKnob = new Knob(knobSmall_17, this); + auto waterfallHeightKnob = new Knob(KnobType::Small17, this); waterfallHeightKnob->setModel(&controls->m_waterfallHeightModel); waterfallHeightKnob->setLabel(tr("Waterfall height")); waterfallHeightKnob->setToolTip(tr("Increase to get slower scrolling, decrease to see fast transitions better. Warning: medium CPU usage.")); @@ -278,7 +278,7 @@ SaControlsDialog::SaControlsDialog(SaControls *controls, SaProcessor *processor) connect(&controls->m_waterfallHeightModel, &FloatModel::dataChanged, [=] {processor->reallocateBuffers();}); // Waterfall gamma correction - auto waterfallGammaKnob = new Knob(knobSmall_17, this); + auto waterfallGammaKnob = new Knob(KnobType::Small17, this); waterfallGammaKnob->setModel(&controls->m_waterfallGammaModel); waterfallGammaKnob->setLabel(tr("Waterfall gamma")); waterfallGammaKnob->setToolTip(tr("Decrease to see very weak signals, increase to get better contrast.")); @@ -286,7 +286,7 @@ SaControlsDialog::SaControlsDialog(SaControls *controls, SaProcessor *processor) advanced_layout->addWidget(waterfallGammaKnob, 1, 2, 1, 1, Qt::AlignCenter); // FFT window overlap - auto windowOverlapKnob = new Knob(knobSmall_17, this); + auto windowOverlapKnob = new Knob(KnobType::Small17, this); windowOverlapKnob->setModel(&controls->m_windowOverlapModel); windowOverlapKnob->setLabel(tr("Window overlap")); windowOverlapKnob->setToolTip(tr("Increase to prevent missing fast transitions arriving near FFT window edges. Warning: high CPU usage.")); @@ -294,7 +294,7 @@ SaControlsDialog::SaControlsDialog(SaControls *controls, SaProcessor *processor) advanced_layout->addWidget(windowOverlapKnob, 0, 3, 1, 1, Qt::AlignCenter); // FFT zero padding - auto zeroPaddingKnob = new Knob(knobSmall_17, this); + auto zeroPaddingKnob = new Knob(KnobType::Small17, this); zeroPaddingKnob->setModel(&controls->m_zeroPaddingModel); zeroPaddingKnob->setLabel(tr("Zero padding")); zeroPaddingKnob->setToolTip(tr("Increase to get smoother-looking spectrum. Warning: high CPU usage.")); diff --git a/plugins/SpectrumAnalyzer/SaProcessor.cpp b/plugins/SpectrumAnalyzer/SaProcessor.cpp index d7a1dd5fb..a79d52bdc 100644 --- a/plugins/SpectrumAnalyzer/SaProcessor.cpp +++ b/plugins/SpectrumAnalyzer/SaProcessor.cpp @@ -58,7 +58,7 @@ SaProcessor::SaProcessor(const SaControls *controls) : m_reallocating(false) { m_fftWindow.resize(m_inBlockSize, 1.0); - precomputeWindow(m_fftWindow.data(), m_inBlockSize, BLACKMAN_HARRIS); + precomputeWindow(m_fftWindow.data(), m_inBlockSize, FFTWindow::BlackmanHarris); m_bufferL.resize(m_inBlockSize, 0); m_bufferR.resize(m_inBlockSize, 0); @@ -402,7 +402,7 @@ void SaProcessor::reallocateBuffers() // allocate new space, create new plan and resize containers m_fftWindow.resize(new_in_size, 1.0); - precomputeWindow(m_fftWindow.data(), new_in_size, (FFT_WINDOWS) m_controls->m_windowModel.value()); + precomputeWindow(m_fftWindow.data(), new_in_size, (FFTWindow) m_controls->m_windowModel.value()); m_bufferL.resize(new_in_size, 0); m_bufferR.resize(new_in_size, 0); m_filteredBufferL.resize(new_fft_size, 0); @@ -448,7 +448,7 @@ void SaProcessor::rebuildWindow() { // computation is done in fft_helpers QMutexLocker lock(&m_dataAccess); - precomputeWindow(m_fftWindow.data(), m_inBlockSize, (FFT_WINDOWS) m_controls->m_windowModel.value()); + precomputeWindow(m_fftWindow.data(), m_inBlockSize, (FFTWindow) m_controls->m_windowModel.value()); } @@ -545,28 +545,28 @@ float SaProcessor::binBandwidth() const float SaProcessor::getFreqRangeMin(bool linear) const { - switch (m_controls->m_freqRangeModel.value()) + switch (static_cast(m_controls->m_freqRangeModel.value())) { - case FRANGE_AUDIBLE: return FRANGE_AUDIBLE_START; - case FRANGE_BASS: return FRANGE_BASS_START; - case FRANGE_MIDS: return FRANGE_MIDS_START; - case FRANGE_HIGH: return FRANGE_HIGH_START; + case FrequencyRange::Audible: return FRANGE_AUDIBLE_START; + case FrequencyRange::Bass: return FRANGE_BASS_START; + case FrequencyRange::Mids: return FRANGE_MIDS_START; + case FrequencyRange::High: return FRANGE_HIGH_START; default: - case FRANGE_FULL: return linear ? 0 : LOWEST_LOG_FREQ; + case FrequencyRange::Full: return linear ? 0 : LOWEST_LOG_FREQ; } } float SaProcessor::getFreqRangeMax() const { - switch (m_controls->m_freqRangeModel.value()) + switch (static_cast(m_controls->m_freqRangeModel.value())) { - case FRANGE_AUDIBLE: return FRANGE_AUDIBLE_END; - case FRANGE_BASS: return FRANGE_BASS_END; - case FRANGE_MIDS: return FRANGE_MIDS_END; - case FRANGE_HIGH: return FRANGE_HIGH_END; + case FrequencyRange::Audible: return FRANGE_AUDIBLE_END; + case FrequencyRange::Bass: return FRANGE_BASS_END; + case FrequencyRange::Mids: return FRANGE_MIDS_END; + case FrequencyRange::High: return FRANGE_HIGH_END; default: - case FRANGE_FULL: return getNyquistFreq(); + case FrequencyRange::Full: return getNyquistFreq(); } } @@ -619,26 +619,26 @@ float SaProcessor::getAmpRangeMin(bool linear) const { // return very low limit to make sure zero gets included at linear grid if (linear) {return -900;} - switch (m_controls->m_ampRangeModel.value()) + switch (static_cast(m_controls->m_ampRangeModel.value())) { - case ARANGE_EXTENDED: return ARANGE_EXTENDED_START; - case ARANGE_SILENT: return ARANGE_SILENT_START; - case ARANGE_LOUD: return ARANGE_LOUD_START; + case AmplitudeRange::Extended: return ARANGE_EXTENDED_START; + case AmplitudeRange::Silent: return ARANGE_SILENT_START; + case AmplitudeRange::Loud: return ARANGE_LOUD_START; default: - case ARANGE_AUDIBLE: return ARANGE_AUDIBLE_START; + case AmplitudeRange::Audible: return ARANGE_AUDIBLE_START; } } float SaProcessor::getAmpRangeMax() const { - switch (m_controls->m_ampRangeModel.value()) + switch (static_cast(m_controls->m_ampRangeModel.value())) { - case ARANGE_EXTENDED: return ARANGE_EXTENDED_END; - case ARANGE_SILENT: return ARANGE_SILENT_END; - case ARANGE_LOUD: return ARANGE_LOUD_END; + case AmplitudeRange::Extended: return ARANGE_EXTENDED_END; + case AmplitudeRange::Silent: return ARANGE_SILENT_END; + case AmplitudeRange::Loud: return ARANGE_LOUD_END; default: - case ARANGE_AUDIBLE: return ARANGE_AUDIBLE_END; + case AmplitudeRange::Audible: return ARANGE_AUDIBLE_END; } } diff --git a/plugins/StereoEnhancer/StereoEnhancer.cpp b/plugins/StereoEnhancer/StereoEnhancer.cpp index 01e55f2de..a7937a2ec 100644 --- a/plugins/StereoEnhancer/StereoEnhancer.cpp +++ b/plugins/StereoEnhancer/StereoEnhancer.cpp @@ -43,7 +43,7 @@ Plugin::Descriptor PLUGIN_EXPORT stereoenhancer_plugin_descriptor = "Plugin for enhancing stereo separation of a stereo input file" ), "Lou Herard ", 0x0100, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader("logo"), nullptr, nullptr, diff --git a/plugins/StereoEnhancer/StereoEnhancerControlDialog.cpp b/plugins/StereoEnhancer/StereoEnhancerControlDialog.cpp index 3f7841706..05c78616e 100644 --- a/plugins/StereoEnhancer/StereoEnhancerControlDialog.cpp +++ b/plugins/StereoEnhancer/StereoEnhancerControlDialog.cpp @@ -40,7 +40,7 @@ StereoEnhancerControlDialog::StereoEnhancerControlDialog( { auto l = new QHBoxLayout(this); - auto widthKnob = new Knob(knobBright_26, this); + auto widthKnob = new Knob(KnobType::Bright26, this); widthKnob->setModel( &_controls->m_widthModel ); widthKnob->setLabel( tr( "WIDTH" ) ); widthKnob->setHintText( tr( "Width:" ) , " samples" ); diff --git a/plugins/StereoMatrix/StereoMatrix.cpp b/plugins/StereoMatrix/StereoMatrix.cpp index 2dff69b77..b96d2e107 100644 --- a/plugins/StereoMatrix/StereoMatrix.cpp +++ b/plugins/StereoMatrix/StereoMatrix.cpp @@ -43,7 +43,7 @@ Plugin::Descriptor PLUGIN_EXPORT stereomatrix_plugin_descriptor = "Plugin for freely manipulating stereo output" ), "Paul Giblock ", 0x0100, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader("logo"), nullptr, nullptr, diff --git a/plugins/StereoMatrix/StereoMatrixControlDialog.cpp b/plugins/StereoMatrix/StereoMatrixControlDialog.cpp index 06ff2a03b..da9a3aa9e 100644 --- a/plugins/StereoMatrix/StereoMatrixControlDialog.cpp +++ b/plugins/StereoMatrix/StereoMatrixControlDialog.cpp @@ -48,22 +48,22 @@ StereoMatrixControlDialog::StereoMatrixControlDialog( PLUGIN_NAME::getIconPixmap( "artwork" ) ); setPalette( pal ); - auto llKnob = new Knob(knobBright_26, this); + auto llKnob = new Knob(KnobType::Bright26, this); llKnob->setModel( &_controls->m_llModel ); llKnob->setHintText( tr( "Left to Left Vol:" ) , "" ); llKnob->move( 10, 79 ); - auto lrKnob = new Knob(knobBright_26, this); + auto lrKnob = new Knob(KnobType::Bright26, this); lrKnob->setModel( &_controls->m_lrModel ); lrKnob->setHintText( tr( "Left to Right Vol:" ) , "" ); lrKnob->move( 48, 79 ); - auto rlKnob = new Knob(knobBright_26, this); + auto rlKnob = new Knob(KnobType::Bright26, this); rlKnob->setModel( &_controls->m_rlModel ); rlKnob->setHintText( tr( "Right to Left Vol:" ) , "" ); rlKnob->move( 85, 79 ); - auto rrKnob = new Knob(knobBright_26, this); + auto rrKnob = new Knob(KnobType::Bright26, this); rrKnob->setModel( &_controls->m_rrModel ); rrKnob->setHintText( tr( "Right to Right Vol:" ) , "" ); rrKnob->move( 123, 79 ); diff --git a/plugins/Stk/Mallets/Mallets.cpp b/plugins/Stk/Mallets/Mallets.cpp index 8aa71d62e..4fb077de5 100644 --- a/plugins/Stk/Mallets/Mallets.cpp +++ b/plugins/Stk/Mallets/Mallets.cpp @@ -59,7 +59,7 @@ Plugin::Descriptor PLUGIN_EXPORT malletsstk_plugin_descriptor = "Tuneful things to bang on" ), "Danny McRae ", 0x0100, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader( "logo" ), nullptr, nullptr, @@ -286,7 +286,7 @@ void MalletsInstrument::playNote( NotePlayHandle * _n, int p = m_presetsModel.value(); const float freq = _n->frequency(); - if ( _n->totalFramesPlayed() == 0 || _n->m_pluginData == nullptr ) + if (!_n->m_pluginData) { // If newer projects, adjust velocity to within stk's limits float velocityAdjust = @@ -409,7 +409,7 @@ MalletsInstrumentView::MalletsInstrumentView( MalletsInstrument * _instrument, connect( &_instrument->m_presetsModel, SIGNAL( dataChanged() ), this, SLOT( changePreset() ) ); - m_spreadKnob = new Knob( knobVintage_32, this ); + m_spreadKnob = new Knob( KnobType::Vintage32, this ); m_spreadKnob->setLabel( tr( "Spread" ) ); m_spreadKnob->move( 190, 140 ); m_spreadKnob->setHintText( tr( "Spread:" ), "" ); @@ -445,27 +445,27 @@ QWidget * MalletsInstrumentView::setupModalBarControls( QWidget * _parent ) auto widget = new QWidget(_parent); widget->setFixedSize( 250, 250 ); - m_hardnessKnob = new Knob( knobVintage_32, widget ); + m_hardnessKnob = new Knob( KnobType::Vintage32, widget ); m_hardnessKnob->setLabel( tr( "Hardness" ) ); m_hardnessKnob->move( 30, 90 ); m_hardnessKnob->setHintText( tr( "Hardness:" ), "" ); - m_positionKnob = new Knob( knobVintage_32, widget ); + m_positionKnob = new Knob( KnobType::Vintage32, widget ); m_positionKnob->setLabel( tr( "Position" ) ); m_positionKnob->move( 110, 90 ); m_positionKnob->setHintText( tr( "Position:" ), "" ); - m_vibratoGainKnob = new Knob( knobVintage_32, widget ); + m_vibratoGainKnob = new Knob( KnobType::Vintage32, widget ); m_vibratoGainKnob->setLabel( tr( "Vibrato gain" ) ); m_vibratoGainKnob->move( 30, 140 ); m_vibratoGainKnob->setHintText( tr( "Vibrato gain:" ), "" ); - m_vibratoFreqKnob = new Knob( knobVintage_32, widget ); + m_vibratoFreqKnob = new Knob( KnobType::Vintage32, widget ); m_vibratoFreqKnob->setLabel( tr( "Vibrato frequency" ) ); m_vibratoFreqKnob->move( 110, 140 ); m_vibratoFreqKnob->setHintText( tr( "Vibrato frequency:" ), "" ); - m_stickKnob = new Knob( knobVintage_32, widget ); + m_stickKnob = new Knob( KnobType::Vintage32, widget ); m_stickKnob->setLabel( tr( "Stick mix" ) ); m_stickKnob->move( 190, 90 ); m_stickKnob->setHintText( tr( "Stick mix:" ), "" ); @@ -481,27 +481,27 @@ QWidget * MalletsInstrumentView::setupTubeBellControls( QWidget * _parent ) auto widget = new QWidget(_parent); widget->setFixedSize( 250, 250 ); - m_modulatorKnob = new Knob( knobVintage_32, widget ); + m_modulatorKnob = new Knob( KnobType::Vintage32, widget ); m_modulatorKnob->setLabel( tr( "Modulator" ) ); m_modulatorKnob->move( 30, 90 ); m_modulatorKnob->setHintText( tr( "Modulator:" ), "" ); - m_crossfadeKnob = new Knob( knobVintage_32, widget ); + m_crossfadeKnob = new Knob( KnobType::Vintage32, widget ); m_crossfadeKnob->setLabel( tr( "Crossfade" ) ); m_crossfadeKnob->move( 110, 90 ); m_crossfadeKnob->setHintText( tr( "Crossfade:" ), "" ); - m_lfoSpeedKnob = new Knob( knobVintage_32, widget ); + m_lfoSpeedKnob = new Knob( KnobType::Vintage32, widget ); m_lfoSpeedKnob->setLabel( tr( "LFO speed" ) ); m_lfoSpeedKnob->move( 30, 140 ); m_lfoSpeedKnob->setHintText( tr( "LFO speed:" ), "" ); - m_lfoDepthKnob = new Knob( knobVintage_32, widget ); + m_lfoDepthKnob = new Knob( KnobType::Vintage32, widget ); m_lfoDepthKnob->setLabel( tr( "LFO depth" ) ); m_lfoDepthKnob->move( 110, 140 ); m_lfoDepthKnob->setHintText( tr( "LFO depth:" ), "" ); - m_adsrKnob = new Knob( knobVintage_32, widget ); + m_adsrKnob = new Knob( KnobType::Vintage32, widget ); m_adsrKnob->setLabel( tr( "ADSR" ) ); m_adsrKnob->move( 190, 90 ); m_adsrKnob->setHintText( tr( "ADSR:" ), "" ); @@ -521,22 +521,22 @@ QWidget * MalletsInstrumentView::setupBandedWGControls( QWidget * _parent ) /* m_strikeLED = new LedCheckBox( tr( "Bowed" ), widget ); m_strikeLED->move( 138, 25 );*/ - m_pressureKnob = new Knob( knobVintage_32, widget ); + m_pressureKnob = new Knob( KnobType::Vintage32, widget ); m_pressureKnob->setLabel( tr( "Pressure" ) ); m_pressureKnob->move( 30, 90 ); m_pressureKnob->setHintText( tr( "Pressure:" ), "" ); -/* m_motionKnob = new Knob( knobVintage_32, widget ); +/* m_motionKnob = new Knob( KnobType::Vintage32, widget ); m_motionKnob->setLabel( tr( "Motion" ) ); m_motionKnob->move( 110, 90 ); m_motionKnob->setHintText( tr( "Motion:" ), "" );*/ - m_velocityKnob = new Knob( knobVintage_32, widget ); + m_velocityKnob = new Knob( KnobType::Vintage32, widget ); m_velocityKnob->setLabel( tr( "Speed" ) ); m_velocityKnob->move( 30, 140 ); m_velocityKnob->setHintText( tr( "Speed:" ), "" ); -/* m_vibratoKnob = new Knob( knobVintage_32, widget, tr( "Vibrato" ) ); +/* m_vibratoKnob = new Knob( KnobType::Vintage32, widget, tr( "Vibrato" ) ); m_vibratoKnob->setLabel( tr( "Vibrato" ) ); m_vibratoKnob->move( 110, 140 ); m_vibratoKnob->setHintText( tr( "Vibrato:" ), "" );*/ diff --git a/plugins/TapTempo/CMakeLists.txt b/plugins/TapTempo/CMakeLists.txt new file mode 100644 index 000000000..1fb6ba8dc --- /dev/null +++ b/plugins/TapTempo/CMakeLists.txt @@ -0,0 +1,3 @@ +INCLUDE(BuildPlugin) + +BUILD_PLUGIN(taptempo TapTempo.cpp TapTempoView.cpp MOCFILES TapTempo.h TapTempoView.h EMBEDDED_RESOURCES logo.png) \ No newline at end of file diff --git a/plugins/TapTempo/TapTempo.cpp b/plugins/TapTempo/TapTempo.cpp new file mode 100644 index 000000000..aad8d99b9 --- /dev/null +++ b/plugins/TapTempo/TapTempo.cpp @@ -0,0 +1,85 @@ +/* + * TapTempo.cpp - Plugin to count beats per minute + * + * + * Copyright (c) 2022 saker + * + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "TapTempo.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "AudioEngine.h" +#include "Engine.h" +#include "LedCheckBox.h" +#include "SamplePlayHandle.h" +#include "Song.h" +#include "embed.h" +#include "plugin_export.h" + +namespace lmms { + +extern "C" { +Plugin::Descriptor PLUGIN_EXPORT taptempo_plugin_descriptor + = {LMMS_STRINGIFY(PLUGIN_NAME), "Tap Tempo", QT_TRANSLATE_NOOP("PluginBrowser", "Tap to the beat"), + "saker ", 0x0100, Plugin::Type::Tool, new PluginPixmapLoader("logo"), nullptr, nullptr}; + +PLUGIN_EXPORT Plugin* lmms_plugin_main(Model*, void*) +{ + return new TapTempo; +} +} + +TapTempo::TapTempo() + : ToolPlugin(&taptempo_plugin_descriptor, nullptr) +{ +} + +void TapTempo::onBpmClick() +{ + const auto currentTime = clock::now(); + if (m_numTaps == 0) + { + m_startTime = currentTime; + } + else + { + using namespace std::chrono_literals; + const auto secondsElapsed = (currentTime - m_startTime) / 1.0s; + if (m_numTaps >= m_tapsNeededToDisplay) { m_bpm = m_numTaps / secondsElapsed * 60; } + } + + ++m_numTaps; +} + +QString TapTempo::nodeName() const +{ + return taptempo_plugin_descriptor.name; +} +} // namespace lmms \ No newline at end of file diff --git a/plugins/TapTempo/TapTempo.h b/plugins/TapTempo/TapTempo.h new file mode 100644 index 000000000..be540b8da --- /dev/null +++ b/plugins/TapTempo/TapTempo.h @@ -0,0 +1,61 @@ +/* + * TapTempo.h - Plugin to count beats per minute + * + * Copyright (c) 2022 saker + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LMMS_TAP_TEMPO_H +#define LMMS_TAP_TEMPO_H + +#include + +#include "TapTempoView.h" +#include "ToolPlugin.h" + +namespace lmms { + +class TapTempo : public ToolPlugin +{ + Q_OBJECT +public: + using clock = std::chrono::steady_clock; + + TapTempo(); + void onBpmClick(); + + QString nodeName() const override; + void saveSettings(QDomDocument&, QDomElement&) override {} + void loadSettings(const QDomElement&) override {} + + gui::PluginView* instantiateView(QWidget*) override { return new gui::TapTempoView(this); } + +private: + std::chrono::time_point m_startTime; + int m_numTaps = 0; + int m_tapsNeededToDisplay = 2; + double m_bpm = 0.0; + bool m_showDecimal = false; + + friend class gui::TapTempoView; +}; +} // namespace lmms + +#endif // LMMS_TAP_TEMPO_H diff --git a/plugins/TapTempo/TapTempoView.cpp b/plugins/TapTempo/TapTempoView.cpp new file mode 100644 index 000000000..d6c24fcf5 --- /dev/null +++ b/plugins/TapTempo/TapTempoView.cpp @@ -0,0 +1,168 @@ +/* + * TapTempoView.cpp - Plugin to count beats per minute + * + * + * Copyright (c) 2022 saker + * + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ +#include "TapTempoView.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Engine.h" +#include "SamplePlayHandle.h" +#include "Song.h" +#include "TapTempo.h" + +namespace lmms::gui { +TapTempoView::TapTempoView(TapTempo* plugin) + : ToolPluginView(plugin) + , m_plugin(plugin) +{ + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + + auto font = QFont(); + font.setPointSize(24); + + m_tapButton = new QPushButton(); + m_tapButton->setFixedSize(200, 200); + m_tapButton->setFont(font); + m_tapButton->setText(tr("0")); + + auto precisionCheckBox = new QCheckBox(tr("Precision")); + precisionCheckBox->setFocusPolicy(Qt::NoFocus); + precisionCheckBox->setToolTip(tr("Display in high precision")); + precisionCheckBox->setText(tr("Precision")); + + auto muteCheckBox = new QCheckBox(tr("0.0 ms")); + muteCheckBox->setFocusPolicy(Qt::NoFocus); + muteCheckBox->setToolTip(tr("Mute metronome")); + muteCheckBox->setText(tr("Mute")); + + m_msLabel = new QLabel(); + m_msLabel->setFocusPolicy(Qt::NoFocus); + m_msLabel->setToolTip(tr("BPM in milliseconds")); + m_msLabel->setText(tr("0 ms")); + + m_hzLabel = new QLabel(); + m_hzLabel->setFocusPolicy(Qt::NoFocus); + m_hzLabel->setToolTip(tr("Frequency of BPM")); + m_hzLabel->setText(tr("0.0000 hz")); + + auto resetButton = new QPushButton(tr("Reset")); + resetButton->setFocusPolicy(Qt::NoFocus); + resetButton->setToolTip(tr("Reset counter and sidebar information")); + + auto syncButton = new QPushButton(tr("Sync")); + syncButton->setFocusPolicy(Qt::NoFocus); + syncButton->setToolTip(tr("Sync with project tempo")); + + auto optionLayout = new QVBoxLayout(); + optionLayout->addWidget(precisionCheckBox); + optionLayout->addWidget(muteCheckBox); + + auto bpmInfoLayout = new QVBoxLayout(); + bpmInfoLayout->addWidget(m_msLabel, 0, Qt::AlignHCenter); + bpmInfoLayout->addWidget(m_hzLabel, 0, Qt::AlignHCenter); + + auto sidebarLayout = new QHBoxLayout(); + sidebarLayout->addLayout(optionLayout); + sidebarLayout->addLayout(bpmInfoLayout); + + auto buttonsLayout = new QHBoxLayout(); + buttonsLayout->addWidget(resetButton, 0, Qt::AlignCenter); + buttonsLayout->addWidget(syncButton, 0, Qt::AlignCenter); + + auto mainLayout = new QVBoxLayout(this); + mainLayout->addWidget(m_tapButton, 0, Qt::AlignCenter); + mainLayout->addLayout(buttonsLayout); + mainLayout->addLayout(sidebarLayout); + + connect(m_tapButton, &QPushButton::pressed, this, [this, muteCheckBox]() { + if (!muteCheckBox->isChecked()) + { + const auto timeSigNumerator = Engine::getSong()->getTimeSigModel().getNumerator(); + Engine::audioEngine()->addPlayHandle(new SamplePlayHandle( + m_plugin->m_numTaps % timeSigNumerator == 0 ? "misc/metronome02.ogg" : "misc/metronome01.ogg")); + } + + m_plugin->onBpmClick(); + updateLabels(); + }); + + connect(resetButton, &QPushButton::pressed, this, [this]() { closeEvent(nullptr); }); + + connect(precisionCheckBox, &QCheckBox::toggled, [this](bool checked) { + m_plugin->m_showDecimal = checked; + updateLabels(); + }); + + connect(syncButton, &QPushButton::clicked, this, [this]() { + const auto& tempoModel = Engine::getSong()->tempoModel(); + if (m_plugin->m_bpm < tempoModel.minValue() || m_plugin->m_bpm > tempoModel.maxValue()) { return; } + Engine::getSong()->setTempo(std::round(m_plugin->m_bpm)); + }); + + hide(); + if (parentWidget()) + { + parentWidget()->hide(); + parentWidget()->layout()->setSizeConstraint(QLayout::SetFixedSize); + + Qt::WindowFlags flags = parentWidget()->windowFlags(); + flags |= Qt::MSWindowsFixedSizeDialogHint; + flags &= ~Qt::WindowMaximizeButtonHint; + parentWidget()->setWindowFlags(flags); + } +} + +void TapTempoView::updateLabels() +{ + const double bpm = m_plugin->m_showDecimal ? m_plugin->m_bpm : std::round(m_plugin->m_bpm); + const double hz = bpm / 60; + const double ms = bpm > 0 ? 1 / hz * 1000 : 0; + + m_tapButton->setText(QString::number(bpm, 'f', m_plugin->m_showDecimal ? 1 : 0)); + m_msLabel->setText(tr("%1 ms").arg(ms, 0, 'f', m_plugin->m_showDecimal ? 1 : 0)); + m_hzLabel->setText(tr("%1 hz").arg(hz, 0, 'f', 4)); +} + +void TapTempoView::keyPressEvent(QKeyEvent* event) +{ + QWidget::keyPressEvent(event); + if (!event->isAutoRepeat()) { m_plugin->onBpmClick(); } +} + +void TapTempoView::closeEvent(QCloseEvent*) +{ + m_plugin->m_numTaps = 0; + m_plugin->m_bpm = 0; + updateLabels(); +} + +} // namespace lmms::gui diff --git a/plugins/TapTempo/TapTempoView.h b/plugins/TapTempo/TapTempoView.h new file mode 100644 index 000000000..a2a522d3f --- /dev/null +++ b/plugins/TapTempo/TapTempoView.h @@ -0,0 +1,64 @@ +/* + * TapTempoView.h - Plugin to count beats per minute + * + * + * Copyright (c) 2022 saker + * + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LMMS_GUI_TAP_TEMPO_VIEW_H +#define LMMS_GUI_TAP_TEMPO_VIEW_H + +#include "ToolPluginView.h" + +class QVBoxLayout; +class QHBoxLayout; +class QPushButton; +class QLabel; +class QCloseEvent; +class QKeyEvent; +class QCheckBox; + +namespace lmms { +class TapTempo; +} + +namespace lmms::gui { + +class TapTempoView : public ToolPluginView +{ + Q_OBJECT +public: + TapTempoView(TapTempo* plugin); + void updateLabels(); + void keyPressEvent(QKeyEvent* event) override; + void closeEvent(QCloseEvent*) override; + +private: + QPushButton* m_tapButton; + QLabel* m_msLabel; + QLabel* m_hzLabel; + TapTempo* m_plugin; + friend class TapTempo; +}; +} // namespace lmms::gui + +#endif // LMMS_GUI_TAP_TEMPO_VIEW_H diff --git a/plugins/TapTempo/logo.png b/plugins/TapTempo/logo.png new file mode 100644 index 000000000..67e6a3503 Binary files /dev/null and b/plugins/TapTempo/logo.png differ diff --git a/plugins/TripleOscillator/TripleOscillator.cpp b/plugins/TripleOscillator/TripleOscillator.cpp index 25baea208..f2340d3d6 100644 --- a/plugins/TripleOscillator/TripleOscillator.cpp +++ b/plugins/TripleOscillator/TripleOscillator.cpp @@ -57,7 +57,7 @@ Plugin::Descriptor PLUGIN_EXPORT tripleoscillator_plugin_descriptor = "in several ways" ), "Tobias Doerffel ", 0x0110, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader( "logo" ), nullptr, nullptr, @@ -84,10 +84,10 @@ OscillatorObject::OscillatorObject( Model * _parent, int _idx ) : tr( "Osc %1 phase-offset" ).arg( _idx+1 ) ), m_stereoPhaseDetuningModel( 0.0f, 0.0f, 360.0f, 1.0f, this, tr( "Osc %1 stereo phase-detuning" ).arg( _idx+1 ) ), - m_waveShapeModel( Oscillator::SineWave, 0, + m_waveShapeModel( static_cast(Oscillator::WaveShape::Sine), 0, Oscillator::NumWaveShapes-1, this, tr( "Osc %1 wave shape" ).arg( _idx+1 ) ), - m_modulationAlgoModel( Oscillator::SignalMix, 0, + m_modulationAlgoModel( static_cast(Oscillator::ModulationAlgo::SignalMix), 0, Oscillator::NumModulationAlgos-1, this, tr( "Modulation type %1" ).arg( _idx+1 ) ), m_useWaveTableModel(true), @@ -308,7 +308,7 @@ QString TripleOscillator::nodeName() const void TripleOscillator::playNote( NotePlayHandle * _n, sampleFrame * _working_buffer ) { - if( _n->totalFramesPlayed() == 0 || _n->m_pluginData == nullptr ) + if (!_n->m_pluginData) { auto oscs_l = std::array{}; auto oscs_r = std::array{}; @@ -426,7 +426,7 @@ class TripleOscKnob : public Knob { public: TripleOscKnob( QWidget * _parent ) : - Knob( knobStyled, _parent ) + Knob( KnobType::Styled, _parent ) { setFixedSize( 28, 35 ); } @@ -554,7 +554,7 @@ TripleOscillatorView::TripleOscillatorView( Instrument * _instrument, int knob_y = osc_y + i * osc_h; // setup volume-knob - auto vk = new Knob(knobStyled, this); + auto vk = new Knob(KnobType::Styled, this); vk->setVolumeKnob( true ); vk->setFixedSize( 28, 35 ); vk->move( 6, knob_y ); diff --git a/plugins/Vectorscope/VecControlsDialog.cpp b/plugins/Vectorscope/VecControlsDialog.cpp index 97898fe70..9aa2cfd8d 100644 --- a/plugins/Vectorscope/VecControlsDialog.cpp +++ b/plugins/Vectorscope/VecControlsDialog.cpp @@ -79,7 +79,7 @@ VecControlsDialog::VecControlsDialog(VecControls *controls) : config_layout->addStretch(); // Persistence knob - auto persistenceKnob = new Knob(knobSmall_17, this); + auto persistenceKnob = new Knob(KnobType::Small17, this); persistenceKnob->setModel(&controls->m_persistenceModel); persistenceKnob->setLabel(tr("Persist.")); persistenceKnob->setToolTip(tr("Trace persistence: higher amount means the trace will stay bright for longer time.")); diff --git a/plugins/Vectorscope/Vectorscope.cpp b/plugins/Vectorscope/Vectorscope.cpp index b9880691c..f843fc86d 100644 --- a/plugins/Vectorscope/Vectorscope.cpp +++ b/plugins/Vectorscope/Vectorscope.cpp @@ -39,7 +39,7 @@ extern "C" { QT_TRANSLATE_NOOP("PluginBrowser", "A stereo field visualizer."), "Martin Pavelek ", 0x0100, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader("logo"), nullptr, nullptr, diff --git a/plugins/Vestige/Vestige.cpp b/plugins/Vestige/Vestige.cpp index eab3693b8..dd8e9cbef 100644 --- a/plugins/Vestige/Vestige.cpp +++ b/plugins/Vestige/Vestige.cpp @@ -77,7 +77,7 @@ Plugin::Descriptor Q_DECL_EXPORT vestige_plugin_descriptor = "VST-host for using VST(i)-plugins within LMMS" ), "Tobias Doerffel ", 0x0100, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader( "logo" ), #ifdef LMMS_BUILD_LINUX "dll,so", @@ -185,8 +185,8 @@ VestigeInstrument::~VestigeInstrument() } Engine::audioEngine()->removePlayHandlesOfTypes( instrumentTrack(), - PlayHandle::TypeNotePlayHandle - | PlayHandle::TypeInstrumentPlayHandle ); + PlayHandle::Type::NotePlayHandle + | PlayHandle::Type::InstrumentPlayHandle ); closePlugin(); } @@ -1004,7 +1004,7 @@ ManageVestigeInstrumentView::ManageVestigeInstrumentView( Instrument * _instrume sprintf(paramStr.data(), "param%d", i); s_dumpValues = dump[paramStr.data()].split(":"); - vstKnobs[ i ] = new CustomTextKnob( knobBright_26, this, s_dumpValues.at( 1 ) ); + vstKnobs[ i ] = new CustomTextKnob( KnobType::Bright26, this, s_dumpValues.at( 1 ) ); vstKnobs[ i ]->setDescription( s_dumpValues.at( 1 ) + ":" ); vstKnobs[ i ]->setLabel( s_dumpValues.at( 1 ).left( 15 ) ); diff --git a/plugins/Vestige/Vestige.h b/plugins/Vestige/Vestige.h index 0a36c4924..f740913ea 100644 --- a/plugins/Vestige/Vestige.h +++ b/plugins/Vestige/Vestige.h @@ -72,7 +72,7 @@ public: virtual Flags flags() const { - return IsSingleStreamed | IsMidiBased; + return Flag::IsSingleStreamed | Flag::IsMidiBased; } virtual bool handleMidiEvent( const MidiEvent& event, const TimePos& time, f_cnt_t offset = 0 ); diff --git a/plugins/Vibed/CMakeLists.txt b/plugins/Vibed/CMakeLists.txt index 39e2ce57c..1cffeccfc 100644 --- a/plugins/Vibed/CMakeLists.txt +++ b/plugins/Vibed/CMakeLists.txt @@ -1,3 +1,6 @@ INCLUDE(BuildPlugin) -BUILD_PLUGIN(vibedstrings Vibed.cpp NineButtonSelector.cpp StringContainer.cpp VibratingString.cpp Vibed.h NineButtonSelector.h StringContainer.h VibratingString.h MOCFILES Vibed.h NineButtonSelector.h EMBEDDED_RESOURCES *.png) +BUILD_PLUGIN(vibedstrings Vibed.cpp NineButtonSelector.cpp VibratingString.cpp + Vibed.h NineButtonSelector.h VibratingString.h + MOCFILES Vibed.h NineButtonSelector.h + EMBEDDED_RESOURCES *.png) diff --git a/plugins/Vibed/NineButtonSelector.cpp b/plugins/Vibed/NineButtonSelector.cpp index 431dbec8b..3a68e5ee6 100644 --- a/plugins/Vibed/NineButtonSelector.cpp +++ b/plugins/Vibed/NineButtonSelector.cpp @@ -3,7 +3,7 @@ * * Copyright (c) 2006-2007 Danny McRae * Copyright (c) 2009 Tobias Doerffel - * + * * This file is part of LMMS - https://lmms.io * * This program is free software; you can redistribute it and/or @@ -23,237 +23,69 @@ * */ - #include "NineButtonSelector.h" #include "CaptionMenu.h" -#include "PixmapButton.h" namespace lmms::gui { -NineButtonSelector::NineButtonSelector( QPixmap _button0_on, - QPixmap _button0_off, - QPixmap _button1_on, - QPixmap _button1_off, - QPixmap _button2_on, - QPixmap _button2_off, - QPixmap _button3_on, - QPixmap _button3_off, - QPixmap _button4_on, - QPixmap _button4_off, - QPixmap _button5_on, - QPixmap _button5_off, - QPixmap _button6_on, - QPixmap _button6_off, - QPixmap _button7_on, - QPixmap _button7_off, - QPixmap _button8_on, - QPixmap _button8_off, - int _default, - int _x, int _y, - QWidget * _parent ): - QWidget( _parent ), - IntModelView( new NineButtonSelectorModel(0, 8, _default, nullptr, - QString(), true ), this ) +NineButtonSelector::NineButtonSelector(std::array onOffIcons, int defaultButton, int x, int y, QWidget* parent) : + QWidget{parent}, + IntModelView{new NineButtonSelectorModel{defaultButton, 0, 8, nullptr, QString{}, true}, this} { - setFixedSize( 50, 50 ); - move( _x, _y ); + setFixedSize(50, 50); + move(x, y); - m_button = new PixmapButton( this, nullptr ); - m_button->move( 1, 1 ); - m_button->setActiveGraphic( _button0_on ); - m_button->setInactiveGraphic( _button0_off ); - m_button->setChecked( false ); - connect( m_button, SIGNAL ( clicked () ), - this, SLOT ( button0Clicked() ) ); - m_buttons.append( m_button ); - - m_button = new PixmapButton( this, nullptr ); - m_button->move( 18, 1 ); - m_button->setActiveGraphic( _button1_on ); - m_button->setInactiveGraphic( _button1_off ); - m_button->setChecked( false ); - connect( m_button, SIGNAL ( clicked () ), - this, SLOT ( button1Clicked() ) ); - m_buttons.append( m_button ); - - m_button = new PixmapButton( this, nullptr ); - m_button->move( 35, 1 ); - m_button->setActiveGraphic( _button2_on ); - m_button->setInactiveGraphic( _button2_off ); - m_button->setChecked( false ); - connect( m_button, SIGNAL ( clicked () ), - this, SLOT ( button2Clicked() ) ); - m_buttons.append( m_button ); - - m_button = new PixmapButton( this, nullptr ); - m_button->move( 1, 18 ); - m_button->setActiveGraphic( _button3_on ); - m_button->setInactiveGraphic( _button3_off ); - m_button->setChecked( false ); - connect( m_button, SIGNAL ( clicked () ), - this, SLOT ( button3Clicked() ) ); - m_buttons.append( m_button ); - - m_button = new PixmapButton( this, nullptr ); - m_button->move( 18, 18 ); - m_button->setActiveGraphic( _button4_on ); - m_button->setInactiveGraphic( _button4_off ); - m_button->setChecked( false ); - connect( m_button, SIGNAL ( clicked () ), - this, SLOT ( button4Clicked() ) ); - m_buttons.append( m_button ); - - m_button = new PixmapButton( this, nullptr ); - m_button->move( 35, 18 ); - m_button->setActiveGraphic( _button5_on ); - m_button->setInactiveGraphic( _button5_off ); - m_button->setChecked( false ); - connect( m_button, SIGNAL ( clicked () ), - this, SLOT ( button5Clicked() ) ); - m_buttons.append( m_button ); - - m_button = new PixmapButton( this, nullptr ); - m_button->move( 1, 35 ); - m_button->setActiveGraphic( _button6_on ); - m_button->setInactiveGraphic( _button6_off ); - m_button->setChecked( false ); - connect( m_button, SIGNAL ( clicked () ), - this, SLOT ( button6Clicked() ) ); - m_buttons.append( m_button ); - - m_button = new PixmapButton( this, nullptr ); - m_button->move( 18, 35 ); - m_button->setActiveGraphic( _button7_on ); - m_button->setInactiveGraphic( _button7_off ); - m_button->setChecked( false ); - connect( m_button, SIGNAL ( clicked () ), - this, SLOT ( button7Clicked() ) ); - m_buttons.append( m_button ); - - m_button = new PixmapButton( this, nullptr ); - m_button->move( 35, 35 ); - m_button->setActiveGraphic( _button8_on ); - m_button->setInactiveGraphic( _button8_off ); - m_button->setChecked( false ); - connect( m_button, SIGNAL ( clicked () ), - this, SLOT ( button8Clicked() ) ); - m_buttons.append( m_button ); - - m_lastBtn = m_buttons[_default]; - m_lastBtn->setChecked( true ); -} - - -NineButtonSelector::~ NineButtonSelector() -{ - for( int i = 0; i < 9; i++ ) + for (int i = 0; i < 9; ++i) { - delete m_buttons[i]; + m_buttons[i] = std::make_unique(this, nullptr); + const int buttonX = 1 + (i % 3) * 17; + const int buttonY = 1 + (i / 3) * 17; + m_buttons[i]->move(buttonX, buttonY); + m_buttons[i]->setActiveGraphic(onOffIcons[i * 2]); + m_buttons[i]->setInactiveGraphic(onOffIcons[(i * 2) + 1]); + m_buttons[i]->setChecked(false); + connect(m_buttons[i].get(), &PixmapButton::clicked, this, [=](){ this->buttonClicked(i); }); } + + m_lastBtn = m_buttons[defaultButton].get(); + m_lastBtn->setChecked(true); } - - - -void NineButtonSelector::button0Clicked() +void NineButtonSelector::buttonClicked(int id) { - setSelected( 0 ); -} - - - - -void NineButtonSelector::button1Clicked() -{ - setSelected( 1 ); -} - - - - -void NineButtonSelector::button2Clicked() -{ - setSelected( 2 ); -} - - - - -void NineButtonSelector::button3Clicked() -{ - setSelected( 3 ); -} - - - - -void NineButtonSelector::button4Clicked() -{ - setSelected( 4 ); -} - - - - -void NineButtonSelector::button5Clicked() -{ - setSelected( 5 ); -} - - - - -void NineButtonSelector::button6Clicked() -{ - setSelected( 6 ); -} - - - - -void NineButtonSelector::button7Clicked() -{ - setSelected( 7 ); -} - - - - -void NineButtonSelector::button8Clicked() -{ - setSelected( 8 ); + setSelected(id); } void NineButtonSelector::modelChanged() { - updateButton( model()->value() ); + updateButton(model()->value()); } -void NineButtonSelector::setSelected( int _new_button ) +void NineButtonSelector::setSelected(int newButton) { - model()->setValue(_new_button); - updateButton( _new_button ); + model()->setValue(newButton); + updateButton(newButton); } -void NineButtonSelector::updateButton( int _new_button ) +void NineButtonSelector::updateButton(int newButton) { - m_lastBtn->setChecked( false ); + m_lastBtn->setChecked(false); m_lastBtn->update(); - m_lastBtn = m_buttons[_new_button]; - m_lastBtn->setChecked( true ); + m_lastBtn = m_buttons[newButton].get(); + m_lastBtn->setChecked(true); m_lastBtn->update(); - - emit NineButtonSelection( _new_button ); + + emit NineButtonSelection(newButton); } -void NineButtonSelector::contextMenuEvent( QContextMenuEvent * ) +void NineButtonSelector::contextMenuEvent(QContextMenuEvent*) { - CaptionMenu contextMenu( windowTitle(), this ); - contextMenu.exec( QCursor::pos() ); + CaptionMenu contextMenu{windowTitle(), this}; + contextMenu.exec(QCursor::pos()); } diff --git a/plugins/Vibed/NineButtonSelector.h b/plugins/Vibed/NineButtonSelector.h index 9c768e996..78ae7c3d1 100644 --- a/plugins/Vibed/NineButtonSelector.h +++ b/plugins/Vibed/NineButtonSelector.h @@ -3,7 +3,7 @@ * * Copyright (c) 2006-2007 Danny McRae * Copyright (c) 2009 Tobias Doerffel - * + * * This file is part of LMMS - https://lmms.io * * This program is free software; you can redistribute it and/or @@ -22,87 +22,56 @@ * Boston, MA 02110-1301 USA. * */ -#ifndef _NINE_BUTTON_SELECTOR_H -#define _NINE_BUTTON_SELECTOR_H +#ifndef LMMS_GUI_NINE_BUTTON_SELECTOR_H +#define LMMS_GUI_NINE_BUTTON_SELECTOR_H + +#include +#include #include + #include "AutomatableModelView.h" +#include "PixmapButton.h" namespace lmms { -class graphModel; -} -namespace lmms::gui + +namespace gui { -class Knob; -class PixmapButton; - - -class NineButtonSelector: public QWidget , public IntModelView +class NineButtonSelector : public QWidget, public IntModelView { Q_OBJECT - public: - NineButtonSelector( QPixmap _button0_on, - QPixmap _button0_off, - QPixmap _button1_on, - QPixmap _button1_off, - QPixmap _button2_on, - QPixmap _button2_off, - QPixmap _button3_on, - QPixmap _button3_off, - QPixmap _button4_on, - QPixmap _button4_off, - QPixmap _button5_on, - QPixmap _button5_off, - QPixmap _button6_on, - QPixmap _button6_off, - QPixmap _button7_on, - QPixmap _button7_off, - QPixmap _button8_on, - QPixmap _button8_off, - int _default, - int _x, int _y, - QWidget * _parent); - ~NineButtonSelector() override; - -// inline int getSelected() { -// return( castModel()->value() ); -// }; + NineButtonSelector(std::array onOffIcons, int defaultButton, int x, int y, QWidget* parent); + ~NineButtonSelector() override = default; protected: - void setSelected( int _new_button ); - + void setSelected(int newButton); + public slots: - void button0Clicked(); - void button1Clicked(); - void button2Clicked(); - void button3Clicked(); - void button4Clicked(); - void button5Clicked(); - void button6Clicked(); - void button7Clicked(); - void button8Clicked(); - void contextMenuEvent( QContextMenuEvent * ) override; - + void buttonClicked(int id); + void contextMenuEvent(QContextMenuEvent*) override; + signals: - void NineButtonSelection( int ); - + void NineButtonSelection(int); + private: void modelChanged() override; - void updateButton( int ); + void updateButton(int); - QList m_buttons; - PixmapButton * m_button; - PixmapButton * m_lastBtn; + std::array, 9> m_buttons; + PixmapButton* m_lastBtn; +}; -} ; + +} // namespace gui using NineButtonSelectorModel = IntModel; -} // namespace lmms::gui -#endif +} // namespace lmms + +#endif // LMMS_GUI_NINE_BUTTON_SELECTOR_H diff --git a/plugins/Vibed/StringContainer.cpp b/plugins/Vibed/StringContainer.cpp deleted file mode 100644 index 36dee6da0..000000000 --- a/plugins/Vibed/StringContainer.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* - * StringContainer.cpp - contains a collection of strings - * - * Copyright (c) 2006 Danny McRae - * - * This file is part of LMMS - https://lmms.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program (see COPYING); if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - */ - -#include "StringContainer.h" - -namespace lmms -{ - - -StringContainer::StringContainer(const float _pitch, - const sample_rate_t _sample_rate, - const int _buffer_length, - const int _strings ) : - m_pitch( _pitch ), - m_sampleRate( _sample_rate ), - m_bufferLength( _buffer_length ) -{ - for( int i = 0; i < _strings; i++ ) - { - m_exists.append( false ); - } -} - - - - -void StringContainer::addString(int _harm, - const float _pick, - const float _pickup, - const float * _impulse, - const float _randomize, - const float _string_loss, - const float _detune, - const int _oversample, - const bool _state, - const int _id ) -{ - float harm; - switch( _harm ) - { - case 0: - harm = 0.25f; - break; - case 1: - harm = 0.5f; - break; - case 2: - harm = 1.0f; - break; - case 3: - harm = 2.0f; - break; - case 4: - harm = 3.0f; - break; - case 5: - harm = 4.0f; - break; - case 6: - harm = 5.0f; - break; - case 7: - harm = 6.0f; - break; - case 8: - harm = 7.0f; - break; - default: - harm = 1.0f; - } - - m_strings.append( new VibratingString( m_pitch * harm, - _pick, - _pickup, - const_cast(_impulse), - m_bufferLength, - m_sampleRate, - _oversample, - _randomize, - _string_loss, - _detune, - _state ) ); - m_exists[_id] = true; -} - - -} // namespace lmms \ No newline at end of file diff --git a/plugins/Vibed/StringContainer.h b/plugins/Vibed/StringContainer.h deleted file mode 100644 index 96408c56a..000000000 --- a/plugins/Vibed/StringContainer.h +++ /dev/null @@ -1,86 +0,0 @@ -/* StringContainer.h - contains a collection of strings - * - * Copyright (c) 2006 Danny McRae - * - * This file is part of LMMS - https://lmms.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program (see COPYING); if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - */ - -#ifndef _STRING_CONTAINER_H -#define _STRING_CONTAINER_H - -#include - -#include "VibratingString.h" -#include "MemoryManager.h" - -namespace lmms -{ - - -class StringContainer -{ - MM_OPERATORS -public: - StringContainer(const float _pitch, - const sample_rate_t _sample_rate, - const int _buffer_length, - const int _strings = 9 ); - - void addString( int _harm, - const float _pick, - const float _pickup, - const float * _impluse, - const float _randomize, - const float _string_loss, - const float _detune, - const int _oversample, - const bool _state, - const int _id ); - - bool exists( int _id ) const - { - return m_exists[_id]; - } - - ~StringContainer() - { - int strings = m_strings.count(); - for( int i = 0; i < strings; i++ ) - { - delete m_strings[i]; - } - } - - float getStringSample( int _string ) - { - return m_strings[_string]->nextSample(); - } - -private: - QVector m_strings; - const float m_pitch; - const sample_rate_t m_sampleRate; - const int m_bufferLength; - QVector m_exists; -} ; - - -} // namespace lmms - -#endif diff --git a/plugins/Vibed/Vibed.cpp b/plugins/Vibed/Vibed.cpp index 9f119aa6e..3ed51fe79 100644 --- a/plugins/Vibed/Vibed.cpp +++ b/plugins/Vibed/Vibed.cpp @@ -22,21 +22,20 @@ * */ +#include "Vibed.h" +#include +#include #include -#include "Vibed.h" #include "AudioEngine.h" #include "Engine.h" -#include "Graph.h" #include "InstrumentTrack.h" -#include "Knob.h" -#include "LedCheckBox.h" #include "NotePlayHandle.h" -#include "PixmapButton.h" +#include "VibratingString.h" +#include "MemoryManager.h" #include "base64.h" #include "CaptionMenu.h" -#include "StringContainer.h" #include "volume.h" #include "Song.h" @@ -52,628 +51,472 @@ extern "C" Plugin::Descriptor PLUGIN_EXPORT vibedstrings_plugin_descriptor = { - LMMS_STRINGIFY( PLUGIN_NAME ), + LMMS_STRINGIFY(PLUGIN_NAME), "Vibed", - QT_TRANSLATE_NOOP( "PluginBrowser", - "Vibrating string modeler" ), + QT_TRANSLATE_NOOP("PluginBrowser", "Vibrating string modeler"), "Danny McRae ", 0x0100, - Plugin::Instrument, - new PluginPixmapLoader( "logo" ), - nullptr, + Plugin::Type::Instrument, + new PluginPixmapLoader("logo"), nullptr, + nullptr }; } -Vibed::Vibed( InstrumentTrack * _instrumentTrack ) : - Instrument( _instrumentTrack, &vibedstrings_plugin_descriptor ) +class Vibed::StringContainer { + MM_OPERATORS +public: + StringContainer(float pitch, sample_rate_t sampleRate, int bufferLength) : + m_pitch(pitch), m_sampleRate(sampleRate), m_bufferLength(bufferLength) {} - FloatModel * knob; - BoolModel * led; - gui::NineButtonSelectorModel * harmonic; - graphModel * graphTmp; + ~StringContainer() = default; - for( int harm = 0; harm < 9; harm++ ) + void addString(int harm, float pick, float pickup, const float* impulse, float randomize, + float stringLoss, float detune, int oversample, bool state, int id) { - knob = new FloatModel( DefaultVolume, MinVolume, MaxVolume, - 1.0f, this, tr( "String %1 volume" ).arg( harm+1 ) ); - m_volumeKnobs.append( knob ); + constexpr auto octave = std::array{0.25f, 0.5f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f}; + assert(harm >= 0 && harm < octave.size()); - knob = new FloatModel( 0.0f, 0.0f, 0.05f, 0.001f, this, - tr( "String %1 stiffness" ).arg( harm+1 ) ); - m_stiffnessKnobs.append( knob ); + m_strings[id] = VibratingString{m_pitch * octave[harm], pick, pickup, impulse, m_bufferLength, + m_sampleRate, oversample, randomize, stringLoss, detune, state}; - knob = new FloatModel( 0.0f, 0.0f, 0.05f, 0.005f, this, - tr( "Pick %1 position" ).arg( harm+1 ) ); - m_pickKnobs.append( knob ); + m_exists[id] = true; + } - knob = new FloatModel( 0.05f, 0.0f, 0.05f, 0.005f, this, - tr( "Pickup %1 position" ).arg( harm+1 ) ); - m_pickupKnobs.append( knob ); + bool exists(int id) const { return m_exists[id]; } - knob = new FloatModel( 0.0f, -1.0f, 1.0f, 0.01f, this, - tr( "String %1 panning" ).arg( harm+1 ) ); - m_panKnobs.append( knob ); + sample_t getStringSample(int id) { return m_strings[id].nextSample(); } - knob = new FloatModel( 0.0f, -0.1f, 0.1f, 0.001f, this, - tr( "String %1 detune" ).arg( harm+1 ) ); - m_detuneKnobs.append( knob ); +private: + const float m_pitch; + const sample_rate_t m_sampleRate; + const int m_bufferLength; + std::array m_strings{}; + std::array m_exists{}; +}; - knob = new FloatModel( 0.0f, 0.0f, 0.75f, 0.01f, this, - tr( "String %1 fuzziness" ).arg( harm+1 ) ); - m_randomKnobs.append( knob ); - - knob = new FloatModel( 1, 1, 16, 1, this, - tr( "String %1 length" ).arg( harm+1 ) ); - m_lengthKnobs.append( knob ); - - led = new BoolModel( false, this, - tr( "Impulse %1" ).arg( harm+1 ) ); - m_impulses.append( led ); - - led = new BoolModel( harm==0, this, - tr( "String %1" ).arg( harm+1 ) ); - m_powerButtons.append( led ); - - harmonic = new gui::NineButtonSelectorModel( 2, 0, 8, this ); - m_harmonics.append( harmonic ); - - graphTmp = new graphModel( -1.0, 1.0, __sampleLength, this ); - graphTmp->setWaveToSine(); - - m_graphs.append( graphTmp ); +Vibed::Vibed(InstrumentTrack* instrumentTrack) : + Instrument(instrumentTrack, &vibedstrings_plugin_descriptor) +{ + for (int harm = 0; harm < s_stringCount; ++harm) + { + m_volumeModels[harm] = std::make_unique( + DefaultVolume, MinVolume, MaxVolume, 1.0f, this, tr("String %1 volume").arg(harm + 1)); + m_stiffnessModels[harm] = std::make_unique( + 0.0f, 0.0f, 0.05f, 0.001f, this, tr("String %1 stiffness").arg(harm + 1)); + m_pickModels[harm] = std::make_unique( + 0.0f, 0.0f, 0.05f, 0.005f, this, tr("Pick %1 position").arg(harm + 1)); + m_pickupModels[harm] = std::make_unique( + 0.05f, 0.0f, 0.05f, 0.005f, this, tr("Pickup %1 position").arg( harm + 1)); + m_panModels[harm] = std::make_unique( + 0.0f, -1.0f, 1.0f, 0.01f, this, tr("String %1 panning").arg(harm + 1)); + m_detuneModels[harm] = std::make_unique( + 0.0f, -0.1f, 0.1f, 0.001f, this, tr("String %1 detune").arg(harm + 1)); + m_randomModels[harm] = std::make_unique( + 0.0f, 0.0f, 0.75f, 0.01f, this, tr("String %1 fuzziness").arg(harm + 1)); + m_lengthModels[harm] = std::make_unique( + 1, 1, 16, 1, this, tr("String %1 length").arg(harm + 1)); + m_impulseModels[harm] = std::make_unique(false, this, tr("Impulse %1").arg(harm + 1)); + m_powerModels[harm] = std::make_unique(harm == 0, this, tr("String %1").arg(harm + 1)); + m_harmonicModels[harm] = std::make_unique(2, 0, 8, this); + m_graphModels[harm] = std::make_unique(-1.0, 1.0, s_sampleLength, this); + m_graphModels[harm]->setWaveToSine(); } } - - - -void Vibed::saveSettings( QDomDocument & _doc, QDomElement & _this ) +void Vibed::saveSettings(QDomDocument& doc, QDomElement& elem) { - - QString name; - // Save plugin version - _this.setAttribute( "version", "0.1" ); - - for( int i = 0; i < 9; i++ ) + elem.setAttribute("version", "0.2"); + + for (int i = 0; i < s_stringCount; ++i) { - name = "active" + QString::number( i ); - _this.setAttribute( name, QString::number( - m_powerButtons[i]->value() ) ); + const auto is = QString::number(i); - if( m_powerButtons[i]->value() ) - { - name = "volume" + QString::number( i ); - m_volumeKnobs[i]->saveSettings( _doc, _this, name ); - - name = "stiffness" + QString::number( i ); - m_stiffnessKnobs[i]->saveSettings( _doc, _this, name ); + elem.setAttribute("active" + is, QString::number(m_powerModels[i]->value())); - name = "pick" + QString::number( i ); - m_pickKnobs[i]->saveSettings( _doc, _this, name ); + m_volumeModels[i]->saveSettings(doc, elem, "volume" + is); + m_stiffnessModels[i]->saveSettings(doc, elem, "stiffness" + is); + m_pickModels[i]->saveSettings(doc, elem, "pick" + is); + m_pickupModels[i]->saveSettings(doc, elem, "pickup" + is); + m_harmonicModels[i]->saveSettings(doc, elem, "octave" + is); + m_lengthModels[i]->saveSettings(doc, elem, "length" + is); + m_panModels[i]->saveSettings(doc, elem, "pan" + is); + m_detuneModels[i]->saveSettings(doc, elem, "detune" + is); + m_randomModels[i]->saveSettings(doc, elem, "slap" + is); + m_impulseModels[i]->saveSettings(doc, elem, "impulse" + is); - name = "pickup" + QString::number( i ); - m_pickupKnobs[i]->saveSettings( _doc, _this, name ); + QString sampleString; + base64::encode((const char*)m_graphModels[i]->samples(), s_sampleLength * sizeof(float), sampleString); - name = "octave" + QString::number( i ); - m_harmonics[i]->saveSettings( _doc, _this, name ); - - name = "length" + QString::number( i ); - m_lengthKnobs[i]->saveSettings( _doc, _this, name ); - - name = "pan" + QString::number( i ); - m_panKnobs[i]->saveSettings( _doc, _this, name ); - - name = "detune" + QString::number( i ); - m_detuneKnobs[i]->saveSettings( _doc, _this, name ); - - name = "slap" + QString::number( i ); - m_randomKnobs[i]->saveSettings( _doc, _this, name ); - - name = "impulse" + QString::number( i ); - m_impulses[i]->saveSettings( _doc, _this, name ); - - QString sampleString; - base64::encode( - (const char *)m_graphs[i]->samples(), - __sampleLength * sizeof(float), - sampleString ); - name = "graph" + QString::number( i ); - _this.setAttribute( name, sampleString ); - } + elem.setAttribute("graph" + is, sampleString); } - } - - -void Vibed::loadSettings( const QDomElement & _this ) +void Vibed::loadSettings(const QDomElement& elem) { - - QString name; - - for( int i = 0; i < 9; i++ ) + // Load plugin version + bool newVersion = false; + if (elem.hasAttribute("version")) { - name = "active" + QString::number( i ); - m_powerButtons[i]->setValue( _this.attribute( name ).toInt() ); - - if( m_powerButtons[i]->value() && - _this.hasAttribute( "volume" + QString::number( i ) ) ) + newVersion = elem.attribute("version").toFloat() >= 0.2f; + } + + for (int i = 0; i < s_stringCount; ++i) + { + const auto is = QString::number(i); + + m_powerModels[i]->setValue(elem.attribute("active" + is).toInt()); + + // Version 0.2 saves/loads all instrument data unconditionally + const bool hasVolumeAttr = elem.hasAttribute("volume" + is) || !elem.firstChildElement("volume" + is).isNull(); + if (newVersion || (m_powerModels[i]->value() && hasVolumeAttr)) { - name = "volume" + QString::number( i ); - m_volumeKnobs[i]->loadSettings( _this, name ); - - name = "stiffness" + QString::number( i ); - m_stiffnessKnobs[i]->loadSettings( _this, name ); - - name = "pick" + QString::number( i ); - m_pickKnobs[i]->loadSettings( _this, name ); - - name = "pickup" + QString::number( i ); - m_pickupKnobs[i]->loadSettings( _this, name ); - - name = "octave" + QString::number( i ); - m_harmonics[i]->loadSettings( _this, name ); - - name = "length" + QString::number( i ); - m_lengthKnobs[i]->loadSettings( _this, name ); - - name = "pan" + QString::number( i ); - m_panKnobs[i]->loadSettings( _this, name ); - - name = "detune" + QString::number( i ); - m_detuneKnobs[i]->loadSettings( _this, name ); - - name = "slap" + QString::number( i ); - m_randomKnobs[i]->loadSettings( _this, name ); - - name = "impulse" + QString::number( i ); - m_impulses[i]->loadSettings( _this, name ); + m_volumeModels[i]->loadSettings(elem, "volume" + is); + m_stiffnessModels[i]->loadSettings(elem, "stiffness" + is); + m_pickModels[i]->loadSettings(elem, "pick" + is); + m_pickupModels[i]->loadSettings(elem, "pickup" + is); + m_harmonicModels[i]->loadSettings(elem, "octave" + is); + m_lengthModels[i]->loadSettings(elem, "length" + is); + m_panModels[i]->loadSettings(elem, "pan" + is); + m_detuneModels[i]->loadSettings(elem, "detune" + is); + m_randomModels[i]->loadSettings(elem, "slap" + is); + m_impulseModels[i]->loadSettings(elem, "impulse" + is); int size = 0; - float * shp = 0; - base64::decode( _this.attribute( "graph" + - QString::number( i ) ), - &shp, - &size ); - // TODO: check whether size == 128 * sizeof( float ), - // otherwise me might and up in a segfault - m_graphs[i]->setSamples( shp ); - delete[] shp; - + float* shp = nullptr; + base64::decode(elem.attribute("graph" + is), &shp, &size); - // TODO: do one of the following to avoid - // "uninitialized" wave-shape-buttongroup - // - activate random-wave-shape-button here - // - make wave-shape-buttons simple toggle-buttons - // instead of checkable buttons - // - save and restore selected wave-shape-button + assert(size == 128 * sizeof(float)); + m_graphModels[i]->setSamples(shp); + delete[] shp; } } - -// update(); } - - - QString Vibed::nodeName() const { - return( vibedstrings_plugin_descriptor.name ); + return vibedstrings_plugin_descriptor.name; } - - - -void Vibed::playNote( NotePlayHandle * _n, sampleFrame * _working_buffer ) +void Vibed::playNote(NotePlayHandle* n, sampleFrame* workingBuffer) { - if ( _n->totalFramesPlayed() == 0 || _n->m_pluginData == nullptr ) + if (!n->m_pluginData) { - _n->m_pluginData = new StringContainer( _n->frequency(), - Engine::audioEngine()->processingSampleRate(), - __sampleLength ); - - for( int i = 0; i < 9; ++i ) + const auto newContainer = new StringContainer{n->frequency(), + Engine::audioEngine()->processingSampleRate(), s_sampleLength}; + + n->m_pluginData = newContainer; + + for (int i = 0; i < s_stringCount; ++i) { - if( m_powerButtons[i]->value() ) + if (m_powerModels[i]->value()) { - static_cast( - _n->m_pluginData )->addString( - m_harmonics[i]->value(), - m_pickKnobs[i]->value(), - m_pickupKnobs[i]->value(), - m_graphs[i]->samples(), - m_randomKnobs[i]->value(), - m_stiffnessKnobs[i]->value(), - m_detuneKnobs[i]->value(), - static_cast( - m_lengthKnobs[i]->value() ), - m_impulses[i]->value(), - i ); + newContainer->addString( + m_harmonicModels[i]->value(), + m_pickModels[i]->value(), + m_pickupModels[i]->value(), + m_graphModels[i]->samples(), + m_randomModels[i]->value(), + m_stiffnessModels[i]->value(), + m_detuneModels[i]->value(), + static_cast(m_lengthModels[i]->value()), + m_impulseModels[i]->value(), + i); } } } - const fpp_t frames = _n->framesLeftForCurrentPeriod(); - const f_cnt_t offset = _n->noteOffset(); - auto ps = static_cast(_n->m_pluginData); + const fpp_t frames = n->framesLeftForCurrentPeriod(); + const f_cnt_t offset = n->noteOffset(); + auto ps = static_cast(n->m_pluginData); - for( fpp_t i = offset; i < frames + offset; ++i ) + for (fpp_t i = offset; i < frames + offset; ++i) { - _working_buffer[i][0] = 0.0f; - _working_buffer[i][1] = 0.0f; - int s = 0; - for( int string = 0; string < 9; ++string ) + workingBuffer[i][0] = 0.0f; + workingBuffer[i][1] = 0.0f; + for (int str = 0; str < s_stringCount; ++str) { - if( ps->exists( string ) ) + if (ps->exists(str)) { // pan: 0 -> left, 1 -> right - const float pan = ( m_panKnobs[string]->value() + 1 ) / 2.0f; - const sample_t sample = ps->getStringSample( s ) * m_volumeKnobs[string]->value() / 100.0f; - _working_buffer[i][0] += ( 1.0f - pan ) * sample; - _working_buffer[i][1] += pan * sample; - s++; + const float pan = (m_panModels[str]->value() + 1) / 2.0f; + const sample_t sample = ps->getStringSample(str) * m_volumeModels[str]->value() / 100.0f; + workingBuffer[i][0] += (1.0f - pan) * sample; + workingBuffer[i][1] += pan * sample; } } } - instrumentTrack()->processAudioBuffer( _working_buffer, frames + offset, _n ); + instrumentTrack()->processAudioBuffer(workingBuffer, frames + offset, n); } - - - -void Vibed::deleteNotePluginData( NotePlayHandle * _n ) +void Vibed::deleteNotePluginData(NotePlayHandle* n) { - delete static_cast( _n->m_pluginData ); + delete static_cast(n->m_pluginData); } - - - -gui::PluginView * Vibed::instantiateView( QWidget * _parent ) +gui::PluginView* Vibed::instantiateView(QWidget* parent) { - return( new gui::VibedView( this, _parent ) ); + return new gui::VibedView(this, parent); } - namespace gui { -VibedView::VibedView( Instrument * _instrument, - QWidget * _parent ) : - InstrumentViewFixedSize( _instrument, _parent ) +VibedView::VibedView(Instrument* instrument, QWidget* parent) : + InstrumentViewFixedSize(instrument, parent), + m_volumeKnob(KnobType::Bright26, this), + m_stiffnessKnob(KnobType::Bright26, this), + m_pickKnob(KnobType::Bright26, this), + m_pickupKnob(KnobType::Bright26, this), + m_panKnob(KnobType::Bright26, this), + m_detuneKnob(KnobType::Bright26, this), + m_randomKnob(KnobType::Bright26, this), + m_lengthKnob(KnobType::Bright26, this), + m_graph(this), + m_impulse("", this), + m_power("", this, tr("Enable waveform")), + m_smoothBtn(this, tr("Smooth waveform")), + m_normalizeBtn(this, tr("Normalize waveform")), + m_sinWaveBtn(this, tr("Sine wave")), + m_triangleWaveBtn(this, tr("Triangle wave")), + m_sawWaveBtn(this, tr("Saw wave")), + m_sqrWaveBtn(this, tr("Square wave")), + m_whiteNoiseWaveBtn(this, tr("White noise")), + m_usrWaveBtn(this, tr("User-defined wave")) { - setAutoFillBackground( true ); + setAutoFillBackground(true); QPalette pal; - pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( - "artwork" ) ); - setPalette( pal ); - - m_volumeKnob = new Knob( knobBright_26, this ); - m_volumeKnob->setVolumeKnob( true ); - m_volumeKnob->move( 103, 142 ); - m_volumeKnob->setHintText( tr( "String volume:" ), "" ); + pal.setBrush(backgroundRole(), PLUGIN_NAME::getIconPixmap("artwork")); + setPalette(pal); - m_stiffnessKnob = new Knob( knobBright_26, this ); - m_stiffnessKnob->move( 129, 142 ); - m_stiffnessKnob->setHintText( tr( "String stiffness:" ) - , "" ); - - - m_pickKnob = new Knob( knobBright_26, this ); - m_pickKnob->move( 153, 142 ); - m_pickKnob->setHintText( tr( "Pick position:" ), "" ); + m_volumeKnob.setVolumeKnob(true); + m_volumeKnob.move(103, 142); + m_volumeKnob.setHintText(tr("String volume:"), ""); - m_pickupKnob = new Knob( knobBright_26, this ); - m_pickupKnob->move( 177, 142 ); - m_pickupKnob->setHintText( tr( "Pickup position:" ) - , "" ); + m_stiffnessKnob.move(129, 142); + m_stiffnessKnob.setHintText(tr("String stiffness:"), ""); - m_panKnob = new Knob( knobBright_26, this ); - m_panKnob->move( 105, 187 ); - m_panKnob->setHintText( tr( "String panning:" ), "" ); - - m_detuneKnob = new Knob( knobBright_26, this ); - m_detuneKnob->move( 150, 187 ); - m_detuneKnob->setHintText( tr( "String detune:" ), "" ); + m_pickKnob.move(153, 142); + m_pickKnob.setHintText(tr("Pick position:"), ""); - m_randomKnob = new Knob( knobBright_26, this ); - m_randomKnob->move( 194, 187 ); - m_randomKnob->setHintText( tr( "String fuzziness:" ) - , "" ); + m_pickupKnob.move(177, 142); + m_pickupKnob.setHintText(tr("Pickup position:"), ""); - m_lengthKnob = new Knob( knobBright_26, this ); - m_lengthKnob->move( 23, 193 ); - m_lengthKnob->setHintText( tr( "String length:" ) - , "" ); + m_panKnob.move(105, 187); + m_panKnob.setHintText(tr("String panning:"), ""); - m_impulse = new LedCheckBox( "", this ); - m_impulse->move( 23, 94 ); - m_impulse->setToolTip( - tr( "Impulse" ) ); + m_detuneKnob.move(150, 187); + m_detuneKnob.setHintText(tr("String detune:"), ""); - m_harmonic = new NineButtonSelector( - PLUGIN_NAME::getIconPixmap( "button_-2_on" ), - PLUGIN_NAME::getIconPixmap( "button_-2_off" ), - PLUGIN_NAME::getIconPixmap( "button_-1_on" ), - PLUGIN_NAME::getIconPixmap( "button_-1_off" ), - PLUGIN_NAME::getIconPixmap( "button_f_on" ), - PLUGIN_NAME::getIconPixmap( "button_f_off" ), - PLUGIN_NAME::getIconPixmap( "button_2_on" ), - PLUGIN_NAME::getIconPixmap( "button_2_off" ), - PLUGIN_NAME::getIconPixmap( "button_3_on" ), - PLUGIN_NAME::getIconPixmap( "button_3_off" ), - PLUGIN_NAME::getIconPixmap( "button_4_on" ), - PLUGIN_NAME::getIconPixmap( "button_4_off" ), - PLUGIN_NAME::getIconPixmap( "button_5_on" ), - PLUGIN_NAME::getIconPixmap( "button_5_off" ), - PLUGIN_NAME::getIconPixmap( "button_6_on" ), - PLUGIN_NAME::getIconPixmap( "button_6_off" ), - PLUGIN_NAME::getIconPixmap( "button_7_on" ), - PLUGIN_NAME::getIconPixmap( "button_7_off" ), + m_randomKnob.move(194, 187); + m_randomKnob.setHintText(tr("String fuzziness:"), ""); + + m_lengthKnob.move(23, 193); + m_lengthKnob.setHintText(tr("String length:"), ""); + + m_graph.setWindowTitle(tr("Impulse Editor")); + m_graph.setForeground(PLUGIN_NAME::getIconPixmap("wavegraph4")); + m_graph.move(76, 21); + m_graph.resize(132, 104); + + m_impulse.move(23, 94); + m_impulse.setToolTip(tr("Impulse")); + + m_power.move(212, 130); + m_power.setToolTip(tr("Enable/disable string")); + + m_harmonic = std::make_unique( + std::array{ + PLUGIN_NAME::getIconPixmap("button_-2_on"), + PLUGIN_NAME::getIconPixmap("button_-2_off"), + PLUGIN_NAME::getIconPixmap("button_-1_on"), + PLUGIN_NAME::getIconPixmap("button_-1_off"), + PLUGIN_NAME::getIconPixmap("button_f_on"), + PLUGIN_NAME::getIconPixmap("button_f_off"), + PLUGIN_NAME::getIconPixmap("button_2_on"), + PLUGIN_NAME::getIconPixmap("button_2_off"), + PLUGIN_NAME::getIconPixmap("button_3_on"), + PLUGIN_NAME::getIconPixmap("button_3_off"), + PLUGIN_NAME::getIconPixmap("button_4_on"), + PLUGIN_NAME::getIconPixmap("button_4_off"), + PLUGIN_NAME::getIconPixmap("button_5_on"), + PLUGIN_NAME::getIconPixmap("button_5_off"), + PLUGIN_NAME::getIconPixmap("button_6_on"), + PLUGIN_NAME::getIconPixmap("button_6_off"), + PLUGIN_NAME::getIconPixmap("button_7_on"), + PLUGIN_NAME::getIconPixmap("button_7_off")}, 2, 21, 127, - this ); + this); - m_harmonic->setWindowTitle( tr( "Octave" ) ); - + m_harmonic->setWindowTitle(tr("Octave")); - m_stringSelector = new NineButtonSelector( - PLUGIN_NAME::getIconPixmap( "button_1_on" ), - PLUGIN_NAME::getIconPixmap( "button_1_off" ), - PLUGIN_NAME::getIconPixmap( "button_2_on" ), - PLUGIN_NAME::getIconPixmap( "button_2_off" ), - PLUGIN_NAME::getIconPixmap( "button_3_on" ), - PLUGIN_NAME::getIconPixmap( "button_3_off" ), - PLUGIN_NAME::getIconPixmap( "button_4_on" ), - PLUGIN_NAME::getIconPixmap( "button_4_off" ), - PLUGIN_NAME::getIconPixmap( "button_5_on" ), - PLUGIN_NAME::getIconPixmap( "button_5_off" ), - PLUGIN_NAME::getIconPixmap( "button_6_on" ), - PLUGIN_NAME::getIconPixmap( "button_6_off" ), - PLUGIN_NAME::getIconPixmap( "button_7_on" ), - PLUGIN_NAME::getIconPixmap( "button_7_off" ), - PLUGIN_NAME::getIconPixmap( "button_8_on" ), - PLUGIN_NAME::getIconPixmap( "button_8_off" ), - PLUGIN_NAME::getIconPixmap( "button_9_on" ), - PLUGIN_NAME::getIconPixmap( "button_9_off" ), - 0, - 21, 39, - this); + m_stringSelector = std::make_unique( + std::array{ + PLUGIN_NAME::getIconPixmap("button_1_on"), + PLUGIN_NAME::getIconPixmap("button_1_off"), + PLUGIN_NAME::getIconPixmap("button_2_on"), + PLUGIN_NAME::getIconPixmap("button_2_off"), + PLUGIN_NAME::getIconPixmap("button_3_on"), + PLUGIN_NAME::getIconPixmap("button_3_off"), + PLUGIN_NAME::getIconPixmap("button_4_on"), + PLUGIN_NAME::getIconPixmap("button_4_off"), + PLUGIN_NAME::getIconPixmap("button_5_on"), + PLUGIN_NAME::getIconPixmap("button_5_off"), + PLUGIN_NAME::getIconPixmap("button_6_on"), + PLUGIN_NAME::getIconPixmap("button_6_off"), + PLUGIN_NAME::getIconPixmap("button_7_on"), + PLUGIN_NAME::getIconPixmap("button_7_off"), + PLUGIN_NAME::getIconPixmap("button_8_on"), + PLUGIN_NAME::getIconPixmap("button_8_off"), + PLUGIN_NAME::getIconPixmap("button_9_on"), + PLUGIN_NAME::getIconPixmap("button_9_off")}, + 0, + 21, 39, + this); - m_graph = new Graph( this ); - m_graph->setWindowTitle( tr( "Impulse Editor" ) ); - m_graph->setForeground( PLUGIN_NAME::getIconPixmap( "wavegraph4" ) ); - m_graph->move( 76, 21 ); - m_graph->resize(132, 104); - - - m_power = new LedCheckBox( "", this, tr( "Enable waveform" ) ); - m_power->move( 212, 130 ); - m_power->setToolTip( - tr( "Enable/disable string" ) ); - - // String selector is not a part of the model - m_stringSelector->setWindowTitle( tr( "String" ) ); + m_stringSelector->setWindowTitle(tr("String")); - connect( m_stringSelector, SIGNAL( NineButtonSelection( int ) ), - this, SLOT( showString( int ) ) ); + connect(m_stringSelector.get(), SIGNAL(NineButtonSelection(int)), this, SLOT(showString(int))); - showString( 0 ); + showString(0); - m_sinWaveBtn = new PixmapButton( this, tr( "Sine wave" ) ); - m_sinWaveBtn->move( 212, 24 ); - m_sinWaveBtn->setActiveGraphic( embed::getIconPixmap( - "sin_wave_active" ) ); - m_sinWaveBtn->setInactiveGraphic( embed::getIconPixmap( - "sin_wave_inactive" ) ); - m_sinWaveBtn->setToolTip( - tr( "Sine wave" ) ); - connect( m_sinWaveBtn, SIGNAL (clicked () ), - this, SLOT ( sinWaveClicked() ) ); + m_smoothBtn.move(79, 129); + m_smoothBtn.setActiveGraphic(PLUGIN_NAME::getIconPixmap("smooth_active")); + m_smoothBtn.setInactiveGraphic(PLUGIN_NAME::getIconPixmap("smooth_inactive")); + m_smoothBtn.setChecked(false); + m_smoothBtn.setToolTip(tr("Smooth waveform")); + connect(&m_smoothBtn, SIGNAL(clicked()), this, SLOT(smoothClicked())); - - m_triangleWaveBtn = new PixmapButton( this, tr( "Triangle wave" ) ); - m_triangleWaveBtn->move( 212, 41 ); - m_triangleWaveBtn->setActiveGraphic( - embed::getIconPixmap( "triangle_wave_active" ) ); - m_triangleWaveBtn->setInactiveGraphic( - embed::getIconPixmap( "triangle_wave_inactive" ) ); - m_triangleWaveBtn->setToolTip( - tr( "Triangle wave" ) ); - connect( m_triangleWaveBtn, SIGNAL ( clicked () ), - this, SLOT ( triangleWaveClicked() ) ); + m_normalizeBtn.move(96, 129); + m_normalizeBtn.setActiveGraphic(PLUGIN_NAME::getIconPixmap("normalize_active")); + m_normalizeBtn.setInactiveGraphic(PLUGIN_NAME::getIconPixmap("normalize_inactive")); + m_normalizeBtn.setChecked(false); + m_normalizeBtn.setToolTip(tr("Normalize waveform")); + connect(&m_normalizeBtn, SIGNAL(clicked()), this, SLOT(normalizeClicked())); - - m_sawWaveBtn = new PixmapButton( this, tr( "Saw wave" ) ); - m_sawWaveBtn->move( 212, 58 ); - m_sawWaveBtn->setActiveGraphic( embed::getIconPixmap( - "saw_wave_active" ) ); - m_sawWaveBtn->setInactiveGraphic( embed::getIconPixmap( - "saw_wave_inactive" ) ); - m_sawWaveBtn->setToolTip( - tr( "Saw wave" ) ); - connect( m_sawWaveBtn, SIGNAL (clicked () ), - this, SLOT ( sawWaveClicked() ) ); + m_sinWaveBtn.move(212, 24); + m_sinWaveBtn.setActiveGraphic(embed::getIconPixmap("sin_wave_active")); + m_sinWaveBtn.setInactiveGraphic(embed::getIconPixmap("sin_wave_inactive")); + m_sinWaveBtn.setToolTip(tr("Sine wave")); + connect(&m_sinWaveBtn, SIGNAL(clicked()), this, SLOT(sinWaveClicked())); - - m_sqrWaveBtn = new PixmapButton( this, tr( "Square wave" ) ); - m_sqrWaveBtn->move( 212, 75 ); - m_sqrWaveBtn->setActiveGraphic( embed::getIconPixmap( - "square_wave_active" ) ); - m_sqrWaveBtn->setInactiveGraphic( embed::getIconPixmap( - "square_wave_inactive" ) ); - m_sqrWaveBtn->setToolTip( - tr( "Square wave" ) ); - connect( m_sqrWaveBtn, SIGNAL ( clicked () ), - this, SLOT ( sqrWaveClicked() ) ); + m_triangleWaveBtn.move(212, 41); + m_triangleWaveBtn.setActiveGraphic(embed::getIconPixmap("triangle_wave_active")); + m_triangleWaveBtn.setInactiveGraphic(embed::getIconPixmap("triangle_wave_inactive")); + m_triangleWaveBtn.setToolTip(tr("Triangle wave")); + connect(&m_triangleWaveBtn, SIGNAL(clicked()), this, SLOT(triangleWaveClicked())); - - m_whiteNoiseWaveBtn = new PixmapButton( this, tr( "White noise" ) ); - m_whiteNoiseWaveBtn->move( 212, 92 ); - m_whiteNoiseWaveBtn->setActiveGraphic( - embed::getIconPixmap( "white_noise_wave_active" ) ); - m_whiteNoiseWaveBtn->setInactiveGraphic( - embed::getIconPixmap( "white_noise_wave_inactive" ) ); - m_whiteNoiseWaveBtn->setToolTip( - tr( "White noise" ) ); - connect( m_whiteNoiseWaveBtn, SIGNAL ( clicked () ), - this, SLOT ( noiseWaveClicked() ) ); + m_sawWaveBtn.move(212, 58); + m_sawWaveBtn.setActiveGraphic(embed::getIconPixmap("saw_wave_active")); + m_sawWaveBtn.setInactiveGraphic(embed::getIconPixmap("saw_wave_inactive")); + m_sawWaveBtn.setToolTip(tr("Saw wave")); + connect(&m_sawWaveBtn, SIGNAL(clicked()), this, SLOT(sawWaveClicked())); - - m_usrWaveBtn = new PixmapButton( this, tr( "User-defined wave" ) ); - m_usrWaveBtn->move( 212, 109 ); - m_usrWaveBtn->setActiveGraphic( embed::getIconPixmap( - "usr_wave_active" ) ); - m_usrWaveBtn->setInactiveGraphic( embed::getIconPixmap( - "usr_wave_inactive" ) ); - m_usrWaveBtn->setToolTip( - tr( "User-defined wave" ) ); - connect( m_usrWaveBtn, SIGNAL ( clicked () ), - this, SLOT ( usrWaveClicked() ) ); + m_sqrWaveBtn.move(212, 75); + m_sqrWaveBtn.setActiveGraphic(embed::getIconPixmap("square_wave_active")); + m_sqrWaveBtn.setInactiveGraphic(embed::getIconPixmap("square_wave_inactive")); + m_sqrWaveBtn.setToolTip(tr("Square wave")); + connect(&m_sqrWaveBtn, SIGNAL(clicked()), this, SLOT(sqrWaveClicked())); + m_whiteNoiseWaveBtn.move(212, 92); + m_whiteNoiseWaveBtn.setActiveGraphic(embed::getIconPixmap("white_noise_wave_active")); + m_whiteNoiseWaveBtn.setInactiveGraphic(embed::getIconPixmap("white_noise_wave_inactive")); + m_whiteNoiseWaveBtn.setToolTip(tr("White noise")); + connect(&m_whiteNoiseWaveBtn, SIGNAL(clicked()), this, SLOT(noiseWaveClicked())); - m_smoothBtn = new PixmapButton( this, tr( "Smooth waveform" ) ); - m_smoothBtn->move( 79, 129 ); - m_smoothBtn->setActiveGraphic( PLUGIN_NAME::getIconPixmap( - "smooth_active" ) ); - m_smoothBtn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( - "smooth_inactive" ) ); - m_smoothBtn->setChecked( false ); - m_smoothBtn->setToolTip( - tr( "Smooth waveform" ) ); - connect( m_smoothBtn, SIGNAL ( clicked () ), - this, SLOT ( smoothClicked() ) ); - - m_normalizeBtn = new PixmapButton( this, tr( "Normalize waveform" ) ); - m_normalizeBtn->move( 96, 129 ); - m_normalizeBtn->setActiveGraphic( PLUGIN_NAME::getIconPixmap( - "normalize_active" ) ); - m_normalizeBtn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( - "normalize_inactive" ) ); - m_normalizeBtn->setChecked( false ); - m_normalizeBtn->setToolTip( - tr( "Normalize waveform" ) ); - - connect( m_normalizeBtn, SIGNAL ( clicked () ), - this, SLOT ( normalizeClicked() ) ); - + m_usrWaveBtn.move(212, 109); + m_usrWaveBtn.setActiveGraphic(embed::getIconPixmap("usr_wave_active")); + m_usrWaveBtn.setInactiveGraphic(embed::getIconPixmap("usr_wave_inactive")); + m_usrWaveBtn.setToolTip(tr("User-defined wave")); + connect(&m_usrWaveBtn, SIGNAL(clicked()),this, SLOT(usrWaveClicked())); } - - - void VibedView::modelChanged() { - showString( 0 ); + showString(0); } - - - -void VibedView::showString( int _string ) +void VibedView::showString(int str) { auto v = castModel(); - m_pickKnob->setModel( v->m_pickKnobs[_string] ); - m_pickupKnob->setModel( v->m_pickupKnobs[_string] ); - m_stiffnessKnob->setModel( v->m_stiffnessKnobs[_string] ); - m_volumeKnob->setModel( v->m_volumeKnobs[_string] ); - m_panKnob->setModel( v->m_panKnobs[_string] ); - m_detuneKnob->setModel( v->m_detuneKnobs[_string] ); - m_randomKnob->setModel( v->m_randomKnobs[_string] ); - m_lengthKnob->setModel( v->m_lengthKnobs[_string] ); - m_graph->setModel( v->m_graphs[_string] ); - m_impulse->setModel( v->m_impulses[_string] ); - m_harmonic->setModel( v->m_harmonics[_string] ); - m_power->setModel( v->m_powerButtons[_string] ); - + m_pickKnob.setModel(v->m_pickModels[str].get()); + m_pickupKnob.setModel(v->m_pickupModels[str].get()); + m_stiffnessKnob.setModel(v->m_stiffnessModels[str].get()); + m_volumeKnob.setModel(v->m_volumeModels[str].get()); + m_panKnob.setModel(v->m_panModels[str].get()); + m_detuneKnob.setModel(v->m_detuneModels[str].get()); + m_randomKnob.setModel(v->m_randomModels[str].get()); + m_lengthKnob.setModel(v->m_lengthModels[str].get()); + m_graph.setModel(v->m_graphModels[str].get()); + m_impulse.setModel(v->m_impulseModels[str].get()); + m_harmonic->setModel(v->m_harmonicModels[str].get()); + m_power.setModel(v->m_powerModels[str].get()); } - - - void VibedView::sinWaveClicked() { - m_graph->model()->setWaveToSine(); + m_graph.model()->setWaveToSine(); Engine::getSong()->setModified(); } - - void VibedView::triangleWaveClicked() { - m_graph->model()->setWaveToTriangle(); + m_graph.model()->setWaveToTriangle(); Engine::getSong()->setModified(); } - - void VibedView::sawWaveClicked() { - m_graph->model()->setWaveToSaw(); + m_graph.model()->setWaveToSaw(); Engine::getSong()->setModified(); } - - void VibedView::sqrWaveClicked() { - m_graph->model()->setWaveToSquare(); + m_graph.model()->setWaveToSquare(); Engine::getSong()->setModified(); } - - void VibedView::noiseWaveClicked() { - m_graph->model()->setWaveToNoise(); + m_graph.model()->setWaveToNoise(); Engine::getSong()->setModified(); } - - void VibedView::usrWaveClicked() { - QString fileName = m_graph->model()->setWaveToUser(); - m_usrWaveBtn->setToolTip(fileName); + QString fileName = m_graph.model()->setWaveToUser(); + m_usrWaveBtn.setToolTip(fileName); Engine::getSong()->setModified(); } - - void VibedView::smoothClicked() { - m_graph->model()->smooth(); + m_graph.model()->smooth(); Engine::getSong()->setModified(); } - - void VibedView::normalizeClicked() { - m_graph->model()->normalize(); + m_graph.model()->normalize(); Engine::getSong()->setModified(); } - - - -void VibedView::contextMenuEvent( QContextMenuEvent * ) +void VibedView::contextMenuEvent(QContextMenuEvent*) { - - CaptionMenu contextMenu( model()->displayName(), this ); - contextMenu.exec( QCursor::pos() ); - + CaptionMenu contextMenu(model()->displayName(), this); + contextMenu.exec(QCursor::pos()); } @@ -683,12 +526,11 @@ extern "C" { // necessary for getting instance out of shared lib -PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * ) +PLUGIN_EXPORT Plugin* lmms_plugin_main(Model* m, void*) { - return( new Vibed( static_cast( m ) ) ); + return new Vibed(static_cast(m)); } - } diff --git a/plugins/Vibed/Vibed.h b/plugins/Vibed/Vibed.h index 75f92157c..18d334c4d 100644 --- a/plugins/Vibed/Vibed.h +++ b/plugins/Vibed/Vibed.h @@ -2,7 +2,7 @@ * Vibed.h - combination of PluckedStringSynth and BitInvader * * Copyright (c) 2006-2008 Danny McRae - * + * * This file is part of LMMS - https://lmms.io * * This program is free software; you can redistribute it and/or @@ -21,12 +21,20 @@ * Boston, MA 02110-1301 USA. * */ -#ifndef _VIBED_H -#define _VIBED_H + +#ifndef LMMS_VIBED_H +#define LMMS_VIBED_H #include "Instrument.h" #include "InstrumentView.h" #include "NineButtonSelector.h" +#include "Knob.h" +#include "LedCheckBox.h" +#include "Graph.h" +#include "PixmapButton.h" + +#include +#include namespace lmms { @@ -46,45 +54,42 @@ class Vibed : public Instrument { Q_OBJECT public: - Vibed( InstrumentTrack * _instrument_track ); + Vibed(InstrumentTrack* instrumentTrack); + ~Vibed() override = default; - void playNote( NotePlayHandle * _n, - sampleFrame * _working_buffer ) override; - void deleteNotePluginData( NotePlayHandle * _n ) override; + void playNote(NotePlayHandle* n, sampleFrame* workingBuffer) override; + void deleteNotePluginData(NotePlayHandle* n) override; - - void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; - void loadSettings( const QDomElement & _this ) override; + void saveSettings(QDomDocument& doc, QDomElement& elem) override; + void loadSettings(const QDomElement& elem) override; QString nodeName() const override; - Flags flags() const override - { - return IsNotBendable; - } - - - gui::PluginView* instantiateView( QWidget * _parent ) override; + Flags flags() const override { return Flag::IsNotBendable; } + gui::PluginView* instantiateView(QWidget* parent) override; private: - QList m_pickKnobs; - QList m_pickupKnobs; - QList m_stiffnessKnobs; - QList m_volumeKnobs; - QList m_panKnobs; - QList m_detuneKnobs; - QList m_randomKnobs; - QList m_lengthKnobs; - QList m_powerButtons; - QList m_graphs; - QList m_impulses; - QList m_harmonics; + class StringContainer; - static const int __sampleLength = 128; + static constexpr int s_sampleLength = 128; + static constexpr int s_stringCount = 9; + + std::array, s_stringCount> m_pickModels; + std::array, s_stringCount> m_pickupModels; + std::array, s_stringCount> m_stiffnessModels; + std::array, s_stringCount> m_volumeModels; + std::array, s_stringCount> m_panModels; + std::array, s_stringCount> m_detuneModels; + std::array, s_stringCount> m_randomModels; + std::array, s_stringCount> m_lengthModels; + std::array, s_stringCount> m_powerModels; + std::array, s_stringCount> m_graphModels; + std::array, s_stringCount> m_impulseModels; + std::array, s_stringCount> m_harmonicModels; friend class gui::VibedView; -} ; +}; namespace gui @@ -95,13 +100,12 @@ class VibedView : public InstrumentViewFixedSize { Q_OBJECT public: - VibedView( Instrument * _instrument, - QWidget * _parent ); + VibedView(Instrument* instrument, QWidget* parent); ~VibedView() override = default; public slots: - void showString( int _string ); - void contextMenuEvent( QContextMenuEvent * ) override; + void showString(int str); + void contextMenuEvent(QContextMenuEvent*) override; protected slots: void sinWaveClicked(); @@ -116,35 +120,32 @@ protected slots: private: void modelChanged() override; - // String-related - Knob * m_pickKnob; - Knob * m_pickupKnob; - Knob * m_stiffnessKnob; - Knob * m_volumeKnob; - Knob * m_panKnob; - Knob * m_detuneKnob; - Knob * m_randomKnob; - Knob * m_lengthKnob; - Graph * m_graph; - NineButtonSelector * m_harmonic; - LedCheckBox * m_impulse; - LedCheckBox * m_power; + Knob m_volumeKnob; + Knob m_stiffnessKnob; + Knob m_pickKnob; + Knob m_pickupKnob; + Knob m_panKnob; + Knob m_detuneKnob; + Knob m_randomKnob; + Knob m_lengthKnob; + Graph m_graph; + LedCheckBox m_impulse; + LedCheckBox m_power; + std::unique_ptr m_harmonic; // Not in model - NineButtonSelector * m_stringSelector; - PixmapButton * m_smoothBtn; - PixmapButton * m_normalizeBtn; + std::unique_ptr m_stringSelector; + PixmapButton m_smoothBtn; + PixmapButton m_normalizeBtn; // From impulse editor - PixmapButton * m_sinWaveBtn; - PixmapButton * m_triangleWaveBtn; - PixmapButton * m_sqrWaveBtn; - PixmapButton * m_sawWaveBtn; - PixmapButton * m_whiteNoiseWaveBtn; - PixmapButton * m_usrWaveBtn; - - + PixmapButton m_sinWaveBtn; + PixmapButton m_triangleWaveBtn; + PixmapButton m_sawWaveBtn; + PixmapButton m_sqrWaveBtn; + PixmapButton m_whiteNoiseWaveBtn; + PixmapButton m_usrWaveBtn; }; @@ -152,4 +153,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_VIBED_H diff --git a/plugins/Vibed/VibratingString.cpp b/plugins/Vibed/VibratingString.cpp index e33ef0582..44ade3c3a 100644 --- a/plugins/Vibed/VibratingString.cpp +++ b/plugins/Vibed/VibratingString.cpp @@ -1,8 +1,8 @@ /* - * vibrating_sring.h - model of a vibrating string lifted from pluckedSynth + * VibratingString.cpp - model of a vibrating string lifted from pluckedSynth * * Copyright (c) 2006-2008 Danny McRae - * + * * This file is part of LMMS - https://lmms.io * * This program is free software; you can redistribute it and/or @@ -21,93 +21,66 @@ * Boston, MA 02110-1301 USA. * */ -#include #include "VibratingString.h" #include "interpolation.h" #include "AudioEngine.h" #include "Engine.h" +#include +#include + namespace lmms { -VibratingString::VibratingString( float _pitch, - float _pick, - float _pickup, - float * _impulse, - int _len, - sample_rate_t _sample_rate, - int _oversample, - float _randomize, - float _string_loss, - float _detune, - bool _state ) : - m_oversample( 2 * _oversample / (int)( _sample_rate / - Engine::audioEngine()->baseSampleRate() ) ), - m_randomize( _randomize ), - m_stringLoss( 1.0f - _string_loss ), - m_state( 0.1f ) +VibratingString::VibratingString(float pitch, float pick, float pickup, const float* impulse, int len, + sample_rate_t sampleRate, int oversample, float randomize, float stringLoss, float detune, bool state) : + m_oversample{2 * oversample / static_cast(sampleRate / Engine::audioEngine()->baseSampleRate())}, + m_randomize{randomize}, + m_stringLoss{1.0f - stringLoss}, + m_choice{static_cast(m_oversample * static_cast(std::rand()) / RAND_MAX)}, + m_state{0.1f}, + m_outsamp{std::make_unique(m_oversample)} { - m_outsamp = new sample_t[m_oversample]; - int string_length; - - string_length = static_cast( m_oversample * _sample_rate / - _pitch ) + 1; - string_length += static_cast( string_length * -_detune ); + int stringLength = static_cast(m_oversample * sampleRate / pitch) + 1; + stringLength += static_cast(stringLength * -detune); - int pick = static_cast( ceil( string_length * _pick ) ); - - if( ! _state ) + const int pickInt = static_cast(std::ceil(stringLength * pick)); + + if (!state) { - m_impulse = new float[string_length]; - resample( _impulse, _len, string_length ); + m_impulse = std::make_unique(stringLength); + resample(impulse, len, stringLength); } else - { - m_impulse = new float[_len]; - for( int i = 0; i < _len; i++ ) - { - m_impulse[i] = _impulse[i]; - } + { + m_impulse = std::make_unique(len); + std::copy_n(impulse, len, m_impulse.get()); } - - m_toBridge = VibratingString::initDelayLine( string_length, pick ); - m_fromBridge = VibratingString::initDelayLine( string_length, pick ); - - VibratingString::setDelayLine( m_toBridge, pick, - m_impulse, _len, 0.5f, - _state ); - VibratingString::setDelayLine( m_fromBridge, pick, - m_impulse, _len, 0.5f, - _state); - - m_choice = static_cast( m_oversample * - static_cast( rand() ) / RAND_MAX ); - - m_pickupLoc = static_cast( _pickup * string_length ); + m_toBridge = VibratingString::initDelayLine(stringLength); + m_fromBridge = VibratingString::initDelayLine(stringLength); + + VibratingString::setDelayLine(m_toBridge.get(), pickInt, m_impulse.get(), len, 0.5f, state); + VibratingString::setDelayLine(m_fromBridge.get(), pickInt, m_impulse.get(), len, 0.5f, state); + + m_pickupLoc = static_cast(pickup * stringLength); } - - - -VibratingString::delayLine * VibratingString::initDelayLine( int _len, - int _pick ) +std::unique_ptr VibratingString::initDelayLine(int len) { - auto dl = new VibratingString::delayLine[_len]; - dl->length = _len; - if( _len > 0 ) + auto dl = std::make_unique(); + dl->length = len; + if (len > 0) { - dl->data = new sample_t[_len]; + dl->data = std::make_unique(len); float r; float offset = 0.0f; - for( int i = 0; i < dl->length; i++ ) + for (int i = 0; i < dl->length; ++i) { - r = static_cast( rand() ) / - RAND_MAX; - offset = ( m_randomize / 2.0f - - m_randomize ) * r; + r = static_cast(std::rand()) / RAND_MAX; + offset = (m_randomize / 2.0f - m_randomize) * r; dl->data[i] = offset; } } @@ -116,46 +89,25 @@ VibratingString::delayLine * VibratingString::initDelayLine( int _len, dl->data = nullptr; } - dl->pointer = dl->data; - dl->end = dl->data + _len - 1; + dl->pointer = dl->data.get(); + dl->end = dl->data.get() + len - 1; - return( dl ); + return dl; } - - - -void VibratingString::freeDelayLine( delayLine * _dl ) +void VibratingString::resample(const float* src, f_cnt_t srcFrames, f_cnt_t dstFrames) { - if( _dl ) + for (f_cnt_t frame = 0; frame < dstFrames; ++frame) { - delete[] _dl->data; - delete[] _dl; - } -} - - - - -void VibratingString::resample( float *_src, f_cnt_t _src_frames, - f_cnt_t _dst_frames ) -{ - for( f_cnt_t frame = 0; frame < _dst_frames; ++frame ) - { - const float src_frame_float = frame * - (float) _src_frames / - _dst_frames; - const float frac_pos = src_frame_float - - static_cast( src_frame_float ); - const f_cnt_t src_frame = qBound( - 1, static_cast( src_frame_float ), - _src_frames - 3 ); + const float srcFrameFloat = frame * static_cast(srcFrames) / dstFrames; + const float fracPos = srcFrameFloat - static_cast(srcFrameFloat); + const f_cnt_t srcFrame = std::clamp(static_cast(srcFrameFloat), 1, srcFrames - 3); m_impulse[frame] = cubicInterpolate( - _src[src_frame - 1], - _src[src_frame + 0], - _src[src_frame + 1], - _src[src_frame + 2], - frac_pos ); + src[srcFrame - 1], + src[srcFrame + 0], + src[srcFrame + 1], + src[srcFrame + 2], + fracPos); } } diff --git a/plugins/Vibed/VibratingString.h b/plugins/Vibed/VibratingString.h index ed7cbe38c..efdaec282 100644 --- a/plugins/Vibed/VibratingString.h +++ b/plugins/Vibed/VibratingString.h @@ -2,7 +2,7 @@ * VibratingString.h - model of a vibrating string lifted from pluckedSynth * * Copyright (c) 2006-2007 Danny McRae - * + * * This file is part of LMMS - https://lmms.io * * This program is free software; you can redistribute it and/or @@ -21,10 +21,12 @@ * Boston, MA 02110-1301 USA. * */ -#ifndef _VIBRATING_STRING_H -#define _VIBRATING_STRING_H -#include +#ifndef LMMS_VIBRATING_STRING_H +#define LMMS_VIBRATING_STRING_H + +#include +#include #include "lmms_basics.h" @@ -34,244 +36,219 @@ namespace lmms class VibratingString { - public: - VibratingString( float _pitch, - float _pick, - float _pickup, - float * impluse, - int _len, - sample_rate_t _sample_rate, - int _oversample, - float _randomize, - float _string_loss, - float _detune, - bool _state ); - - inline ~VibratingString() - { - delete[] m_outsamp; - delete[] m_impulse; - VibratingString::freeDelayLine( m_fromBridge ); - VibratingString::freeDelayLine( m_toBridge ); - } + VibratingString() = default; + VibratingString(float pitch, float pick, float pickup, const float* impulse, int len, + sample_rate_t sampleRate, int oversample, float randomize, float stringLoss, float detune, bool state); + ~VibratingString() = default; - inline sample_t nextSample() - { + VibratingString(const VibratingString&) = delete; + VibratingString& operator=(const VibratingString&) = delete; + VibratingString(VibratingString&&) noexcept = delete; + VibratingString& operator=(VibratingString&&) noexcept = default; + + sample_t nextSample() + { sample_t ym0; sample_t ypM; - for( int i = 0; i < m_oversample; i++) + for (int i = 0; i < m_oversample; ++i) { // Output at pickup position - m_outsamp[i] = fromBridgeAccess( m_fromBridge, - m_pickupLoc ); - m_outsamp[i] += toBridgeAccess( m_toBridge, - m_pickupLoc ); - + m_outsamp[i] = fromBridgeAccess(m_fromBridge.get(), m_pickupLoc); + m_outsamp[i] += toBridgeAccess(m_toBridge.get(), m_pickupLoc); + // Sample traveling into "bridge" - ym0 = toBridgeAccess( m_toBridge, 1 ); + ym0 = toBridgeAccess(m_toBridge.get(), 1); // Sample to "nut" - ypM = fromBridgeAccess( m_fromBridge, - m_fromBridge->length - 2 ); + ypM = fromBridgeAccess(m_fromBridge.get(), m_fromBridge->length - 2); // String state update // Decrement pointer and then update - fromBridgeUpdate( m_fromBridge, - -bridgeReflection( ym0 ) ); + fromBridgeUpdate(m_fromBridge.get(), -bridgeReflection(ym0)); // Update and then increment pointer - toBridgeUpdate( m_toBridge, -ypM ); + toBridgeUpdate(m_toBridge.get(), -ypM); } - return( m_outsamp[m_choice] ); + + return m_outsamp[m_choice]; } private: - struct delayLine + struct DelayLine { - sample_t * data; + std::unique_ptr data; int length; - sample_t * pointer; - sample_t * end; - } ; + sample_t* pointer; + sample_t* end; + }; - delayLine * m_fromBridge; - delayLine * m_toBridge; + std::unique_ptr m_fromBridge; + std::unique_ptr m_toBridge; int m_pickupLoc; int m_oversample; float m_randomize; float m_stringLoss; - - float * m_impulse; + + std::unique_ptr m_impulse; int m_choice; float m_state; - - sample_t * m_outsamp; - delayLine * initDelayLine( int _len, int _pick ); - static void freeDelayLine( delayLine * _dl ); - void resample( float *_src, f_cnt_t _src_frames, f_cnt_t _dst_frames ); - - /* setDelayLine initializes the string with an impulse at the pick + std::unique_ptr m_outsamp; + + std::unique_ptr initDelayLine(int len); + void resample(const float* src, f_cnt_t srcFrames, f_cnt_t dstFrames); + + /** + * setDelayLine initializes the string with an impulse at the pick * position unless the impulse is longer than the string, in which - * case the impulse gets truncated. */ - inline void setDelayLine( delayLine * _dl, - int _pick, - const float * _values, - int _len, - float _scale, - bool _state ) + * case the impulse gets truncated. + */ + void setDelayLine(DelayLine* dl, int pick, const float* values, int len, float scale, bool state) { float r; float offset; - - if( ! _state ) + + if (!state) { - for( int i = 0; i < _pick; i++ ) + for (int i = 0; i < pick; ++i) { - r = static_cast( rand() ) / - RAND_MAX; - offset = ( m_randomize / 2.0f - - m_randomize ) * r; - _dl->data[i] = _scale * - _values[_dl->length - i - 1] + - offset; + r = static_cast(std::rand()) / RAND_MAX; + offset = (m_randomize / 2.0f - m_randomize) * r; + dl->data[i] = scale * values[dl->length - i - 1] + offset; } - for( int i = _pick; i < _dl->length; i++ ) + for (int i = pick; i < dl->length; ++i) { - r = static_cast( rand() ) / - RAND_MAX; - offset = ( m_randomize / 2.0f - - m_randomize ) * r; - _dl->data[i] = _scale * - _values[i - _pick] + offset ; + r = static_cast(std::rand()) / RAND_MAX; + offset = (m_randomize / 2.0f - m_randomize) * r; + dl->data[i] = scale * values[i - pick] + offset; } } else { - if( _len + _pick > _dl->length ) + if (len + pick > dl->length) { - for( int i = _pick; i < _dl->length; i++ ) + for (int i = pick; i < dl->length; ++i) { - r = static_cast( rand() ) / - RAND_MAX; - offset = ( m_randomize / 2.0f - - m_randomize ) * r; - _dl->data[i] = _scale * - _values[i-_pick] + - offset; + r = static_cast(std::rand()) / RAND_MAX; + offset = (m_randomize / 2.0f - m_randomize) * r; + dl->data[i] = scale * values[i - pick] + offset; } } else { - for( int i = 0; i < _len; i++ ) + for (int i = 0; i < len; ++i) { - r = static_cast( rand() ) / - RAND_MAX; - offset = ( m_randomize / 2.0f - - m_randomize ) * r; - _dl->data[i+_pick] = _scale * - _values[i] + - offset; + r = static_cast(std::rand()) / RAND_MAX; + offset = (m_randomize / 2.0f - m_randomize) * r; + dl->data[i+pick] = scale * values[i] + offset; } } } } - /* toBridgeUpdate(dl, insamp); - * Places "nut-reflected" sample from upper delay-line into - * current lower delay-line pointer position (which represents - * x = 0 position). The pointer is then incremented (i.e. the - * wave travels one sample to the left), turning the previous - * position into an "effective" x = L position for the next - * iteration. */ - inline void toBridgeUpdate( delayLine * _dl, sample_t _insamp ) + /** + * toBridgeUpdate(dl, insamp); + * Places "nut-reflected" sample from upper delay-line into + * current lower delay-line pointer position (which represents + * x = 0 position). The pointer is then incremented (i.e. the + * wave travels one sample to the left), turning the previous + * position into an "effective" x = L position for the next + * iteration. + */ + void toBridgeUpdate(DelayLine* dl, sample_t insamp) { - sample_t * ptr = _dl->pointer; - *ptr = _insamp * m_stringLoss; + sample_t* ptr = dl->pointer; + *ptr = insamp * m_stringLoss; ++ptr; - if( ptr > _dl->end ) + if (ptr > dl->end) { - ptr = _dl->data; + ptr = dl->data.get(); } - _dl->pointer = ptr; + dl->pointer = ptr; } - /* fromBridgeUpdate(dl, insamp); - * Decrements current upper delay-line pointer position (i.e. - * the wave travels one sample to the right), moving it to the - * "effective" x = 0 position for the next iteration. The - * "bridge-reflected" sample from lower delay-line is then placed - * into this position. */ - inline void fromBridgeUpdate( delayLine * _dl, - sample_t _insamp ) + /** + * fromBridgeUpdate(dl, insamp); + * Decrements current upper delay-line pointer position (i.e. + * the wave travels one sample to the right), moving it to the + * "effective" x = 0 position for the next iteration. The + * "bridge-reflected" sample from lower delay-line is then placed + * into this position. + */ + void fromBridgeUpdate(DelayLine* dl, sample_t insamp) { - sample_t * ptr = _dl->pointer; + sample_t* ptr = dl->pointer; --ptr; - if( ptr < _dl->data ) + if (ptr < dl->data.get()) { - ptr = _dl->end; + ptr = dl->end; } - *ptr = _insamp * m_stringLoss; - _dl->pointer = ptr; + *ptr = insamp * m_stringLoss; + dl->pointer = ptr; } - /* dlAccess(dl, position); - * Returns sample "position" samples into delay-line's past. - * Position "0" points to the most recently inserted sample. */ - static inline sample_t dlAccess( delayLine * _dl, int _position ) + /** + * dlAccess(dl, position); + * Returns sample "position" samples into delay-line's past. + * Position "0" points to the most recently inserted sample. + */ + static sample_t dlAccess(DelayLine* dl, int position) { - sample_t * outpos = _dl->pointer + _position; - while( outpos < _dl->data ) + sample_t* outpos = dl->pointer + position; + while (outpos < dl->data.get()) { - outpos += _dl->length; + outpos += dl->length; } - while( outpos > _dl->end ) + while (outpos > dl->end) { - outpos -= _dl->length; + outpos -= dl->length; } - return( *outpos ); + return *outpos; } /* - * Right-going delay line: - * -->---->---->--- - * x=0 - * (pointer) - * Left-going delay line: - * --<----<----<--- - * x=0 - * (pointer) - */ + * Right-going delay line: + * -->---->---->--- + * x=0 + * (pointer) + * Left-going delay line: + * --<----<----<--- + * x=0 + * (pointer) + */ - /* fromBridgeAccess(dl, position); - * Returns spatial sample at position "position", where position zero - * is equal to the current upper delay-line pointer position (x = 0). - * In a right-going delay-line, position increases to the right, and - * delay increases to the right => left = past and right = future. */ - static inline sample_t fromBridgeAccess( delayLine * _dl, - int _position ) + /** + * fromBridgeAccess(dl, position); + * Returns spatial sample at position "position", where position zero + * is equal to the current upper delay-line pointer position (x = 0). + * In a right-going delay-line, position increases to the right, and + * delay increases to the right => left = past and right = future. + */ + static sample_t fromBridgeAccess(DelayLine* dl, int position) { - return( dlAccess( _dl, _position ) ); + return dlAccess(dl, position); } - /* toBridgeAccess(dl, position); - * Returns spatial sample at position "position", where position zero - * is equal to the current lower delay-line pointer position (x = 0). - * In a left-going delay-line, position increases to the right, and - * delay DEcreases to the right => left = future and right = past. */ - static inline sample_t toBridgeAccess( delayLine * _dl, int _position ) + /** + * toBridgeAccess(dl, position); + * Returns spatial sample at position "position", where position zero + * is equal to the current lower delay-line pointer position (x = 0). + * In a left-going delay-line, position increases to the right, and + * delay DEcreases to the right => left = future and right = past. + */ + static sample_t toBridgeAccess(DelayLine* dl, int position) { - return( dlAccess( _dl, _position ) ); + return dlAccess(dl, position); } - inline sample_t bridgeReflection( sample_t _insamp ) + sample_t bridgeReflection(sample_t insamp) { - return( m_state = ( m_state + _insamp ) * 0.5 ); + m_state = (m_state + insamp) * 0.5; + return m_state; } - -} ; +}; } // namespace lmms -#endif +#endif // LMMS_VIBRATING_STRING_H diff --git a/plugins/VstBase/RemoteVstPlugin.cpp b/plugins/VstBase/RemoteVstPlugin.cpp index aaa88f6c8..0ec60bea4 100644 --- a/plugins/VstBase/RemoteVstPlugin.cpp +++ b/plugins/VstBase/RemoteVstPlugin.cpp @@ -127,7 +127,7 @@ struct ERect using namespace std; -static lmms::VstHostLanguages hlang = lmms::LanguageEnglish; +static lmms::VstHostLanguage hlang = lmms::VstHostLanguage::English; static bool EMBED = false; static bool EMBED_X11 = false; @@ -390,7 +390,7 @@ public: #endif private: - enum GuiThreadMessages + enum class GuiThreadMessage { None, ProcessPluginMessage, @@ -628,7 +628,7 @@ bool RemoteVstPlugin::processMessage( const message & _m ) break; case IdVstSetLanguage: - hlang = static_cast( _m.getInt() ); + hlang = static_cast( _m.getInt() ); break; case IdVstGetParameterDump: @@ -1763,7 +1763,7 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, // call application idle routine (this will // call effEditIdle for all open editors too) #ifndef NATIVE_LINUX_VST - PostMessage( __MessageHwnd, WM_USER, GiveIdle, 0 ); + PostMessage( __MessageHwnd, WM_USER, static_cast(GuiThreadMessage::GiveIdle), 0 ); #else __plugin->sendX11Idle(); #endif @@ -2066,7 +2066,7 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, case audioMasterGetLanguage: SHOW_CALLBACK( "amc: audioMasterGetLanguage\n" ); - return hlang; + return static_cast(hlang); case audioMasterGetDirectory: SHOW_CALLBACK( "amc: audioMasterGetDirectory\n" ); @@ -2077,7 +2077,7 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, SHOW_CALLBACK( "amc: audioMasterUpdateDisplay\n" ); // something has changed, update 'multi-fx' display #ifndef NATIVE_LINUX_VST - PostMessage( __MessageHwnd, WM_USER, GiveIdle, 0 ); + PostMessage( __MessageHwnd, WM_USER, static_cast(GuiThreadMessage::GiveIdle), 0 ); #else __plugin->sendX11Idle(); #endif @@ -2234,7 +2234,7 @@ void * RemoteVstPlugin::processingThread(void * _param) #ifndef NATIVE_LINUX_VST PostMessage( __MessageHwnd, WM_USER, - ProcessPluginMessage, + static_cast(GuiThreadMessage::ProcessPluginMessage), (LPARAM) new message( m ) ); #else _this->queueMessage( m ); @@ -2244,7 +2244,7 @@ void * RemoteVstPlugin::processingThread(void * _param) // notify GUI thread about shutdown #ifndef NATIVE_LINUX_VST - PostMessage( __MessageHwnd, WM_USER, ClosePlugin, 0 ); + PostMessage( __MessageHwnd, WM_USER, static_cast(GuiThreadMessage::ClosePlugin), 0 ); return 0; #else @@ -2349,9 +2349,9 @@ LRESULT CALLBACK RemoteVstPlugin::wndProc( HWND hwnd, UINT uMsg, } else if( uMsg == WM_USER ) { - switch( wParam ) + switch( static_cast(wParam) ) { - case ProcessPluginMessage: + case GuiThreadMessage::ProcessPluginMessage: { message * m = (message *) lParam; __plugin->queueMessage( *m ); @@ -2363,11 +2363,11 @@ LRESULT CALLBACK RemoteVstPlugin::wndProc( HWND hwnd, UINT uMsg, return 0; } - case GiveIdle: + case GuiThreadMessage::GiveIdle: __plugin->idle(); return 0; - case ClosePlugin: + case GuiThreadMessage::ClosePlugin: PostQuitMessage(0); return 0; diff --git a/plugins/VstBase/VstPlugin.cpp b/plugins/VstBase/VstPlugin.cpp index c3fe17d72..b23ae39bf 100644 --- a/plugins/VstBase/VstPlugin.cpp +++ b/plugins/VstBase/VstPlugin.cpp @@ -216,18 +216,18 @@ void VstPlugin::tryLoad( const QString &remoteVstPluginExecutable ) lock(); - VstHostLanguages hlang = LanguageEnglish; + VstHostLanguage hlang = VstHostLanguage::English; switch( QLocale::system().language() ) { - case QLocale::French: hlang = LanguageFrench; break; - case QLocale::German: hlang = LanguageGerman; break; - case QLocale::Italian: hlang = LanguageItalian; break; - case QLocale::Japanese: hlang = LanguageJapanese; break; - case QLocale::Korean: hlang = LanguageKorean; break; - case QLocale::Spanish: hlang = LanguageSpanish; break; + case QLocale::French: hlang = VstHostLanguage::French; break; + case QLocale::German: hlang = VstHostLanguage::German; break; + case QLocale::Italian: hlang = VstHostLanguage::Italian; break; + case QLocale::Japanese: hlang = VstHostLanguage::Japanese; break; + case QLocale::Korean: hlang = VstHostLanguage::Korean; break; + case QLocale::Spanish: hlang = VstHostLanguage::Spanish; break; default: break; } - sendMessage( message( IdVstSetLanguage ).addInt( hlang ) ); + sendMessage( message( IdVstSetLanguage ).addInt( static_cast(hlang) ) ); sendMessage( message( IdVstLoadPlugin ).addString( QSTR_TO_STDSTR( m_plugin ) ) ); waitForInitDone(); diff --git a/plugins/VstBase/communication.h b/plugins/VstBase/communication.h index 1f32dd135..50351d38e 100644 --- a/plugins/VstBase/communication.h +++ b/plugins/VstBase/communication.h @@ -40,15 +40,15 @@ struct VstParameterDumpItem -enum VstHostLanguages +enum class VstHostLanguage { - LanguageEnglish = 1, - LanguageGerman, - LanguageFrench, - LanguageItalian, - LanguageSpanish, - LanguageJapanese, - LanguageKorean + English = 1, + German, + French, + Italian, + Spanish, + Japanese, + Korean } ; diff --git a/plugins/VstBase/vst_base.cpp b/plugins/VstBase/vst_base.cpp index 80cb9d736..154dca975 100644 --- a/plugins/VstBase/vst_base.cpp +++ b/plugins/VstBase/vst_base.cpp @@ -41,7 +41,7 @@ Plugin::Descriptor VSTBASE_EXPORT vstbase_plugin_descriptor = "library for all LMMS plugins dealing with VST-plugins", "Tobias Doerffel ", 0x0100, - Plugin::Library, + Plugin::Type::Library, nullptr, nullptr, } ; diff --git a/plugins/VstEffect/VstEffect.cpp b/plugins/VstEffect/VstEffect.cpp index c3e40cfa7..bdbdea806 100644 --- a/plugins/VstEffect/VstEffect.cpp +++ b/plugins/VstEffect/VstEffect.cpp @@ -49,10 +49,10 @@ Plugin::Descriptor PLUGIN_EXPORT vsteffect_plugin_descriptor = "plugin for using arbitrary VST effects inside LMMS." ), "Tobias Doerffel ", 0x0200, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader("logo"), nullptr, - new VstSubPluginFeatures( Plugin::Effect ) + new VstSubPluginFeatures( Plugin::Type::Effect ) } ; } diff --git a/plugins/VstEffect/VstEffectControlDialog.cpp b/plugins/VstEffect/VstEffectControlDialog.cpp index 52160af57..5bee94155 100644 --- a/plugins/VstEffect/VstEffectControlDialog.cpp +++ b/plugins/VstEffect/VstEffectControlDialog.cpp @@ -48,6 +48,16 @@ VstEffectControlDialog::VstEffectControlDialog( VstEffectControls * _ctl ) : m_plugin( nullptr ), tbLabel( nullptr ) { +#if QT_VERSION < 0x50C00 + // Workaround for a bug in Qt versions below 5.12, + // where argument-dependent-lookup fails for QFlags operators + // declared inside a namepsace. + // This affects the Q_DECLARE_OPERATORS_FOR_FLAGS macro in Instrument.h + // See also: https://codereview.qt-project.org/c/qt/qtbase/+/225348 + + using ::operator|; +#endif + auto l = new QGridLayout(this); l->setContentsMargins( 10, 10, 10, 10 ); l->setVerticalSpacing( 2 ); diff --git a/plugins/VstEffect/VstEffectControls.cpp b/plugins/VstEffect/VstEffectControls.cpp index e73530a09..cf0c831a6 100644 --- a/plugins/VstEffect/VstEffectControls.cpp +++ b/plugins/VstEffect/VstEffectControls.cpp @@ -316,6 +316,16 @@ namespace gui ManageVSTEffectView::ManageVSTEffectView( VstEffect * _eff, VstEffectControls * m_vi ) : m_effect( _eff ) { +#if QT_VERSION < 0x50C00 + // Workaround for a bug in Qt versions below 5.12, + // where argument-dependent-lookup fails for QFlags operators + // declared inside a namepsace. + // This affects the Q_DECLARE_OPERATORS_FOR_FLAGS macro in Instrument.h + // See also: https://codereview.qt-project.org/c/qt/qtbase/+/225348 + + using ::operator|; +#endif + m_vi2 = m_vi; widget = new QWidget(); m_vi->m_scrollArea = new QScrollArea( widget ); @@ -379,7 +389,7 @@ ManageVSTEffectView::ManageVSTEffectView( VstEffect * _eff, VstEffectControls * sprintf(paramStr.data(), "param%d", i); s_dumpValues = dump[paramStr.data()].split(":"); - vstKnobs[ i ] = new CustomTextKnob( knobBright_26, widget, s_dumpValues.at( 1 ) ); + vstKnobs[ i ] = new CustomTextKnob( KnobType::Bright26, widget, s_dumpValues.at( 1 ) ); vstKnobs[ i ]->setDescription( s_dumpValues.at( 1 ) + ":" ); vstKnobs[ i ]->setLabel( s_dumpValues.at( 1 ).left( 15 ) ); diff --git a/plugins/VstEffect/VstSubPluginFeatures.cpp b/plugins/VstEffect/VstSubPluginFeatures.cpp index e60fee0c1..f929b5526 100644 --- a/plugins/VstEffect/VstSubPluginFeatures.cpp +++ b/plugins/VstEffect/VstSubPluginFeatures.cpp @@ -34,7 +34,7 @@ namespace lmms { -VstSubPluginFeatures::VstSubPluginFeatures( Plugin::PluginTypes _type ) : +VstSubPluginFeatures::VstSubPluginFeatures( Plugin::Type _type ) : SubPluginFeatures( _type ) { } diff --git a/plugins/VstEffect/VstSubPluginFeatures.h b/plugins/VstEffect/VstSubPluginFeatures.h index c5dc87d14..a5673dfb7 100644 --- a/plugins/VstEffect/VstSubPluginFeatures.h +++ b/plugins/VstEffect/VstSubPluginFeatures.h @@ -38,7 +38,7 @@ namespace lmms class VstSubPluginFeatures : public Plugin::Descriptor::SubPluginFeatures { public: - VstSubPluginFeatures( Plugin::PluginTypes _type ); + VstSubPluginFeatures( Plugin::Type _type ); void fillDescriptionWidget( QWidget * _parent, const Key * _key ) const override; diff --git a/plugins/Watsyn/Watsyn.cpp b/plugins/Watsyn/Watsyn.cpp index 9ceaaddb8..7603a9c1b 100644 --- a/plugins/Watsyn/Watsyn.cpp +++ b/plugins/Watsyn/Watsyn.cpp @@ -52,7 +52,7 @@ Plugin::Descriptor PLUGIN_EXPORT watsyn_plugin_descriptor = "4-oscillator modulatable wavetable synth" ), "Vesa Kivimäki ", 0x0100, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader( "logo" ), nullptr, nullptr, @@ -329,7 +329,7 @@ WatsynInstrument::WatsynInstrument( InstrumentTrack * _instrument_track ) : void WatsynInstrument::playNote( NotePlayHandle * _n, sampleFrame * _working_buffer ) { - if ( _n->totalFramesPlayed() == 0 || _n->m_pluginData == nullptr ) + if (!_n->m_pluginData) { auto w = new WatsynObject(&A1_wave[0], &A2_wave[0], &B1_wave[0], &B2_wave[0], m_amod.value(), m_bmod.value(), Engine::audioEngine()->processingSampleRate(), _n, Engine::audioEngine()->framesPerPeriod(), this); @@ -816,7 +816,7 @@ WatsynView::WatsynView( Instrument * _instrument, pal = QPalette(); pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap("wavegraph") ); // a1 graph - a1_graph = new Graph( this, Graph::LinearStyle, 224, 105 ); + a1_graph = new Graph( this, Graph::Style::Linear, 224, 105 ); a1_graph->move( 4, 141 ); a1_graph->setAutoFillBackground( true ); a1_graph->setGraphColor( QColor( 0x43, 0xb2, 0xff ) ); @@ -824,7 +824,7 @@ WatsynView::WatsynView( Instrument * _instrument, a1_graph->setPalette( pal ); // a2 graph - a2_graph = new Graph( this, Graph::LinearStyle, 224, 105 ); + a2_graph = new Graph( this, Graph::Style::Linear, 224, 105 ); a2_graph->move( 4, 141 ); a2_graph->setAutoFillBackground( true ); a2_graph->setGraphColor( QColor( 0x43, 0xb2, 0xff ) ); @@ -832,7 +832,7 @@ WatsynView::WatsynView( Instrument * _instrument, a2_graph->setPalette( pal ); // b1 graph - b1_graph = new Graph( this, Graph::LinearStyle, 224, 105 ); + b1_graph = new Graph( this, Graph::Style::Linear, 224, 105 ); b1_graph->move( 4, 141 ); b1_graph->setAutoFillBackground( true ); b1_graph->setGraphColor( QColor( 0xfc, 0x54, 0x31 ) ); @@ -840,7 +840,7 @@ WatsynView::WatsynView( Instrument * _instrument, b1_graph->setPalette( pal ); // b2 graph - b2_graph = new Graph( this, Graph::LinearStyle, 224, 105 ); + b2_graph = new Graph( this, Graph::Style::Linear, 224, 105 ); b2_graph->move( 4, 141 ); b2_graph->setAutoFillBackground( true ); b2_graph->setGraphColor( QColor( 0xfc, 0x54, 0x31 ) ); diff --git a/plugins/Watsyn/Watsyn.h b/plugins/Watsyn/Watsyn.h index 3c69be06f..3a736e162 100644 --- a/plugins/Watsyn/Watsyn.h +++ b/plugins/Watsyn/Watsyn.h @@ -39,14 +39,14 @@ namespace lmms #define makeknob( name, x, y, hint, unit, oname ) \ - name = new Knob( knobStyled, this ); \ + name = new Knob( KnobType::Styled, this ); \ name ->move( x, y ); \ name ->setHintText( hint, unit ); \ name ->setObjectName( oname ); \ name ->setFixedSize( 19, 19 ); #define maketsknob( name, x, y, hint, unit, oname ) \ - name = new TempoSyncKnob( knobStyled, this ); \ + name = new TempoSyncKnob( KnobType::Styled, this ); \ name ->move( x, y ); \ name ->setHintText( hint, unit ); \ name ->setObjectName( oname ); \ diff --git a/plugins/WaveShaper/WaveShaper.cpp b/plugins/WaveShaper/WaveShaper.cpp index 94845e672..acd5a933b 100644 --- a/plugins/WaveShaper/WaveShaper.cpp +++ b/plugins/WaveShaper/WaveShaper.cpp @@ -46,7 +46,7 @@ Plugin::Descriptor PLUGIN_EXPORT waveshaper_plugin_descriptor = "plugin for waveshaping" ), "Vesa Kivimäki ", 0x0100, - Plugin::Effect, + Plugin::Type::Effect, new PluginPixmapLoader("logo"), nullptr, nullptr, diff --git a/plugins/WaveShaper/WaveShaperControlDialog.cpp b/plugins/WaveShaper/WaveShaperControlDialog.cpp index 5ef061fdb..045f84763 100644 --- a/plugins/WaveShaper/WaveShaperControlDialog.cpp +++ b/plugins/WaveShaper/WaveShaperControlDialog.cpp @@ -48,7 +48,7 @@ WaveShaperControlDialog::WaveShaperControlDialog( setPalette( pal ); setFixedSize( 224, 274 ); - auto waveGraph = new Graph(this, Graph::LinearNonCyclicStyle, 204, 205); + auto waveGraph = new Graph(this, Graph::Style::LinearNonCyclic, 204, 205); waveGraph -> move( 10, 6 ); waveGraph -> setModel( &_controls -> m_wavegraphModel ); waveGraph -> setAutoFillBackground( true ); @@ -59,7 +59,7 @@ WaveShaperControlDialog::WaveShaperControlDialog( waveGraph->setGraphColor( QColor( 85, 204, 145 ) ); waveGraph -> setMaximumSize( 204, 205 ); - auto inputKnob = new Knob(knobBright_26, this); + auto inputKnob = new Knob(KnobType::Bright26, this); inputKnob -> setVolumeKnob( true ); inputKnob -> setVolumeRatio( 1.0 ); inputKnob -> move( 26, 225 ); @@ -67,7 +67,7 @@ WaveShaperControlDialog::WaveShaperControlDialog( inputKnob->setLabel( tr( "INPUT" ) ); inputKnob->setHintText( tr( "Input gain:" ) , "" ); - auto outputKnob = new Knob(knobBright_26, this); + auto outputKnob = new Knob(KnobType::Bright26, this); outputKnob -> setVolumeKnob( true ); outputKnob -> setVolumeRatio( 1.0 ); outputKnob -> move( 76, 225 ); @@ -103,7 +103,7 @@ WaveShaperControlDialog::WaveShaperControlDialog( subOneButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "sub1_inactive" ) ); subOneButton->setToolTip(tr("Decrease wavegraph amplitude by 1 dB")); - auto clipInputToggle = new LedCheckBox("Clip input", this, tr("Clip input"), LedCheckBox::Green); + auto clipInputToggle = new LedCheckBox("Clip input", this, tr("Clip input"), LedCheckBox::LedColor::Green); clipInputToggle -> move( 131, 252 ); clipInputToggle -> setModel( &_controls -> m_clipModel ); clipInputToggle->setToolTip(tr("Clip input signal to 0 dB")); diff --git a/plugins/Xpressive/Xpressive.cpp b/plugins/Xpressive/Xpressive.cpp index 18ac8c052..b1a17a1ce 100644 --- a/plugins/Xpressive/Xpressive.cpp +++ b/plugins/Xpressive/Xpressive.cpp @@ -57,7 +57,7 @@ extern "C" { Plugin::Descriptor PLUGIN_EXPORT xpressive_plugin_descriptor = { LMMS_STRINGIFY( PLUGIN_NAME), "Xpressive", QT_TRANSLATE_NOOP("PluginBrowser", "Mathematical expression parser"), "Orr Dvori", 0x0100, - Plugin::Instrument, new PluginPixmapLoader("logo"), nullptr, nullptr }; + Plugin::Type::Instrument, new PluginPixmapLoader("logo"), nullptr, nullptr }; } @@ -201,7 +201,7 @@ void Xpressive::playNote(NotePlayHandle* nph, sampleFrame* working_buffer) { m_A2=m_parameterA2.value(); m_A3=m_parameterA3.value(); - if (nph->totalFramesPlayed() == 0 || nph->m_pluginData == nullptr) { + if (!nph->m_pluginData) { auto exprO1 = new ExprFront(m_outputExpression[0].constData(), Engine::audioEngine()->processingSampleRate()); // give the "last" function a whole second @@ -291,11 +291,11 @@ public: setLineWidth(3); } XpressiveKnob(QWidget * _parent, const QString & _name) : - Knob(knobStyled, _parent,_name) { + Knob(KnobType::Styled, _parent,_name) { setStyle(); } XpressiveKnob(QWidget * _parent) : - Knob(knobStyled, _parent) { + Knob(KnobType::Styled, _parent) { setStyle(); } @@ -325,7 +325,7 @@ XpressiveView::XpressiveView(Instrument * _instrument, QWidget * _parent) : pal.setBrush(backgroundRole(), PLUGIN_NAME::getIconPixmap("artwork")); setPalette(pal); - m_graph = new Graph(this, Graph::LinearStyle, 180, 81); + m_graph = new Graph(this, Graph::Style::Linear, 180, 81); m_graph->move(3, BASE_START + 1); m_graph->setAutoFillBackground(true); m_graph->setGraphColor(QColor(255, 255, 255)); @@ -447,11 +447,11 @@ XpressiveView::XpressiveView(Instrument * _instrument, QWidget * _parent) : m_waveInterpolate = new LedCheckBox("Interpolate", this, tr("WaveInterpolate"), - LedCheckBox::Green); + LedCheckBox::LedColor::Green); m_waveInterpolate->move(2, 230); m_expressionValidToggle = new LedCheckBox("", this, tr("ExpressionValid"), - LedCheckBox::Red); + LedCheckBox::LedColor::Red); m_expressionValidToggle->move(168, EXPR_TEXT_Y+EXPR_TEXT_H-2); m_expressionValidToggle->setEnabled( false ); @@ -485,7 +485,7 @@ XpressiveView::XpressiveView(Instrument * _instrument, QWidget * _parent) : - m_smoothKnob=new Knob(knobStyled, this, "Smoothness"); + m_smoothKnob=new Knob(KnobType::Styled, this, "Smoothness"); m_smoothKnob->setFixedSize(25, 25); m_smoothKnob->setCenterPointX(12.5); m_smoothKnob->setCenterPointY(12.5); diff --git a/plugins/ZynAddSubFx/ZynAddSubFx.cpp b/plugins/ZynAddSubFx/ZynAddSubFx.cpp index d3d23c65f..2ec864592 100644 --- a/plugins/ZynAddSubFx/ZynAddSubFx.cpp +++ b/plugins/ZynAddSubFx/ZynAddSubFx.cpp @@ -66,7 +66,7 @@ Plugin::Descriptor PLUGIN_EXPORT zynaddsubfx_plugin_descriptor = "Embedded ZynAddSubFX" ), "Tobias Doerffel ", 0x0100, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader( "logo" ), "xiz", nullptr, @@ -151,8 +151,8 @@ ZynAddSubFxInstrument::ZynAddSubFxInstrument( ZynAddSubFxInstrument::~ZynAddSubFxInstrument() { Engine::audioEngine()->removePlayHandlesOfTypes( instrumentTrack(), - PlayHandle::TypeNotePlayHandle - | PlayHandle::TypeInstrumentPlayHandle ); + PlayHandle::Type::NotePlayHandle + | PlayHandle::Type::InstrumentPlayHandle ); m_pluginMutex.lock(); delete m_plugin; @@ -380,7 +380,7 @@ bool ZynAddSubFxInstrument::handleMidiEvent( const MidiEvent& event, const TimeP void ZynAddSubFxInstrument::reloadPlugin() { // save state of current plugin instance - DataFile m( DataFile::InstrumentTrackSettings ); + DataFile m( DataFile::Type::InstrumentTrackSettings ); saveSettings( m, m.content() ); // init plugin (will delete current one and create a new instance) @@ -508,31 +508,31 @@ ZynAddSubFxView::ZynAddSubFxView( Instrument * _instrument, QWidget * _parent ) l->setVerticalSpacing( 16 ); l->setHorizontalSpacing( 10 ); - m_portamento = new Knob( knobBright_26, this ); + m_portamento = new Knob( KnobType::Bright26, this ); m_portamento->setHintText( tr( "Portamento:" ), "" ); m_portamento->setLabel( tr( "PORT" ) ); - m_filterFreq = new Knob( knobBright_26, this ); + m_filterFreq = new Knob( KnobType::Bright26, this ); m_filterFreq->setHintText( tr( "Filter frequency:" ), "" ); m_filterFreq->setLabel( tr( "FREQ" ) ); - m_filterQ = new Knob( knobBright_26, this ); + m_filterQ = new Knob( KnobType::Bright26, this ); m_filterQ->setHintText( tr( "Filter resonance:" ), "" ); m_filterQ->setLabel( tr( "RES" ) ); - m_bandwidth = new Knob( knobBright_26, this ); + m_bandwidth = new Knob( KnobType::Bright26, this ); m_bandwidth->setHintText( tr( "Bandwidth:" ), "" ); m_bandwidth->setLabel( tr( "BW" ) ); - m_fmGain = new Knob( knobBright_26, this ); + m_fmGain = new Knob( KnobType::Bright26, this ); m_fmGain->setHintText( tr( "FM gain:" ), "" ); m_fmGain->setLabel( tr( "FM GAIN" ) ); - m_resCenterFreq = new Knob( knobBright_26, this ); + m_resCenterFreq = new Knob( KnobType::Bright26, this ); m_resCenterFreq->setHintText( tr( "Resonance center frequency:" ), "" ); m_resCenterFreq->setLabel( tr( "RES CF" ) ); - m_resBandwidth = new Knob( knobBright_26, this ); + m_resBandwidth = new Knob( KnobType::Bright26, this ); m_resBandwidth->setHintText( tr( "Resonance bandwidth:" ), "" ); m_resBandwidth->setLabel( tr( "RES BW" ) ); diff --git a/plugins/ZynAddSubFx/ZynAddSubFx.h b/plugins/ZynAddSubFx/ZynAddSubFx.h index 996c187ee..a391203f3 100644 --- a/plugins/ZynAddSubFx/ZynAddSubFx.h +++ b/plugins/ZynAddSubFx/ZynAddSubFx.h @@ -88,7 +88,7 @@ public: Flags flags() const override { - return IsSingleStreamed | IsMidiBased; + return Flag::IsSingleStreamed | Flag::IsMidiBased; } gui::PluginView* instantiateView( QWidget * _parent ) override; diff --git a/src/3rdparty/CMakeLists.txt b/src/3rdparty/CMakeLists.txt index 7a6b88775..a95332a07 100644 --- a/src/3rdparty/CMakeLists.txt +++ b/src/3rdparty/CMakeLists.txt @@ -7,6 +7,12 @@ ADD_SUBDIRECTORY(hiir) ADD_SUBDIRECTORY(rpmalloc) ADD_SUBDIRECTORY(weakjack) +if(MINGW) + option(MINGW_STDTHREADS_GENERATE_STDHEADERS "" ON) + add_subdirectory(mingw-std-threads) + set(LMMS_USE_MINGW_STD_THREADS ON PARENT_SCOPE) +endif() + # The lockless ring buffer library is compiled as part of the core SET(RINGBUFFER_DIR "${CMAKE_SOURCE_DIR}/src/3rdparty/ringbuffer/") SET(RINGBUFFER_DIR ${RINGBUFFER_DIR} PARENT_SCOPE) diff --git a/src/3rdparty/mingw-std-threads b/src/3rdparty/mingw-std-threads index 10665829d..6c2061b7d 160000 --- a/src/3rdparty/mingw-std-threads +++ b/src/3rdparty/mingw-std-threads @@ -1 +1 @@ -Subproject commit 10665829daaedc28629e5e9b014fe498c20d73f2 +Subproject commit 6c2061b7da41d6aa1b2162ff4383ec3ece864bc6 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bd543779f..f483d8b41 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,7 +12,7 @@ SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) # Enable C++17 SET(CMAKE_CXX_STANDARD 17) -IF(LMMS_BUILD_APPLE) +IF(LMMS_BUILD_APPLE AND CMAKE_CXX_COMPILER_ID MATCHES "Clang") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") ENDIF() @@ -170,6 +170,10 @@ if(LMMS_HAVE_MP3LAME) list(APPEND EXTRA_LIBRARIES mp3lame::mp3lame) endif() +if(LMMS_USE_MINGW_STD_THREADS) + list(APPEND EXTRA_LIBRARIES mingw_stdthreads) +endif() + SET(LMMS_REQUIRED_LIBS ${LMMS_REQUIRED_LIBS} ${CMAKE_THREAD_LIBS_INIT} ${QT_LIBRARIES} diff --git a/src/core/AudioEngine.cpp b/src/core/AudioEngine.cpp index a91e88f38..2d077babc 100644 --- a/src/core/AudioEngine.cpp +++ b/src/core/AudioEngine.cpp @@ -81,7 +81,7 @@ AudioEngine::AudioEngine( bool renderOnly ) : m_workers(), m_numWorkers( QThread::idealThreadCount()-1 ), m_newPlayHandles( PlayHandle::MaxNumber ), - m_qualitySettings( qualitySettings::Mode_Draft ), + m_qualitySettings( qualitySettings::Mode::Draft ), m_masterGain( 1.0f ), m_isProcessing( false ), m_audioDev( nullptr ), @@ -314,7 +314,7 @@ void AudioEngine::pushInputFrames( sampleFrame * _ab, const f_cnt_t _frames ) if( frames + _frames > size ) { - size = qMax( size * 2, frames + _frames ); + size = std::max(size * 2, frames + _frames); auto ab = new sampleFrame[size]; memcpy( ab, buf, frames * sizeof( sampleFrame ) ); delete [] buf; @@ -333,12 +333,9 @@ void AudioEngine::pushInputFrames( sampleFrame * _ab, const f_cnt_t _frames ) - -const surroundSampleFrame * AudioEngine::renderNextBuffer() +void AudioEngine::renderStageNoteSetup() { - m_profiler.startPeriod(); - - s_renderingThread = true; + AudioEngineProfiler::Probe profilerProbe(m_profiler, AudioEngineProfiler::DetailType::NoteSetup); if( m_clearSignal ) { @@ -357,7 +354,7 @@ const surroundSampleFrame * AudioEngine::renderNextBuffer() if( it != m_playHandles.end() ) { ( *it )->audioPort()->removePlayHandle( ( *it ) ); - if( ( *it )->type() == PlayHandle::TypeNotePlayHandle ) + if( ( *it )->type() == PlayHandle::Type::NotePlayHandle ) { NotePlayHandleManager::release( (NotePlayHandle*) *it ); } @@ -387,9 +384,15 @@ const surroundSampleFrame * AudioEngine::renderNextBuffer() m_newPlayHandles.free( e ); e = next; } +} - // STAGE 1: run and render all play handles - AudioEngineWorkerThread::fillJobQueue( m_playHandles ); + + +void AudioEngine::renderStageInstruments() +{ + AudioEngineProfiler::Probe profilerProbe(m_profiler, AudioEngineProfiler::DetailType::Instruments); + + AudioEngineWorkerThread::fillJobQueue(m_playHandles); AudioEngineWorkerThread::startAndWaitForJobs(); // removed all play handles which are done @@ -405,7 +408,7 @@ const surroundSampleFrame * AudioEngine::renderNextBuffer() if( ( *it )->isFinished() ) { ( *it )->audioPort()->removePlayHandle( ( *it ) ); - if( ( *it )->type() == PlayHandle::TypeNotePlayHandle ) + if( ( *it )->type() == PlayHandle::Type::NotePlayHandle ) { NotePlayHandleManager::release( (NotePlayHandle*) *it ); } @@ -417,16 +420,28 @@ const surroundSampleFrame * AudioEngine::renderNextBuffer() ++it; } } +} + + + +void AudioEngine::renderStageEffects() +{ + AudioEngineProfiler::Probe profilerProbe(m_profiler, AudioEngineProfiler::DetailType::Effects); // STAGE 2: process effects of all instrument- and sampletracks - AudioEngineWorkerThread::fillJobQueue >( m_audioPorts ); + AudioEngineWorkerThread::fillJobQueue(m_audioPorts); AudioEngineWorkerThread::startAndWaitForJobs(); +} - // STAGE 3: do master mix in mixer + +void AudioEngine::renderStageMix() +{ + AudioEngineProfiler::Probe profilerProbe(m_profiler, AudioEngineProfiler::DetailType::Mixing); + + Mixer *mixer = Engine::mixer(); mixer->masterMix(m_outputBufferWrite); - emit nextAudioBuffer(m_outputBufferRead); runChangesInModel(); @@ -435,10 +450,22 @@ const surroundSampleFrame * AudioEngine::renderNextBuffer() EnvelopeAndLfoParameters::instances()->trigger(); Controller::triggerFrameCounter(); AutomatableModel::incrementPeriodCounter(); +} + + + +const surroundSampleFrame *AudioEngine::renderNextBuffer() +{ + m_profiler.startPeriod(); + s_renderingThread = true; + + renderStageNoteSetup(); // STAGE 0: clear old play handles and buffers, setup new play handles + renderStageInstruments(); // STAGE 1: run and render all play handles + renderStageEffects(); // STAGE 2: process effects of all instrument- and sampletracks + renderStageMix(); // STAGE 3: do master mix in mixer s_renderingThread = false; - - m_profiler.finishPeriod( processingSampleRate(), m_framesPerPeriod ); + m_profiler.finishPeriod(processingSampleRate(), m_framesPerPeriod); return m_outputBufferRead; } @@ -464,12 +491,12 @@ void AudioEngine::handleMetronome() static tick_t lastMetroTicks = -1; Song * song = Engine::getSong(); - Song::PlayModes currentPlayMode = song->playMode(); + Song::PlayMode currentPlayMode = song->playMode(); bool metronomeSupported = - currentPlayMode == Song::Mode_PlayMidiClip - || currentPlayMode == Song::Mode_PlaySong - || currentPlayMode == Song::Mode_PlayPattern; + currentPlayMode == Song::PlayMode::MidiClip + || currentPlayMode == Song::PlayMode::Song + || currentPlayMode == Song::PlayMode::Pattern; if (!metronomeSupported || !m_metronomeActive || song->isExporting()) { @@ -534,7 +561,7 @@ void AudioEngine::clearInternal() // TODO: m_midiClient->noteOffAll(); for (auto ph : m_playHandles) { - if (ph->type() != PlayHandle::TypeInstrumentPlayHandle) + if (ph->type() != PlayHandle::Type::InstrumentPlayHandle) { m_playHandlesToRemove.push_back(ph); } @@ -551,8 +578,8 @@ AudioEngine::StereoSample AudioEngine::getPeakValues(sampleFrame * ab, const f_c for (f_cnt_t f = 0; f < frames; ++f) { - float const absLeft = qAbs(ab[f][0]); - float const absRight = qAbs(ab[f][1]); + float const absLeft = std::abs(ab[f][0]); + float const absRight = std::abs(ab[f][1]); if (absLeft > peakLeft) { peakLeft = absLeft; @@ -663,7 +690,7 @@ void AudioEngine::removeAudioPort(AudioPort * port) { requestChangeInModel(); - QVector::Iterator it = std::find(m_audioPorts.begin(), m_audioPorts.end(), port); + auto it = std::find(m_audioPorts.begin(), m_audioPorts.end(), port); if (it != m_audioPorts.end()) { m_audioPorts.erase(it); @@ -681,7 +708,7 @@ bool AudioEngine::addPlayHandle( PlayHandle* handle ) return true; } - if( handle->type() == PlayHandle::TypeNotePlayHandle ) + if( handle->type() == PlayHandle::Type::NotePlayHandle ) { NotePlayHandleManager::release( (NotePlayHandle*)handle ); } @@ -732,7 +759,7 @@ void AudioEngine::removePlayHandle(PlayHandle * ph) // (See tobydox's 2008 commit 4583e48) if ( removedFromList ) { - if (ph->type() == PlayHandle::TypeNotePlayHandle) + if (ph->type() == PlayHandle::Type::NotePlayHandle) { NotePlayHandleManager::release(dynamic_cast(ph)); } @@ -749,7 +776,7 @@ void AudioEngine::removePlayHandle(PlayHandle * ph) -void AudioEngine::removePlayHandlesOfTypes(Track * track, const quint8 types) +void AudioEngine::removePlayHandlesOfTypes(Track * track, PlayHandle::Types types) { requestChangeInModel(); PlayHandleList::Iterator it = m_playHandles.begin(); @@ -758,7 +785,7 @@ void AudioEngine::removePlayHandlesOfTypes(Track * track, const quint8 types) if ((*it)->isFromTrack(track) && ((*it)->type() & types)) { ( *it )->audioPort()->removePlayHandle( ( *it ) ); - if( ( *it )->type() == PlayHandle::TypeNotePlayHandle ) + if( ( *it )->type() == PlayHandle::Type::NotePlayHandle ) { NotePlayHandleManager::release( (NotePlayHandle*) *it ); } diff --git a/src/core/AudioEngineProfiler.cpp b/src/core/AudioEngineProfiler.cpp index 5fd5a813c..82a412cbb 100644 --- a/src/core/AudioEngineProfiler.cpp +++ b/src/core/AudioEngineProfiler.cpp @@ -24,6 +24,8 @@ #include "AudioEngineProfiler.h" +#include + namespace lmms { @@ -38,10 +40,24 @@ AudioEngineProfiler::AudioEngineProfiler() : void AudioEngineProfiler::finishPeriod( sample_rate_t sampleRate, fpp_t framesPerPeriod ) { - int periodElapsed = m_periodTimer.elapsed(); + // Time taken to process all data and fill the audio buffer. + const unsigned int periodElapsed = m_periodTimer.elapsed(); + // Maximum time the processing can take before causing buffer underflow. Convert to us. + const uint64_t timeLimit = static_cast(1000000) * framesPerPeriod / sampleRate; - const float newCpuLoad = periodElapsed / 10000.0f * sampleRate / framesPerPeriod; - m_cpuLoad = qBound( 0, ( newCpuLoad * 0.1f + m_cpuLoad * 0.9f ), 100 ); + // Compute new overall CPU load and apply exponential averaging. + // The result is used for overload detection in AudioEngine::criticalXRuns() + // → the weight of a new sample must be high enough to allow relatively fast changes! + const auto newCpuLoad = 100.f * periodElapsed / timeLimit; + m_cpuLoad = newCpuLoad * 0.1f + m_cpuLoad * 0.9f; + + // Compute detailed load analysis. Can use stronger averaging to get more stable readout. + for (std::size_t i = 0; i < DetailCount; i++) + { + const auto newLoad = 100.f * m_detailTime[i] / timeLimit; + const auto oldLoad = m_detailLoad[i].load(std::memory_order_relaxed); + m_detailLoad[i].store(newLoad * 0.05f + oldLoad * 0.95f, std::memory_order_relaxed); + } if( m_outputFile.isOpen() ) { diff --git a/src/core/AudioEngineWorkerThread.cpp b/src/core/AudioEngineWorkerThread.cpp index 129b3accf..528841c71 100644 --- a/src/core/AudioEngineWorkerThread.cpp +++ b/src/core/AudioEngineWorkerThread.cpp @@ -91,7 +91,7 @@ void AudioEngineWorkerThread::JobQueue::run() } } // always exit loop if we're not in dynamic mode - processedJob = processedJob && ( m_opMode == Dynamic ); + processedJob = processedJob && ( m_opMode == OperationMode::Dynamic ); } } diff --git a/src/core/AutomatableModel.cpp b/src/core/AutomatableModel.cpp index 378ccd91e..e46a864f8 100644 --- a/src/core/AutomatableModel.cpp +++ b/src/core/AutomatableModel.cpp @@ -44,7 +44,7 @@ AutomatableModel::AutomatableModel( const float val, const float min, const float max, const float step, Model* parent, const QString & displayName, bool defaultConstructed ) : Model( parent, displayName, defaultConstructed ), - m_scaleType( Linear ), + m_scaleType( ScaleType::Linear ), m_minValue( min ), m_maxValue( max ), m_step( step ), @@ -71,7 +71,7 @@ AutomatableModel::~AutomatableModel() { while( m_linkedModels.empty() == false ) { - m_linkedModels.last()->unlinkModel( this ); + m_linkedModels.back()->unlinkModel(this); m_linkedModels.erase( m_linkedModels.end() - 1 ); } @@ -105,7 +105,7 @@ void AutomatableModel::saveSettings( QDomDocument& doc, QDomElement& element, co { bool mustQuote = mustQuoteName(name); - if( isAutomated() || m_scaleType != Linear ) + if( isAutomated() || m_scaleType != ScaleType::Linear ) { // automation needs tuple of data (name, id, value) // scale type also needs an extra value @@ -114,7 +114,7 @@ void AutomatableModel::saveSettings( QDomDocument& doc, QDomElement& element, co QDomElement me = doc.createElement( mustQuote ? QString("automatablemodel") : name ); me.setAttribute( "id", ProjectJournal::idToSave( id() ) ); me.setAttribute( "value", m_value ); - me.setAttribute( "scale_type", m_scaleType == Logarithmic ? "log" : "linear" ); + me.setAttribute( "scale_type", m_scaleType == ScaleType::Logarithmic ? "log" : "linear" ); if(mustQuote) { me.setAttribute( "nodename", name ); } @@ -140,11 +140,11 @@ void AutomatableModel::saveSettings( QDomDocument& doc, QDomElement& element, co // the discardMIDIConnections option is true. auto controllerType = m_controllerConnection ? m_controllerConnection->getController()->type() - : Controller::DummyController; + : Controller::ControllerType::Dummy; bool skipMidiController = Engine::getSong()->isSavingProject() && Engine::getSong()->getSaveOptions().discardMIDIConnections.value(); - if (m_controllerConnection && controllerType != Controller::DummyController - && !(skipMidiController && controllerType == Controller::MidiController)) + if (m_controllerConnection && controllerType != Controller::ControllerType::Dummy + && !(skipMidiController && controllerType == Controller::ControllerType::Midi)) { QDomElement controllerElement; @@ -264,18 +264,18 @@ void AutomatableModel::loadSettings( const QDomElement& element, const QString& { if( nodeElement.attribute( "scale_type" ) == "linear" ) { - setScaleType( Linear ); + setScaleType( ScaleType::Linear ); } else if( nodeElement.attribute( "scale_type" ) == "log" ) { - setScaleType( Logarithmic ); + setScaleType( ScaleType::Logarithmic ); } } } else { - setScaleType( Linear ); + setScaleType( ScaleType::Linear ); if( element.hasAttribute( name ) ) // attribute => read the element's value from the attribute list @@ -335,7 +335,7 @@ template T AutomatableModel::logToLinearScale( T value ) const float AutomatableModel::scaledValue( float value ) const { - return m_scaleType == Linear + return m_scaleType == ScaleType::Linear ? value : logToLinearScale( ( value - minValue() ) / m_range ); } @@ -343,7 +343,7 @@ float AutomatableModel::scaledValue( float value ) const float AutomatableModel::inverseScaledValue( float value ) const { - return m_scaleType == Linear + return m_scaleType == ScaleType::Linear ? value : lmms::linearToLogScale( minValue(), maxValue(), value ); } @@ -354,8 +354,8 @@ float AutomatableModel::inverseScaledValue( float value ) const template void roundAt( T& value, const T& where, const T& step_size ) { - if( qAbs( value - where ) - < typeInfo::minEps() * qAbs( step_size ) ) + if (std::abs(value - where) + < typeInfo::minEps() * std::abs(step_size)) { value = where; } @@ -444,7 +444,7 @@ void AutomatableModel::setStep( const float step ) float AutomatableModel::fittedValue( float value ) const { - value = qBound( m_minValue, value, m_maxValue ); + value = std::clamp(value, m_minValue, m_maxValue); if( m_step != 0 && m_hasStrictStepSize ) { @@ -473,7 +473,8 @@ float AutomatableModel::fittedValue( float value ) const void AutomatableModel::linkModel( AutomatableModel* model ) { - if( !m_linkedModels.contains( model ) && model != this ) + auto containsModel = std::find(m_linkedModels.begin(), m_linkedModels.end(), model) != m_linkedModels.end(); + if (!containsModel && model != this) { m_linkedModels.push_back( model ); @@ -490,7 +491,7 @@ void AutomatableModel::linkModel( AutomatableModel* model ) void AutomatableModel::unlinkModel( AutomatableModel* model ) { - AutoModelVector::Iterator it = std::find( m_linkedModels.begin(), m_linkedModels.end(), model ); + auto it = std::find(m_linkedModels.begin(), m_linkedModels.end(), model); if( it != m_linkedModels.end() ) { m_linkedModels.erase( it ); @@ -504,7 +505,8 @@ void AutomatableModel::unlinkModel( AutomatableModel* model ) void AutomatableModel::linkModels( AutomatableModel* model1, AutomatableModel* model2 ) { - if (!model1->m_linkedModels.contains( model2 ) && model1 != model2) + auto model1ContainsModel2 = std::find(model1->m_linkedModels.begin(), model1->m_linkedModels.end(), model2) != model1->m_linkedModels.end(); + if (!model1ContainsModel2 && model1 != model2) { // copy data model1->m_value = model2->m_value; @@ -569,10 +571,10 @@ float AutomatableModel::controllerValue( int frameOffset ) const float v = 0; switch(m_scaleType) { - case Linear: + case ScaleType::Linear: v = minValue() + ( range() * controllerConnection()->currentValue( frameOffset ) ); break; - case Logarithmic: + case ScaleType::Logarithmic: v = logToLinearScale( controllerConnection()->currentValue( frameOffset )); break; @@ -583,12 +585,12 @@ float AutomatableModel::controllerValue( int frameOffset ) const } if( typeInfo::isEqual( m_step, 1 ) && m_hasStrictStepSize ) { - return qRound( v ); + return std::round(v); } return v; } - AutomatableModel* lm = m_linkedModels.first(); + AutomatableModel* lm = m_linkedModels.front(); if (lm->controllerConnection() && lm->useControllerValue()) { return fittedValue( lm->controllerValue( frameOffset ) ); @@ -621,13 +623,13 @@ ValueBuffer * AutomatableModel::valueBuffer() float * nvalues = m_valueBuffer.values(); switch( m_scaleType ) { - case Linear: + case ScaleType::Linear: for( int i = 0; i < m_valueBuffer.length(); i++ ) { nvalues[i] = minValue() + ( range() * values[i] ); } break; - case Logarithmic: + case ScaleType::Logarithmic: for( int i = 0; i < m_valueBuffer.length(); i++ ) { nvalues[i] = logToLinearScale( values[i] ); @@ -649,7 +651,7 @@ ValueBuffer * AutomatableModel::valueBuffer() AutomatableModel* lm = nullptr; if (hasLinkedModels()) { - lm = m_linkedModels.first(); + lm = m_linkedModels.front(); } if (lm && lm->controllerConnection() && lm->useControllerValue() && lm->controllerConnection()->getController()->isSampleExact()) @@ -721,8 +723,8 @@ void AutomatableModel::reset() float AutomatableModel::globalAutomationValueAt( const TimePos& time ) { // get clips that connect to this model - QVector clips = AutomationClip::clipsForModel( this ); - if( clips.isEmpty() ) + auto clips = AutomationClip::clipsForModel(this); + if (clips.empty()) { // if no such clips exist, return current value return m_value; @@ -731,17 +733,17 @@ float AutomatableModel::globalAutomationValueAt( const TimePos& time ) { // of those clips: // find the clips which overlap with the time position - QVector clipsInRange; + std::vector clipsInRange; for (const auto& clip : clips) { int s = clip->startPosition(); int e = clip->endPosition(); - if (s <= time && e >= time) { clipsInRange += clip; } + if (s <= time && e >= time) { clipsInRange.push_back(clip); } } AutomationClip * latestClip = nullptr; - if( ! clipsInRange.isEmpty() ) + if (!clipsInRange.empty()) { // if there are more than one overlapping clips, just use the first one because // multiple clip behaviour is undefined anyway @@ -792,7 +794,7 @@ void AutomatableModel::setUseControllerValue(bool b) float FloatModel::getRoundedValue() const { - return qRound( value() / step() ) * step(); + return std::round(value() / step()) * step(); } diff --git a/src/core/AutomationClip.cpp b/src/core/AutomationClip.cpp index c031c5a41..3b36f6b49 100644 --- a/src/core/AutomationClip.cpp +++ b/src/core/AutomationClip.cpp @@ -53,7 +53,7 @@ AutomationClip::AutomationClip( AutomationTrack * _auto_track ) : m_autoTrack( _auto_track ), m_objects(), m_tension( 1.0 ), - m_progressionType( DiscreteProgression ), + m_progressionType( ProgressionType::Discrete ), m_dragging( false ), m_isRecording( false ), m_lastRecordedValue( 0 ) @@ -63,11 +63,11 @@ AutomationClip::AutomationClip( AutomationTrack * _auto_track ) : { switch( getTrack()->trackContainer()->type() ) { - case TrackContainer::PatternContainer: + case TrackContainer::Type::Pattern: setAutoResize( true ); break; - case TrackContainer::SongContainer: + case TrackContainer::Type::Song: // move down default: setAutoResize( false ); @@ -104,11 +104,11 @@ AutomationClip::AutomationClip( const AutomationClip & _clip_to_copy ) : if (!getTrack()){ return; } switch( getTrack()->trackContainer()->type() ) { - case TrackContainer::PatternContainer: + case TrackContainer::Type::Pattern: setAutoResize( true ); break; - case TrackContainer::SongContainer: + case TrackContainer::Type::Song: // move down default: setAutoResize( false ); @@ -120,19 +120,19 @@ bool AutomationClip::addObject( AutomatableModel * _obj, bool _search_dup ) { QMutexLocker m(&m_clipMutex); - if( _search_dup && m_objects.contains(_obj) ) + if (_search_dup && std::find(m_objects.begin(), m_objects.end(), _obj) != m_objects.end()) { return false; } // the automation track is unconnected and there is nothing in the track - if( m_objects.isEmpty() && hasAutomation() == false ) + if (m_objects.empty() && hasAutomation() == false) { // then initialize first value putValue( TimePos(0), _obj->inverseScaledValue( _obj->value() ), false ); } - m_objects += _obj; + m_objects.push_back(_obj); connect( _obj, SIGNAL(destroyed(lmms::jo_id_t)), this, SLOT(objectDestroyed(lmms::jo_id_t)), @@ -147,13 +147,13 @@ bool AutomationClip::addObject( AutomatableModel * _obj, bool _search_dup ) void AutomationClip::setProgressionType( - ProgressionTypes _new_progression_type ) + ProgressionType _new_progression_type ) { QMutexLocker m(&m_clipMutex); - if ( _new_progression_type == DiscreteProgression || - _new_progression_type == LinearProgression || - _new_progression_type == CubicHermiteProgression ) + if ( _new_progression_type == ProgressionType::Discrete || + _new_progression_type == ProgressionType::Linear || + _new_progression_type == ProgressionType::CubicHermite ) { m_progressionType = _new_progression_type; emit dataChanged(); @@ -184,7 +184,7 @@ const AutomatableModel * AutomationClip::firstObject() const QMutexLocker m(&m_clipMutex); AutomatableModel* model; - if (!m_objects.isEmpty() && (model = m_objects.first()) != nullptr) + if (!m_objects.empty() && (model = m_objects.front()) != nullptr) { return model; } @@ -225,7 +225,7 @@ TimePos AutomationClip::timeMapLength() const void AutomationClip::updateLength() { // Do not resize down in case user manually extended up - changeLength(qMax(length(), timeMapLength())); + changeLength(std::max(length(), timeMapLength())); } @@ -374,17 +374,17 @@ void AutomationClip::removeNodes(const int tick0, const int tick1) return; } - auto start = TimePos(qMin(tick0, tick1)); - auto end = TimePos(qMax(tick0, tick1)); + auto start = TimePos(std::min(tick0, tick1)); + auto end = TimePos(std::max(tick0, tick1)); // Make a list of TimePos with nodes to be removed // because we can't simply remove the nodes from // the timeMap while we are iterating it. - QVector nodesToRemove; + std::vector nodesToRemove; for (auto it = m_timeMap.lowerBound(start), endIt = m_timeMap.upperBound(end); it != endIt; ++it) { - nodesToRemove.append(POS(it)); + nodesToRemove.push_back(POS(it)); } for (auto node: nodesToRemove) @@ -410,8 +410,8 @@ void AutomationClip::resetNodes(const int tick0, const int tick1) return; } - auto start = TimePos(qMin(tick0, tick1)); - auto end = TimePos(qMax(tick0, tick1)); + auto start = TimePos(std::min(tick0, tick1)); + auto end = TimePos(std::max(tick0, tick1)); for (auto it = m_timeMap.lowerBound(start), endIt = m_timeMap.upperBound(end); it != endIt; ++it) { @@ -560,11 +560,11 @@ float AutomationClip::valueAt( timeMap::const_iterator v, int offset ) const // value if we do if (offset == 0) { return INVAL(v); } - if (m_progressionType == DiscreteProgression) + if (m_progressionType == ProgressionType::Discrete) { return OUTVAL(v); } - else if( m_progressionType == LinearProgression ) + else if( m_progressionType == ProgressionType::Linear ) { float slope = (INVAL(v + 1) - OUTVAL(v)) @@ -572,7 +572,7 @@ float AutomationClip::valueAt( timeMap::const_iterator v, int offset ) const return OUTVAL(v) + offset * slope; } - else /* CubicHermiteProgression */ + else /* ProgressionType::CubicHermite */ { // Implements a Cubic Hermite spline as explained at: // http://en.wikipedia.org/wiki/Cubic_Hermite_spline#Unit_interval_.280.2C_1.29 @@ -767,7 +767,7 @@ void AutomationClip::saveSettings( QDomDocument & _doc, QDomElement & _this ) _this.setAttribute( "pos", startPosition() ); _this.setAttribute( "len", length() ); _this.setAttribute( "name", name() ); - _this.setAttribute( "prog", QString::number( progressionType() ) ); + _this.setAttribute( "prog", QString::number( static_cast(progressionType()) ) ); _this.setAttribute( "tens", QString::number( getTension() ) ); _this.setAttribute( "mute", QString::number( isMuted() ) ); @@ -808,7 +808,7 @@ void AutomationClip::loadSettings( const QDomElement & _this ) movePosition( _this.attribute( "pos" ).toInt() ); setName( _this.attribute( "name" ) ); - setProgressionType( static_cast( _this.attribute( + setProgressionType( static_cast( _this.attribute( "prog" ).toInt() ) ); setTension( _this.attribute( "tens" ) ); setMuted(_this.attribute( "mute", QString::number( false ) ).toInt() ); @@ -831,7 +831,7 @@ void AutomationClip::loadSettings( const QDomElement & _this ) } else if( element.tagName() == "object" ) { - m_idsToResolve << element.attribute( "id" ).toInt(); + m_idsToResolve.push_back(element.attribute("id").toInt()); } } @@ -865,9 +865,9 @@ QString AutomationClip::name() const { return Clip::name(); } - if( !m_objects.isEmpty() && m_objects.first() != nullptr ) + if (!m_objects.empty() && m_objects.front() != nullptr) { - return m_objects.first()->fullDisplayName(); + return m_objects.front()->fullDisplayName(); } return tr( "Drag a control while pressing <%1>" ).arg(UI_CTRL_KEY); } @@ -888,14 +888,10 @@ gui::ClipView * AutomationClip::createView( gui::TrackView * _tv ) bool AutomationClip::isAutomated( const AutomatableModel * _m ) { - TrackContainer::TrackList l; - l += Engine::getSong()->tracks(); - l += Engine::patternStore()->tracks(); - l += Engine::getSong()->globalAutomationTrack(); - - for (const auto& track : l) + auto l = combineAllTracks(); + for (const auto track : l) { - if (track->type() == Track::AutomationTrack || track->type() == Track::HiddenAutomationTrack) + if (track->type() == Track::Type::Automation || track->type() == Track::Type::HiddenAutomation) { for (const auto& clip : track->getClips()) { @@ -921,19 +917,16 @@ bool AutomationClip::isAutomated( const AutomatableModel * _m ) * @brief returns a list of all the automation clips that are connected to a specific model * @param _m the model we want to look for */ -QVector AutomationClip::clipsForModel( const AutomatableModel * _m ) +std::vector AutomationClip::clipsForModel(const AutomatableModel* _m) { - QVector clips; - TrackContainer::TrackList tracks; - tracks += Engine::getSong()->tracks(); - tracks += Engine::patternStore()->tracks(); - tracks += Engine::getSong()->globalAutomationTrack(); + std::vector clips; + auto l = combineAllTracks(); // go through all tracks... - for (const auto& track : tracks) + for (const auto track : l) { // we want only automation tracks... - if (track->type() == Track::AutomationTrack || track->type() == Track::HiddenAutomationTrack ) + if (track->type() == Track::Type::Automation || track->type() == Track::Type::HiddenAutomation ) { // go through all the clips... for (const auto& trackClip : track->getClips()) @@ -953,7 +946,7 @@ QVector AutomationClip::clipsForModel( const AutomatableModel } } // if the clips is connected to the model, add it to the list - if( has_object ) { clips += a; } + if (has_object) { clips.push_back(a); } } } } @@ -989,12 +982,10 @@ AutomationClip * AutomationClip::globalAutomationClip( void AutomationClip::resolveAllIDs() { - TrackContainer::TrackList l = Engine::getSong()->tracks() + - Engine::patternStore()->tracks(); - l += Engine::getSong()->globalAutomationTrack(); + auto l = combineAllTracks(); for (const auto& track : l) { - if (track->type() == Track::AutomationTrack || track->type() == Track::HiddenAutomationTrack) + if (track->type() == Track::Type::Automation || track->type() == Track::Type::HiddenAutomation) { for (const auto& clip : track->getClips()) { @@ -1060,10 +1051,9 @@ void AutomationClip::objectDestroyed( jo_id_t _id ) // when switching samplerate) and real deletions because in the latter // case we had to remove ourselves if we're the global automation // clip of the destroyed object - m_idsToResolve += _id; + m_idsToResolve.push_back(_id); - for( objectVector::Iterator objIt = m_objects.begin(); - objIt != m_objects.end(); objIt++ ) + for (auto objIt = m_objects.begin(); objIt != m_objects.end(); objIt++) { Q_ASSERT( !(*objIt).isNull() ); if( (*objIt)->id() == _id ) @@ -1116,16 +1106,16 @@ void AutomationClip::generateTangents(timeMap::iterator it, int numToGenerate) { QMutexLocker m(&m_clipMutex); - if( m_timeMap.size() < 2 && numToGenerate > 0 ) + for (int i = 0; i < numToGenerate && it != m_timeMap.end(); ++i, ++it) { - it.value().setInTangent(0); - it.value().setOutTangent(0); - return; - } - - for( int i = 0; i < numToGenerate; i++ ) - { - if( it == m_timeMap.begin() ) + if (it + 1 == m_timeMap.end()) + { + // Previously, the last value's tangent was always set to 0. That logic was kept for both tangents + // of the last node + it.value().setInTangent(0); + it.value().setOutTangent(0); + } + else if (it == m_timeMap.begin()) { // On the first node there's no curve behind it, so we will only calculate the outTangent // and inTangent will be set to 0. @@ -1133,14 +1123,6 @@ void AutomationClip::generateTangents(timeMap::iterator it, int numToGenerate) it.value().setInTangent(0); it.value().setOutTangent(tangent); } - else if( it+1 == m_timeMap.end() ) - { - // Previously, the last value's tangent was always set to 0. That logic was kept for both tangents - // of the last node - it.value().setInTangent(0); - it.value().setOutTangent(0); - return; - } else { // When we are in a node that is in the middle of two other nodes, we need to check if we @@ -1169,8 +1151,21 @@ void AutomationClip::generateTangents(timeMap::iterator it, int numToGenerate) it.value().setOutTangent(outTangent); } } - it++; } } +std::vector AutomationClip::combineAllTracks() +{ + std::vector combinedTrackList; + + auto& songTracks = Engine::getSong()->tracks(); + auto& patternStoreTracks = Engine::patternStore()->tracks(); + + combinedTrackList.insert(combinedTrackList.end(), songTracks.begin(), songTracks.end()); + combinedTrackList.insert(combinedTrackList.end(), patternStoreTracks.begin(), patternStoreTracks.end()); + combinedTrackList.push_back(Engine::getSong()->globalAutomationTrack()); + + return combinedTrackList; +} + } // namespace lmms diff --git a/src/core/BandLimitedWave.cpp b/src/core/BandLimitedWave.cpp index a7dd650c0..cb09dc5b8 100644 --- a/src/core/BandLimitedWave.cpp +++ b/src/core/BandLimitedWave.cpp @@ -30,7 +30,7 @@ namespace lmms { -std::array BandLimitedWave::s_waveforms = { }; +std::array BandLimitedWave::s_waveforms = { }; bool BandLimitedWave::s_wavesGenerated = false; QString BandLimitedWave::s_wavetableDir = ""; @@ -84,7 +84,7 @@ void BandLimitedWave::generateWaves() { saw_file.open( QIODevice::ReadOnly ); QDataStream in( &saw_file ); - in >> s_waveforms[ BandLimitedWave::BLSaw ]; + in >> s_waveforms[static_cast(BandLimitedWave::Waveform::BLSaw)]; saw_file.close(); } else @@ -108,14 +108,14 @@ void BandLimitedWave::generateWaves() s += amp * /*a2 **/sin( static_cast( ph * harm ) / static_cast( len ) * F_2PI ); harm++; } while( hlen > 2.0 ); - s_waveforms[ BandLimitedWave::BLSaw ].setSampleAt( i, ph, s ); - max = qMax( max, qAbs( s ) ); + s_waveforms[static_cast(BandLimitedWave::Waveform::BLSaw)].setSampleAt( i, ph, s ); + max = std::max(max, std::abs(s)); } // normalize for( int ph = 0; ph < len; ph++ ) { - sample_t s = s_waveforms[ BandLimitedWave::BLSaw ].sampleAt( i, ph ) / max; - s_waveforms[ BandLimitedWave::BLSaw ].setSampleAt( i, ph, s ); + sample_t s = s_waveforms[static_cast(BandLimitedWave::Waveform::BLSaw)].sampleAt( i, ph ) / max; + s_waveforms[static_cast(BandLimitedWave::Waveform::BLSaw)].setSampleAt( i, ph, s ); } } } @@ -126,7 +126,7 @@ void BandLimitedWave::generateWaves() { sqr_file.open( QIODevice::ReadOnly ); QDataStream in( &sqr_file ); - in >> s_waveforms[ BandLimitedWave::BLSquare ]; + in >> s_waveforms[static_cast(BandLimitedWave::Waveform::BLSquare)]; sqr_file.close(); } else @@ -150,14 +150,14 @@ void BandLimitedWave::generateWaves() s += amp * /*a2 **/ sin( static_cast( ph * harm ) / static_cast( len ) * F_2PI ); harm += 2; } while( hlen > 2.0 ); - s_waveforms[ BandLimitedWave::BLSquare ].setSampleAt( i, ph, s ); - max = qMax( max, qAbs( s ) ); + s_waveforms[static_cast(BandLimitedWave::Waveform::BLSquare)].setSampleAt( i, ph, s ); + max = std::max(max, std::abs(s)); } // normalize for( int ph = 0; ph < len; ph++ ) { - sample_t s = s_waveforms[ BandLimitedWave::BLSquare ].sampleAt( i, ph ) / max; - s_waveforms[ BandLimitedWave::BLSquare ].setSampleAt( i, ph, s ); + sample_t s = s_waveforms[static_cast(BandLimitedWave::Waveform::BLSquare)].sampleAt( i, ph ) / max; + s_waveforms[static_cast(BandLimitedWave::Waveform::BLSquare)].setSampleAt( i, ph, s ); } } } @@ -167,7 +167,7 @@ void BandLimitedWave::generateWaves() { tri_file.open( QIODevice::ReadOnly ); QDataStream in( &tri_file ); - in >> s_waveforms[ BandLimitedWave::BLTriangle ]; + in >> s_waveforms[static_cast(BandLimitedWave::Waveform::BLTriangle)]; tri_file.close(); } else @@ -192,14 +192,14 @@ void BandLimitedWave::generateWaves() ( ( harm + 1 ) % 4 == 0 ? 0.5 : 0.0 ) ) * F_2PI ); harm += 2; } while( hlen > 2.0 ); - s_waveforms[ BandLimitedWave::BLTriangle ].setSampleAt( i, ph, s ); - max = qMax( max, qAbs( s ) ); + s_waveforms[static_cast(BandLimitedWave::Waveform::BLTriangle)].setSampleAt( i, ph, s ); + max = std::max(max, std::abs(s)); } // normalize for( int ph = 0; ph < len; ph++ ) { - sample_t s = s_waveforms[ BandLimitedWave::BLTriangle ].sampleAt( i, ph ) / max; - s_waveforms[ BandLimitedWave::BLTriangle ].setSampleAt( i, ph, s ); + sample_t s = s_waveforms[static_cast(BandLimitedWave::Waveform::BLTriangle)].sampleAt( i, ph ) / max; + s_waveforms[static_cast(BandLimitedWave::Waveform::BLTriangle)].setSampleAt( i, ph, s ); } } } @@ -210,7 +210,7 @@ void BandLimitedWave::generateWaves() { moog_file.open( QIODevice::ReadOnly ); QDataStream in( &moog_file ); - in >> s_waveforms[ BandLimitedWave::BLMoog ]; + in >> s_waveforms[static_cast(BandLimitedWave::Waveform::BLMoog)]; moog_file.close(); } else @@ -222,9 +222,9 @@ void BandLimitedWave::generateWaves() for( int ph = 0; ph < len; ph++ ) { const int sawph = ( ph + static_cast( len * 0.75 ) ) % len; - const sample_t saw = s_waveforms[ BandLimitedWave::BLSaw ].sampleAt( i, sawph ); - const sample_t tri = s_waveforms[ BandLimitedWave::BLTriangle ].sampleAt( i, ph ); - s_waveforms[ BandLimitedWave::BLMoog ].setSampleAt( i, ph, ( saw + tri ) * 0.5f ); + const sample_t saw = s_waveforms[static_cast(BandLimitedWave::Waveform::BLSaw)].sampleAt( i, sawph ); + const sample_t tri = s_waveforms[static_cast(BandLimitedWave::Waveform::BLTriangle)].sampleAt( i, ph ); + s_waveforms[static_cast(BandLimitedWave::Waveform::BLMoog)].setSampleAt( i, ph, ( saw + tri ) * 0.5f ); } } } @@ -252,22 +252,22 @@ QFile moogfile( "path-to-wavetables/moog.bin" ); sawfile.open( QIODevice::WriteOnly ); QDataStream sawout( &sawfile ); -sawout << s_waveforms[ BandLimitedWave::BLSaw ]; +sawout << s_waveforms[static_cast(BandLimitedWave::Waveform::BLSaw)]; sawfile.close(); sqrfile.open( QIODevice::WriteOnly ); QDataStream sqrout( &sqrfile ); -sqrout << s_waveforms[ BandLimitedWave::BLSquare ]; +sqrout << s_waveforms[static_cast(BandLimitedWave::Waveform::BLSquare)]; sqrfile.close(); trifile.open( QIODevice::WriteOnly ); QDataStream triout( &trifile ); -triout << s_waveforms[ BandLimitedWave::BLTriangle ]; +triout << s_waveforms[static_cast(BandLimitedWave::Waveform::BLTriangle)]; trifile.close(); moogfile.open( QIODevice::WriteOnly ); QDataStream moogout( &moogfile ); -moogout << s_waveforms[ BandLimitedWave::BLMoog ]; +moogout << s_waveforms[static_cast(BandLimitedWave::Waveform::BLMoog)]; moogfile.close(); */ diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index b8809ed78..319882af2 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -77,6 +77,8 @@ set(LMMS_SRCS core/ToolPlugin.cpp core/Track.cpp core/TrackContainer.cpp + core/UpgradeExtendedNoteRange.h + core/UpgradeExtendedNoteRange.cpp core/Clip.cpp core/ValueBuffer.cpp core/VstSyncController.cpp diff --git a/src/core/Clip.cpp b/src/core/Clip.cpp index 74a168fbd..db1200aae 100644 --- a/src/core/Clip.cpp +++ b/src/core/Clip.cpp @@ -92,7 +92,7 @@ Clip::~Clip() */ void Clip::movePosition( const TimePos & pos ) { - TimePos newPos = qMax(0, pos.getTicks()); + TimePos newPos = std::max(0, pos.getTicks()); if (m_startPosition != newPos) { Engine::audioEngine()->requestChangeInModel(); diff --git a/src/core/ConfigManager.cpp b/src/core/ConfigManager.cpp index bfe9e31f1..61d84770a 100644 --- a/src/core/ConfigManager.cpp +++ b/src/core/ConfigManager.cpp @@ -77,9 +77,9 @@ ConfigManager::ConfigManager() : m_sf2Dir = m_workingDir + SF2_PATH; m_gigDir = m_workingDir + GIG_PATH; m_themeDir = defaultThemeDir(); - if (!qgetenv("LMMS_DATA_DIR").isEmpty()) + if (std::getenv("LMMS_DATA_DIR")) { - QDir::addSearchPath("data", QString::fromLocal8Bit(qgetenv("LMMS_DATA_DIR"))); + QDir::addSearchPath("data", QString::fromLocal8Bit(std::getenv("LMMS_DATA_DIR"))); } initDevelopmentWorkingDir(); @@ -173,7 +173,7 @@ void ConfigManager::upgrade() ProjectVersion createdWith = m_version; // Don't use old themes as they break the UI (i.e. 0.4 != 1.0, etc) - if (createdWith.setCompareType(ProjectVersion::Minor) != LMMS_VERSION) + if (createdWith.setCompareType(ProjectVersion::CompareType::Minor) != LMMS_VERSION) { m_themeDir = defaultThemeDir(); } @@ -334,10 +334,9 @@ void ConfigManager::addRecentlyOpenedProject(const QString & file) -const QString & ConfigManager::value(const QString & cls, - const QString & attribute) const +QString ConfigManager::value(const QString& cls, const QString& attribute, const QString& defaultVal) const { - if(m_settings.contains(cls)) + if (m_settings.find(cls) != m_settings.end()) { for (const auto& setting : m_settings[cls]) { @@ -347,18 +346,7 @@ const QString & ConfigManager::value(const QString & cls, } } } - static QString empty; - return empty; -} - - - -const QString & ConfigManager::value(const QString & cls, - const QString & attribute, - const QString & defaultVal) const -{ - const QString & val = value(cls, attribute); - return val.isEmpty() ? defaultVal : val; + return defaultVal; } @@ -569,8 +557,8 @@ void ConfigManager::loadConfigFile(const QString & configFile) upgrade(); QStringList searchPaths; - if(! qgetenv("LMMS_THEME_PATH").isNull()) - searchPaths << qgetenv("LMMS_THEME_PATH"); + if (std::getenv("LMMS_THEME_PATH")) + searchPaths << std::getenv("LMMS_THEME_PATH"); searchPaths << themeDir() << defaultThemeDir(); QDir::setSearchPaths("resources", searchPaths); @@ -719,7 +707,7 @@ unsigned int ConfigManager::legacyConfigVersion() { ProjectVersion createdWith = m_version; - createdWith.setCompareType(ProjectVersion::Build); + createdWith.setCompareType(ProjectVersion::CompareType::Build); if( createdWith < "1.1.90" ) { diff --git a/src/core/Controller.cpp b/src/core/Controller.cpp index aee6481cc..3e1b596b8 100644 --- a/src/core/Controller.cpp +++ b/src/core/Controller.cpp @@ -25,8 +25,8 @@ */ #include -#include +#include #include "AudioEngine.h" #include "ControllerConnection.h" @@ -40,11 +40,11 @@ namespace lmms long Controller::s_periods = 0; -QVector Controller::s_controllers; +std::vector Controller::s_controllers; -Controller::Controller( ControllerTypes _type, Model * _parent, +Controller::Controller( ControllerType _type, Model * _parent, const QString & _display_name ) : Model( _parent, _display_name ), JournallingObject(), @@ -53,9 +53,9 @@ Controller::Controller( ControllerTypes _type, Model * _parent, m_connectionCount( 0 ), m_type( _type ) { - if( _type != DummyController && _type != MidiController ) + if( _type != ControllerType::Dummy && _type != ControllerType::Midi ) { - s_controllers.append( this ); + s_controllers.push_back(this); // Determine which name to use for ( uint i=s_controllers.size(); ; i++ ) { @@ -86,10 +86,10 @@ Controller::Controller( ControllerTypes _type, Model * _parent, Controller::~Controller() { - int idx = s_controllers.indexOf( this ); - if( idx >= 0 ) + auto it = std::find(s_controllers.begin(), s_controllers.end(), this); + if (it != s_controllers.end()) { - s_controllers.remove( idx ); + s_controllers.erase(it); } m_valueBuffer.clear(); @@ -182,30 +182,30 @@ void Controller::resetFrameCounter() -Controller * Controller::create( ControllerTypes _ct, Model * _parent ) +Controller * Controller::create( ControllerType _ct, Model * _parent ) { static Controller * dummy = nullptr; Controller * c = nullptr; switch( _ct ) { - case Controller::DummyController: + case ControllerType::Dummy: if (!dummy) - dummy = new Controller( DummyController, nullptr, + dummy = new Controller( ControllerType::Dummy, nullptr, QString() ); c = dummy; break; - case Controller::LfoController: + case ControllerType::Lfo: c = new class LfoController( _parent ); break; - case Controller::PeakController: + case ControllerType::Peak: //Already instantiated in EffectChain::loadSettings() Q_ASSERT( false ); break; - case Controller::MidiController: + case ControllerType::Midi: c = new class MidiController( _parent ); break; @@ -221,14 +221,14 @@ Controller * Controller::create( ControllerTypes _ct, Model * _parent ) Controller * Controller::create( const QDomElement & _this, Model * _parent ) { Controller * c; - if( _this.attribute( "type" ).toInt() == Controller::PeakController ) + if( static_cast(_this.attribute( "type" ).toInt()) == ControllerType::Peak ) { c = PeakController::getControllerBySetting( _this ); } else { c = create( - static_cast( _this.attribute( "type" ).toInt() ), + static_cast( _this.attribute( "type" ).toInt() ), _parent ); } @@ -269,7 +269,7 @@ bool Controller::hasModel( const Model * m ) const void Controller::saveSettings( QDomDocument & _doc, QDomElement & _this ) { - _this.setAttribute( "type", type() ); + _this.setAttribute( "type", static_cast(type()) ); _this.setAttribute( "name", name() ); } @@ -277,7 +277,7 @@ void Controller::saveSettings( QDomDocument & _doc, QDomElement & _this ) void Controller::loadSettings( const QDomElement & _this ) { - if( _this.attribute( "type" ).toInt() != type() ) + if( static_cast(_this.attribute( "type" ).toInt()) != type() ) { qWarning( "controller-type does not match controller-type of " "settings-node!\n" ); diff --git a/src/core/ControllerConnection.cpp b/src/core/ControllerConnection.cpp index c65cd8ae9..fea907942 100644 --- a/src/core/ControllerConnection.cpp +++ b/src/core/ControllerConnection.cpp @@ -50,21 +50,21 @@ ControllerConnection::ControllerConnection(Controller * _controller) : } else { - m_controller = Controller::create( Controller::DummyController, + m_controller = Controller::create( Controller::ControllerType::Dummy, nullptr ); } - s_connections.append( this ); + s_connections.push_back(this); } ControllerConnection::ControllerConnection( int _controllerId ) : - m_controller( Controller::create( Controller::DummyController, nullptr ) ), + m_controller( Controller::create( Controller::ControllerType::Dummy, nullptr ) ), m_controllerId( _controllerId ), m_ownsController( false ) { - s_connections.append( this ); + s_connections.push_back(this); } @@ -72,11 +72,14 @@ ControllerConnection::ControllerConnection( int _controllerId ) : ControllerConnection::~ControllerConnection() { - if( m_controller && m_controller->type() != Controller::DummyController ) + if( m_controller && m_controller->type() != Controller::ControllerType::Dummy ) { m_controller->removeConnection( this ); } - s_connections.remove( s_connections.indexOf( this ) ); + + auto it = std::find(s_connections.begin(), s_connections.end(), this); + if (it != s_connections.end()) { s_connections.erase(it); }; + if( m_ownsController ) { delete m_controller; @@ -101,14 +104,14 @@ void ControllerConnection::setController( Controller * _controller ) m_controller = nullptr; } - if( m_controller && m_controller->type() != Controller::DummyController ) + if( m_controller && m_controller->type() != Controller::ControllerType::Dummy ) { m_controller->removeConnection( this ); } if( !_controller ) { - m_controller = Controller::create( Controller::DummyController, nullptr ); + m_controller = Controller::create( Controller::ControllerType::Dummy, nullptr ); } else { @@ -116,7 +119,7 @@ void ControllerConnection::setController( Controller * _controller ) } m_controllerId = -1; - if( _controller->type() != Controller::DummyController ) + if( _controller->type() != Controller::ControllerType::Dummy ) { _controller->addConnection( this ); QObject::connect( _controller, SIGNAL(valueChanged()), @@ -124,7 +127,7 @@ void ControllerConnection::setController( Controller * _controller ) } m_ownsController = - (_controller->type() == Controller::MidiController); + (_controller->type() == Controller::ControllerType::Midi); // If we don't own the controller, allow deletion of controller // to delete the connection @@ -165,7 +168,7 @@ void ControllerConnection::finalizeConnections() c->setController( Engine::getSong()-> controllers().at( c->m_controllerId ) ); } - else if (c->getController()->type() == Controller::DummyController) + else if (c->getController()->type() == Controller::ControllerType::Dummy) { delete c; --i; @@ -186,10 +189,12 @@ void ControllerConnection::saveSettings( QDomDocument & _doc, QDomElement & _thi } else { - int id = Engine::getSong()->controllers().indexOf( m_controller ); - if( id >= 0 ) + const auto& controllers = Engine::getSong()->controllers(); + const auto it = std::find(controllers.begin(), controllers.end(), m_controller); + if (it != controllers.end()) { - _this.setAttribute( "id", id ); + const int id = std::distance(controllers.begin(), it); + _this.setAttribute("id", id); } } } @@ -223,7 +228,7 @@ void ControllerConnection::loadSettings( const QDomElement & _this ) } else { - m_controller = Controller::create( Controller::DummyController, nullptr ); + m_controller = Controller::create( Controller::ControllerType::Dummy, nullptr ); } } } diff --git a/src/core/DataFile.cpp b/src/core/DataFile.cpp index 2e7b21e8b..5c98ec81c 100644 --- a/src/core/DataFile.cpp +++ b/src/core/DataFile.cpp @@ -26,6 +26,7 @@ #include "DataFile.h" +#include #include #include @@ -47,6 +48,7 @@ #include "TextFloat.h" #include "Track.h" #include "PathUtil.h" +#include "UpgradeExtendedNoteRange.h" #include "lmmsversion.h" @@ -97,17 +99,16 @@ namespace QString m_name; }; - const auto s_types = std::array - { - TypeDescStruct{ DataFile::UnknownType, "unknown" }, - TypeDescStruct{ DataFile::SongProject, "song" }, - TypeDescStruct{ DataFile::SongProjectTemplate, "songtemplate" }, - TypeDescStruct{ DataFile::InstrumentTrackSettings, "instrumenttracksettings" }, - TypeDescStruct{ DataFile::DragNDropData, "dnddata" }, - TypeDescStruct{ DataFile::ClipboardData, "clipboard-data" }, - TypeDescStruct{ DataFile::JournalData, "journaldata" }, - TypeDescStruct{ DataFile::EffectSettings, "effectsettings" }, - TypeDescStruct{ DataFile::MidiClip, "midiclip" } + const auto s_types = std::array{ + TypeDescStruct{ DataFile::Type::Unknown, "unknown" }, + TypeDescStruct{ DataFile::Type::SongProject, "song" }, + TypeDescStruct{ DataFile::Type::SongProjectTemplate, "songtemplate" }, + TypeDescStruct{ DataFile::Type::InstrumentTrackSettings, "instrumenttracksettings" }, + TypeDescStruct{ DataFile::Type::DragNDropData, "dnddata" }, + TypeDescStruct{ DataFile::Type::ClipboardData, "clipboard-data" }, + TypeDescStruct{ DataFile::Type::JournalData, "journaldata" }, + TypeDescStruct{ DataFile::Type::EffectSettings, "effectsettings" }, + TypeDescStruct{ DataFile::Type::MidiClip, "midiclip" } }; } @@ -213,7 +214,7 @@ bool DataFile::validate( QString extension ) return true; } break; - case Type::UnknownType: + case Type::Unknown: if (! ( extension == "mmp" || extension == "mpt" || extension == "mmpz" || extension == "xpf" || extension == "xml" || ( extension == "xiz" && ! getPluginFactory()->pluginSupportingExtension(extension).isNull()) || @@ -250,7 +251,7 @@ QString DataFile::nameWithExtension( const QString & _fn ) const switch( type() ) { - case SongProject: + case Type::SongProject: if( extension != "mmp" && extension != "mpt" && extension != "mmpz" ) @@ -263,13 +264,13 @@ QString DataFile::nameWithExtension( const QString & _fn ) const return _fn + ".mmp"; } break; - case SongProjectTemplate: + case Type::SongProjectTemplate: if( extension != "mpt" ) { return _fn + ".mpt"; } break; - case InstrumentTrackSettings: + case Type::InstrumentTrackSettings: if( extension != "xpf" ) { return _fn + ".xpf"; @@ -285,8 +286,8 @@ QString DataFile::nameWithExtension( const QString & _fn ) const void DataFile::write( QTextStream & _strm ) { - if( type() == SongProject || type() == SongProjectTemplate - || type() == InstrumentTrackSettings ) + if( type() == Type::SongProject || type() == Type::SongProjectTemplate + || type() == Type::InstrumentTrackSettings ) { cleanMetaNodes( documentElement() ); } @@ -584,21 +585,17 @@ bool DataFile::hasLocalPlugins(QDomElement parent /* = QDomElement()*/, bool fir DataFile::Type DataFile::type( const QString& typeName ) { - for( int i = 0; i < TypeCount; ++i ) - { - if( s_types[i].m_name == typeName ) - { - return static_cast( i ); - } - } + const auto it = std::find_if(s_types.begin(), s_types.end(), + [&typeName](const TypeDescStruct& type) { return type.m_name == typeName; }); + if (it != s_types.end()) { return it->m_type; } // compat code if( typeName == "channelsettings" ) { - return DataFile::InstrumentTrackSettings; + return Type::InstrumentTrackSettings; } - return UnknownType; + return Type::Unknown; } @@ -606,12 +603,7 @@ DataFile::Type DataFile::type( const QString& typeName ) QString DataFile::typeName( Type type ) { - if( type >= UnknownType && type < TypeCount ) - { - return s_types[type].m_name; - } - - return s_types[UnknownType].m_name; + return s_types[static_cast(type)].m_name; } @@ -1677,74 +1669,10 @@ void DataFile::upgrade_automationNodes() */ void DataFile::upgrade_extendedNoteRange() { - auto affected = [](const QDomElement& instrument) - { - return instrument.attribute("name") == "zynaddsubfx" || - instrument.attribute("name") == "vestige" || - instrument.attribute("name") == "lv2instrument" || - instrument.attribute("name") == "carlapatchbay" || - instrument.attribute("name") == "carlarack"; - }; + auto root = documentElement(); + UpgradeExtendedNoteRange upgradeExtendedNoteRange(root); - if (!elementsByTagName("song").item(0).isNull()) - { - // Dealing with a project file, go through all the tracks - QDomNodeList tracks = elementsByTagName("track"); - for (int i = 0; !tracks.item(i).isNull(); i++) - { - // Ignore BB container tracks - if (tracks.item(i).toElement().attribute("type").toInt() == 1) { continue; } - - QDomNodeList instruments = tracks.item(i).toElement().elementsByTagName("instrument"); - if (instruments.isEmpty()) { continue; } - QDomElement instrument = instruments.item(0).toElement(); - // Raise the base note of every instrument by 12 to compensate for the change - // of A4 key code from 57 to 69. This ensures that notes are labeled correctly. - instrument.parentNode().toElement().setAttribute( - "basenote", - instrument.parentNode().toElement().attribute("basenote").toInt() + 12); - // Raise the pitch of all notes in patterns assigned to instruments not affected - // by #1857 by an octave. This negates the base note change for normal instruments, - // but leaves the MIDI-based instruments sounding an octave lower, preserving their - // pitch in existing projects. - if (!affected(instrument)) - { - QDomNodeList patterns = tracks.item(i).toElement().elementsByTagName("pattern"); - for (int i = 0; !patterns.item(i).isNull(); i++) - { - QDomNodeList notes = patterns.item(i).toElement().elementsByTagName("note"); - for (int i = 0; !notes.item(i).isNull(); i++) - { - notes.item(i).toElement().setAttribute( - "key", - notes.item(i).toElement().attribute("key").toInt() + 12 - ); - } - } - } - } - } - else - { - // Dealing with a preset, not a song - QDomNodeList presets = elementsByTagName("instrumenttrack"); - if (presets.item(0).isNull()) { return; } - QDomElement preset = presets.item(0).toElement(); - // Common correction for all instrument presets (make base notes match the new MIDI range). - // NOTE: Many older presets do not have any basenote defined, assume they were "made for 57". - // (Specifying a default like this also happens to fix a FileBrowser bug where previews of presets - // with undefined basenote always play with the basenote inherited from previously played preview.) - int oldBase = preset.attribute("basenote", "57").toInt(); - preset.setAttribute("basenote", oldBase + 12); - // Extra correction for Zyn, VeSTige, LV2 and Carla (to preserve the original buggy behavior). - QDomNodeList instruments = presets.item(0).toElement().elementsByTagName("instrument"); - if (instruments.isEmpty()) { return; } - QDomElement instrument = instruments.item(0).toElement(); - if (affected(instrument)) - { - preset.setAttribute("basenote", preset.attribute("basenote").toInt() + 12); - } - } + upgradeExtendedNoteRange.upgrade(); } @@ -1825,8 +1753,8 @@ void DataFile::upgrade_bbTcoRename() for (int i = 0; !elements.item(i).isNull(); ++i) { auto e = elements.item(i).toElement(); - static_assert(Track::PatternTrack == 1, "Must be type=1 for backwards compatibility"); - if (e.attribute("type").toInt() == Track::PatternTrack) + static_assert(Track::Type::Pattern == static_cast(1), "Must be type=1 for backwards compatibility"); + if (static_cast(e.attribute("type").toInt()) == Track::Type::Pattern) { e.setAttribute("name", e.attribute("name").replace("Beat/Bassline", "Pattern")); } @@ -1854,7 +1782,7 @@ void DataFile::upgrade() documentElement().setAttribute( "creator", "LMMS" ); documentElement().setAttribute( "creatorversion", LMMS_VERSION ); - if( type() == SongProject || type() == SongProjectTemplate ) + if( type() == Type::SongProject || type() == Type::SongProjectTemplate ) { // Time-signature if ( !m_head.hasAttribute( "timesig_numerator" ) ) @@ -1932,8 +1860,8 @@ void DataFile::loadData( const QByteArray & _data, const QString & _sourceFile ) ProjectVersion createdWith = root.attribute("creatorversion"); ProjectVersion openedWith = LMMS_VERSION; - if (createdWith.setCompareType(ProjectVersion::Minor) - != openedWith.setCompareType(ProjectVersion::Minor) + if (createdWith.setCompareType(ProjectVersion::CompareType::Minor) + != openedWith.setCompareType(ProjectVersion::CompareType::Minor) && gui::getGUI() != nullptr && root.attribute("type") == "song" ){ auto projectType = _sourceFile.endsWith(".mpt") ? diff --git a/src/core/EffectChain.cpp b/src/core/EffectChain.cpp index 024ddab64..4da5c5197 100644 --- a/src/core/EffectChain.cpp +++ b/src/core/EffectChain.cpp @@ -25,6 +25,7 @@ #include +#include #include "EffectChain.h" #include "Effect.h" @@ -56,7 +57,7 @@ EffectChain::~EffectChain() void EffectChain::saveSettings( QDomDocument & _doc, QDomElement & _this ) { m_enabledModel.saveSettings( _doc, _this, "enabled" ); - _this.setAttribute( "numofeffects", m_effects.count() ); + _this.setAttribute("numofeffects", static_cast(m_effects.size())); for( Effect* effect : m_effects) { @@ -121,7 +122,7 @@ void EffectChain::loadSettings( const QDomElement & _this ) void EffectChain::appendEffect( Effect * _effect ) { Engine::audioEngine()->requestChangeInModel(); - m_effects.append( _effect ); + m_effects.push_back(_effect); Engine::audioEngine()->doneChangeInModel(); m_enabledModel.setValue( true ); @@ -136,7 +137,7 @@ void EffectChain::removeEffect( Effect * _effect ) { Engine::audioEngine()->requestChangeInModel(); - Effect ** found = std::find( m_effects.begin(), m_effects.end(), _effect ); + auto found = std::find(m_effects.begin(), m_effects.end(), _effect); if( found == m_effects.end() ) { Engine::audioEngine()->doneChangeInModel(); @@ -146,7 +147,7 @@ void EffectChain::removeEffect( Effect * _effect ) Engine::audioEngine()->doneChangeInModel(); - if( m_effects.isEmpty() ) + if (m_effects.empty()) { m_enabledModel.setValue( false ); } @@ -159,10 +160,11 @@ void EffectChain::removeEffect( Effect * _effect ) void EffectChain::moveDown( Effect * _effect ) { - if( _effect != m_effects.last() ) + if (_effect != m_effects.back()) { - int i = m_effects.indexOf(_effect); - std::swap(m_effects[i + 1], m_effects[i]); + auto it = std::find(m_effects.begin(), m_effects.end(), _effect); + assert(it != m_effects.end()); + std::swap(*std::next(it), *it); } } @@ -171,10 +173,11 @@ void EffectChain::moveDown( Effect * _effect ) void EffectChain::moveUp( Effect * _effect ) { - if( _effect != m_effects.first() ) + if (_effect != m_effects.front()) { - int i = m_effects.indexOf(_effect); - std::swap(m_effects[i - 1], m_effects[i]); + auto it = std::find(m_effects.begin(), m_effects.end(), _effect); + assert(it != m_effects.end()); + std::swap(*std::prev(it), *it); } } @@ -228,9 +231,9 @@ void EffectChain::clear() Engine::audioEngine()->requestChangeInModel(); - while( m_effects.count() ) + while (m_effects.size()) { - Effect * e = m_effects[m_effects.count() - 1]; + auto e = m_effects[m_effects.size() - 1]; m_effects.pop_back(); delete e; } diff --git a/src/core/EnvelopeAndLfoParameters.cpp b/src/core/EnvelopeAndLfoParameters.cpp index 2aa77e6aa..0a9673c8e 100644 --- a/src/core/EnvelopeAndLfoParameters.cpp +++ b/src/core/EnvelopeAndLfoParameters.cpp @@ -113,7 +113,7 @@ EnvelopeAndLfoParameters::EnvelopeAndLfoParameters( SECS_PER_LFO_OSCILLATION * 1000.0, this, tr( "LFO frequency" ) ), m_lfoAmountModel( 0.0, -1.0, 1.0, 0.005, this, tr( "LFO mod amount" ) ), - m_lfoWaveModel( SineWave, 0, NumLfoShapes, this, tr( "LFO wave shape" ) ), + m_lfoWaveModel( static_cast(LfoShape::SineWave), 0, NumLfoShapes, this, tr( "LFO wave shape" ) ), m_x100Model( false, this, tr( "LFO frequency x 100" ) ), m_controlEnvAmountModel( false, this, tr( "Modulate env amount" ) ), m_lfoFrame( 0 ), @@ -209,28 +209,28 @@ inline sample_t EnvelopeAndLfoParameters::lfoShapeSample( fpp_t _frame_offset ) const float phase = frame / static_cast( m_lfoOscillationFrames ); sample_t shape_sample; - switch( m_lfoWaveModel.value() ) + switch( static_cast(m_lfoWaveModel.value()) ) { - case TriangleWave: + case LfoShape::TriangleWave: shape_sample = Oscillator::triangleSample( phase ); break; - case SquareWave: + case LfoShape::SquareWave: shape_sample = Oscillator::squareSample( phase ); break; - case SawWave: + case LfoShape::SawWave: shape_sample = Oscillator::sawSample( phase ); break; - case UserDefinedWave: + case LfoShape::UserDefinedWave: shape_sample = m_userWave.userWaveSample( phase ); break; - case RandomWave: + case LfoShape::RandomWave: if( frame == 0 ) { m_random = Oscillator::noiseSample( 0.0f ); } shape_sample = m_random; break; - case SineWave: + case LfoShape::SineWave: default: shape_sample = Oscillator::sinSample( phase ); break; @@ -274,7 +274,7 @@ inline void EnvelopeAndLfoParameters::fillLfoLevel( float * _buf, } fpp_t offset = 0; - const float lafI = 1.0f / qMax( minimumFrames, m_lfoAttackFrames ); + const float lafI = 1.0f / std::max(minimumFrames, m_lfoAttackFrames); for( ; offset < _frames && _frame < m_lfoAttackFrames; ++offset, ++_frame ) { @@ -404,16 +404,16 @@ void EnvelopeAndLfoParameters::updateSampleVars() // TODO: Remove the expKnobVals, time should be linear const auto predelay_frames = static_cast(frames_per_env_seg * expKnobVal(m_predelayModel.value())); - const f_cnt_t attack_frames = qMax( minimumFrames, - static_cast( frames_per_env_seg * - expKnobVal( m_attackModel.value() ) ) ); + const f_cnt_t attack_frames = std::max(minimumFrames, + static_cast(frames_per_env_seg * + expKnobVal(m_attackModel.value()))); const auto hold_frames = static_cast(frames_per_env_seg * expKnobVal(m_holdModel.value())); - const f_cnt_t decay_frames = qMax( minimumFrames, - static_cast( frames_per_env_seg * - expKnobVal( m_decayModel.value() * - ( 1 - m_sustainModel.value() ) ) ) ); + const f_cnt_t decay_frames = std::max(minimumFrames, + static_cast(frames_per_env_seg * + expKnobVal(m_decayModel.value() * + (1 - m_sustainModel.value())))); m_sustainLevel = m_sustainModel.value(); m_amount = m_amountModel.value(); @@ -430,7 +430,7 @@ void EnvelopeAndLfoParameters::updateSampleVars() decay_frames; m_rFrames = static_cast( frames_per_env_seg * expKnobVal( m_releaseModel.value() ) ); - m_rFrames = qMax( minimumFrames, m_rFrames ); + m_rFrames = std::max(minimumFrames, m_rFrames); if( static_cast( floorf( m_amount * 1000.0f ) ) == 0 ) { diff --git a/src/core/ImportFilter.cpp b/src/core/ImportFilter.cpp index 35c34078e..bc43b0c6c 100644 --- a/src/core/ImportFilter.cpp +++ b/src/core/ImportFilter.cpp @@ -61,7 +61,7 @@ void ImportFilter::import( const QString & _file_to_import, const bool j = Engine::projectJournal()->isJournalling(); Engine::projectJournal()->setJournalling( false ); - for (const Plugin::Descriptor* desc : getPluginFactory()->descriptors(Plugin::ImportFilter)) + for (const Plugin::Descriptor* desc : getPluginFactory()->descriptors(Plugin::Type::ImportFilter)) { unique_ptr p(Plugin::instantiate( desc->name, nullptr, s.data() )); if( dynamic_cast( p.get() ) != nullptr && diff --git a/src/core/Instrument.cpp b/src/core/Instrument.cpp index dde260fdc..b715bcac0 100644 --- a/src/core/Instrument.cpp +++ b/src/core/Instrument.cpp @@ -185,8 +185,8 @@ void Instrument::applyRelease( sampleFrame * buf, const NotePlayHandle * _n ) if( fl <= desiredReleaseFrames()+fpp ) { for( fpp_t f = (fpp_t)( ( fl > desiredReleaseFrames() ) ? - ( qMax( fpp - desiredReleaseFrames(), 0 ) + - fl % fpp ) : 0 ); f < frames; ++f ) + (std::max(fpp - desiredReleaseFrames(), 0) + + fl % fpp) : 0); f < frames; ++f) { const float fac = (float)( fl-f-1 ) / desiredReleaseFrames(); diff --git a/src/core/InstrumentFunctions.cpp b/src/core/InstrumentFunctions.cpp index 06e56666c..431afd2fe 100644 --- a/src/core/InstrumentFunctions.cpp +++ b/src/core/InstrumentFunctions.cpp @@ -177,12 +177,11 @@ bool InstrumentFunctionNoteStacking::Chord::hasSemiTone( int8_t semi_tone ) cons -InstrumentFunctionNoteStacking::ChordTable::ChordTable() : - QVector() +InstrumentFunctionNoteStacking::ChordTable::ChordTable() { for (const auto& chord : s_initTable) { - push_back(Chord(chord.m_name, chord.m_semiTones)); + m_chords.emplace_back(chord.m_name, chord.m_semiTones); } } @@ -191,10 +190,12 @@ InstrumentFunctionNoteStacking::ChordTable::ChordTable() : const InstrumentFunctionNoteStacking::Chord & InstrumentFunctionNoteStacking::ChordTable::getByName( const QString & name, bool is_scale ) const { - for( int i = 0; i < size(); i++ ) + for (const auto& chord : m_chords) { - if( at( i ).getName() == name && is_scale == at( i ).isScale() ) - return at( i ); + if (chord.getName() == name && is_scale == chord.isScale()) + { + return chord; + } } static Chord empty; @@ -211,9 +212,10 @@ InstrumentFunctionNoteStacking::InstrumentFunctionNoteStacking( Model * _parent m_chordRangeModel( 1.0f, 1.0f, 9.0f, 1.0f, this, tr( "Chord range" ) ) { const ChordTable & chord_table = ChordTable::getInstance(); - for( int i = 0; i < chord_table.size(); ++i ) + + for (const auto& chord : chord_table.chords()) { - m_chordsModel.addItem( chord_table[i].getName() ); + m_chordsModel.addItem(chord.getName()); } } @@ -232,7 +234,7 @@ void InstrumentFunctionNoteStacking::processNote( NotePlayHandle * _n ) // at the same time we only add sub-notes if nothing of the note was // played yet, because otherwise we would add chord-subnotes every // time an audio-buffer is rendered... - if( ( _n->origin() == NotePlayHandle::OriginArpeggio || ( _n->hasParent() == false && _n->instrumentTrack()->isArpeggioEnabled() == false ) ) && + if( ( _n->origin() == NotePlayHandle::Origin::Arpeggio || ( _n->hasParent() == false && _n->instrumentTrack()->isArpeggioEnabled() == false ) ) && _n->totalFramesPlayed() == 0 && m_chordsEnabledModel.value() == true && ! _n->isReleased() ) { @@ -244,10 +246,10 @@ void InstrumentFunctionNoteStacking::processNote( NotePlayHandle * _n ) const int sub_note_key_base = base_note_key + octave_cnt * KeysPerOctave; // process all notes in the chord - for( int i = 0; i < chord_table[selected_chord].size(); ++i ) + for( int i = 0; i < chord_table.chords()[selected_chord].size(); ++i ) { // add interval to sub-note-key - const int sub_note_key = sub_note_key_base + (int) chord_table[selected_chord][i]; + const int sub_note_key = sub_note_key_base + (int) chord_table.chords()[selected_chord][i]; // maybe we're out of range -> let's get outta // here! if( sub_note_key > NumKeys ) @@ -261,7 +263,7 @@ void InstrumentFunctionNoteStacking::processNote( NotePlayHandle * _n ) // different Engine::audioEngine()->addPlayHandle( NotePlayHandleManager::acquire( _n->instrumentTrack(), _n->offset(), _n->frames(), note_copy, - _n, -1, NotePlayHandle::OriginNoteStacking ) + _n, -1, NotePlayHandle::Origin::NoteStacking ) ); } } @@ -309,9 +311,9 @@ InstrumentFunctionArpeggio::InstrumentFunctionArpeggio( Model * _parent ) : m_arpModeModel( this, tr( "Arpeggio mode" ) ) { const InstrumentFunctionNoteStacking::ChordTable & chord_table = InstrumentFunctionNoteStacking::ChordTable::getInstance(); - for( int i = 0; i < chord_table.size(); ++i ) + for (auto& chord : chord_table.chords()) { - m_arpModel.addItem( chord_table[i].getName() ); + m_arpModel.addItem(chord.getName()); } m_arpDirectionModel.addItem( tr( "Up" ), std::make_unique( "arp_up" ) ); @@ -319,7 +321,7 @@ InstrumentFunctionArpeggio::InstrumentFunctionArpeggio( Model * _parent ) : m_arpDirectionModel.addItem( tr( "Up and down" ), std::make_unique( "arp_up_and_down" ) ); m_arpDirectionModel.addItem( tr( "Down and up" ), std::make_unique( "arp_up_and_down" ) ); m_arpDirectionModel.addItem( tr( "Random" ), std::make_unique( "arp_random" ) ); - m_arpDirectionModel.setInitValue( ArpDirUp ); + m_arpDirectionModel.setInitValue( static_cast(ArpDirection::Up) ); m_arpModeModel.addItem( tr( "Free" ), std::make_unique( "arp_free" ) ); m_arpModeModel.addItem( tr( "Sort" ), std::make_unique( "arp_sort" ) ); @@ -334,8 +336,8 @@ InstrumentFunctionArpeggio::InstrumentFunctionArpeggio( Model * _parent ) : void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) { const int base_note_key = _n->key(); - if( _n->origin() == NotePlayHandle::OriginArpeggio || - _n->origin() == NotePlayHandle::OriginNoteStacking || + if( _n->origin() == NotePlayHandle::Origin::Arpeggio || + _n->origin() == NotePlayHandle::Origin::NoteStacking || !m_arpEnabledModel.value() || _n->isReleased() ) { @@ -349,7 +351,7 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) ConstNotePlayHandleList cnphv = NotePlayHandle::nphsOfInstrumentTrack( _n->instrumentTrack() ); - if( m_arpModeModel.value() != FreeMode && cnphv.size() == 0 ) + if( static_cast(m_arpModeModel.value()) != ArpMode::Free && cnphv.size() == 0 ) { // maybe we're playing only a preset-preview-note? cnphv = PresetPreviewPlayHandle::nphsOfInstrumentTrack( _n->instrumentTrack() ); @@ -362,7 +364,7 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) } const InstrumentFunctionNoteStacking::ChordTable & chord_table = InstrumentFunctionNoteStacking::ChordTable::getInstance(); - const int cur_chord_size = chord_table[selected_arp].size(); + const int cur_chord_size = chord_table.chords()[selected_arp].size(); const int range = static_cast(cur_chord_size * m_arpRangeModel.value() * m_arpRepeatsModel.value()); const int total_range = range * cnphv.size(); @@ -373,11 +375,11 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) // used for calculating remaining frames for arp-note, we have to add // arp_frames-1, otherwise the first arp-note will not be setup // correctly... -> arp_frames frames silence at the start of every note! - int cur_frame = ( ( m_arpModeModel.value() != FreeMode ) ? + int cur_frame = ( ( static_cast(m_arpModeModel.value()) != ArpMode::Free ) ? cnphv.first()->totalFramesPlayed() : _n->totalFramesPlayed() ) + arp_frames - 1; // used for loop - f_cnt_t frames_processed = ( m_arpModeModel.value() != FreeMode ) ? cnphv.first()->noteOffset() : _n->noteOffset(); + f_cnt_t frames_processed = ( static_cast(m_arpModeModel.value()) != ArpMode::Free ) ? cnphv.first()->noteOffset() : _n->noteOffset(); while( frames_processed < Engine::audioEngine()->framesPerPeriod() ) { @@ -395,7 +397,7 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) // in sorted mode: is it our turn or do we have to be quiet for // now? - if( m_arpModeModel.value() == SortMode && + if( static_cast(m_arpModeModel.value()) == ArpMode::Sort && ( ( cur_frame / arp_frames ) % total_range ) / range != (f_cnt_t) _n->index() ) { // update counters @@ -416,7 +418,7 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) } } - int dir = m_arpDirectionModel.value(); + auto dir = static_cast(m_arpDirectionModel.value()); // Miss notes randomly. We intercept int dir and abuse it // after need. :) @@ -425,22 +427,22 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) { if( 100 * ( (float) rand() / (float)( RAND_MAX + 1.0f ) ) < m_arpMissModel.value() ) { - dir = ArpDirRandom; + dir = ArpDirection::Random; } } int cur_arp_idx = 0; // process according to arpeggio-direction... - if( dir == ArpDirUp ) + if( dir == ArpDirection::Up ) { cur_arp_idx = ( cur_frame / arp_frames ) % range; } - else if( dir == ArpDirDown ) + else if( dir == ArpDirection::Down ) { cur_arp_idx = range - ( cur_frame / arp_frames ) % range - 1; } - else if( dir == ArpDirUpAndDown && range > 1 ) + else if( dir == ArpDirection::UpAndDown && range > 1 ) { // imagine, we had to play the arp once up and then // once down -> makes 2 * range possible notes... @@ -454,9 +456,9 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) cur_arp_idx = range - cur_arp_idx % ( range - 1 ) - 1; } } - else if( dir == ArpDirDownAndUp && range > 1 ) + else if( dir == ArpDirection::DownAndUp && range > 1 ) { - // copied from ArpDirUpAndDown above + // copied from ArpDirection::UpAndDown above cur_arp_idx = ( cur_frame / arp_frames ) % ( range * 2 - 2 ); // if greater than range, we have to play down... // looks like the code for arp_dir==DOWN... :) @@ -467,7 +469,7 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) // inverts direction cur_arp_idx = range - cur_arp_idx - 1; } - else if( dir == ArpDirRandom ) + else if( dir == ArpDirection::Random ) { // just pick a random chord-index cur_arp_idx = (int)( range * ( (float) rand() / (float) RAND_MAX ) ); @@ -477,7 +479,7 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) cur_arp_idx = static_cast(cur_arp_idx / m_arpRepeatsModel.value()); // Cycle notes - if( m_arpCycleModel.value() && dir != ArpDirRandom ) + if( m_arpCycleModel.value() && dir != ArpDirection::Random ) { cur_arp_idx *= m_arpCycleModel.value() + 1; cur_arp_idx %= static_cast( range / m_arpRepeatsModel.value() ); @@ -485,7 +487,7 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) // now calculate final key for our arp-note const int sub_note_key = base_note_key + (cur_arp_idx / cur_chord_size ) * - KeysPerOctave + chord_table[selected_arp][cur_arp_idx % cur_chord_size]; + KeysPerOctave + chord_table.chords()[selected_arp][cur_arp_idx % cur_chord_size]; // range-checking if( sub_note_key >= NumKeys || @@ -505,7 +507,7 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) gated_frames, Note( TimePos( 0 ), TimePos( 0 ), sub_note_key, _n->getVolume(), _n->getPanning(), _n->detuning() ), - _n, -1, NotePlayHandle::OriginArpeggio ) + _n, -1, NotePlayHandle::Origin::Arpeggio ) ); // update counters diff --git a/src/core/InstrumentPlayHandle.cpp b/src/core/InstrumentPlayHandle.cpp index 8c272cd47..e1a9d9d65 100644 --- a/src/core/InstrumentPlayHandle.cpp +++ b/src/core/InstrumentPlayHandle.cpp @@ -31,7 +31,7 @@ namespace lmms InstrumentPlayHandle::InstrumentPlayHandle( Instrument * instrument, InstrumentTrack* instrumentTrack ) : - PlayHandle( TypeInstrumentPlayHandle ), + PlayHandle( Type::InstrumentPlayHandle ), m_instrument( instrument ) { setAudioPort( instrumentTrack->audioPort() ); diff --git a/src/core/InstrumentSoundShaping.cpp b/src/core/InstrumentSoundShaping.cpp index edf3b403c..07c3bbf7c 100644 --- a/src/core/InstrumentSoundShaping.cpp +++ b/src/core/InstrumentSoundShaping.cpp @@ -69,7 +69,7 @@ InstrumentSoundShaping::InstrumentSoundShaping( for( int i = 0; i < NumTargets; ++i ) { float value_for_zero_amount = 0.0; - if( i == Volume ) + if( static_cast(i) == Target::Volume ) { value_for_zero_amount = 1.0; } @@ -119,7 +119,7 @@ float InstrumentSoundShaping::volumeLevel( NotePlayHandle* n, const f_cnt_t fram } float level; - m_envLfoParameters[Volume]->fillLevel( &level, frame, envReleaseBegin, 1 ); + m_envLfoParameters[static_cast(Target::Volume)]->fillLevel( &level, frame, envReleaseBegin, 1 ); return level; } @@ -160,22 +160,22 @@ void InstrumentSoundShaping::processAudioBuffer( sampleFrame* buffer, { n->m_filter = std::make_unique>( Engine::audioEngine()->processingSampleRate() ); } - n->m_filter->setFilterType( m_filterModel.value() ); + n->m_filter->setFilterType( static_cast::FilterType>(m_filterModel.value()) ); - if( m_envLfoParameters[Cut]->isUsed() ) + if( m_envLfoParameters[static_cast(Target::Cut)]->isUsed() ) { - m_envLfoParameters[Cut]->fillLevel( cutBuffer.data(), envTotalFrames, envReleaseBegin, frames ); + m_envLfoParameters[static_cast(Target::Cut)]->fillLevel( cutBuffer.data(), envTotalFrames, envReleaseBegin, frames ); } - if( m_envLfoParameters[Resonance]->isUsed() ) + if( m_envLfoParameters[static_cast(Target::Resonance)]->isUsed() ) { - m_envLfoParameters[Resonance]->fillLevel( resBuffer.data(), envTotalFrames, envReleaseBegin, frames ); + m_envLfoParameters[static_cast(Target::Resonance)]->fillLevel( resBuffer.data(), envTotalFrames, envReleaseBegin, frames ); } const float fcv = m_filterCutModel.value(); const float frv = m_filterResModel.value(); - if( m_envLfoParameters[Cut]->isUsed() && - m_envLfoParameters[Resonance]->isUsed() ) + if( m_envLfoParameters[static_cast(Target::Cut)]->isUsed() && + m_envLfoParameters[static_cast(Target::Resonance)]->isUsed() ) { for( fpp_t frame = 0; frame < frames; ++frame ) { @@ -196,7 +196,7 @@ void InstrumentSoundShaping::processAudioBuffer( sampleFrame* buffer, buffer[frame][1] = n->m_filter->update( buffer[frame][1], 1 ); } } - else if( m_envLfoParameters[Cut]->isUsed() ) + else if( m_envLfoParameters[static_cast(Target::Cut)]->isUsed() ) { for( fpp_t frame = 0; frame < frames; ++frame ) { @@ -213,7 +213,7 @@ void InstrumentSoundShaping::processAudioBuffer( sampleFrame* buffer, buffer[frame][1] = n->m_filter->update( buffer[frame][1], 1 ); } } - else if( m_envLfoParameters[Resonance]->isUsed() ) + else if( m_envLfoParameters[static_cast(Target::Resonance)]->isUsed() ) { for( fpp_t frame = 0; frame < frames; ++frame ) { @@ -241,10 +241,10 @@ void InstrumentSoundShaping::processAudioBuffer( sampleFrame* buffer, } } - if( m_envLfoParameters[Volume]->isUsed() ) + if( m_envLfoParameters[static_cast(Target::Volume)]->isUsed() ) { QVarLengthArray volBuffer(frames); - m_envLfoParameters[Volume]->fillLevel( volBuffer.data(), envTotalFrames, envReleaseBegin, frames ); + m_envLfoParameters[static_cast(Target::Volume)]->fillLevel( volBuffer.data(), envTotalFrames, envReleaseBegin, frames ); for( fpp_t frame = 0; frame < frames; ++frame ) { @@ -255,7 +255,7 @@ void InstrumentSoundShaping::processAudioBuffer( sampleFrame* buffer, } } -/* else if( m_envLfoParameters[Volume]->isUsed() == false && m_envLfoParameters[PANNING]->isUsed() ) +/* else if( m_envLfoParameters[static_cast(Target::Volume)]->isUsed() == false && m_envLfoParameters[PANNING]->isUsed() ) { // only use panning-envelope... for( fpp_t frame = 0; frame < frames; ++frame ) @@ -275,11 +275,11 @@ void InstrumentSoundShaping::processAudioBuffer( sampleFrame* buffer, f_cnt_t InstrumentSoundShaping::envFrames( const bool _only_vol ) const { - f_cnt_t ret_val = m_envLfoParameters[Volume]->PAHD_Frames(); + f_cnt_t ret_val = m_envLfoParameters[static_cast(Target::Volume)]->PAHD_Frames(); if( _only_vol == false ) { - for( int i = Volume+1; i < NumTargets; ++i ) + for( int i = static_cast(Target::Volume)+1; i < NumTargets; ++i ) { if( m_envLfoParameters[i]->isUsed() && m_envLfoParameters[i]->PAHD_Frames() > ret_val ) @@ -303,21 +303,21 @@ f_cnt_t InstrumentSoundShaping::releaseFrames() const f_cnt_t ret_val = m_instrumentTrack->instrument()->desiredReleaseFrames(); - if( m_instrumentTrack->instrument()->flags().testFlag( Instrument::IsSingleStreamed ) ) + if( m_instrumentTrack->instrument()->flags().testFlag( Instrument::Flag::IsSingleStreamed ) ) { return ret_val; } - if( m_envLfoParameters[Volume]->isUsed() ) + if( m_envLfoParameters[static_cast(Target::Volume)]->isUsed() ) { - return m_envLfoParameters[Volume]->releaseFrames(); + return m_envLfoParameters[static_cast(Target::Volume)]->releaseFrames(); } - for( int i = Volume+1; i < NumTargets; ++i ) + for( int i = static_cast(Target::Volume)+1; i < NumTargets; ++i ) { if( m_envLfoParameters[i]->isUsed() ) { - ret_val = qMax( ret_val, m_envLfoParameters[i]->releaseFrames() ); + ret_val = std::max(ret_val, m_envLfoParameters[i]->releaseFrames()); } } return ret_val; diff --git a/src/core/Ladspa2LMMS.cpp b/src/core/Ladspa2LMMS.cpp index 24dfc76f1..440b052f8 100644 --- a/src/core/Ladspa2LMMS.cpp +++ b/src/core/Ladspa2LMMS.cpp @@ -40,12 +40,12 @@ Ladspa2LMMS::Ladspa2LMMS() ladspa_key_t key = plugin.second; LadspaManagerDescription * desc = getDescription( key ); - if( desc->type == SOURCE ) + if( desc->type == LadspaPluginType::Source ) { m_instruments.append( qMakePair( getName( key ), key ) ); } - else if( desc->type == TRANSFER && + else if( desc->type == LadspaPluginType::Transfer && ( desc->inputChannels == desc->outputChannels && ( desc->inputChannels == 1 || desc->inputChannels == 2 || @@ -55,7 +55,7 @@ Ladspa2LMMS::Ladspa2LMMS() m_validEffects.append( qMakePair( getName( key ), key ) ); } - else if( desc->type == TRANSFER && + else if( desc->type == LadspaPluginType::Transfer && ( desc->inputChannels != desc->outputChannels || ( desc->inputChannels != 1 && desc->inputChannels != 2 && @@ -65,12 +65,12 @@ Ladspa2LMMS::Ladspa2LMMS() m_invalidEffects.append( qMakePair( getName( key ), key ) ); } - else if( desc->type == SINK ) + else if( desc->type == LadspaPluginType::Sink ) { m_analysisTools.append( qMakePair( getName( key ), key ) ); } - else if( desc->type == OTHER ) + else if( desc->type == LadspaPluginType::Other ) { m_otherPlugins.append( qMakePair( getName( key ), key ) ); diff --git a/src/core/LadspaControl.cpp b/src/core/LadspaControl.cpp index 7e8e92623..3282a0c7a 100644 --- a/src/core/LadspaControl.cpp +++ b/src/core/LadspaControl.cpp @@ -53,7 +53,7 @@ LadspaControl::LadspaControl( Model * _parent, port_desc_t * _port, switch( m_port->data_type ) { - case TOGGLED: + case BufferDataType::Toggled: m_toggledModel.setInitValue( static_cast( m_port->def ) ); connect( &m_toggledModel, SIGNAL(dataChanged()), @@ -66,8 +66,8 @@ LadspaControl::LadspaControl( Model * _parent, port_desc_t * _port, m_toggledModel.setScaleLogarithmic( m_port->suggests_logscale ); break; - case INTEGER: - case ENUM: + case BufferDataType::Integer: + case BufferDataType::Enum: m_knobModel.setRange( static_cast( m_port->max ), static_cast( m_port->min ), 1 + static_cast( m_port->max - @@ -80,7 +80,7 @@ LadspaControl::LadspaControl( Model * _parent, port_desc_t * _port, m_knobModel.setScaleLogarithmic( m_port->suggests_logscale ); break; - case FLOATING: + case BufferDataType::Floating: m_knobModel.setRange( m_port->min, m_port->max, ( m_port->max - m_port->min ) / ( m_port->name.toUpper() == "GAIN" @@ -93,7 +93,7 @@ LadspaControl::LadspaControl( Model * _parent, port_desc_t * _port, m_knobModel.setScaleLogarithmic( m_port->suggests_logscale ); break; - case TIME: + case BufferDataType::Time: m_tempoSyncKnobModel.setRange( m_port->min, m_port->max, ( m_port->max - m_port->min ) / 800.0f ); @@ -116,13 +116,13 @@ LADSPA_Data LadspaControl::value() { switch( m_port->data_type ) { - case TOGGLED: + case BufferDataType::Toggled: return static_cast( m_toggledModel.value() ); - case INTEGER: - case ENUM: - case FLOATING: + case BufferDataType::Integer: + case BufferDataType::Enum: + case BufferDataType::Floating: return static_cast( m_knobModel.value() ); - case TIME: + case BufferDataType::Time: return static_cast( m_tempoSyncKnobModel.value() ); default: qWarning( "LadspaControl::value(): BAD BAD BAD\n" ); @@ -137,13 +137,13 @@ ValueBuffer * LadspaControl::valueBuffer() { switch( m_port->data_type ) { - case TOGGLED: - case INTEGER: - case ENUM: + case BufferDataType::Toggled: + case BufferDataType::Integer: + case BufferDataType::Enum: return nullptr; - case FLOATING: + case BufferDataType::Floating: return m_knobModel.valueBuffer(); - case TIME: + case BufferDataType::Time: return m_tempoSyncKnobModel.valueBuffer(); default: qWarning( "LadspaControl::valueBuffer(): BAD BAD BAD\n" ); @@ -159,17 +159,17 @@ void LadspaControl::setValue( LADSPA_Data _value ) { switch( m_port->data_type ) { - case TOGGLED: + case BufferDataType::Toggled: m_toggledModel.setValue( static_cast( _value ) ); break; - case INTEGER: - case ENUM: + case BufferDataType::Integer: + case BufferDataType::Enum: m_knobModel.setValue( static_cast( _value ) ); break; - case FLOATING: + case BufferDataType::Floating: m_knobModel.setValue( static_cast( _value ) ); break; - case TIME: + case BufferDataType::Time: m_tempoSyncKnobModel.setValue( static_cast( _value ) ); break; @@ -194,15 +194,15 @@ void LadspaControl::saveSettings( QDomDocument& doc, } switch( m_port->data_type ) { - case TOGGLED: + case BufferDataType::Toggled: m_toggledModel.saveSettings( doc, e, "data" ); break; - case INTEGER: - case ENUM: - case FLOATING: + case BufferDataType::Integer: + case BufferDataType::Enum: + case BufferDataType::Floating: m_knobModel.saveSettings( doc, e, "data" ); break; - case TIME: + case BufferDataType::Time: m_tempoSyncKnobModel.saveSettings( doc, e, "data" ); break; default: @@ -230,15 +230,15 @@ void LadspaControl::loadSettings( const QDomElement& parent, const QString& name m_linkEnabledModel.setValue(m_linkEnabledModel.initValue()); switch( m_port->data_type ) { - case TOGGLED: + case BufferDataType::Toggled: m_toggledModel.setValue(m_toggledModel.initValue()); break; - case INTEGER: - case ENUM: - case FLOATING: + case BufferDataType::Integer: + case BufferDataType::Enum: + case BufferDataType::Floating: m_knobModel.setValue(m_knobModel.initValue()); break; - case TIME: + case BufferDataType::Time: m_tempoSyncKnobModel.setValue(m_tempoSyncKnobModel.initValue()); break; default: @@ -265,15 +265,15 @@ void LadspaControl::loadSettings( const QDomElement& parent, const QString& name switch( m_port->data_type ) { - case TOGGLED: + case BufferDataType::Toggled: m_toggledModel.loadSettings( e, dataModelName ); break; - case INTEGER: - case ENUM: - case FLOATING: + case BufferDataType::Integer: + case BufferDataType::Enum: + case BufferDataType::Floating: m_knobModel.loadSettings( e, dataModelName ); break; - case TIME: + case BufferDataType::Time: m_tempoSyncKnobModel.loadSettings( e, dataModelName ); break; default: @@ -290,15 +290,15 @@ void LadspaControl::linkControls( LadspaControl * _control ) { switch( m_port->data_type ) { - case TOGGLED: + case BufferDataType::Toggled: BoolModel::linkModels( &m_toggledModel, _control->toggledModel() ); break; - case INTEGER: - case ENUM: - case FLOATING: + case BufferDataType::Integer: + case BufferDataType::Enum: + case BufferDataType::Floating: FloatModel::linkModels( &m_knobModel, _control->knobModel() ); break; - case TIME: + case BufferDataType::Time: TempoSyncKnobModel::linkModels( &m_tempoSyncKnobModel, _control->tempoSyncKnobModel() ); break; @@ -341,15 +341,15 @@ void LadspaControl::unlinkControls( LadspaControl * _control ) { switch( m_port->data_type ) { - case TOGGLED: + case BufferDataType::Toggled: BoolModel::unlinkModels( &m_toggledModel, _control->toggledModel() ); break; - case INTEGER: - case ENUM: - case FLOATING: + case BufferDataType::Integer: + case BufferDataType::Enum: + case BufferDataType::Floating: FloatModel::unlinkModels( &m_knobModel, _control->knobModel() ); break; - case TIME: + case BufferDataType::Time: TempoSyncKnobModel::unlinkModels( &m_tempoSyncKnobModel, _control->tempoSyncKnobModel() ); break; diff --git a/src/core/LadspaManager.cpp b/src/core/LadspaManager.cpp index 8c3ab8f97..064c928ef 100644 --- a/src/core/LadspaManager.cpp +++ b/src/core/LadspaManager.cpp @@ -159,21 +159,21 @@ void LadspaManager::addPlugins( if( plugIn->inputChannels == 0 && plugIn->outputChannels > 0 ) { - plugIn->type = SOURCE; + plugIn->type = LadspaPluginType::Source; } else if( plugIn->inputChannels > 0 && plugIn->outputChannels > 0 ) { - plugIn->type = TRANSFER; + plugIn->type = LadspaPluginType::Transfer; } else if( plugIn->inputChannels > 0 && plugIn->outputChannels == 0 ) { - plugIn->type = SINK; + plugIn->type = LadspaPluginType::Sink; } else { - plugIn->type = OTHER; + plugIn->type = LadspaPluginType::Other; } m_ladspaManagerMap[key] = plugIn; diff --git a/src/core/LfoController.cpp b/src/core/LfoController.cpp index 495ae54d4..23621b847 100644 --- a/src/core/LfoController.cpp +++ b/src/core/LfoController.cpp @@ -36,12 +36,12 @@ namespace lmms LfoController::LfoController( Model * _parent ) : - Controller( Controller::LfoController, _parent, tr( "LFO Controller" ) ), + Controller( ControllerType::Lfo, _parent, tr( "LFO Controller" ) ), m_baseModel( 0.5, 0.0, 1.0, 0.001, this, tr( "Base value" ) ), m_speedModel( 2.0, 0.01, 20.0, 0.0001, 20000.0, this, tr( "Oscillator speed" ) ), m_amountModel( 1.0, -1.0, 1.0, 0.005, this, tr( "Oscillator amount" ) ), m_phaseModel( 0.0, 0.0, 360.0, 4.0, this, tr( "Oscillator phase" ) ), - m_waveModel( Oscillator::SineWave, 0, Oscillator::NumWaveShapes, + m_waveModel( static_cast(Oscillator::WaveShape::Sine), 0, Oscillator::NumWaveShapes, this, tr( "Oscillator waveform" ) ), m_multiplierModel( 0, 0, 2, this, tr( "Frequency Multiplier" ) ), m_duration( 1000 ), @@ -109,7 +109,7 @@ void LfoController::updateValueBuffer() ? m_sampleFunction( phase ) : m_userDefSampleBuffer->userWaveSample( phase ); - f = qBound( 0.0f, m_baseModel.value() + ( *amountPtr * currentSample / 2.0f ), 1.0f ); + f = std::clamp(m_baseModel.value() + (*amountPtr * currentSample / 2.0f), 0.0f, 1.0f); phase += 1.0 / m_duration; amountPtr += amountInc; @@ -149,30 +149,31 @@ void LfoController::updateDuration() void LfoController::updateSampleFunction() { - switch( m_waveModel.value() ) + switch( static_cast(m_waveModel.value()) ) { - case Oscillator::SineWave: + case Oscillator::WaveShape::Sine: + default: m_sampleFunction = &Oscillator::sinSample; break; - case Oscillator::TriangleWave: + case Oscillator::WaveShape::Triangle: m_sampleFunction = &Oscillator::triangleSample; break; - case Oscillator::SawWave: + case Oscillator::WaveShape::Saw: m_sampleFunction = &Oscillator::sawSample; break; - case Oscillator::SquareWave: + case Oscillator::WaveShape::Square: m_sampleFunction = &Oscillator::squareSample; break; - case Oscillator::MoogSawWave: + case Oscillator::WaveShape::MoogSaw: m_sampleFunction = &Oscillator::moogSawSample; break; - case Oscillator::ExponentialWave: + case Oscillator::WaveShape::Exponential: m_sampleFunction = &Oscillator::expSample; break; - case Oscillator::WhiteNoise: + case Oscillator::WaveShape::WhiteNoise: m_sampleFunction = &Oscillator::noiseSample; break; - case Oscillator::UserDefinedWave: + case Oscillator::WaveShape::UserDefined: m_sampleFunction = nullptr; /*TODO: If C++11 is allowed, should change the type of m_sampleFunction be std::function diff --git a/src/core/MixHelpers.cpp b/src/core/MixHelpers.cpp index 02f3d8775..bc55419e9 100644 --- a/src/core/MixHelpers.cpp +++ b/src/core/MixHelpers.cpp @@ -121,7 +121,7 @@ bool sanitize( sampleFrame * src, int frames ) } else { - src[f][c] = qBound( -1000.0f, src[f][c], 1000.0f ); + src[f][c] = std::clamp(src[f][c], -1000.0f, 1000.0f); } } } diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index b2a9f9e3f..59c2dd72e 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -173,8 +173,8 @@ void MixerChannel::doProcessing() m_stillRunning = m_fxChain.processAudioBuffer( m_buffer, fpp, m_hasInput ); AudioEngine::StereoSample peakSamples = Engine::audioEngine()->getPeakValues(m_buffer, fpp); - m_peakLeft = qMax( m_peakLeft, peakSamples.left * v ); - m_peakRight = qMax( m_peakRight, peakSamples.right * v ); + m_peakLeft = std::max(m_peakLeft, peakSamples.left * v); + m_peakRight = std::max(m_peakRight, peakSamples.right * v); } else { @@ -201,9 +201,9 @@ Mixer::Mixer() : Mixer::~Mixer() { - while( ! m_mixerRoutes.isEmpty() ) + while (!m_mixerRoutes.empty()) { - deleteChannelSend( m_mixerRoutes.first() ); + deleteChannelSend(m_mixerRoutes.front()); } while( m_mixerChannels.size() ) { @@ -293,12 +293,15 @@ void Mixer::deleteChannel( int index ) // go through every instrument and adjust for the channel index change TrackContainer::TrackList tracks; - tracks += Engine::getSong()->tracks(); - tracks += Engine::patternStore()->tracks(); + + auto& songTracks = Engine::getSong()->tracks(); + auto& patternStoreTracks = Engine::patternStore()->tracks(); + tracks.insert(tracks.end(), songTracks.begin(), songTracks.end()); + tracks.insert(tracks.end(), patternStoreTracks.begin(), patternStoreTracks.end()); for( Track* t : tracks ) { - if( t->type() == Track::InstrumentTrack ) + if( t->type() == Track::Type::Instrument ) { auto inst = dynamic_cast(t); int val = inst->mixerChannelModel()->value(0); @@ -314,7 +317,7 @@ void Mixer::deleteChannel( int index ) inst->mixerChannelModel()->setValue(val-1); } } - else if( t->type() == Track::SampleTrack ) + else if( t->type() == Track::Type::Sample ) { auto strk = dynamic_cast(t); int val = strk->mixerChannelModel()->value(0); @@ -335,13 +338,13 @@ void Mixer::deleteChannel( int index ) MixerChannel * ch = m_mixerChannels[index]; // delete all of this channel's sends and receives - while( ! ch->m_sends.isEmpty() ) + while (!ch->m_sends.empty()) { - deleteChannelSend( ch->m_sends.first() ); + deleteChannelSend(ch->m_sends.front()); } - while( ! ch->m_receives.isEmpty() ) + while (!ch->m_receives.empty()) { - deleteChannelSend( ch->m_receives.first() ); + deleteChannelSend(ch->m_receives.front()); } // if m_lastSoloed was our index, reset it @@ -350,7 +353,7 @@ void Mixer::deleteChannel( int index ) else if (m_lastSoloed > index) { --m_lastSoloed; } // actually delete the channel - m_mixerChannels.remove(index); + m_mixerChannels.erase(m_mixerChannels.begin() + index); delete ch; for( int i = index; i < m_mixerChannels.size(); ++i ) @@ -391,14 +394,14 @@ void Mixer::moveChannelLeft( int index ) else if (m_lastSoloed == b) { m_lastSoloed = a; } // go through every instrument and adjust for the channel index change - TrackContainer::TrackList songTrackList = Engine::getSong()->tracks(); - TrackContainer::TrackList patternTrackList = Engine::patternStore()->tracks(); + const TrackContainer::TrackList& songTrackList = Engine::getSong()->tracks(); + const TrackContainer::TrackList& patternTrackList = Engine::patternStore()->tracks(); for (const auto& trackList : {songTrackList, patternTrackList}) { for (const auto& track : trackList) { - if (track->type() == Track::InstrumentTrack) + if (track->type() == Track::Type::Instrument) { auto inst = (InstrumentTrack*)track; int val = inst->mixerChannelModel()->value(0); @@ -411,7 +414,7 @@ void Mixer::moveChannelLeft( int index ) inst->mixerChannelModel()->setValue(a); } } - else if (track->type() == Track::SampleTrack) + else if (track->type() == Track::Type::Sample) { auto strk = (SampleTrack*)track; int val = strk->mixerChannelModel()->value(0); @@ -477,13 +480,13 @@ MixerRoute * Mixer::createRoute( MixerChannel * from, MixerChannel * to, float a auto route = new MixerRoute(from, to, amount); // add us to from's sends - from->m_sends.append( route ); + from->m_sends.push_back(route); // add us to to's receives - to->m_receives.append( route ); + to->m_receives.push_back(route); // add us to mixer's list - Engine::mixer()->m_mixerRoutes.append( route ); + Engine::mixer()->m_mixerRoutes.push_back(route); Engine::audioEngine()->doneChangeInModel(); return route; @@ -512,12 +515,22 @@ void Mixer::deleteChannelSend( mix_ch_t fromChannel, mix_ch_t toChannel ) void Mixer::deleteChannelSend( MixerRoute * route ) { Engine::audioEngine()->requestChangeInModel(); + + auto removeFromMixerRoute = [route](MixerRouteVector& routeVec) + { + auto it = std::find(routeVec.begin(), routeVec.end(), route); + if (it != routeVec.end()) { routeVec.erase(it); } + }; + // remove us from from's sends - route->sender()->m_sends.remove( route->sender()->m_sends.indexOf( route ) ); + removeFromMixerRoute(route->sender()->m_sends); + // remove us from to's receives - route->receiver()->m_receives.remove( route->receiver()->m_receives.indexOf( route ) ); + removeFromMixerRoute(route->receiver()->m_receives); + // remove us from mixer's list - Engine::mixer()->m_mixerRoutes.remove( Engine::mixer()->m_mixerRoutes.indexOf( route ) ); + removeFromMixerRoute(Engine::mixer()->m_mixerRoutes); + delete route; Engine::audioEngine()->doneChangeInModel(); } @@ -617,7 +630,7 @@ void Mixer::masterMix( sampleFrame * _buf ) // also instantly add all muted channels as they don't need to care // about their senders, and can just increment the deps of their // recipients right away. - AudioEngineWorkerThread::resetJobQueue( AudioEngineWorkerThread::JobQueue::Dynamic ); + AudioEngineWorkerThread::resetJobQueue( AudioEngineWorkerThread::JobQueue::OperationMode::Dynamic ); for( MixerChannel * ch : m_mixerChannels ) { ch->m_muted = ch->m_muteModel.value(); @@ -714,9 +727,9 @@ void Mixer::clearChannel(mix_ch_t index) if( index > 0) { // delete existing sends - while( ! ch->m_sends.isEmpty() ) + while (!ch->m_sends.empty()) { - deleteChannelSend( ch->m_sends.first() ); + deleteChannelSend(ch->m_sends.front()); } // add send to master @@ -724,9 +737,9 @@ void Mixer::clearChannel(mix_ch_t index) } // delete receives - while( ! ch->m_receives.isEmpty() ) + while (!ch->m_receives.empty()) { - deleteChannelSend( ch->m_receives.first() ); + deleteChannelSend(ch->m_receives.front()); } } @@ -835,19 +848,22 @@ void Mixer::validateChannelName( int index, int oldIndex ) bool Mixer::isChannelInUse(int index) { // check if the index mixer channel receives audio from any other channel - if (!m_mixerChannels[index]->m_receives.isEmpty()) + if (!m_mixerChannels[index]->m_receives.empty()) { return true; } // check if the destination mixer channel on any instrument or sample track is the index mixer channel TrackContainer::TrackList tracks; - tracks += Engine::getSong()->tracks(); - tracks += Engine::patternStore()->tracks(); + + auto& songTracks = Engine::getSong()->tracks(); + auto& patternStoreTracks = Engine::patternStore()->tracks(); + tracks.insert(tracks.end(), songTracks.begin(), songTracks.end()); + tracks.insert(tracks.end(), patternStoreTracks.begin(), patternStoreTracks.end()); for (const auto t : tracks) { - if (t->type() == Track::InstrumentTrack) + if (t->type() == Track::Type::Instrument) { auto inst = dynamic_cast(t); if (inst->mixerChannelModel()->value() == index) @@ -855,7 +871,7 @@ bool Mixer::isChannelInUse(int index) return true; } } - else if (t->type() == Track::SampleTrack) + else if (t->type() == Track::Type::Sample) { auto strack = dynamic_cast(t); if (strack->mixerChannelModel()->value() == index) diff --git a/src/core/Note.cpp b/src/core/Note.cpp index e4e5f0e5d..a4ad61412 100644 --- a/src/core/Note.cpp +++ b/src/core/Note.cpp @@ -38,13 +38,13 @@ Note::Note( const TimePos & length, const TimePos & pos, int key, volume_t volume, panning_t panning, DetuningHelper * detuning ) : m_selected( false ), - m_oldKey( qBound( 0, key, NumKeys ) ), + m_oldKey(std::clamp(key, 0, NumKeys)), m_oldPos( pos ), m_oldLength( length ), m_isPlaying( false ), - m_key( qBound( 0, key, NumKeys ) ), - m_volume( qBound( MinVolume, volume, MaxVolume ) ), - m_panning( qBound( PanningLeft, panning, PanningRight ) ), + m_key(std::clamp(key, 0, NumKeys)), + m_volume(std::clamp(volume, MinVolume, MaxVolume)), + m_panning(std::clamp(panning, PanningLeft, PanningRight)), m_length( length ), m_pos( pos ), m_detuning( nullptr ) @@ -114,7 +114,7 @@ void Note::setPos( const TimePos & pos ) void Note::setKey( const int key ) { - const int k = qBound( 0, key, NumKeys - 1 ); + const int k = std::clamp(key, 0, NumKeys - 1); m_key = k; } @@ -123,7 +123,7 @@ void Note::setKey( const int key ) void Note::setVolume( volume_t volume ) { - const volume_t v = qBound( MinVolume, volume, MaxVolume ); + const volume_t v = std::clamp(volume, MinVolume, MaxVolume); m_volume = v; } @@ -132,7 +132,7 @@ void Note::setVolume( volume_t volume ) void Note::setPanning( panning_t panning ) { - const panning_t p = qBound( PanningLeft, panning, PanningRight ); + const panning_t p = std::clamp(panning, PanningLeft, PanningRight); m_panning = p; } @@ -192,7 +192,7 @@ void Note::saveSettings( QDomDocument & doc, QDomElement & parent ) void Note::loadSettings( const QDomElement & _this ) { const int oldKey = _this.attribute( "tone" ).toInt() + _this.attribute( "oct" ).toInt() * KeysPerOctave; - m_key = qMax( oldKey, _this.attribute( "key" ).toInt() ); + m_key = std::max(oldKey, _this.attribute("key").toInt()); m_volume = _this.attribute( "vol" ).toInt(); m_panning = _this.attribute( "pan" ).toInt(); m_length = _this.attribute( "len" ).toInt(); @@ -216,7 +216,7 @@ void Note::createDetuning() m_detuning = new DetuningHelper; (void) m_detuning->automationClip(); m_detuning->setRange( -MaxDetuning, MaxDetuning, 0.5f ); - m_detuning->automationClip()->setProgressionType( AutomationClip::LinearProgression ); + m_detuning->automationClip()->setProgressionType( AutomationClip::ProgressionType::Linear ); } } diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index e87637476..eb9c7ddbf 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -53,7 +53,7 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack, NotePlayHandle *parent, int midiEventChannel, Origin origin ) : - PlayHandle( TypeNotePlayHandle, _offset ), + PlayHandle( Type::NotePlayHandle, _offset ), Note( n.length(), n.pos(), n.key(), n.getVolume(), n.getPanning(), n.detuning() ), m_pluginData( nullptr ), m_instrumentTrack( instrumentTrack ), @@ -104,12 +104,12 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack, setFrames( _frames ); // inform attached components about new MIDI note (used for recording in Piano Roll) - if( m_origin == OriginMidiInput ) + if( m_origin == Origin::MidiInput ) { m_instrumentTrack->midiNoteOn( *this ); } - if(m_instrumentTrack->instrument() && m_instrumentTrack->instrument()->flags() & Instrument::IsSingleStreamed ) + if(m_instrumentTrack->instrument() && m_instrumentTrack->instrument()->flags() & Instrument::Flag::IsSingleStreamed ) { setUsesBuffer( false ); } @@ -350,9 +350,9 @@ fpp_t NotePlayHandle::framesLeftForCurrentPeriod() const { if( m_totalFramesPlayed == 0 ) { - return (fpp_t) qMin( framesLeft(), Engine::audioEngine()->framesPerPeriod() - offset() ); + return static_cast(std::min(framesLeft(), Engine::audioEngine()->framesPerPeriod() - offset())); } - return (fpp_t) qMin( framesLeft(), Engine::audioEngine()->framesPerPeriod() ); + return static_cast(std::min(framesLeft(), Engine::audioEngine()->framesPerPeriod())); } @@ -384,7 +384,7 @@ void NotePlayHandle::noteOff( const f_cnt_t _s ) // then set some variables indicating release-state m_framesBeforeRelease = _s; - m_releaseFramesToDo = qMax( 0, actualReleaseFramesToDo() ); + m_releaseFramesToDo = std::max(0, actualReleaseFramesToDo()); if( m_hasMidiNote ) { @@ -400,7 +400,7 @@ void NotePlayHandle::noteOff( const f_cnt_t _s ) // inform attached components about MIDI finished (used for recording in Piano Roll) if (!instrumentTrack()->isSustainPedalPressed()) { - if( m_origin == OriginMidiInput ) + if( m_origin == Origin::MidiInput ) { setLength( TimePos( static_cast( totalFramesPlayed() / Engine::framesPerTick() ) ) ); m_instrumentTrack->midiNoteOff( *this ); @@ -557,14 +557,20 @@ void NotePlayHandle::updateFrequency() -void NotePlayHandle::processTimePos( const TimePos& time ) +void NotePlayHandle::processTimePos(const TimePos& time, float pitchValue, bool isRecording) { - if( detuning() && time >= songGlobalParentOffset()+pos() ) + if (!detuning() || time < songGlobalParentOffset() + pos()) { return; } + + if (isRecording && m_origin == Origin::MidiInput) { - const float v = detuning()->automationClip()->valueAt( time - songGlobalParentOffset() - pos() ); - if( !typeInfo::isEqual( v, m_baseDetuning->value() ) ) + detuning()->automationClip()->recordValue(time - songGlobalParentOffset() - pos(), pitchValue / 100); + } + else + { + const float v = detuning()->automationClip()->valueAt(time - songGlobalParentOffset() - pos()); + if (!typeInfo::isEqual(v, m_baseDetuning->value())) { - m_baseDetuning->setValue( v ); + m_baseDetuning->setValue(v); updateFrequency(); } } @@ -575,8 +581,8 @@ void NotePlayHandle::processTimePos( const TimePos& time ) void NotePlayHandle::resize( const bpm_t _new_tempo ) { - if (origin() == OriginMidiInput || - (origin() == OriginNoteStacking && m_parent->origin() == OriginMidiInput)) + if (origin() == Origin::MidiInput || + (origin() == Origin::NoteStacking && m_parent->origin() == Origin::MidiInput)) { // Don't resize notes from MIDI input - they should continue to play // until the key is released, and their large duration can cause diff --git a/src/core/Oscillator.cpp b/src/core/Oscillator.cpp index 189dede6e..06033b63e 100644 --- a/src/core/Oscillator.cpp +++ b/src/core/Oscillator.cpp @@ -90,21 +90,22 @@ void Oscillator::update(sampleFrame* ab, const fpp_t frames, const ch_cnt_t chnl m_isModulator = modulator; if (m_subOsc != nullptr) { - switch (m_modulationAlgoModel->value()) + switch (static_cast(m_modulationAlgoModel->value())) { - case PhaseModulation: + case ModulationAlgo::PhaseModulation: updatePM(ab, frames, chnl); break; - case AmplitudeModulation: + case ModulationAlgo::AmplitudeModulation: updateAM(ab, frames, chnl); break; - case SignalMix: + case ModulationAlgo::SignalMix: + default: updateMix(ab, frames, chnl); break; - case SynchronizedBySubOsc: + case ModulationAlgo::SynchronizedBySubOsc: updateSync(ab, frames, chnl); break; - case FrequencyModulation: + case ModulationAlgo::FrequencyModulation: updateFM(ab, frames, chnl); } } @@ -199,7 +200,7 @@ void Oscillator::generateAntiAliasUserWaveTable(SampleBuffer *sampleBuffer) sample_t Oscillator::s_waveTables - [Oscillator::WaveShapes::NumWaveShapeTables] + [Oscillator::NumWaveShapeTables] [OscillatorConstants::WAVE_TABLES_PER_WAVEFORM_COUNT] [OscillatorConstants::WAVETABLE_LENGTH]; fftwf_plan Oscillator::s_fftPlan; @@ -235,9 +236,9 @@ void Oscillator::generateWaveTables() // Start from the table that contains the least number of bands, and re-use each table in the following // iteration, adding more bands in each step and avoiding repeated computation of earlier bands. using generator_t = void (*)(int, sample_t*, int); - auto simpleGen = [](WaveShapes shape, generator_t generator) + auto simpleGen = [](WaveShape shape, generator_t generator) { - const int shapeID = shape - FirstWaveShapeTable; + const int shapeID = static_cast(shape) - FirstWaveShapeTable; int lastBands = 0; // Clear the first wave table @@ -273,7 +274,7 @@ void Oscillator::generateWaveTables() Oscillator::s_sampleBuffer[i] = moogSawSample((float)i / (float)OscillatorConstants::WAVETABLE_LENGTH); } fftwf_execute(s_fftPlan); - generateFromFFT(OscillatorConstants::MAX_FREQ / freqFromWaveTableBand(i), s_waveTables[WaveShapes::MoogSawWave - FirstWaveShapeTable][i]); + generateFromFFT(OscillatorConstants::MAX_FREQ / freqFromWaveTableBand(i), s_waveTables[static_cast(WaveShape::MoogSaw) - FirstWaveShapeTable][i]); } // Generate exponential tables @@ -284,7 +285,7 @@ void Oscillator::generateWaveTables() s_sampleBuffer[i] = expSample((float)i / (float)OscillatorConstants::WAVETABLE_LENGTH); } fftwf_execute(s_fftPlan); - generateFromFFT(OscillatorConstants::MAX_FREQ / freqFromWaveTableBand(i), s_waveTables[WaveShapes::ExponentialWave - FirstWaveShapeTable][i]); + generateFromFFT(OscillatorConstants::MAX_FREQ / freqFromWaveTableBand(i), s_waveTables[static_cast(WaveShape::Exponential) - FirstWaveShapeTable][i]); } }; @@ -292,18 +293,18 @@ void Oscillator::generateWaveTables() // but since threading is not essential in this case, it is easier and more reliable to simply generate // the wavetables serially. Remove the the check and #else branch once std::thread is well supported. #if !defined(__MINGW32__) && !defined(__MINGW64__) - std::thread sawThread(simpleGen, WaveShapes::SawWave, generateSawWaveTable); - std::thread squareThread(simpleGen, WaveShapes::SquareWave, generateSquareWaveTable); - std::thread triangleThread(simpleGen, WaveShapes::TriangleWave, generateTriangleWaveTable); + std::thread sawThread(simpleGen, WaveShape::Saw, generateSawWaveTable); + std::thread squareThread(simpleGen, WaveShape::Square, generateSquareWaveTable); + std::thread triangleThread(simpleGen, WaveShape::Triangle, generateTriangleWaveTable); std::thread fftThread(fftGen); sawThread.join(); squareThread.join(); triangleThread.join(); fftThread.join(); #else - simpleGen(WaveShapes::SawWave, generateSawWaveTable); - simpleGen(WaveShapes::SquareWave, generateSquareWaveTable); - simpleGen(WaveShapes::TriangleWave, generateTriangleWaveTable); + simpleGen(WaveShape::Saw, generateSawWaveTable); + simpleGen(WaveShape::Square, generateSquareWaveTable); + simpleGen(WaveShape::Triangle, generateTriangleWaveTable); fftGen(); #endif } @@ -314,32 +315,32 @@ void Oscillator::generateWaveTables() void Oscillator::updateNoSub( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ) { - switch( m_waveShapeModel->value() ) + switch( static_cast(m_waveShapeModel->value()) ) { - case SineWave: + case WaveShape::Sine: default: - updateNoSub( _ab, _frames, _chnl ); + updateNoSub( _ab, _frames, _chnl ); break; - case TriangleWave: - updateNoSub( _ab, _frames, _chnl ); + case WaveShape::Triangle: + updateNoSub( _ab, _frames, _chnl ); break; - case SawWave: - updateNoSub( _ab, _frames, _chnl ); + case WaveShape::Saw: + updateNoSub( _ab, _frames, _chnl ); break; - case SquareWave: - updateNoSub( _ab, _frames, _chnl ); + case WaveShape::Square: + updateNoSub( _ab, _frames, _chnl ); break; - case MoogSawWave: - updateNoSub( _ab, _frames, _chnl ); + case WaveShape::MoogSaw: + updateNoSub( _ab, _frames, _chnl ); break; - case ExponentialWave: - updateNoSub( _ab, _frames, _chnl ); + case WaveShape::Exponential: + updateNoSub( _ab, _frames, _chnl ); break; - case WhiteNoise: - updateNoSub( _ab, _frames, _chnl ); + case WaveShape::WhiteNoise: + updateNoSub( _ab, _frames, _chnl ); break; - case UserDefinedWave: - updateNoSub( _ab, _frames, _chnl ); + case WaveShape::UserDefined: + updateNoSub( _ab, _frames, _chnl ); break; } } @@ -350,32 +351,32 @@ void Oscillator::updateNoSub( sampleFrame * _ab, const fpp_t _frames, void Oscillator::updatePM( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ) { - switch( m_waveShapeModel->value() ) + switch( static_cast(m_waveShapeModel->value()) ) { - case SineWave: + case WaveShape::Sine: default: - updatePM( _ab, _frames, _chnl ); + updatePM( _ab, _frames, _chnl ); break; - case TriangleWave: - updatePM( _ab, _frames, _chnl ); + case WaveShape::Triangle: + updatePM( _ab, _frames, _chnl ); break; - case SawWave: - updatePM( _ab, _frames, _chnl ); + case WaveShape::Saw: + updatePM( _ab, _frames, _chnl ); break; - case SquareWave: - updatePM( _ab, _frames, _chnl ); + case WaveShape::Square: + updatePM( _ab, _frames, _chnl ); break; - case MoogSawWave: - updatePM( _ab, _frames, _chnl ); + case WaveShape::MoogSaw: + updatePM( _ab, _frames, _chnl ); break; - case ExponentialWave: - updatePM( _ab, _frames, _chnl ); + case WaveShape::Exponential: + updatePM( _ab, _frames, _chnl ); break; - case WhiteNoise: - updatePM( _ab, _frames, _chnl ); + case WaveShape::WhiteNoise: + updatePM( _ab, _frames, _chnl ); break; - case UserDefinedWave: - updatePM( _ab, _frames, _chnl ); + case WaveShape::UserDefined: + updatePM( _ab, _frames, _chnl ); break; } } @@ -386,32 +387,32 @@ void Oscillator::updatePM( sampleFrame * _ab, const fpp_t _frames, void Oscillator::updateAM( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ) { - switch( m_waveShapeModel->value() ) + switch( static_cast(m_waveShapeModel->value()) ) { - case SineWave: + case WaveShape::Sine: default: - updateAM( _ab, _frames, _chnl ); + updateAM( _ab, _frames, _chnl ); break; - case TriangleWave: - updateAM( _ab, _frames, _chnl ); + case WaveShape::Triangle: + updateAM( _ab, _frames, _chnl ); break; - case SawWave: - updateAM( _ab, _frames, _chnl ); + case WaveShape::Saw: + updateAM( _ab, _frames, _chnl ); break; - case SquareWave: - updateAM( _ab, _frames, _chnl ); + case WaveShape::Square: + updateAM( _ab, _frames, _chnl ); break; - case MoogSawWave: - updateAM( _ab, _frames, _chnl ); + case WaveShape::MoogSaw: + updateAM( _ab, _frames, _chnl ); break; - case ExponentialWave: - updateAM( _ab, _frames, _chnl ); + case WaveShape::Exponential: + updateAM( _ab, _frames, _chnl ); break; - case WhiteNoise: - updateAM( _ab, _frames, _chnl ); + case WaveShape::WhiteNoise: + updateAM( _ab, _frames, _chnl ); break; - case UserDefinedWave: - updateAM( _ab, _frames, _chnl ); + case WaveShape::UserDefined: + updateAM( _ab, _frames, _chnl ); break; } } @@ -422,32 +423,32 @@ void Oscillator::updateAM( sampleFrame * _ab, const fpp_t _frames, void Oscillator::updateMix( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ) { - switch( m_waveShapeModel->value() ) + switch( static_cast(m_waveShapeModel->value()) ) { - case SineWave: + case WaveShape::Sine: default: - updateMix( _ab, _frames, _chnl ); + updateMix( _ab, _frames, _chnl ); break; - case TriangleWave: - updateMix( _ab, _frames, _chnl ); + case WaveShape::Triangle: + updateMix( _ab, _frames, _chnl ); break; - case SawWave: - updateMix( _ab, _frames, _chnl ); + case WaveShape::Saw: + updateMix( _ab, _frames, _chnl ); break; - case SquareWave: - updateMix( _ab, _frames, _chnl ); + case WaveShape::Square: + updateMix( _ab, _frames, _chnl ); break; - case MoogSawWave: - updateMix( _ab, _frames, _chnl ); + case WaveShape::MoogSaw: + updateMix( _ab, _frames, _chnl ); break; - case ExponentialWave: - updateMix( _ab, _frames, _chnl ); + case WaveShape::Exponential: + updateMix( _ab, _frames, _chnl ); break; - case WhiteNoise: - updateMix( _ab, _frames, _chnl ); + case WaveShape::WhiteNoise: + updateMix( _ab, _frames, _chnl ); break; - case UserDefinedWave: - updateMix( _ab, _frames, _chnl ); + case WaveShape::UserDefined: + updateMix( _ab, _frames, _chnl ); break; } } @@ -458,32 +459,32 @@ void Oscillator::updateMix( sampleFrame * _ab, const fpp_t _frames, void Oscillator::updateSync( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ) { - switch( m_waveShapeModel->value() ) + switch( static_cast(m_waveShapeModel->value()) ) { - case SineWave: + case WaveShape::Sine: default: - updateSync( _ab, _frames, _chnl ); + updateSync( _ab, _frames, _chnl ); break; - case TriangleWave: - updateSync( _ab, _frames, _chnl ); + case WaveShape::Triangle: + updateSync( _ab, _frames, _chnl ); break; - case SawWave: - updateSync( _ab, _frames, _chnl ); + case WaveShape::Saw: + updateSync( _ab, _frames, _chnl ); break; - case SquareWave: - updateSync( _ab, _frames, _chnl ); + case WaveShape::Square: + updateSync( _ab, _frames, _chnl ); break; - case MoogSawWave: - updateSync( _ab, _frames, _chnl ); + case WaveShape::MoogSaw: + updateSync( _ab, _frames, _chnl ); break; - case ExponentialWave: - updateSync( _ab, _frames, _chnl ); + case WaveShape::Exponential: + updateSync( _ab, _frames, _chnl ); break; - case WhiteNoise: - updateSync( _ab, _frames, _chnl ); + case WaveShape::WhiteNoise: + updateSync( _ab, _frames, _chnl ); break; - case UserDefinedWave: - updateSync( _ab, _frames, _chnl ); + case WaveShape::UserDefined: + updateSync( _ab, _frames, _chnl ); break; } } @@ -494,32 +495,32 @@ void Oscillator::updateSync( sampleFrame * _ab, const fpp_t _frames, void Oscillator::updateFM( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ) { - switch( m_waveShapeModel->value() ) + switch( static_cast(m_waveShapeModel->value()) ) { - case SineWave: + case WaveShape::Sine: default: - updateFM( _ab, _frames, _chnl ); + updateFM( _ab, _frames, _chnl ); break; - case TriangleWave: - updateFM( _ab, _frames, _chnl ); + case WaveShape::Triangle: + updateFM( _ab, _frames, _chnl ); break; - case SawWave: - updateFM( _ab, _frames, _chnl ); + case WaveShape::Saw: + updateFM( _ab, _frames, _chnl ); break; - case SquareWave: - updateFM( _ab, _frames, _chnl ); + case WaveShape::Square: + updateFM( _ab, _frames, _chnl ); break; - case MoogSawWave: - updateFM( _ab, _frames, _chnl ); + case WaveShape::MoogSaw: + updateFM( _ab, _frames, _chnl ); break; - case ExponentialWave: - updateFM( _ab, _frames, _chnl ); + case WaveShape::Exponential: + updateFM( _ab, _frames, _chnl ); break; - case WhiteNoise: - updateFM( _ab, _frames, _chnl ); + case WaveShape::WhiteNoise: + updateFM( _ab, _frames, _chnl ); break; - case UserDefinedWave: - updateFM( _ab, _frames, _chnl ); + case WaveShape::UserDefined: + updateFM( _ab, _frames, _chnl ); break; } } @@ -568,7 +569,7 @@ float Oscillator::syncInit( sampleFrame * _ab, const fpp_t _frames, // if we have no sub-osc, we can't do any modulation... just get our samples -template +template void Oscillator::updateNoSub( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ) { @@ -586,7 +587,7 @@ void Oscillator::updateNoSub( sampleFrame * _ab, const fpp_t _frames, // do pm by using sub-osc as modulator -template +template void Oscillator::updatePM( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ) { @@ -607,7 +608,7 @@ void Oscillator::updatePM( sampleFrame * _ab, const fpp_t _frames, // do am by using sub-osc as modulator -template +template void Oscillator::updateAM( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ) { @@ -626,7 +627,7 @@ void Oscillator::updateAM( sampleFrame * _ab, const fpp_t _frames, // do mix by using sub-osc as mix-sample -template +template void Oscillator::updateMix( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ) { @@ -646,7 +647,7 @@ void Oscillator::updateMix( sampleFrame * _ab, const fpp_t _frames, // sync with sub-osc (every time sub-osc starts new period, we also start new // period) -template +template void Oscillator::updateSync( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ) { @@ -669,7 +670,7 @@ void Oscillator::updateSync( sampleFrame * _ab, const fpp_t _frames, // do fm by using sub-osc as modulator -template +template void Oscillator::updateFM( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ) { @@ -690,7 +691,7 @@ void Oscillator::updateFM( sampleFrame * _ab, const fpp_t _frames, template<> -inline sample_t Oscillator::getSample(const float sample) +inline sample_t Oscillator::getSample(const float sample) { const float current_freq = m_freq * m_detuning_div_samplerate * Engine::audioEngine()->processingSampleRate(); @@ -708,12 +709,12 @@ inline sample_t Oscillator::getSample(const float sample) template<> -inline sample_t Oscillator::getSample( +inline sample_t Oscillator::getSample( const float _sample ) { if (m_useWaveTable && !m_isModulator) { - return wtSample(s_waveTables[WaveShapes::TriangleWave - FirstWaveShapeTable],_sample); + return wtSample(s_waveTables[static_cast(WaveShape::Triangle) - FirstWaveShapeTable],_sample); } else { @@ -725,12 +726,12 @@ inline sample_t Oscillator::getSample( template<> -inline sample_t Oscillator::getSample( +inline sample_t Oscillator::getSample( const float _sample ) { if (m_useWaveTable && !m_isModulator) { - return wtSample(s_waveTables[WaveShapes::SawWave - FirstWaveShapeTable], _sample); + return wtSample(s_waveTables[static_cast(WaveShape::Saw) - FirstWaveShapeTable], _sample); } else { @@ -742,12 +743,12 @@ inline sample_t Oscillator::getSample( template<> -inline sample_t Oscillator::getSample( +inline sample_t Oscillator::getSample( const float _sample ) { if (m_useWaveTable && !m_isModulator) { - return wtSample(s_waveTables[WaveShapes::SquareWave - FirstWaveShapeTable], _sample); + return wtSample(s_waveTables[static_cast(WaveShape::Square) - FirstWaveShapeTable], _sample); } else { @@ -759,12 +760,12 @@ inline sample_t Oscillator::getSample( template<> -inline sample_t Oscillator::getSample( +inline sample_t Oscillator::getSample( const float _sample ) { if (m_useWaveTable && !m_isModulator) { - return wtSample(s_waveTables[WaveShapes::MoogSawWave - FirstWaveShapeTable], _sample); + return wtSample(s_waveTables[static_cast(WaveShape::MoogSaw) - FirstWaveShapeTable], _sample); } else { @@ -776,12 +777,12 @@ inline sample_t Oscillator::getSample( template<> -inline sample_t Oscillator::getSample( +inline sample_t Oscillator::getSample( const float _sample ) { if (m_useWaveTable && !m_isModulator) { - return wtSample(s_waveTables[WaveShapes::ExponentialWave - FirstWaveShapeTable], _sample); + return wtSample(s_waveTables[static_cast(WaveShape::Exponential) - FirstWaveShapeTable], _sample); } else { @@ -793,7 +794,7 @@ inline sample_t Oscillator::getSample( template<> -inline sample_t Oscillator::getSample( +inline sample_t Oscillator::getSample( const float _sample ) { return( noiseSample( _sample ) ); @@ -803,7 +804,7 @@ inline sample_t Oscillator::getSample( template<> -inline sample_t Oscillator::getSample( +inline sample_t Oscillator::getSample( const float _sample ) { if (m_useWaveTable && !m_isModulator) diff --git a/src/core/PatternStore.cpp b/src/core/PatternStore.cpp index f91c42b72..6af434f65 100644 --- a/src/core/PatternStore.cpp +++ b/src/core/PatternStore.cpp @@ -44,7 +44,7 @@ PatternStore::PatternStore() : // not change upon setCurrentPattern()-call connect(&m_patternComboBoxModel, SIGNAL(dataUnchanged()), this, SLOT(currentPatternChanged())); - setType(PatternContainer); + setType(Type::Pattern); } @@ -61,7 +61,7 @@ bool PatternStore::play(TimePos start, fpp_t frames, f_cnt_t offset, int clipNum start = start % (lengthOfPattern(clipNum) * TimePos::ticksPerBar()); - TrackList tl = tracks(); + const TrackList& tl = tracks(); for (Track * t : tl) { if (t->play(start, frames, offset, clipNum)) @@ -97,7 +97,7 @@ bar_t PatternStore::lengthOfPattern(int pattern) const // Don't create Clips here if they don't exist if (pattern < t->numOfClips()) { - maxLength = qMax(maxLength, t->getClip(pattern)->length()); + maxLength = std::max(maxLength, t->getClip(pattern)->length()); } } @@ -109,7 +109,7 @@ bar_t PatternStore::lengthOfPattern(int pattern) const int PatternStore::numOfPatterns() const { - return Engine::getSong()->countTracks(Track::PatternTrack); + return Engine::getSong()->countTracks(Track::Type::Pattern); } @@ -117,7 +117,7 @@ int PatternStore::numOfPatterns() const void PatternStore::removePattern(int pattern) { - TrackList tl = tracks(); + const TrackList& tl = tracks(); for (Track * t : tl) { delete t->getClip(pattern); @@ -125,7 +125,7 @@ void PatternStore::removePattern(int pattern) } if (pattern <= currentPattern()) { - setCurrentPattern(qMax(currentPattern() - 1, 0)); + setCurrentPattern(std::max(currentPattern() - 1, 0)); } } @@ -134,7 +134,7 @@ void PatternStore::removePattern(int pattern) void PatternStore::swapPattern(int pattern1, int pattern2) { - TrackList tl = tracks(); + const TrackList& tl = tracks(); for (Track * t : tl) { t->swapPositionOfClips(pattern1, pattern2); @@ -159,7 +159,7 @@ void PatternStore::updatePatternTrack(Clip* clip) void PatternStore::fixIncorrectPositions() { - TrackList tl = tracks(); + const TrackList& tl = tracks(); for (Track * t : tl) { for (int i = 0; i < numOfPatterns(); ++i) @@ -174,7 +174,7 @@ void PatternStore::fixIncorrectPositions() void PatternStore::play() { - if (Engine::getSong()->playMode() != Song::Mode_PlayPattern) + if (Engine::getSong()->playMode() != Song::PlayMode::Pattern) { Engine::getSong()->playPattern(); } @@ -215,10 +215,10 @@ void PatternStore::updateComboBox() void PatternStore::currentPatternChanged() { // now update all track-labels (the current one has to become white, the others gray) - TrackList tl = Engine::getSong()->tracks(); + const TrackList& tl = Engine::getSong()->tracks(); for (Track * t : tl) { - if (t->type() == Track::PatternTrack) + if (t->type() == Track::Type::Pattern) { t->dataChanged(); } @@ -230,7 +230,7 @@ void PatternStore::currentPatternChanged() void PatternStore::createClipsForPattern(int pattern) { - TrackList tl = tracks(); + const TrackList& tl = tracks(); for (Track * t : tl) { t->createClipsForPattern(pattern); diff --git a/src/core/PeakController.cpp b/src/core/PeakController.cpp index a9215325e..cfcd3765c 100644 --- a/src/core/PeakController.cpp +++ b/src/core/PeakController.cpp @@ -46,7 +46,7 @@ bool PeakController::m_buggedFile; PeakController::PeakController( Model * _parent, PeakControllerEffect * _peak_effect ) : - Controller( Controller::PeakController, _parent, tr( "Peak Controller" ) ), + Controller( ControllerType::Peak, _parent, tr( "Peak Controller" ) ), m_peakEffect( _peak_effect ), m_currentSample( 0.0f ) { @@ -161,12 +161,11 @@ void PeakController::loadSettings( const QDomElement & _this ) effectId = m_loadCount++; } - PeakControllerEffectVector::Iterator i; - for( i = s_effects.begin(); i != s_effects.end(); ++i ) + for (const auto& effect : s_effects) { - if( (*i)->m_effectId == effectId ) + if (effect->m_effectId == effectId) { - m_peakEffect = *i; + m_peakEffect = effect; return; } } @@ -190,16 +189,14 @@ PeakController * PeakController::getControllerBySetting(const QDomElement & _thi { int effectId = _this.attribute( "effectId" ).toInt(); - PeakControllerEffectVector::Iterator i; - //Backward compatibility for bug in <= 0.4.15 . For >= 1.0.0 , //foundCount should always be 1 because m_effectId is initialized with rand() int foundCount = 0; if( m_buggedFile == false ) { - for( i = s_effects.begin(); i != s_effects.end(); ++i ) + for (const auto& effect : s_effects) { - if( (*i)->m_effectId == effectId ) + if (effect->m_effectId == effectId) { foundCount++; } @@ -208,9 +205,9 @@ PeakController * PeakController::getControllerBySetting(const QDomElement & _thi { m_buggedFile = true; int newEffectId = 0; - for( i = s_effects.begin(); i != s_effects.end(); ++i ) + for (const auto& effect : s_effects) { - (*i)->m_effectId = newEffectId++; + effect->m_effectId = newEffectId++; } QMessageBox msgBox; msgBox.setIcon( QMessageBox::Information ); @@ -231,11 +228,11 @@ PeakController * PeakController::getControllerBySetting(const QDomElement & _thi } m_getCount++; //NB: m_getCount should be increased even m_buggedFile is false - for( i = s_effects.begin(); i != s_effects.end(); ++i ) + for (const auto& effect : s_effects) { - if( (*i)->m_effectId == effectId ) + if (effect->m_effectId == effectId) { - return (*i)->controller(); + return effect->controller(); } } diff --git a/src/core/Piano.cpp b/src/core/Piano.cpp index 82323526e..0ddbf5c60 100644 --- a/src/core/Piano.cpp +++ b/src/core/Piano.cpp @@ -49,12 +49,12 @@ namespace lmms */ static const auto KEY_ORDER = std::array { -// C CIS D DIS - Piano::WhiteKey, Piano::BlackKey, Piano::WhiteKey, Piano::BlackKey, -// E F FIS G - Piano::WhiteKey, Piano::WhiteKey, Piano::BlackKey, Piano::WhiteKey, -// GIS A AIS B - Piano::BlackKey, Piano::WhiteKey, Piano::BlackKey, Piano::WhiteKey +// C CIS D DIS + Piano::KeyType::White, Piano::KeyType::Black, Piano::KeyType::White, Piano::KeyType::Black, +// E F FIS G + Piano::KeyType::White, Piano::KeyType::White, Piano::KeyType::Black, Piano::KeyType::White, +// GIS A AIS B + Piano::KeyType::Black, Piano::KeyType::White, Piano::KeyType::Black, Piano::KeyType::White } ; @@ -127,7 +127,7 @@ bool Piano::isBlackKey(int key) { int keyCode = key % KeysPerOctave; - return KEY_ORDER[keyCode] == Piano::BlackKey; + return KEY_ORDER[keyCode] == Piano::KeyType::Black; } diff --git a/src/core/Plugin.cpp b/src/core/Plugin.cpp index edc183c23..973914501 100644 --- a/src/core/Plugin.cpp +++ b/src/core/Plugin.cpp @@ -50,7 +50,7 @@ static Plugin::Descriptor dummyPluginDescriptor = QT_TRANSLATE_NOOP( "PluginBrowser", "no description" ), "Tobias Doerffel ", 0x0100, - Plugin::Undefined, + Plugin::Type::Undefined, &dummyLoader, nullptr } ; diff --git a/src/core/PluginFactory.cpp b/src/core/PluginFactory.cpp index ece589274..ec0f4ec4e 100644 --- a/src/core/PluginFactory.cpp +++ b/src/core/PluginFactory.cpp @@ -85,8 +85,7 @@ void PluginFactory::setupSearchPaths() addRelativeIfExists(PLUGIN_DIR); #endif // Or via an environment variable: - QString env_path; - if (!(env_path = qgetenv("LMMS_PLUGIN_DIR")).isEmpty()) + if (const char* env_path = std::getenv("LMMS_PLUGIN_DIR")) QDir::addSearchPath("plugins", env_path); QDir::addSearchPath("plugins", ConfigManager::inst()->workingDir() + "plugins"); @@ -110,7 +109,7 @@ Plugin::DescriptorList PluginFactory::descriptors() const return m_descriptors.values(); } -Plugin::DescriptorList PluginFactory::descriptors(Plugin::PluginTypes type) const +Plugin::DescriptorList PluginFactory::descriptors(Plugin::Type type) const { return m_descriptors.values(type); } diff --git a/src/core/PluginIssue.cpp b/src/core/PluginIssue.cpp index f8ae06bc7..c9cf3400f 100644 --- a/src/core/PluginIssue.cpp +++ b/src/core/PluginIssue.cpp @@ -34,43 +34,43 @@ const char *PluginIssue::msgFor(const PluginIssueType &it) { switch (it) { - case unknownPortFlow: + case PluginIssueType::UnknownPortFlow: return "unknown port flow for mandatory port"; - case unknownPortType: + case PluginIssueType::UnknownPortType: return "unknown port type for mandatory port"; - case tooManyInputChannels: + case PluginIssueType::TooManyInputChannels: return "too many audio input channels"; - case tooManyOutputChannels: + case PluginIssueType::TooManyOutputChannels: return "too many audio output channels"; - case tooManyMidiInputChannels: + case PluginIssueType::TooManyMidiInputChannels: return "too many MIDI input channels"; - case tooManyMidiOutputChannels: + case PluginIssueType::TooManyMidiOutputChannels: return "too many MIDI output channels"; - case noOutputChannel: + case PluginIssueType::NoOutputChannel: return "no audio output channel"; - case portHasNoDef: + case PluginIssueType::PortHasNoDef: return "port is missing default value"; - case portHasNoMin: + case PluginIssueType::PortHasNoMin: return "port is missing min value"; - case portHasNoMax: + case PluginIssueType::PortHasNoMax: return "port is missing max value"; - case minGreaterMax: + case PluginIssueType::MinGreaterMax: return "port minimum is greater than maximum"; - case defaultValueNotInRange: + case PluginIssueType::DefaultValueNotInRange: return "default value is not in range [min, max]"; - case logScaleMinMissing: + case PluginIssueType::LogScaleMinMissing: return "logscale requires minimum value"; - case logScaleMaxMissing: + case PluginIssueType::LogScaleMaxMissing: return "logscale requires maximum value"; - case logScaleMinMaxDifferentSigns: + case PluginIssueType::LogScaleMinMaxDifferentSigns: return "logscale with min < 0 < max"; - case featureNotSupported: + case PluginIssueType::FeatureNotSupported: return "required feature not supported"; - case badPortType: + case PluginIssueType::BadPortType: return "unsupported port type"; - case blacklisted: + case PluginIssueType::Blacklisted: return "blacklisted plugin"; - case noIssue: + case PluginIssueType::NoIssue: return nullptr; } return nullptr; diff --git a/src/core/PresetPreviewPlayHandle.cpp b/src/core/PresetPreviewPlayHandle.cpp index 6a5b86424..0930de0de 100644 --- a/src/core/PresetPreviewPlayHandle.cpp +++ b/src/core/PresetPreviewPlayHandle.cpp @@ -48,7 +48,7 @@ public: m_dataMutex() { setJournalling( false ); - m_previewInstrumentTrack = dynamic_cast( Track::create( Track::InstrumentTrack, this ) ); + m_previewInstrumentTrack = dynamic_cast( Track::create( Track::Type::Instrument, this ) ); m_previewInstrumentTrack->setJournalling( false ); m_previewInstrumentTrack->setPreviewMode( true ); } @@ -116,7 +116,7 @@ PreviewTrackContainer * PresetPreviewPlayHandle::s_previewTC; PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file, bool _load_by_plugin, DataFile *dataFile ) : - PlayHandle( TypePresetPreviewHandle ), + PlayHandle( Type::PresetPreviewHandle ), m_previewNote(nullptr) { setUsesBuffer( false ); @@ -169,7 +169,7 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file, // make sure, our preset-preview-track does not appear in any MIDI- // devices list, so just disable receiving/sending MIDI-events at all s_previewTC->previewInstrumentTrack()-> - midiPort()->setMode( MidiPort::Disabled ); + midiPort()->setMode( MidiPort::Mode::Disabled ); Engine::audioEngine()->requestChangeInModel(); // create note-play-handle for it diff --git a/src/core/ProjectJournal.cpp b/src/core/ProjectJournal.cpp index bc1fee5c0..fc77c98e6 100644 --- a/src/core/ProjectJournal.cpp +++ b/src/core/ProjectJournal.cpp @@ -58,7 +58,7 @@ void ProjectJournal::undo() if( jo ) { - DataFile curState( DataFile::JournalData ); + DataFile curState( DataFile::Type::JournalData ); jo->saveState( curState, curState.content() ); m_redoCheckPoints.push( CheckPoint( c.joID, curState ) ); @@ -83,7 +83,7 @@ void ProjectJournal::redo() if( jo ) { - DataFile curState( DataFile::JournalData ); + DataFile curState( DataFile::Type::JournalData ); jo->saveState( curState, curState.content() ); m_undoCheckPoints.push( CheckPoint( c.joID, curState ) ); @@ -115,7 +115,7 @@ void ProjectJournal::addJournalCheckPoint( JournallingObject *jo ) { m_redoCheckPoints.clear(); - DataFile dataFile( DataFile::JournalData ); + DataFile dataFile( DataFile::Type::JournalData ); jo->saveState( dataFile, dataFile.content() ); m_undoCheckPoints.push( CheckPoint( jo->id(), dataFile ) ); diff --git a/src/core/ProjectRenderer.cpp b/src/core/ProjectRenderer.cpp index da6c729c8..3f101330a 100644 --- a/src/core/ProjectRenderer.cpp +++ b/src/core/ProjectRenderer.cpp @@ -42,15 +42,15 @@ namespace lmms const std::array ProjectRenderer::fileEncodeDevices { - FileEncodeDevice{ ProjectRenderer::WaveFile, + FileEncodeDevice{ ProjectRenderer::ExportFileFormat::Wave, QT_TRANSLATE_NOOP( "ProjectRenderer", "WAV (*.wav)" ), ".wav", &AudioFileWave::getInst }, - FileEncodeDevice{ ProjectRenderer::FlacFile, + FileEncodeDevice{ ProjectRenderer::ExportFileFormat::Flac, QT_TRANSLATE_NOOP("ProjectRenderer", "FLAC (*.flac)"), ".flac", &AudioFileFlac::getInst }, - FileEncodeDevice{ ProjectRenderer::OggFile, + FileEncodeDevice{ ProjectRenderer::ExportFileFormat::Ogg, QT_TRANSLATE_NOOP( "ProjectRenderer", "OGG (*.ogg)" ), ".ogg", #ifdef LMMS_HAVE_OGGVORBIS @@ -59,7 +59,7 @@ const std::array ProjectRenderer::fileEnco nullptr #endif }, - FileEncodeDevice{ ProjectRenderer::MP3File, + FileEncodeDevice{ ProjectRenderer::ExportFileFormat::MP3, QT_TRANSLATE_NOOP( "ProjectRenderer", "MP3 (*.mp3)" ), ".mp3", #ifdef LMMS_HAVE_MP3LAME @@ -71,7 +71,7 @@ const std::array ProjectRenderer::fileEnco // Insert your own file-encoder infos here. // Maybe one day the user can add own encoders inside the program. - FileEncodeDevice{ ProjectRenderer::NumFileFormats, nullptr, nullptr, nullptr } + FileEncodeDevice{ ProjectRenderer::ExportFileFormat::Count, nullptr, nullptr, nullptr } } ; @@ -80,7 +80,7 @@ const std::array ProjectRenderer::fileEnco ProjectRenderer::ProjectRenderer( const AudioEngine::qualitySettings & qualitySettings, const OutputSettings & outputSettings, - ExportFileFormats exportFileFormat, + ExportFileFormat exportFileFormat, const QString & outputFilename ) : QThread( Engine::audioEngine() ), m_fileDev( nullptr ), @@ -88,7 +88,7 @@ ProjectRenderer::ProjectRenderer( const AudioEngine::qualitySettings & qualitySe m_progress( 0 ), m_abort( false ) { - AudioFileDeviceInstantiaton audioEncoderFactory = fileEncodeDevices[exportFileFormat].m_getDevInst; + AudioFileDeviceInstantiaton audioEncoderFactory = fileEncodeDevices[static_cast(exportFileFormat)].m_getDevInst; if (audioEncoderFactory) { @@ -110,11 +110,11 @@ ProjectRenderer::ProjectRenderer( const AudioEngine::qualitySettings & qualitySe // Little help function for getting file format from a file extension // (only for registered file-encoders). -ProjectRenderer::ExportFileFormats ProjectRenderer::getFileFormatFromExtension( +ProjectRenderer::ExportFileFormat ProjectRenderer::getFileFormatFromExtension( const QString & _ext ) { int idx = 0; - while( fileEncodeDevices[idx].m_fileFormat != NumFileFormats ) + while( fileEncodeDevices[idx].m_fileFormat != ExportFileFormat::Count ) { if( QString( fileEncodeDevices[idx].m_extension ) == _ext ) { @@ -123,16 +123,16 @@ ProjectRenderer::ExportFileFormats ProjectRenderer::getFileFormatFromExtension( ++idx; } - return( WaveFile ); // Default. + return( ExportFileFormat::Wave ); // Default. } QString ProjectRenderer::getFileExtensionFromFormat( - ExportFileFormats fmt ) + ExportFileFormat fmt ) { - return fileEncodeDevices[fmt].m_extension; + return fileEncodeDevices[static_cast(fmt)].m_extension; } diff --git a/src/core/ProjectVersion.cpp b/src/core/ProjectVersion.cpp index b6ee2843f..ffdb8cd43 100644 --- a/src/core/ProjectVersion.cpp +++ b/src/core/ProjectVersion.cpp @@ -95,12 +95,12 @@ int ProjectVersion::compare(const ProjectVersion & a, const ProjectVersion & b, if(aPat != bPat){ return aPat - bPat; } // Decide how many optional identifiers we care about - const int maxLabels = qMax(0, limit - 3); + const int maxLabels = std::max(0, limit - 3); const auto aLabels = a.getLabels().mid(0, maxLabels); const auto bLabels = b.getLabels().mid(0, maxLabels); // We can only compare identifiers if both versions have them - const int commonLabels = qMin(aLabels.size(), bLabels.size()); + const int commonLabels = std::min(aLabels.size(), bLabels.size()); // If one version has optional labels and the other doesn't, // the one without them is bigger if (commonLabels == 0){ return bLabels.size() - aLabels.size(); } diff --git a/src/core/RemotePlugin.cpp b/src/core/RemotePlugin.cpp index 14c6f3f32..088bc3cd8 100644 --- a/src/core/RemotePlugin.cpp +++ b/src/core/RemotePlugin.cpp @@ -359,7 +359,7 @@ bool RemotePlugin::process( const sampleFrame * _in_buf, sampleFrame * _out_buf memset( m_audioBuffer.get(), 0, m_audioBufferSize ); - ch_cnt_t inputs = qMin( m_inputCount, DEFAULT_CHANNELS ); + ch_cnt_t inputs = std::min(m_inputCount, DEFAULT_CHANNELS); if( _in_buf != nullptr && inputs > 0 ) { @@ -403,8 +403,8 @@ bool RemotePlugin::process( const sampleFrame * _in_buf, sampleFrame * _out_buf waitForMessage( IdProcessingDone ); unlock(); - const ch_cnt_t outputs = qMin( m_outputCount, - DEFAULT_CHANNELS ); + const ch_cnt_t outputs = std::min(m_outputCount, + DEFAULT_CHANNELS); if( m_splitChannels ) { for( ch_cnt_t ch = 0; ch < outputs; ++ch ) @@ -427,8 +427,8 @@ bool RemotePlugin::process( const sampleFrame * _in_buf, sampleFrame * _out_buf // clear buffer, if plugin didn't fill up both channels BufferManager::clear( _out_buf, frames ); - for( ch_cnt_t ch = 0; ch < - qMin( DEFAULT_CHANNELS, outputs ); ++ch ) + for (ch_cnt_t ch = 0; ch < + std::min(DEFAULT_CHANNELS, outputs); ++ch) { for( fpp_t frame = 0; frame < frames; ++frame ) { diff --git a/src/core/RenderManager.cpp b/src/core/RenderManager.cpp index 56b4ce9d7..9f6192039 100644 --- a/src/core/RenderManager.cpp +++ b/src/core/RenderManager.cpp @@ -37,7 +37,7 @@ namespace lmms RenderManager::RenderManager( const AudioEngine::qualitySettings & qualitySettings, const OutputSettings & outputSettings, - ProjectRenderer::ExportFileFormats fmt, + ProjectRenderer::ExportFileFormat fmt, QString outputPath) : m_qualitySettings(qualitySettings), m_oldQualitySettings( Engine::audioEngine()->currentQualitySettings() ), @@ -69,7 +69,7 @@ void RenderManager::renderNextTrack() { m_activeRenderer.reset(); - if( m_tracksToRender.isEmpty() ) + if (m_tracksToRender.empty()) { // nothing left to render restoreMutedState(); @@ -97,29 +97,29 @@ void RenderManager::renderNextTrack() // Render the song into individual tracks void RenderManager::renderTracks() { - const TrackContainer::TrackList & tl = Engine::getSong()->tracks(); + const TrackContainer::TrackList& tl = Engine::getSong()->tracks(); // find all currently unnmuted tracks -- we want to render these. for (const auto& tk : tl) { - Track::TrackTypes type = tk->type(); + Track::Type type = tk->type(); // Don't render automation tracks if ( tk->isMuted() == false && - ( type == Track::InstrumentTrack || type == Track::SampleTrack ) ) + ( type == Track::Type::Instrument || type == Track::Type::Sample ) ) { m_unmuted.push_back(tk); } } - const TrackContainer::TrackList t2 = Engine::patternStore()->tracks(); + const TrackContainer::TrackList& t2 = Engine::patternStore()->tracks(); for (const auto& tk : t2) { - Track::TrackTypes type = tk->type(); + Track::Type type = tk->type(); // Don't render automation tracks if ( tk->isMuted() == false && - ( type == Track::InstrumentTrack || type == Track::SampleTrack ) ) + ( type == Track::Type::Instrument || type == Track::Type::Sample ) ) { m_unmuted.push_back(tk); } @@ -169,7 +169,7 @@ void RenderManager::render(QString outputPath) // Unmute all tracks that were muted while rendering tracks void RenderManager::restoreMutedState() { - while( !m_unmuted.isEmpty() ) + while (!m_unmuted.empty()) { Track* restoreTrack = m_unmuted.back(); m_unmuted.pop_back(); diff --git a/src/core/SampleBuffer.cpp b/src/core/SampleBuffer.cpp index 677366fdb..775db125b 100644 --- a/src/core/SampleBuffer.cpp +++ b/src/core/SampleBuffer.cpp @@ -456,10 +456,10 @@ void SampleBuffer::normalizeSampleRate(const sample_rate_t srcSR, bool keepSetti { auto oldRateToNewRateRatio = static_cast(audioEngineSampleRate()) / oldRate; - m_startFrame = qBound(0, f_cnt_t(m_startFrame * oldRateToNewRateRatio), m_frames); - m_endFrame = qBound(m_startFrame, f_cnt_t(m_endFrame * oldRateToNewRateRatio), m_frames); - m_loopStartFrame = qBound(0, f_cnt_t(m_loopStartFrame * oldRateToNewRateRatio), m_frames); - m_loopEndFrame = qBound(m_loopStartFrame, f_cnt_t(m_loopEndFrame * oldRateToNewRateRatio), m_frames); + m_startFrame = std::clamp(f_cnt_t(m_startFrame * oldRateToNewRateRatio), 0, m_frames); + m_endFrame = std::clamp(f_cnt_t(m_endFrame * oldRateToNewRateRatio), m_startFrame, m_frames); + m_loopStartFrame = std::clamp(f_cnt_t(m_loopStartFrame * oldRateToNewRateRatio), 0, m_frames); + m_loopEndFrame = std::clamp(f_cnt_t(m_loopEndFrame * oldRateToNewRateRatio), m_loopStartFrame, m_frames); m_sampleRate = audioEngineSampleRate(); } } @@ -736,9 +736,9 @@ bool SampleBuffer::play( // this holds the index of the first frame to play - f_cnt_t playFrame = qMax(state->m_frameIndex, startFrame); + f_cnt_t playFrame = std::max(state->m_frameIndex, startFrame); - if (loopMode == LoopOff) + if (loopMode == LoopMode::Off) { if (playFrame >= endFrame || (endFrame - playFrame) / freqFactor == 0) { @@ -746,7 +746,7 @@ bool SampleBuffer::play( return false; } } - else if (loopMode == LoopOn) + else if (loopMode == LoopMode::On) { playFrame = getLoopedIndex(playFrame, loopStartFrame, loopEndFrame); } @@ -786,14 +786,14 @@ bool SampleBuffer::play( // Advance switch (loopMode) { - case LoopOff: + case LoopMode::Off: playFrame += srcData.input_frames_used; break; - case LoopOn: + case LoopMode::On: playFrame += srcData.input_frames_used; playFrame = getLoopedIndex(playFrame, loopStartFrame, loopEndFrame); break; - case LoopPingPong: + case LoopMode::PingPong: { f_cnt_t left = srcData.input_frames_used; if (state->isBackwards()) @@ -825,14 +825,14 @@ bool SampleBuffer::play( // Advance switch (loopMode) { - case LoopOff: + case LoopMode::Off: playFrame += frames; break; - case LoopOn: + case LoopMode::On: playFrame += frames; playFrame = getLoopedIndex(playFrame, loopStartFrame, loopEndFrame); break; - case LoopPingPong: + case LoopMode::PingPong: { f_cnt_t left = frames; if (state->isBackwards()) @@ -883,14 +883,14 @@ sampleFrame * SampleBuffer::getSampleFragment( f_cnt_t end ) const { - if (loopMode == LoopOff) + if (loopMode == LoopMode::Off) { if (index + frames <= end) { return m_data + index; } } - else if (loopMode == LoopOn) + else if (loopMode == LoopMode::On) { if (index + frames <= loopEnd) { @@ -907,20 +907,20 @@ sampleFrame * SampleBuffer::getSampleFragment( *tmp = MM_ALLOC( frames); - if (loopMode == LoopOff) + if (loopMode == LoopMode::Off) { f_cnt_t available = end - index; memcpy(*tmp, m_data + index, available * BYTES_PER_FRAME); memset(*tmp + available, 0, (frames - available) * BYTES_PER_FRAME); } - else if (loopMode == LoopOn) + else if (loopMode == LoopMode::On) { - f_cnt_t copied = qMin(frames, loopEnd - index); + f_cnt_t copied = std::min(frames, loopEnd - index); memcpy(*tmp, m_data + index, copied * BYTES_PER_FRAME); f_cnt_t loopFrames = loopEnd - loopStart; while (copied < frames) { - f_cnt_t todo = qMin(frames - copied, loopFrames); + f_cnt_t todo = std::min(frames - copied, loopFrames); memcpy(*tmp + copied, m_data + loopStart, todo * BYTES_PER_FRAME); copied += todo; } @@ -936,7 +936,7 @@ sampleFrame * SampleBuffer::getSampleFragment( if (currentBackwards) { - copied = qMin(frames, pos - loopStart); + copied = std::min(frames, pos - loopStart); for (int i = 0; i < copied; i++) { (*tmp)[i][0] = m_data[pos - i][0]; @@ -947,7 +947,7 @@ sampleFrame * SampleBuffer::getSampleFragment( } else { - copied = qMin(frames, loopEnd - pos); + copied = std::min(frames, loopEnd - pos); memcpy(*tmp, m_data + pos, copied * BYTES_PER_FRAME); pos += copied; if (pos == loopEnd) { currentBackwards = true; } @@ -957,7 +957,7 @@ sampleFrame * SampleBuffer::getSampleFragment( { if (currentBackwards) { - f_cnt_t todo = qMin(frames - copied, pos - loopStart); + f_cnt_t todo = std::min(frames - copied, pos - loopStart); for (int i = 0; i < todo; i++) { (*tmp)[copied + i][0] = m_data[pos - i][0]; @@ -969,7 +969,7 @@ sampleFrame * SampleBuffer::getSampleFragment( } else { - f_cnt_t todo = qMin(frames - copied, loopEnd - pos); + f_cnt_t todo = std::min(frames - copied, loopEnd - pos); memcpy(*tmp + copied, m_data + pos, todo * BYTES_PER_FRAME); pos += todo; copied += todo; @@ -1085,8 +1085,8 @@ void SampleBuffer::visualize( const float trueRmsData = (rmsData[0] + rmsData[1]) / 2 / fpp; const float sqrtRmsData = sqrt(trueRmsData); - const float maxRmsData = qBound(minData, sqrtRmsData, maxData); - const float minRmsData = qBound(minData, -sqrtRmsData, maxData); + const float maxRmsData = std::clamp(sqrtRmsData, minData, maxData); + const float minRmsData = std::clamp(-sqrtRmsData, minData, maxData); // If nbFrames >= w, we can use curPixel to calculate X // but if nbFrames < w, we need to calculate it proportionally @@ -1291,7 +1291,7 @@ QString & SampleBuffer::toBase64(QString & dst) const while (frameCnt < m_frames) { - f_cnt_t remaining = qMin(FRAMES_PER_BUF, m_frames - frameCnt); + f_cnt_t remaining = std::min(FRAMES_PER_BUF, m_frames - frameCnt); FLAC__int32 buf[FRAMES_PER_BUF * DEFAULT_CHANNELS]; for (f_cnt_t f = 0; f < remaining; ++f) { diff --git a/src/core/SampleClip.cpp b/src/core/SampleClip.cpp index 6396d49f3..592a63827 100644 --- a/src/core/SampleClip.cpp +++ b/src/core/SampleClip.cpp @@ -53,7 +53,7 @@ SampleClip::SampleClip( Track * _track ) : this, SLOT(updateLength())); //care about positionmarker - gui::TimeLineWidget* timeLine = Engine::getSong()->getPlayPos( Engine::getSong()->Mode_PlaySong ).m_timeLine; + gui::TimeLineWidget* timeLine = Engine::getSong()->getPlayPos( Song::PlayMode::Song ).m_timeLine; if( timeLine ) { connect( timeLine, SIGNAL(positionMarkerMoved()), this, SLOT(playbackPositionChanged())); @@ -74,11 +74,11 @@ SampleClip::SampleClip( Track * _track ) : switch( getTrack()->trackContainer()->type() ) { - case TrackContainer::PatternContainer: + case TrackContainer::Type::Pattern: setAutoResize( true ); break; - case TrackContainer::SongContainer: + case TrackContainer::Type::Song: // move down default: setAutoResize( false ); @@ -117,7 +117,7 @@ SampleClip::~SampleClip() void SampleClip::changeLength( const TimePos & _length ) { - Clip::changeLength( qMax( static_cast( _length ), 1 ) ); + Clip::changeLength(std::max(static_cast(_length), 1)); } @@ -179,7 +179,7 @@ void SampleClip::toggleRecord() void SampleClip::playbackPositionChanged() { - Engine::audioEngine()->removePlayHandlesOfTypes( getTrack(), PlayHandle::TypeSamplePlayHandle ); + Engine::audioEngine()->removePlayHandlesOfTypes( getTrack(), PlayHandle::Type::SamplePlayHandle ); auto st = dynamic_cast(getTrack()); st->setPlayingClips( false ); } diff --git a/src/core/SamplePlayHandle.cpp b/src/core/SamplePlayHandle.cpp index 77658e1d8..ea27146cb 100644 --- a/src/core/SamplePlayHandle.cpp +++ b/src/core/SamplePlayHandle.cpp @@ -36,7 +36,7 @@ namespace lmms SamplePlayHandle::SamplePlayHandle( SampleBuffer* sampleBuffer , bool ownAudioPort ) : - PlayHandle( TypeSamplePlayHandle ), + PlayHandle( Type::SamplePlayHandle ), m_sampleBuffer( sharedObject::ref( sampleBuffer ) ), m_doneMayReturnTrue( true ), m_frame( 0 ), diff --git a/src/core/SampleRecordHandle.cpp b/src/core/SampleRecordHandle.cpp index edebd27fd..10e970b8f 100644 --- a/src/core/SampleRecordHandle.cpp +++ b/src/core/SampleRecordHandle.cpp @@ -37,7 +37,7 @@ namespace lmms SampleRecordHandle::SampleRecordHandle( SampleClip* clip ) : - PlayHandle( TypeSamplePlayHandle ), + PlayHandle( Type::SamplePlayHandle ), m_framesRecorded( 0 ), m_minLength( clip->length() ), m_track( clip->getTrack() ), diff --git a/src/core/Song.cpp b/src/core/Song.cpp index fef66f193..3a735331c 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -68,7 +68,7 @@ tick_t TimePos::s_ticksPerBar = DefaultTicksPerBar; Song::Song() : TrackContainer(), m_globalAutomationTrack( dynamic_cast( - Track::create( Track::HiddenAutomationTrack, + Track::create( Track::Type::HiddenAutomation, this ) ) ), m_tempoModel( DefaultTempo, MinTempo, MaxTempo, this, tr( "Tempo" ) ), m_timeSigModel( this ), @@ -89,7 +89,7 @@ Song::Song() : m_savingProject( false ), m_loadingProject( false ), m_isCancelled( false ), - m_playMode( Mode_None ), + m_playMode( PlayMode::None ), m_length( 0 ), m_midiClipToPlay( nullptr ), m_loopMidiClip( false ), @@ -117,7 +117,7 @@ Song::Song() : this, SLOT(masterPitchChanged()));*/ qRegisterMetaType( "lmms::Note" ); - setType( SongContainer ); + setType( Type::Song ); for (auto& scale : m_scales) {scale = std::make_shared();} for (auto& keymap : m_keymaps) {keymap = std::make_shared();} @@ -186,11 +186,11 @@ void Song::setTimeSignature() void Song::savePos() { - gui::TimeLineWidget* tl = m_playPos[m_playMode].m_timeLine; + gui::TimeLineWidget* tl = getPlayPos().m_timeLine; if( tl != nullptr ) { - tl->savePos( m_playPos[m_playMode] ); + tl->savePos( getPlayPos() ); } } @@ -205,7 +205,7 @@ void Song::processNextBuffer() if (!m_playing) { return; } // At the beginning of the song, we have to reset the LFOs - if (m_playMode == Mode_PlaySong && getPlayPos() == 0) + if (m_playMode == PlayMode::Song && getPlayPos() == 0) { EnvelopeAndLfoParameters::instances()->reset(); } @@ -216,11 +216,11 @@ void Song::processNextBuffer() // Determine the list of tracks to play and the clip number switch (m_playMode) { - case Mode_PlaySong: + case PlayMode::Song: trackList = tracks(); break; - case Mode_PlayPattern: + case PlayMode::Pattern: if (Engine::patternStore()->numOfPatterns() > 0) { clipNum = Engine::patternStore()->currentPattern(); @@ -228,7 +228,7 @@ void Song::processNextBuffer() } break; - case Mode_PlayMidiClip: + case PlayMode::MidiClip: if (m_midiClipToPlay) { clipNum = m_midiClipToPlay->getTrack()->getClipNum(m_midiClipToPlay); @@ -291,11 +291,11 @@ void Song::processNextBuffer() // If we are playing a pattern track, or a MIDI clip with no loop enabled, // loop back to the beginning when we reach the end - if (m_playMode == Mode_PlayPattern) + if (m_playMode == PlayMode::Pattern) { enforceLoop(TimePos{0}, TimePos{Engine::patternStore()->lengthOfCurrentPattern(), 0}); } - else if (m_playMode == Mode_PlayMidiClip && m_loopMidiClip && !loopEnabled) + else if (m_playMode == PlayMode::MidiClip && m_loopMidiClip && !loopEnabled) { enforceLoop(TimePos{0}, m_midiClipToPlay->length()); } @@ -349,9 +349,9 @@ void Song::processNextBuffer() frameOffsetInPeriod += framesToPlay; frameOffsetInTick += framesToPlay; getPlayPos().setCurrentFrame(frameOffsetInTick); - m_elapsedMilliSeconds[m_playMode] += TimePos::ticksToMilliseconds(framesToPlay / framesPerTick, getTempo()); - m_elapsedBars = m_playPos[Mode_PlaySong].getBar(); - m_elapsedTicks = (m_playPos[Mode_PlaySong].getTicks() % ticksPerBar()) / 48; + m_elapsedMilliSeconds[static_cast(m_playMode)] += TimePos::ticksToMilliseconds(framesToPlay / framesPerTick, getTempo()); + m_elapsedBars = getPlayPos(PlayMode::Song).getBar(); + m_elapsedTicks = (getPlayPos(PlayMode::Song).getTicks() % ticksPerBar()) / 48; } } @@ -367,12 +367,12 @@ void Song::processAutomations(const TrackList &tracklist, TimePos timeStart, fpp switch (m_playMode) { - case Mode_PlaySong: + case PlayMode::Song: break; - case Mode_PlayPattern: + case PlayMode::Pattern: { Q_ASSERT(tracklist.size() == 1); - Q_ASSERT(tracklist.at(0)->type() == Track::PatternTrack); + Q_ASSERT(tracklist.at(0)->type() == Track::Type::Pattern); auto patternTrack = dynamic_cast(tracklist.at(0)); container = Engine::patternStore(); clipNum = patternTrack->patternIndex(); @@ -383,12 +383,12 @@ void Song::processAutomations(const TrackList &tracklist, TimePos timeStart, fpp } values = container->automatedValuesAt(timeStart, clipNum); - TrackList tracks = container->tracks(); + const TrackList& tracks = container->tracks(); Track::clipVector clips; for (Track* track : tracks) { - if (track->type() == Track::AutomationTrack) { + if (track->type() == Track::Type::Automation) { track->getClipsInRange(clips, 0, timeStart); } } @@ -444,12 +444,12 @@ void Song::setModified(bool value) bool Song::isExportDone() const { - return !isExporting() || m_playPos[m_playMode] >= m_exportSongEnd; + return !isExporting() || getPlayPos() >= m_exportSongEnd; } int Song::getExportProgress() const { - TimePos pos = m_playPos[m_playMode]; + TimePos pos = getPlayPos(); if (pos >= m_exportSongEnd) { @@ -486,7 +486,7 @@ void Song::playSong() stop(); } - m_playMode = Mode_PlaySong; + m_playMode = PlayMode::Song; m_playing = true; m_paused = false; @@ -525,7 +525,7 @@ void Song::playPattern() stop(); } - m_playMode = Mode_PlayPattern; + m_playMode = PlayMode::Pattern; m_playing = true; m_paused = false; @@ -551,7 +551,7 @@ void Song::playMidiClip( const MidiClip* midiClipToPlay, bool loop ) if( m_midiClipToPlay != nullptr ) { - m_playMode = Mode_PlayMidiClip; + m_playMode = PlayMode::MidiClip; m_playing = true; m_paused = false; } @@ -589,14 +589,14 @@ void Song::updateLength() -void Song::setPlayPos( tick_t ticks, PlayModes playMode ) +void Song::setPlayPos( tick_t ticks, PlayMode playMode ) { - tick_t ticksFromPlayMode = m_playPos[playMode].getTicks(); + tick_t ticksFromPlayMode = getPlayPos(playMode).getTicks(); m_elapsedTicks += ticksFromPlayMode - ticks; - m_elapsedMilliSeconds[playMode] += TimePos::ticksToMilliseconds( ticks - ticksFromPlayMode, getTempo() ); - m_playPos[playMode].setTicks( ticks ); - m_playPos[playMode].setCurrentFrame( 0.0f ); - m_playPos[playMode].setJumped( true ); + m_elapsedMilliSeconds[static_cast(playMode)] += TimePos::ticksToMilliseconds( ticks - ticksFromPlayMode, getTempo() ); + getPlayPos(playMode).setTicks( ticks ); + getPlayPos(playMode).setCurrentFrame( 0.0f ); + getPlayPos(playMode).setJumped( true ); // send a signal if playposition changes during playback if( isPlaying() ) @@ -634,7 +634,7 @@ void Song::togglePause() void Song::stop() { // do not stop/reset things again if we're stopped already - if( m_playMode == Mode_None ) + if( m_playMode == PlayMode::None ) { return; } @@ -644,7 +644,7 @@ void Song::stop() // To avoid race conditions with the processing threads Engine::audioEngine()->requestChangeInModel(); - TimeLineWidget * tl = m_playPos[m_playMode].m_timeLine; + TimeLineWidget * tl = getPlayPos().m_timeLine; m_paused = false; m_recording = true; @@ -652,41 +652,41 @@ void Song::stop() { switch( tl->behaviourAtStop() ) { - case TimeLineWidget::BackToZero: - m_playPos[m_playMode].setTicks(0); - m_elapsedMilliSeconds[m_playMode] = 0; + case TimeLineWidget::BehaviourAtStopState::BackToZero: + getPlayPos().setTicks(0); + m_elapsedMilliSeconds[static_cast(m_playMode)] = 0; break; - case TimeLineWidget::BackToStart: + case TimeLineWidget::BehaviourAtStopState::BackToStart: if( tl->savedPos() >= 0 ) { - m_playPos[m_playMode].setTicks(tl->savedPos().getTicks()); + getPlayPos().setTicks(tl->savedPos().getTicks()); setToTime(tl->savedPos()); tl->savePos( -1 ); } break; - case TimeLineWidget::KeepStopPosition: + case TimeLineWidget::BehaviourAtStopState::KeepStopPosition: break; } } else { - m_playPos[m_playMode].setTicks( 0 ); - m_elapsedMilliSeconds[m_playMode] = 0; + getPlayPos().setTicks( 0 ); + m_elapsedMilliSeconds[static_cast(m_playMode)] = 0; } m_playing = false; - m_elapsedMilliSeconds[Mode_None] = m_elapsedMilliSeconds[m_playMode]; - m_playPos[Mode_None].setTicks(m_playPos[m_playMode].getTicks()); + m_elapsedMilliSeconds[static_cast(PlayMode::None)] = m_elapsedMilliSeconds[static_cast(m_playMode)]; + getPlayPos(PlayMode::None).setTicks(getPlayPos().getTicks()); - m_playPos[m_playMode].setCurrentFrame( 0 ); + getPlayPos().setCurrentFrame( 0 ); m_vstSyncController.setPlaybackState( m_exporting ); m_vstSyncController.setAbsolutePosition( - m_playPos[m_playMode].getTicks() - + m_playPos[m_playMode].currentFrame() + getPlayPos().getTicks() + + getPlayPos().currentFrame() / (double) Engine::framesPerTick() ); // remove all note-play-handles that are active @@ -701,7 +701,7 @@ void Song::stop() } m_oldAutomatedValues.clear(); - m_playMode = Mode_None; + m_playMode = PlayMode::None; Engine::audioEngine()->doneChangeInModel(); @@ -721,19 +721,19 @@ void Song::startExport() if (m_renderBetweenMarkers) { - m_exportSongBegin = m_exportLoopBegin = m_playPos[Mode_PlaySong].m_timeLine->loopBegin(); - m_exportSongEnd = m_exportLoopEnd = m_playPos[Mode_PlaySong].m_timeLine->loopEnd(); + m_exportSongBegin = m_exportLoopBegin = getPlayPos(PlayMode::Song).m_timeLine->loopBegin(); + m_exportSongEnd = m_exportLoopEnd = getPlayPos(PlayMode::Song).m_timeLine->loopEnd(); - m_playPos[Mode_PlaySong].setTicks( m_playPos[Mode_PlaySong].m_timeLine->loopBegin().getTicks() ); + getPlayPos(PlayMode::Song).setTicks( getPlayPos(PlayMode::Song).m_timeLine->loopBegin().getTicks() ); } else { m_exportSongEnd = TimePos(m_length, 0); // Handle potentially ridiculous loop points gracefully. - if (m_loopRenderCount > 1 && m_playPos[Mode_PlaySong].m_timeLine->loopEnd() > m_exportSongEnd) + if (m_loopRenderCount > 1 && getPlayPos(PlayMode::Song).m_timeLine->loopEnd() > m_exportSongEnd) { - m_exportSongEnd = m_playPos[Mode_PlaySong].m_timeLine->loopEnd(); + m_exportSongEnd = getPlayPos(PlayMode::Song).m_timeLine->loopEnd(); } if (!m_exportLoop) @@ -741,17 +741,17 @@ void Song::startExport() m_exportSongBegin = TimePos(0,0); // FIXME: remove this check once we load timeline in headless mode - if (m_playPos[Mode_PlaySong].m_timeLine) + if (getPlayPos(PlayMode::Song).m_timeLine) { - m_exportLoopBegin = m_playPos[Mode_PlaySong].m_timeLine->loopBegin() < m_exportSongEnd && - m_playPos[Mode_PlaySong].m_timeLine->loopEnd() <= m_exportSongEnd ? - m_playPos[Mode_PlaySong].m_timeLine->loopBegin() : TimePos(0,0); - m_exportLoopEnd = m_playPos[Mode_PlaySong].m_timeLine->loopBegin() < m_exportSongEnd && - m_playPos[Mode_PlaySong].m_timeLine->loopEnd() <= m_exportSongEnd ? - m_playPos[Mode_PlaySong].m_timeLine->loopEnd() : TimePos(0,0); + m_exportLoopBegin = getPlayPos(PlayMode::Song).m_timeLine->loopBegin() < m_exportSongEnd && + getPlayPos(PlayMode::Song).m_timeLine->loopEnd() <= m_exportSongEnd ? + getPlayPos(PlayMode::Song).m_timeLine->loopBegin() : TimePos(0,0); + m_exportLoopEnd = getPlayPos(PlayMode::Song).m_timeLine->loopBegin() < m_exportSongEnd && + getPlayPos(PlayMode::Song).m_timeLine->loopEnd() <= m_exportSongEnd ? + getPlayPos(PlayMode::Song).m_timeLine->loopEnd() : TimePos(0,0); } - m_playPos[Mode_PlaySong].setTicks( 0 ); + getPlayPos(PlayMode::Song).setTicks( 0 ); } m_exportEffectiveLength = (m_exportLoopBegin - m_exportSongBegin) + (m_exportLoopEnd - m_exportLoopBegin) @@ -784,7 +784,7 @@ void Song::insertBar() { // FIXME journal batch of tracks instead of each track individually if (track->numOfClips() > 0) { track->addJournalCheckPoint(); } - track->insertBar(m_playPos[Mode_PlaySong]); + track->insertBar(getPlayPos(PlayMode::Song)); } m_tracksMutex.unlock(); } @@ -799,7 +799,7 @@ void Song::removeBar() { // FIXME journal batch of tracks instead of each track individually if (track->numOfClips() > 0) { track->addJournalCheckPoint(); } - track->removeBar(m_playPos[Mode_PlaySong]); + track->removeBar(getPlayPos(PlayMode::Song)); } m_tracksMutex.unlock(); } @@ -809,7 +809,7 @@ void Song::removeBar() void Song::addPatternTrack() { - Track * t = Track::create(Track::PatternTrack, this); + Track * t = Track::create(Track::Type::Pattern, this); Engine::patternStore()->setCurrentPattern(dynamic_cast(t)->patternIndex()); } @@ -818,7 +818,7 @@ void Song::addPatternTrack() void Song::addSampleTrack() { - ( void )Track::create( Track::SampleTrack, this ); + ( void )Track::create( Track::Type::Sample, this ); } @@ -826,7 +826,7 @@ void Song::addSampleTrack() void Song::addAutomationTrack() { - ( void )Track::create( Track::AutomationTrack, this ); + ( void )Track::create( Track::Type::Automation, this ); } @@ -840,7 +840,9 @@ bpm_t Song::getTempo() AutomatedValueMap Song::automatedValuesAt(TimePos time, int clipNum) const { - return TrackContainer::automatedValuesFromTracks(TrackList{m_globalAutomationTrack} << tracks(), time, clipNum); + auto trackList = TrackList{m_globalAutomationTrack}; + trackList.insert(trackList.end(), tracks().begin(), tracks().end()); + return TrackContainer::automatedValuesFromTracks(trackList, time, clipNum); } @@ -857,9 +859,9 @@ void Song::clearProject() stop(); } - for( int i = 0; i < Mode_Count; i++ ) + for( int i = 0; i < PlayModeCount; i++ ) { - setPlayPos( 0, ( PlayModes )i ); + setPlayPos( 0, ( PlayMode )i ); } @@ -958,15 +960,15 @@ void Song::createNewProject() setProjectFileName(""); Track * t; - t = Track::create( Track::InstrumentTrack, this ); + t = Track::create( Track::Type::Instrument, this ); dynamic_cast( t )->loadInstrument( "tripleoscillator" ); - t = Track::create(Track::InstrumentTrack, Engine::patternStore()); + t = Track::create(Track::Type::Instrument, Engine::patternStore()); dynamic_cast( t )->loadInstrument( "kicker" ); - Track::create( Track::SampleTrack, this ); - Track::create( Track::PatternTrack, this ); - Track::create( Track::AutomationTrack, this ); + Track::create( Track::Type::Sample, this ); + Track::create( Track::Type::Pattern, this ); + Track::create( Track::Type::Automation, this ); m_tempoModel.setInitValue( DefaultTempo ); m_timeSigModel.reset(); @@ -1078,10 +1080,10 @@ void Song::loadProject( const QString & fileName ) m_masterVolumeModel.loadSettings( dataFile.head(), "mastervol" ); m_masterPitchModel.loadSettings( dataFile.head(), "masterpitch" ); - if( m_playPos[Mode_PlaySong].m_timeLine ) + if( getPlayPos(PlayMode::Song).m_timeLine ) { // reset loop-point-state - m_playPos[Mode_PlaySong].m_timeLine->toggleLoopPoints( 0 ); + getPlayPos(PlayMode::Song).m_timeLine->toggleLoopPoints( 0 ); } if( !dataFile.content().firstChildElement( "track" ).isNull() ) @@ -1117,7 +1119,7 @@ void Song::loadProject( const QString & fileName ) if( nd.isElement() && nd.nodeName() == "track" ) { ++m_nLoadingTrack; - if (nd.toElement().attribute("type").toInt() == Track::PatternTrack) + if (static_cast(nd.toElement().attribute("type").toInt()) == Track::Type::Pattern) { n += nd.toElement().elementsByTagName("patterntrack").at(0) .toElement().firstChildElement().childNodes().count(); @@ -1165,9 +1167,9 @@ void Song::loadProject( const QString & fileName ) { getGUI()->getProjectNotes()->SerializingObject::restoreState( node.toElement() ); } - else if( node.nodeName() == m_playPos[Mode_PlaySong].m_timeLine->nodeName() ) + else if( node.nodeName() == getPlayPos(PlayMode::Song).m_timeLine->nodeName() ) { - m_playPos[Mode_PlaySong].m_timeLine->restoreState( node.toElement() ); + getPlayPos(PlayMode::Song).m_timeLine->restoreState( node.toElement() ); } } } @@ -1183,7 +1185,7 @@ void Song::loadProject( const QString & fileName ) // Remove dummy controllers that was added for correct connections m_controllers.erase(std::remove_if(m_controllers.begin(), m_controllers.end(), - [](Controller* c){return c->type() == Controller::DummyController;}), + [](Controller* c){return c->type() == Controller::ControllerType::Dummy;}), m_controllers.end()); // resolve all IDs so that autoModels are automated @@ -1233,7 +1235,7 @@ bool Song::saveProjectFile(const QString & filename, bool withResources) { using gui::getGUI; - DataFile dataFile( DataFile::SongProject ); + DataFile dataFile( DataFile::Type::SongProject ); m_savingProject = true; m_tempoModel.saveSettings( dataFile, dataFile.head(), "bpm" ); @@ -1251,7 +1253,7 @@ bool Song::saveProjectFile(const QString & filename, bool withResources) getGUI()->pianoRoll()->saveState( dataFile, dataFile.content() ); getGUI()->automationEditor()->m_editor->saveState( dataFile, dataFile.content() ); getGUI()->getProjectNotes()->SerializingObject::saveState( dataFile, dataFile.content() ); - m_playPos[Mode_PlaySong].m_timeLine->saveState( dataFile, dataFile.content() ); + getPlayPos(PlayMode::Song).m_timeLine->saveState( dataFile, dataFile.content() ); } saveControllerStates( dataFile, dataFile.content() ); @@ -1278,7 +1280,7 @@ bool Song::guiSaveProject() // Save the current song with the given filename bool Song::guiSaveProjectAs(const QString & filename) { - DataFile dataFile(DataFile::SongProject); + DataFile dataFile(DataFile::Type::SongProject); QString fileNameWithExtension = dataFile.nameWithExtension(filename); bool withResources = m_saveOptions.saveAsProjectBundle.value(); @@ -1326,8 +1328,7 @@ void Song::restoreControllerStates( const QDomElement & element ) else { // Fix indices to ensure correct connections - m_controllers.append(Controller::create( - Controller::DummyController, this)); + m_controllers.push_back(Controller::create(Controller::ControllerType::Dummy, this)); } node = node.nextSibling(); @@ -1445,9 +1446,10 @@ void Song::setProjectFileName(QString const & projectFileName) void Song::addController( Controller * controller ) { - if( controller && !m_controllers.contains( controller ) ) + bool containsController = std::find(m_controllers.begin(), m_controllers.end(), controller) != m_controllers.end(); + if (controller && !containsController) { - m_controllers.append( controller ); + m_controllers.push_back(controller); emit controllerAdded( controller ); this->setModified(); @@ -1459,10 +1461,10 @@ void Song::addController( Controller * controller ) void Song::removeController( Controller * controller ) { - int index = m_controllers.indexOf( controller ); - if( index != -1 ) + auto it = std::find(m_controllers.begin(), m_controllers.end(), controller); + if (it != m_controllers.end()) { - m_controllers.remove( index ); + m_controllers.erase(it); emit controllerRemoved( controller ); delete controller; diff --git a/src/core/StepRecorder.cpp b/src/core/StepRecorder.cpp index e8f31f644..9c2a216ae 100644 --- a/src/core/StepRecorder.cpp +++ b/src/core/StepRecorder.cpp @@ -91,7 +91,7 @@ void StepRecorder::notePressed(const Note & n) StepNote* stepNote = findCurStepNote(n.key()); if(stepNote == nullptr) { - m_curStepNotes.append(new StepNote(Note(m_curStepLength, m_curStepStartPos, n.key(), n.getVolume(), n.getPanning()))); + m_curStepNotes.push_back(new StepNote(Note(m_curStepLength, m_curStepStartPos, n.key(), n.getVolume(), n.getPanning()))); m_pianoRoll.update(); } else if (stepNote->isReleased()) @@ -175,15 +175,15 @@ void StepRecorder::setStepsLength(const TimePos& newLength) updateWidget(); } -QVector StepRecorder::getCurStepNotes() +std::vector StepRecorder::getCurStepNotes() { - QVector notes; + std::vector notes; if(m_isStepInProgress) { - for(StepNote* stepNote: m_curStepNotes) + for (StepNote* stepNote: m_curStepNotes) { - notes.append(&stepNote->m_note); + notes.push_back(&stepNote->m_note); } } @@ -288,18 +288,13 @@ void StepRecorder::removeNotesReleasedForTooLong() int nextTimout = std::numeric_limits::max(); bool notesRemoved = false; - QMutableVectorIterator itr(m_curStepNotes); - while (itr.hasNext()) + for (const auto& stepNote : m_curStepNotes) { - StepNote* stepNote = itr.next(); - - if(stepNote->isReleased()) + if (stepNote->isReleased()) { const int timeSinceReleased = stepNote->timeSinceReleased(); // capture value to avoid wraparound when calculting nextTimout if (timeSinceReleased >= REMOVE_RELEASED_NOTE_TIME_THRESHOLD_MS) { - delete stepNote; - itr.remove(); notesRemoved = true; } else @@ -309,6 +304,17 @@ void StepRecorder::removeNotesReleasedForTooLong() } } + m_curStepNotes.erase(std::remove_if(m_curStepNotes.begin(), m_curStepNotes.end(), [](auto stepNote) + { + bool shouldRemove = stepNote->isReleased() && stepNote->timeSinceReleased() >= REMOVE_RELEASED_NOTE_TIME_THRESHOLD_MS; + if (shouldRemove) + { + delete stepNote; + } + + return shouldRemove; + }), m_curStepNotes.end()); + if(notesRemoved) { m_pianoRoll.update(); diff --git a/src/core/TempoSyncKnobModel.cpp b/src/core/TempoSyncKnobModel.cpp index 6fb457f2c..7f707478f 100644 --- a/src/core/TempoSyncKnobModel.cpp +++ b/src/core/TempoSyncKnobModel.cpp @@ -40,8 +40,8 @@ TempoSyncKnobModel::TempoSyncKnobModel( const float _val, const float _min, const float _scale, Model * _parent, const QString & _display_name ) : FloatModel( _val, _min, _max, _step, _parent, _display_name ), - m_tempoSyncMode( SyncNone ), - m_tempoLastSyncMode( SyncNone ), + m_tempoSyncMode( SyncMode::None ), + m_tempoLastSyncMode( SyncMode::None ), m_scale( _scale ), m_custom( _parent ) { @@ -55,15 +55,15 @@ TempoSyncKnobModel::TempoSyncKnobModel( const float _val, const float _min, void TempoSyncKnobModel::setTempoSync( QAction * _item ) { - setTempoSync( _item->data().toInt() ); + setTempoSync( static_cast(_item->data().toInt()) ); } -void TempoSyncKnobModel::setTempoSync( int _note_type ) +void TempoSyncKnobModel::setTempoSync( SyncMode _note_type ) { - setSyncMode( ( TempoSyncMode ) _note_type ); + setSyncMode( _note_type ); Engine::getSong()->setModified(); } @@ -74,34 +74,34 @@ void TempoSyncKnobModel::calculateTempoSyncTime( bpm_t _bpm ) { float conversionFactor = 1.0; - if( m_tempoSyncMode ) + if( m_tempoSyncMode != SyncMode::None ) { switch( m_tempoSyncMode ) { - case SyncCustom: + case SyncMode::Custom: conversionFactor = static_cast( m_custom.getDenominator() ) / static_cast( m_custom.getNumerator() ); break; - case SyncDoubleWholeNote: + case SyncMode::DoubleWholeNote: conversionFactor = 0.125; break; - case SyncWholeNote: + case SyncMode::WholeNote: conversionFactor = 0.25; break; - case SyncHalfNote: + case SyncMode::HalfNote: conversionFactor = 0.5; break; - case SyncQuarterNote: + case SyncMode::QuarterNote: conversionFactor = 1.0; break; - case SyncEighthNote: + case SyncMode::EighthNote: conversionFactor = 2.0; break; - case SyncSixteenthNote: + case SyncMode::SixteenthNote: conversionFactor = 4.0; break; - case SyncThirtysecondNote: + case SyncMode::ThirtysecondNote: conversionFactor = 8.0; break; default: ; @@ -117,6 +117,10 @@ void TempoSyncKnobModel::calculateTempoSyncTime( bpm_t _bpm ) emit syncModeChanged( m_tempoSyncMode ); m_tempoLastSyncMode = m_tempoSyncMode; } + else if (m_tempoSyncMode == SyncMode::Custom) + { + emit syncModeChanged(m_tempoSyncMode); + } } @@ -138,18 +142,18 @@ void TempoSyncKnobModel::loadSettings( const QDomElement & _this, { FloatModel::loadSettings( _this, _name ); m_custom.loadSettings( _this, _name ); - setSyncMode( ( TempoSyncMode ) _this.attribute( _name + "_syncmode" ).toInt() ); + setSyncMode( ( SyncMode ) _this.attribute( _name + "_syncmode" ).toInt() ); } -void TempoSyncKnobModel::setSyncMode( TempoSyncMode _new_mode ) +void TempoSyncKnobModel::setSyncMode( SyncMode _new_mode ) { if( m_tempoSyncMode != _new_mode ) { m_tempoSyncMode = _new_mode; - if( _new_mode == SyncCustom ) + if( _new_mode == SyncMode::Custom ) { connect( &m_custom, SIGNAL(dataChanged()), this, SLOT(updateCustom()), @@ -174,7 +178,7 @@ void TempoSyncKnobModel::setScale( float _new_scale ) void TempoSyncKnobModel::updateCustom() { - setSyncMode( SyncCustom ); + setSyncMode( SyncMode::Custom ); } diff --git a/src/core/TimePos.cpp b/src/core/TimePos.cpp index f3b09474d..86a65f103 100644 --- a/src/core/TimePos.cpp +++ b/src/core/TimePos.cpp @@ -194,7 +194,7 @@ tick_t TimePos::ticksPerBar( const TimeSig &sig ) int TimePos::stepsPerBar() { int steps = ticksPerBar() / DefaultBeatsPerBar; - return qMax( 1, steps ); + return std::max(1, steps); } diff --git a/src/core/ToolPlugin.cpp b/src/core/ToolPlugin.cpp index 137029137..dfcacc1bc 100644 --- a/src/core/ToolPlugin.cpp +++ b/src/core/ToolPlugin.cpp @@ -42,7 +42,7 @@ ToolPlugin * ToolPlugin::instantiate( const QString & _plugin_name, Model * _par { Plugin * p = Plugin::instantiate( _plugin_name, _parent, nullptr ); // check whether instantiated plugin is a tool - if( p->type() == Plugin::Tool ) + if( p->type() == Plugin::Type::Tool ) { // everything ok, so return pointer return dynamic_cast( p ); diff --git a/src/core/Track.cpp b/src/core/Track.cpp index 084f302f8..b034b95fb 100644 --- a/src/core/Track.cpp +++ b/src/core/Track.cpp @@ -56,7 +56,7 @@ namespace lmms * * \todo check the definitions of all the properties - are they OK? */ -Track::Track( TrackTypes type, TrackContainer * tc ) : +Track::Track( Type type, TrackContainer * tc ) : Model( tc ), /*!< The track Model */ m_trackContainer( tc ), /*!< The track container object */ m_type( type ), /*!< The track type */ @@ -84,9 +84,9 @@ Track::~Track() lock(); emit destroyedTrack(); - while( !m_clips.isEmpty() ) + while (!m_clips.empty()) { - delete m_clips.last(); + delete m_clips.back(); } m_trackContainer->removeTrack( this ); @@ -101,7 +101,7 @@ Track::~Track() * \param tt The type of track to create * \param tc The track container to attach to */ -Track * Track::create( TrackTypes tt, TrackContainer * tc ) +Track * Track::create( Type tt, TrackContainer * tc ) { Engine::audioEngine()->requestChangeInModel(); @@ -109,13 +109,13 @@ Track * Track::create( TrackTypes tt, TrackContainer * tc ) switch( tt ) { - case InstrumentTrack: t = new class InstrumentTrack( tc ); break; - case PatternTrack: t = new class PatternTrack( tc ); break; - case SampleTrack: t = new class SampleTrack( tc ); break; -// case EVENT_TRACK: -// case VIDEO_TRACK: - case AutomationTrack: t = new class AutomationTrack( tc ); break; - case HiddenAutomationTrack: + case Type::Instrument: t = new class InstrumentTrack( tc ); break; + case Type::Pattern: t = new class PatternTrack( tc ); break; + case Type::Sample: t = new class SampleTrack( tc ); break; +// case Type::Event: +// case Type::Video: + case Type::Automation: t = new class AutomationTrack( tc ); break; + case Type::HiddenAutomation: t = new class AutomationTrack( tc, true ); break; default: break; } @@ -145,7 +145,7 @@ Track * Track::create( const QDomElement & element, TrackContainer * tc ) Engine::audioEngine()->requestChangeInModel(); Track * t = create( - static_cast( element.attribute( "type" ).toInt() ), + static_cast( element.attribute( "type" ).toInt() ), tc ); if( t != nullptr ) { @@ -197,7 +197,7 @@ void Track::saveSettings( QDomDocument & doc, QDomElement & element ) { element.setTagName( "track" ); } - element.setAttribute( "type", type() ); + element.setAttribute( "type", static_cast(type()) ); element.setAttribute( "name", name() ); m_mutedModel.saveSettings( doc, element, "muted" ); m_soloModel.saveSettings( doc, element, "solo" ); @@ -249,7 +249,7 @@ void Track::saveSettings( QDomDocument & doc, QDomElement & element ) */ void Track::loadSettings( const QDomElement & element ) { - if( element.attribute( "type" ).toInt() != type() ) + if( static_cast(element.attribute( "type" ).toInt()) != type() ) { qWarning( "Current track-type does not match track-type of " "settings-node!\n" ); @@ -365,9 +365,9 @@ void Track::removeClip( Clip * clip ) /*! \brief Remove all Clips from this track */ void Track::deleteClips() { - while( ! m_clips.isEmpty() ) + while (!m_clips.empty()) { - delete m_clips.first(); + delete m_clips.front(); } } @@ -613,7 +613,7 @@ void Track::toggleSolo() { track->setMuted(false); } - else if (soloLegacyBehavior || track->type() != AutomationTrack) + else if (soloLegacyBehavior || track->type() != Type::Automation) { track->setMuted(true); } @@ -626,7 +626,7 @@ void Track::toggleSolo() { // Unless we are on the sololegacybehavior mode, only restores the // mute state if the track isn't an Automation Track - if (soloLegacyBehavior || track->type() != AutomationTrack) + if (soloLegacyBehavior || track->type() != Type::Automation) { track->setMuted(track->m_mutedBeforeSolo); } diff --git a/src/core/TrackContainer.cpp b/src/core/TrackContainer.cpp index 0347773ed..d4120e761 100644 --- a/src/core/TrackContainer.cpp +++ b/src/core/TrackContainer.cpp @@ -156,13 +156,13 @@ void TrackContainer::loadSettings( const QDomElement & _this ) -int TrackContainer::countTracks( Track::TrackTypes _tt ) const +int TrackContainer::countTracks( Track::Type _tt ) const { int cnt = 0; m_tracksMutex.lockForRead(); for (const auto& track : m_tracks) { - if (track->type() == _tt || _tt == Track::NumTrackTypes) + if (track->type() == _tt || _tt == Track::Type::Count) { ++cnt; } @@ -176,7 +176,7 @@ int TrackContainer::countTracks( Track::TrackTypes _tt ) const void TrackContainer::addTrack( Track * _track ) { - if( _track->type() != Track::HiddenAutomationTrack ) + if( _track->type() != Track::Type::HiddenAutomation ) { _track->lock(); m_tracksMutex.lockForWrite(); @@ -196,14 +196,14 @@ void TrackContainer::removeTrack( Track * _track ) // After checking that index != -1, we need to upgrade the lock to a write locker before changing m_tracks. // But since Qt offers no function to promote a read lock to a write lock, we must start with the write locker. QWriteLocker lockTracksAccess(&m_tracksMutex); - int index = m_tracks.indexOf( _track ); - if( index != -1 ) + auto it = std::find(m_tracks.begin(), m_tracks.end(), _track); + if (it != m_tracks.end()) { // If the track is solo, all other tracks are muted. Change this before removing the solo track: if (_track->isSolo()) { _track->setSolo(false); } - m_tracks.remove( index ); + m_tracks.erase(it); lockTracksAccess.unlock(); if( Engine::getSong() ) @@ -226,9 +226,9 @@ void TrackContainer::updateAfterTrackAdd() void TrackContainer::clearAllTracks() { //m_tracksMutex.lockForWrite(); - while( !m_tracks.isEmpty() ) + while (!m_tracks.empty()) { - delete m_tracks.first(); + delete m_tracks.front(); } //m_tracksMutex.unlock(); } @@ -240,7 +240,7 @@ bool TrackContainer::isEmpty() const { for (const auto& track : m_tracks) { - if (!track->getClips().isEmpty()) + if (!track->getClips().empty()) { return false; } @@ -268,14 +268,14 @@ AutomatedValueMap TrackContainer::automatedValuesFromTracks(const TrackList &tra switch(track->type()) { - case Track::AutomationTrack: - case Track::HiddenAutomationTrack: - case Track::PatternTrack: + case Track::Type::Automation: + case Track::Type::HiddenAutomation: + case Track::Type::Pattern: if (clipNum < 0) { track->getClipsInRange(clips, 0, time); } else { Q_ASSERT(track->numOfClips() > clipNum); - clips << track->getClip(clipNum); + clips.push_back(track->getClip(clipNum)); } default: break; @@ -299,7 +299,7 @@ AutomatedValueMap TrackContainer::automatedValuesFromTracks(const TrackList &tra } TimePos relTime = time - p->startPosition(); if (! p->getAutoResize()) { - relTime = qMin(relTime, p->length()); + relTime = std::min(relTime, p->length()); } float value = p->valueAt(relTime); diff --git a/src/core/UpgradeExtendedNoteRange.cpp b/src/core/UpgradeExtendedNoteRange.cpp new file mode 100644 index 000000000..6ed98e63e --- /dev/null +++ b/src/core/UpgradeExtendedNoteRange.cpp @@ -0,0 +1,434 @@ +/* + * UpgradeExtendedNoteRange.cpp - Upgrades the extended note range + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "UpgradeExtendedNoteRange.h" + +#include "Track.h" + +#include + +#include +#include + + +namespace lmms +{ + +/** + * @brief Used by the helper function that analyzes automation patterns. + */ +struct PatternAnalysisResult +{ + PatternAnalysisResult(bool hasBaseNoteAutomations, bool hasNonBaseNoteAutomations) + { + this->hasBaseNoteAutomations = hasBaseNoteAutomations; + this->hasNonBaseNoteAutomations = hasNonBaseNoteAutomations; + } + bool hasBaseNoteAutomations; + bool hasNonBaseNoteAutomations; +}; + +/** + * @brief Helper function that checks for an automation pattern if it contains automation for + * targets that are base notes and/or other targets. + * @param automationPattern The automation pattern to be checked. + * @param automatedBaseNoteIds A set of id of automated base notes that are used in the check. + * @return A struct that contains the results. + */ +static PatternAnalysisResult analyzeAutomationPattern(QDomElement const & automationPattern, std::set const & automatedBaseNoteIds) +{ + bool hasBaseNoteAutomations = false; + bool hasNonBaseNoteAutomations = false; + + // Iterate the objects. These contain the ids of the automated objects. + QDomElement object = automationPattern.firstChildElement("object"); + while (!object.isNull()) + { + unsigned int const id = object.attribute("id").toUInt(); + + // Check if the automated object is a base note. + if (automatedBaseNoteIds.find(id) != automatedBaseNoteIds.end()) + { + hasBaseNoteAutomations = true; + } + else + { + hasNonBaseNoteAutomations = true; + } + + object = object.nextSiblingElement("object"); + } + + return PatternAnalysisResult(hasBaseNoteAutomations, hasNonBaseNoteAutomations); +} + +static void fixNotePatterns(QDomNodeList & patterns) +{ + for (int i = 0; i < patterns.size(); ++i) + { + QDomNodeList notes = patterns.item(i).toElement().elementsByTagName("note"); + for (int j = 0; j < notes.size(); ++j) + { + QDomElement note = notes.item(j).toElement(); + if (note.hasAttribute("key")) + { + int const currentKey = note.attribute("key").toInt(); + note.setAttribute("key", currentKey + 12); + } + } + } +} + +static void fixInstrumentBaseNoteAndCollectIds(QDomElement & instrument, std::set & automatedBaseNoteIds) +{ + // Raise the base note of every instrument by 12 to compensate for the change + // of A4 key code from 57 to 69. This ensures that notes are labeled correctly. + QDomElement instrumentParent = instrument.parentNode().toElement(); + + // Correct the base note of the instrument. Base notes which are automated are + // stored as elements. Non-automated base notes are stored as attributes. + if (instrumentParent.hasAttribute("basenote")) + { + // TODO Base notes can have float values in the save file! This might need to be changed! + int const currentBaseNote = instrumentParent.attribute("basenote").toInt(); + instrumentParent.setAttribute("basenote", currentBaseNote + 12); + } + else + { + // Check if the instrument track has an automated base note. + // Correct the value of the base note and collect their ids while doing so. + // The ids are used later to find the automations that automate these corrected base + // notes so that we can correct the automation values as well. + QDomNodeList baseNotes = instrumentParent.elementsByTagName("basenote"); + for (int j = 0; j < baseNotes.size(); ++j) + { + QDomElement baseNote = baseNotes.item(j).toElement(); + if (!baseNote.isNull()) + { + if (baseNote.hasAttribute("value")) + { + // Base notes can have float values in the save file, e.g. if the file + // is saved after a linear automation has run on the base note. Therefore + // it is fixed here as a float even if the nominal values of base notes + // are integers. + float const value = baseNote.attribute("value").toFloat(); + baseNote.setAttribute("value", value + 12); + } + + // The ids of base notes are of type jo_id_t which are in fact uint32_t. + // So let's just use these here to save some casting. + unsigned int const id = baseNote.attribute("id").toUInt(); + automatedBaseNoteIds.insert(id); + } + } + } +} + +/** + * @brief Helper method that fixes the values and out values for an automation pattern. + * @param automationPattern The automation pattern to be fixed. + */ +static void fixAutomationPattern(QDomElement & automationPattern) +{ + QDomElement time = automationPattern.firstChildElement("time"); + while (!time.isNull()) + { + // Automation patterns can automate base notes as floats + // so we read and correct them as floats here. + float const value = time.attribute("value").toFloat(); + time.setAttribute("value", value + 12.); + + // The method "upgrade_automationNodes" adds some attributes + // with the name "outValue". We have to correct these as well. + float const outValue = time.attribute("outValue").toFloat(); + time.setAttribute("outValue", outValue + 12.); + + time = time.nextSiblingElement("time"); + }; +} + +static bool affected(QDomElement & instrument) +{ + assert(instrument.hasAttribute("name")); + QString const name = instrument.attribute("name"); + + return name == "zynaddsubfx" || + name == "vestige" || name == "lv2instrument" || + name == "carlapatchbay" || name == "carlarack"; +} + +static void fixTrack(QDomElement & track, std::set & automatedBaseNoteIds) +{ + if (!track.hasAttribute("type")) + { + return; + } + + Track::Type const trackType = static_cast(track.attribute("type").toInt()); + + // BB tracks need special handling because they contain a track container of their own + if (trackType == Track::Type::Pattern) + { + // Assuming that a BB track cannot contain another BB track here... + QDomNodeList subTracks = track.elementsByTagName("track"); + for (int i = 0; i < subTracks.size(); ++i) + { + QDomElement subTrack = subTracks.item(i).toElement(); + assert (static_cast(subTrack.attribute("type").toInt()) != Track::Type::Pattern); + fixTrack(subTrack, automatedBaseNoteIds); + } + } + else + { + QDomNodeList instruments = track.elementsByTagName("instrument"); + + for (int i = 0; i < instruments.size(); ++i) + { + QDomElement instrument = instruments.item(i).toElement(); + + fixInstrumentBaseNoteAndCollectIds(instrument, automatedBaseNoteIds); + + // Raise the pitch of all notes in patterns assigned to instruments not affected + // by #1857 by an octave. This negates the base note change for normal instruments, + // but leaves the MIDI-based instruments sounding an octave lower, preserving their + // pitch in existing projects. + if (!affected(instrument)) + { + QDomNodeList patterns = track.elementsByTagName("pattern"); + fixNotePatterns(patterns); + } + } + } +} + +static void fixAutomationTracks(QDomElement & song, std::set const & automatedBaseNoteIds) +{ + // Now fix all the automation tracks. + QDomNodeList tracks = song.elementsByTagName("track"); + + // We have to collect the tracks that we need to duplicate and cannot do this in-place + // because if we did the iteration might never stop. + std::vector tracksToDuplicate; + tracksToDuplicate.reserve(tracks.size()); + + // Iterate the tracks again. This time work on all automation tracks. + for (int i = 0; i < tracks.size(); ++i) + { + QDomElement currentTrack = tracks.item(i).toElement(); + if (static_cast(currentTrack.attribute("type").toInt()) != Track::Type::Automation) + { + continue; + } + + // Check each track for the types of automations it contains in its patterns. + bool containsPatternsWithBaseNoteTargets = false; + bool containsPatternsWithNonBaseNoteTargets = false; + + QDomElement automationPattern = currentTrack.firstChildElement("automationpattern"); + while (!automationPattern.isNull()) + { + auto const analysis = analyzeAutomationPattern(automationPattern, automatedBaseNoteIds); + containsPatternsWithBaseNoteTargets |= analysis.hasBaseNoteAutomations; + containsPatternsWithNonBaseNoteTargets |= analysis.hasNonBaseNoteAutomations; + + automationPattern = automationPattern.nextSiblingElement("automationpattern"); + } + + if (!containsPatternsWithBaseNoteTargets) + { + // No base notes are automated by this automation track so we have nothing to do + continue; + } + else + { + if (!containsPatternsWithNonBaseNoteTargets) + { + // Only base note targets. This means we can simply keep the track and fix it. + automationPattern = currentTrack.firstChildElement("automationpattern"); + while (!automationPattern.isNull()) + { + fixAutomationPattern(automationPattern); + + automationPattern = automationPattern.nextSiblingElement("automationpattern"); + } + } + else + { + // The automation track has automations for base notes and other targets in its patterns. + // We will later need to duplicate/split the track. + tracksToDuplicate.push_back(currentTrack); + } + } + } + + // Now fix the tracks that need duplication/splitting + for (QDomElement & track : tracksToDuplicate) + { + // First clone the original track + QDomNode cloneOfTrack = track.cloneNode(); + + // Now that we have the original and the clone we can manipulate both of them. + // The original track will keep only patterns without base note automations. + // Note: for the original track these might also be automation patterns without + // any targets. We will keep these because they might have been saved by the users + // like this. + QDomElement automationPattern = track.firstChildElement("automationpattern"); + while (!automationPattern.isNull()) + { + auto const analysis = analyzeAutomationPattern(automationPattern, automatedBaseNoteIds); + if (!analysis.hasBaseNoteAutomations) + { + // This pattern has no base note automations. Leave it alone. + automationPattern = automationPattern.nextSiblingElement("automationpattern"); + } + else if (!analysis.hasNonBaseNoteAutomations) + { + // The pattern only has base note automations. Remove it completely as it would become empty. + QDomElement patternToRemove = automationPattern; + automationPattern = automationPattern.nextSiblingElement("automationpattern"); + track.removeChild(patternToRemove); + } + else + { + // The pattern itself is mixed. Remove the base note objects. + QDomElement object = automationPattern.firstChildElement("object"); + while (!object.isNull()) + { + unsigned int const id = object.attribute("id").toUInt(); + + if (automatedBaseNoteIds.find(id) != automatedBaseNoteIds.end()) + { + QDomElement objectToRemove = object; + object = object.nextSiblingElement("object"); + automationPattern.removeChild(objectToRemove); + } + else + { + object = object.nextSiblingElement("object"); + } + } + + automationPattern = automationPattern.nextSiblingElement("automationpattern"); + } + } + + // The clone will only keep non-empty patterns with base note automations + // and the values of the patterns will be corrected. + automationPattern = cloneOfTrack.firstChildElement("automationpattern"); + while (!automationPattern.isNull()) + { + auto const analysis = analyzeAutomationPattern(automationPattern, automatedBaseNoteIds); + if (analysis.hasBaseNoteAutomations) + { + // This pattern has base note automations. Remove all other ones and fix the pattern. + QDomElement object = automationPattern.firstChildElement("object"); + while (!object.isNull()) + { + unsigned int const id = object.attribute("id").toUInt(); + + if (automatedBaseNoteIds.find(id) == automatedBaseNoteIds.end()) + { + QDomElement objectToRemove = object; + object = object.nextSiblingElement("object"); + automationPattern.removeChild(objectToRemove); + } + else + { + object = object.nextSiblingElement("object"); + } + } + + fixAutomationPattern(automationPattern); + + automationPattern = automationPattern.nextSiblingElement("automationpattern"); + } + else + { + // The pattern has no base note automations. Remove it completely. + QDomElement patternToRemove = automationPattern; + automationPattern = automationPattern.nextSiblingElement("automationpattern"); + cloneOfTrack.removeChild(patternToRemove); + } + } + track.parentNode().appendChild(cloneOfTrack); + } +} + + +UpgradeExtendedNoteRange::UpgradeExtendedNoteRange(QDomElement & domElement) : + m_domElement(domElement) +{ +} + +void UpgradeExtendedNoteRange::upgrade() +{ + QDomElement song = m_domElement.firstChildElement("song"); + while (!song.isNull()) + { + // This set will later contain all ids of automated base notes. They are + // used to find out which automation patterns must to be corrected, i.e. to + // check if an automation pattern has one or more base notes as its target. + std::set automatedBaseNoteIds; + + QDomElement trackContainer = song.firstChildElement("trackcontainer"); + while (!trackContainer.isNull()) + { + QDomElement track = trackContainer.firstChildElement("track"); + while (!track.isNull()) + { + fixTrack(track, automatedBaseNoteIds); + + track = track.nextSiblingElement("track"); + } + + trackContainer = trackContainer.nextSiblingElement("trackcontainer"); + } + + fixAutomationTracks(song, automatedBaseNoteIds); + + song = song.nextSiblingElement("song"); + }; + + if (m_domElement.elementsByTagName("song").item(0).isNull()) + { + // Dealing with a preset, not a song + QDomNodeList presets = m_domElement.elementsByTagName("instrumenttrack"); + if (presets.item(0).isNull()) { return; } + QDomElement preset = presets.item(0).toElement(); + // Common correction for all instrument presets (make base notes match the new MIDI range). + // NOTE: Many older presets do not have any basenote defined, assume they were "made for 57". + // (Specifying a default like this also happens to fix a FileBrowser bug where previews of presets + // with undefined basenote always play with the basenote inherited from previously played preview.) + int oldBase = preset.attribute("basenote", "57").toInt(); + preset.setAttribute("basenote", oldBase + 12); + // Extra correction for Zyn, VeSTige, LV2 and Carla (to preserve the original buggy behavior). + QDomNodeList instruments = presets.item(0).toElement().elementsByTagName("instrument"); + if (instruments.isEmpty()) { return; } + QDomElement instrument = instruments.item(0).toElement(); + if (affected(instrument)) + { + preset.setAttribute("basenote", preset.attribute("basenote").toInt() + 12); + } + } +} + +} // namespace lmms diff --git a/src/core/UpgradeExtendedNoteRange.h b/src/core/UpgradeExtendedNoteRange.h new file mode 100644 index 000000000..ae444e82a --- /dev/null +++ b/src/core/UpgradeExtendedNoteRange.h @@ -0,0 +1,47 @@ +/* + * UpgradeExtendedNoteRange.h - Upgrades the extended note range + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#pragma once + +#ifndef LMMS_UPGRADEEXTENDEDNOTERANGE_H +#define LMMS_UPGRADEEXTENDEDNOTERANGE_H + + +class QDomElement; + +namespace lmms +{ + +class UpgradeExtendedNoteRange +{ +public: + UpgradeExtendedNoteRange(QDomElement & domElement); + + void upgrade(); + +private: + QDomElement & m_domElement; +}; + +} // namespace lmms + +#endif // LMMS_UPGRADEEXTENDEDNOTERANGE_H diff --git a/src/core/audio/AudioAlsa.cpp b/src/core/audio/AudioAlsa.cpp index 8b3eb32be..6e17ad0fe 100644 --- a/src/core/audio/AudioAlsa.cpp +++ b/src/core/audio/AudioAlsa.cpp @@ -36,10 +36,10 @@ namespace lmms { AudioAlsa::AudioAlsa( bool & _success_ful, AudioEngine* _audioEngine ) : - AudioDevice( qBound( + AudioDevice(std::clamp( + ConfigManager::inst()->value("audioalsa", "channels").toInt(), DEFAULT_CHANNELS, - ConfigManager::inst()->value( "audioalsa", "channels" ).toInt(), - SURROUND_CHANNELS ), _audioEngine ), + SURROUND_CHANNELS), _audioEngine), m_handle( nullptr ), m_hwParams( nullptr ), m_swParams( nullptr ), @@ -87,7 +87,7 @@ AudioAlsa::AudioAlsa( bool & _success_ful, AudioEngine* _audioEngine ) : int count = snd_pcm_poll_descriptors_count( m_handle ); ufds = new pollfd[count]; snd_pcm_poll_descriptors( m_handle, ufds, count ); - for( int i = 0; i < qMax( 3, count ); ++i ) + for (int i = 0; i < std::max(3, count); ++i) { const int fd = ( i >= count ) ? ufds[0].fd+i : ufds[i].fd; int oldflags = fcntl( fd, F_GETFD, 0 ); @@ -328,7 +328,7 @@ void AudioAlsa::run() outbuf, m_convertEndian ); } - int min_len = qMin( len, outbuf_size - outbuf_pos ); + int min_len = std::min(len, outbuf_size - outbuf_pos); memcpy( ptr, outbuf + outbuf_pos, min_len * sizeof( int_sample_t ) ); ptr += min_len; diff --git a/src/core/audio/AudioFileFlac.cpp b/src/core/audio/AudioFileFlac.cpp index 6af063683..af71003d1 100644 --- a/src/core/audio/AudioFileFlac.cpp +++ b/src/core/audio/AudioFileFlac.cpp @@ -58,8 +58,8 @@ bool AudioFileFlac::startEncoding() switch (getOutputSettings().getBitDepth()) { - case OutputSettings::Depth_24Bit: - case OutputSettings::Depth_32Bit: + case OutputSettings::BitDepth::Depth24Bit: + case OutputSettings::BitDepth::Depth32Bit: // FLAC does not support 32bit sampling, so take it as 24. m_sfinfo.format |= SF_FORMAT_PCM_24; break; @@ -94,7 +94,7 @@ void AudioFileFlac::writeBuffer(surroundSampleFrame const* _ab, fpp_t const fram OutputSettings::BitDepth depth = getOutputSettings().getBitDepth(); float clipvalue = std::nextafterf( -1.0f, 0.0f ); - if (depth == OutputSettings::Depth_24Bit || depth == OutputSettings::Depth_32Bit) // Float encoding + if (depth == OutputSettings::BitDepth::Depth24Bit || depth == OutputSettings::BitDepth::Depth32Bit) // Float encoding { auto buf = std::vector(frames * channels()); for(fpp_t frame = 0; frame < frames; ++frame) @@ -104,7 +104,7 @@ void AudioFileFlac::writeBuffer(surroundSampleFrame const* _ab, fpp_t const fram // Clip the negative side to just above -1.0 in order to prevent it from changing sign // Upstream issue: https://github.com/erikd/libsndfile/issues/309 // When this commit is reverted libsndfile-1.0.29 must be made a requirement for FLAC - buf[frame*channels() + channel] = qMax( clipvalue, _ab[frame][channel] * master_gain ); + buf[frame*channels() + channel] = std::max(clipvalue, _ab[frame][channel] * master_gain); } } sf_writef_float(m_sf, static_cast(buf.data()), frames); diff --git a/src/core/audio/AudioFileMP3.cpp b/src/core/audio/AudioFileMP3.cpp index 4930e9ad6..ef0677152 100644 --- a/src/core/audio/AudioFileMP3.cpp +++ b/src/core/audio/AudioFileMP3.cpp @@ -94,11 +94,11 @@ MPEG_mode mapToMPEG_mode(OutputSettings::StereoMode stereoMode) { switch (stereoMode) { - case OutputSettings::StereoMode_Stereo: + case OutputSettings::StereoMode::Stereo: return STEREO; - case OutputSettings::StereoMode_JointStereo: + case OutputSettings::StereoMode::JointStereo: return JOINT_STEREO; - case OutputSettings::StereoMode_Mono: + case OutputSettings::StereoMode::Mono: return MONO; default: return NOT_SET; diff --git a/src/core/audio/AudioFileWave.cpp b/src/core/audio/AudioFileWave.cpp index b78b04403..9c51437ff 100644 --- a/src/core/audio/AudioFileWave.cpp +++ b/src/core/audio/AudioFileWave.cpp @@ -64,13 +64,13 @@ bool AudioFileWave::startEncoding() switch( getOutputSettings().getBitDepth() ) { - case OutputSettings::Depth_32Bit: + case OutputSettings::BitDepth::Depth32Bit: m_si.format |= SF_FORMAT_FLOAT; break; - case OutputSettings::Depth_24Bit: + case OutputSettings::BitDepth::Depth24Bit: m_si.format |= SF_FORMAT_PCM_24; break; - case OutputSettings::Depth_16Bit: + case OutputSettings::BitDepth::Depth16Bit: default: m_si.format |= SF_FORMAT_PCM_16; break; @@ -102,7 +102,7 @@ void AudioFileWave::writeBuffer( const surroundSampleFrame * _ab, { OutputSettings::BitDepth bitDepth = getOutputSettings().getBitDepth(); - if( bitDepth == OutputSettings::Depth_32Bit || bitDepth == OutputSettings::Depth_24Bit ) + if( bitDepth == OutputSettings::BitDepth::Depth32Bit || bitDepth == OutputSettings::BitDepth::Depth24Bit ) { auto buf = new float[_frames * channels()]; for( fpp_t frame = 0; frame < _frames; ++frame ) diff --git a/src/core/audio/AudioJack.cpp b/src/core/audio/AudioJack.cpp index 222ebf10d..7371c7bfb 100644 --- a/src/core/audio/AudioJack.cpp +++ b/src/core/audio/AudioJack.cpp @@ -44,10 +44,10 @@ namespace lmms { AudioJack::AudioJack( bool & _success_ful, AudioEngine* _audioEngine ) : - AudioDevice( qBound( + AudioDevice(std::clamp( + ConfigManager::inst()->value("audiojack", "channels").toInt(), DEFAULT_CHANNELS, - ConfigManager::inst()->value( "audiojack", "channels" ).toInt(), - SURROUND_CHANNELS ), _audioEngine ), + SURROUND_CHANNELS), _audioEngine), m_client( nullptr ), m_active( false ), m_midiClient( nullptr ), @@ -364,7 +364,7 @@ int AudioJack::processCallback( jack_nframes_t _nframes, void * _udata ) } #ifdef AUDIO_PORT_SUPPORT - const int frames = qMin( _nframes, audioEngine()->framesPerPeriod() ); + const int frames = std::min(_nframes, audioEngine()->framesPerPeriod()); for( JackPortMap::iterator it = m_portMap.begin(); it != m_portMap.end(); ++it ) { @@ -389,10 +389,10 @@ int AudioJack::processCallback( jack_nframes_t _nframes, void * _udata ) jack_nframes_t done = 0; while( done < _nframes && m_stopped == false ) { - jack_nframes_t todo = qMin( + jack_nframes_t todo = std::min( _nframes, m_framesToDoInCurBuf - - m_framesDoneInCurBuf ); + m_framesDoneInCurBuf); const float gain = audioEngine()->masterGain(); for( int c = 0; c < channels(); ++c ) { diff --git a/src/core/audio/AudioOss.cpp b/src/core/audio/AudioOss.cpp index 5166bad79..73969533f 100644 --- a/src/core/audio/AudioOss.cpp +++ b/src/core/audio/AudioOss.cpp @@ -70,10 +70,10 @@ static const QString PATH_DEV_DSP = AudioOss::AudioOss( bool & _success_ful, AudioEngine* _audioEngine ) : - AudioDevice( qBound( + AudioDevice(std::clamp( + ConfigManager::inst()->value("audiooss", "channels").toInt(), DEFAULT_CHANNELS, - ConfigManager::inst()->value( "audiooss", "channels" ).toInt(), - SURROUND_CHANNELS ), _audioEngine ), + SURROUND_CHANNELS), _audioEngine), m_convertEndian( false ) { _success_ful = false; diff --git a/src/core/audio/AudioPort.cpp b/src/core/audio/AudioPort.cpp index 4bbf509d8..7bae3db1c 100644 --- a/src/core/audio/AudioPort.cpp +++ b/src/core/audio/AudioPort.cpp @@ -121,7 +121,7 @@ void AudioPort::doProcessing() if( ph->buffer() ) { if( ph->usesBuffer() - && ( ph->type() == PlayHandle::TypeNotePlayHandle + && ( ph->type() == PlayHandle::Type::NotePlayHandle || !MixHelpers::isSilent( ph->buffer(), fpp ) ) ) { m_bufferUsage = true; diff --git a/src/core/audio/AudioPortAudio.cpp b/src/core/audio/AudioPortAudio.cpp index 0f5a4122f..c06eee3d4 100644 --- a/src/core/audio/AudioPortAudio.cpp +++ b/src/core/audio/AudioPortAudio.cpp @@ -62,10 +62,10 @@ namespace lmms AudioPortAudio::AudioPortAudio( bool & _success_ful, AudioEngine * _audioEngine ) : - AudioDevice( qBound( + AudioDevice(std::clamp( + ConfigManager::inst()->value("audioportaudio", "channels").toInt(), DEFAULT_CHANNELS, - ConfigManager::inst()->value( "audioportaudio", "channels" ).toInt(), - SURROUND_CHANNELS ), _audioEngine ), + SURROUND_CHANNELS), _audioEngine), m_paStream( nullptr ), m_wasPAInitError( false ), m_outBuf( new surroundSampleFrame[audioEngine()->framesPerPeriod()] ), @@ -295,8 +295,8 @@ int AudioPortAudio::process_callback( } m_outBufSize = frames; } - const int min_len = qMin( (int)_framesPerBuffer, - m_outBufSize - m_outBufPos ); + const int min_len = std::min(static_cast(_framesPerBuffer), + m_outBufSize - m_outBufPos); float master_gain = audioEngine()->masterGain(); @@ -496,12 +496,12 @@ void AudioPortAudio::setupWidget::show() const QString& device = ConfigManager::inst()->value( "audioportaudio", "device" ); - int i = qMax( 0, m_setupUtil.m_backendModel.findText( backend ) ); + int i = std::max(0, m_setupUtil.m_backendModel.findText(backend)); m_setupUtil.m_backendModel.setValue( i ); m_setupUtil.updateDevices(); - i = qMax( 0, m_setupUtil.m_deviceModel.findText( device ) ); + i = std::max(0, m_setupUtil.m_deviceModel.findText(device)); m_setupUtil.m_deviceModel.setValue( i ); } diff --git a/src/core/audio/AudioPulseAudio.cpp b/src/core/audio/AudioPulseAudio.cpp index bac997075..26a5a02e2 100644 --- a/src/core/audio/AudioPulseAudio.cpp +++ b/src/core/audio/AudioPulseAudio.cpp @@ -47,10 +47,10 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) AudioPulseAudio::AudioPulseAudio( bool & _success_ful, AudioEngine* _audioEngine ) : - AudioDevice( qBound( + AudioDevice(std::clamp( + ConfigManager::inst()->value("audiopa", "channels").toInt(), DEFAULT_CHANNELS, - ConfigManager::inst()->value( "audiopa", "channels" ).toInt(), - SURROUND_CHANNELS ), _audioEngine ), + SURROUND_CHANNELS), _audioEngine), m_s( nullptr ), m_quit( false ), m_convertEndian( false ) diff --git a/src/core/audio/AudioSdl.cpp b/src/core/audio/AudioSdl.cpp index e73ccadc1..c5ffa64a9 100644 --- a/src/core/audio/AudioSdl.cpp +++ b/src/core/audio/AudioSdl.cpp @@ -70,7 +70,7 @@ AudioSdl::AudioSdl( bool & _success_ful, AudioEngine* _audioEngine ) : // to convert the buffers #endif m_audioHandle.channels = channels(); - m_audioHandle.samples = qMax( 1024, audioEngine()->framesPerPeriod()*2 ); + m_audioHandle.samples = std::max(1024, audioEngine()->framesPerPeriod() * 2); m_audioHandle.callback = sdlAudioCallback; m_audioHandle.userdata = this; @@ -257,9 +257,9 @@ void AudioSdl::sdlAudioCallback( Uint8 * _buf, int _len ) m_currentBufferFramesCount = frames; } - const uint min_frames_count = qMin( _len/sizeof(sampleFrame), + const uint min_frames_count = std::min(_len/sizeof(sampleFrame), m_currentBufferFramesCount - - m_currentBufferFramePos ); + - m_currentBufferFramePos); const float gain = audioEngine()->masterGain(); for (uint f = 0; f < min_frames_count; f++) @@ -296,8 +296,8 @@ void AudioSdl::sdlAudioCallback( Uint8 * _buf, int _len ) (int_sample_t *)m_convertedBuf, m_outConvertEndian ); } - const int min_len = qMin( _len, m_convertedBufSize - - m_convertedBufPos ); + const int min_len = std::min(_len, m_convertedBufSize + - m_convertedBufPos); memcpy( _buf, m_convertedBuf + m_convertedBufPos, min_len ); _buf += min_len; _len -= min_len; diff --git a/src/core/audio/AudioSndio.cpp b/src/core/audio/AudioSndio.cpp index a8ea34ce1..0e46d08f6 100644 --- a/src/core/audio/AudioSndio.cpp +++ b/src/core/audio/AudioSndio.cpp @@ -44,10 +44,10 @@ namespace lmms { AudioSndio::AudioSndio(bool & _success_ful, AudioEngine * _audioEngine) : - AudioDevice( qBound( + AudioDevice(std::clamp( + ConfigManager::inst()->value("audiosndio", "channels").toInt(), DEFAULT_CHANNELS, - ConfigManager::inst()->value( "audiosndio", "channels" ).toInt(), - SURROUND_CHANNELS ), _audioEngine ), + SURROUND_CHANNELS), _audioEngine), m_convertEndian ( false ) { _success_ful = false; diff --git a/src/core/audio/AudioSoundIo.cpp b/src/core/audio/AudioSoundIo.cpp index 633808204..556909a84 100644 --- a/src/core/audio/AudioSoundIo.cpp +++ b/src/core/audio/AudioSoundIo.cpp @@ -40,10 +40,10 @@ namespace lmms { AudioSoundIo::AudioSoundIo( bool & outSuccessful, AudioEngine * _audioEngine ) : - AudioDevice( qBound( + AudioDevice(std::clamp( + ConfigManager::inst()->value("audiosoundio", "channels").toInt(), DEFAULT_CHANNELS, - ConfigManager::inst()->value( "audiosoundio", "channels" ).toInt(), - SURROUND_CHANNELS ), _audioEngine ) + SURROUND_CHANNELS), _audioEngine) { outSuccessful = false; m_soundio = nullptr; diff --git a/src/core/fft_helpers.cpp b/src/core/fft_helpers.cpp index 63088f655..35906e8d3 100644 --- a/src/core/fft_helpers.cpp +++ b/src/core/fft_helpers.cpp @@ -102,7 +102,7 @@ int notEmpty(const std::vector &spectrum) * * return -1 on error */ -int precomputeWindow(float *window, unsigned int length, FFT_WINDOWS type, bool normalized) +int precomputeWindow(float *window, unsigned int length, FFTWindow type, bool normalized) { if (window == nullptr) {return -1;} @@ -117,23 +117,23 @@ int precomputeWindow(float *window, unsigned int length, FFT_WINDOWS type, bool switch (type) { default: - case RECTANGULAR: + case FFTWindow::Rectangular: for (unsigned int i = 0; i < length; i++) {window[i] = 1.0;} gain = 1; return 0; - case BLACKMAN_HARRIS: + case FFTWindow::BlackmanHarris: a0 = 0.35875; a1 = 0.48829; a2 = 0.14128; a3 = 0.01168; break; - case HAMMING: + case FFTWindow::Hamming: a0 = 0.54; a1 = 1.0 - a0; a2 = 0; a3 = 0; break; - case HANNING: + case FFTWindow::Hanning: a0 = 0.5; a1 = 1.0 - a0; a2 = 0; diff --git a/src/core/lv2/Lv2ControlBase.cpp b/src/core/lv2/Lv2ControlBase.cpp index 3d21474b0..64cdc51fd 100644 --- a/src/core/lv2/Lv2ControlBase.cpp +++ b/src/core/lv2/Lv2ControlBase.cpp @@ -39,7 +39,7 @@ namespace lmms { -Plugin::PluginTypes Lv2ControlBase::check(const LilvPlugin *plugin, +Plugin::Type Lv2ControlBase::check(const LilvPlugin *plugin, std::vector &issues) { // for some reason, all checks can be done by one processor... diff --git a/src/core/lv2/Lv2Manager.cpp b/src/core/lv2/Lv2Manager.cpp index cc90f5e05..9c62703e0 100644 --- a/src/core/lv2/Lv2Manager.cpp +++ b/src/core/lv2/Lv2Manager.cpp @@ -217,7 +217,7 @@ void Lv2Manager::initPlugins() const LilvPlugin* curPlug = lilv_plugins_get(plugins, itr); std::vector issues; - Plugin::PluginTypes type = Lv2ControlBase::check(curPlug, issues); + Plugin::Type type = Lv2ControlBase::check(curPlug, issues); std::sort(issues.begin(), issues.end()); auto last = std::unique(issues.begin(), issues.end()); issues.erase(last, issues.end()); @@ -240,7 +240,7 @@ void Lv2Manager::initPlugins() { if(std::any_of(issues.begin(), issues.end(), [](const PluginIssue& iss) { - return iss.type() == PluginIssueType::blacklisted; })) + return iss.type() == PluginIssueType::Blacklisted; })) { ++blacklisted; } diff --git a/src/core/lv2/Lv2Ports.cpp b/src/core/lv2/Lv2Ports.cpp index 1ce1d6956..a4625936e 100644 --- a/src/core/lv2/Lv2Ports.cpp +++ b/src/core/lv2/Lv2Ports.cpp @@ -114,19 +114,19 @@ std::vector Meta::get(const LilvPlugin *plugin, m_optional = hasProperty(LV2_CORE__connectionOptional); - m_vis = hasProperty(LV2_CORE__integer) - ? Vis::Integer // WARNING: this may still be changed below + m_vis = hasProperty(LV2_CORE__toggled) + ? Vis::Toggled : hasProperty(LV2_CORE__enumeration) ? Vis::Enumeration - : hasProperty(LV2_CORE__toggled) - ? Vis::Toggled + : hasProperty(LV2_CORE__integer) + ? Vis::Integer // WARNING: this may still be changed below : Vis::Generic; if (isA(LV2_CORE__InputPort)) { m_flow = Flow::Input; } else if (isA(LV2_CORE__OutputPort)) { m_flow = Flow::Output; } else { m_flow = Flow::Unknown; - issue(unknownPortFlow, portName); + issue(PluginIssueType::UnknownPortFlow, portName); } m_def = .0f; @@ -145,7 +145,7 @@ std::vector Meta::get(const LilvPlugin *plugin, if (isA(LV2_CORE__CVPort)) { // currently not supported, but we can still check the metadata - issue(badPortType, "cvPort"); + issue(PluginIssueType::BadPortType, "cvPort"); } m_type = isA(LV2_CORE__CVPort) ? Type::Cv : Type::Control; @@ -172,21 +172,21 @@ std::vector Meta::get(const LilvPlugin *plugin, } }; - takeRangeValue(def.get(), m_def, portHasNoDef); + takeRangeValue(def.get(), m_def, PluginIssueType::PortHasNoDef); if (isToggle) { m_min = .0f; m_max = 1.f; if(def.get() && m_def != m_min && m_def != m_max) { - issue(defaultValueNotInRange, portName); + issue(PluginIssueType::DefaultValueNotInRange, portName); } } else { // take min/max - takeRangeValue(min.get(), m_min, portHasNoMin); - takeRangeValue(max.get(), m_max, portHasNoMax); + takeRangeValue(min.get(), m_min, PluginIssueType::PortHasNoMin); + takeRangeValue(max.get(), m_max, PluginIssueType::PortHasNoMax); if(m_type == Type::Cv) { // no range is allowed and bashed to [-1,+1], @@ -196,10 +196,10 @@ std::vector Meta::get(const LilvPlugin *plugin, m_min = -1.f; m_max = +1.f; } - else if(!m_min_set()) { issue(portHasNoMin, portName); } - else if(!m_max_set()) { issue(portHasNoMax, portName); } + else if(!m_min_set()) { issue(PluginIssueType::PortHasNoMin, portName); } + else if(!m_max_set()) { issue(PluginIssueType::PortHasNoMax, portName); } } - if(m_min > m_max) { issue(minGreaterMax, portName); } + if(m_min > m_max) { issue(PluginIssueType::MinGreaterMax, portName); } // sampleRate if (hasProperty(LV2_CORE__sampleRate)) { m_sampleRate = true; } @@ -207,7 +207,7 @@ std::vector Meta::get(const LilvPlugin *plugin, // default value if (def.get()) { - if (m_def < m_min) { issue(defaultValueNotInRange, portName); } + if (m_def < m_min) { issue(PluginIssueType::DefaultValueNotInRange, portName); } else if (m_def > m_max) { if(m_sampleRate) @@ -215,7 +215,7 @@ std::vector Meta::get(const LilvPlugin *plugin, // multiplying with sample rate will hopefully lead us // to a good default value } - else { issue(defaultValueNotInRange, portName); } + else { issue(PluginIssueType::DefaultValueNotInRange, portName); } } } @@ -254,7 +254,7 @@ std::vector Meta::get(const LilvPlugin *plugin, { if (m_optional) { m_used = false; } else { - issue(PluginIssueType::unknownPortType, portName); + issue(PluginIssueType::UnknownPortType, portName); } } @@ -265,16 +265,16 @@ std::vector Meta::get(const LilvPlugin *plugin, // be non-Lv2-conforming if(m_min == std::numeric_limits::lowest()) { - issue(PluginIssueType::logScaleMinMissing, portName); + issue(PluginIssueType::LogScaleMinMissing, portName); } if(m_max == std::numeric_limits::max()) { - issue(PluginIssueType::logScaleMaxMissing, portName); + issue(PluginIssueType::LogScaleMaxMissing, portName); } // forbid min < 0 < max if(m_min < 0.f && m_max > 0.f) { - issue(PluginIssueType::logScaleMinMaxDifferentSigns, portName); + issue(PluginIssueType::LogScaleMinMaxDifferentSigns, portName); } m_logarithmic = true; } diff --git a/src/core/lv2/Lv2Proc.cpp b/src/core/lv2/Lv2Proc.cpp index 31af47a63..e0541b948 100644 --- a/src/core/lv2/Lv2Proc.cpp +++ b/src/core/lv2/Lv2Proc.cpp @@ -61,7 +61,7 @@ struct MidiInputEvent -Plugin::PluginTypes Lv2Proc::check(const LilvPlugin *plugin, +Plugin::Type Lv2Proc::check(const LilvPlugin *plugin, std::vector& issues) { unsigned maxPorts = lilv_plugin_get_num_ports(plugin); @@ -79,7 +79,7 @@ Plugin::PluginTypes Lv2Proc::check(const LilvPlugin *plugin, if (!Engine::ignorePluginBlacklist() && pluginBlacklist.find(pluginUri) != pluginBlacklist.end()) { - issues.emplace_back(blacklisted); + issues.emplace_back(PluginIssueType::Blacklisted); } for (unsigned portNum = 0; portNum < maxPorts; ++portNum) @@ -106,19 +106,19 @@ Plugin::PluginTypes Lv2Proc::check(const LilvPlugin *plugin, } if (audioChannels[inCount] > 2) - issues.emplace_back(tooManyInputChannels, + issues.emplace_back(PluginIssueType::TooManyInputChannels, std::to_string(audioChannels[inCount])); if (audioChannels[outCount] == 0) - issues.emplace_back(noOutputChannel); + issues.emplace_back(PluginIssueType::NoOutputChannel); else if (audioChannels[outCount] > 2) - issues.emplace_back(tooManyOutputChannels, + issues.emplace_back(PluginIssueType::TooManyOutputChannels, std::to_string(audioChannels[outCount])); if (midiChannels[inCount] > 1) - issues.emplace_back(tooManyMidiInputChannels, + issues.emplace_back(PluginIssueType::TooManyMidiInputChannels, std::to_string(midiChannels[inCount])); if (midiChannels[outCount] > 1) - issues.emplace_back(tooManyMidiOutputChannels, + issues.emplace_back(PluginIssueType::TooManyMidiOutputChannels, std::to_string(midiChannels[outCount])); AutoLilvNodes reqFeats(lilv_plugin_get_required_features(plugin)); @@ -128,7 +128,7 @@ Plugin::PluginTypes Lv2Proc::check(const LilvPlugin *plugin, lilv_nodes_get(reqFeats.get(), itr)); if(!Lv2Features::isFeatureSupported(reqFeatName)) { - issues.emplace_back(featureNotSupported, reqFeatName); + issues.emplace_back(PluginIssueType::FeatureNotSupported, reqFeatName); } } @@ -144,16 +144,16 @@ Plugin::PluginTypes Lv2Proc::check(const LilvPlugin *plugin, { // yes, this is not a Lv2 feature, // but it's a feature in abstract sense - issues.emplace_back(featureNotSupported, ro); + issues.emplace_back(PluginIssueType::FeatureNotSupported, ro); } } } return (audioChannels[inCount] > 2 || audioChannels[outCount] > 2) - ? Plugin::Undefined + ? Plugin::Type::Undefined : (audioChannels[inCount] > 0) - ? Plugin::Effect - : Plugin::Instrument; + ? Plugin::Type::Effect + : Plugin::Type::Instrument; } diff --git a/src/core/lv2/Lv2SubPluginFeatures.cpp b/src/core/lv2/Lv2SubPluginFeatures.cpp index 4e02bc698..135da3e2a 100644 --- a/src/core/lv2/Lv2SubPluginFeatures.cpp +++ b/src/core/lv2/Lv2SubPluginFeatures.cpp @@ -59,7 +59,7 @@ QString Lv2SubPluginFeatures::pluginName(const LilvPlugin *plug) -Lv2SubPluginFeatures::Lv2SubPluginFeatures(Plugin::PluginTypes type) : +Lv2SubPluginFeatures::Lv2SubPluginFeatures(Plugin::Type type) : SubPluginFeatures(type) { } diff --git a/src/core/main.cpp b/src/core/main.cpp index da13181fe..25a6ab9c5 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -363,9 +363,9 @@ int main( int argc, char * * argv ) new QCoreApplication( argc, argv ) : new gui::MainApplication(argc, argv); - AudioEngine::qualitySettings qs( AudioEngine::qualitySettings::Mode_HighQuality ); - OutputSettings os( 44100, OutputSettings::BitRateSettings(160, false), OutputSettings::Depth_16Bit, OutputSettings::StereoMode_JointStereo ); - ProjectRenderer::ExportFileFormats eff = ProjectRenderer::WaveFile; + AudioEngine::qualitySettings qs( AudioEngine::qualitySettings::Mode::HighQuality ); + OutputSettings os( 44100, OutputSettings::BitRateSettings(160, false), OutputSettings::BitDepth::Depth16Bit, OutputSettings::StereoMode::JointStereo ); + ProjectRenderer::ExportFileFormat eff = ProjectRenderer::ExportFileFormat::Wave; // second of two command-line parsing stages for( int i = 1; i < argc; ++i ) @@ -517,23 +517,23 @@ int main( int argc, char * * argv ) if( ext == "wav" ) { - eff = ProjectRenderer::WaveFile; + eff = ProjectRenderer::ExportFileFormat::Wave; } #ifdef LMMS_HAVE_OGGVORBIS else if( ext == "ogg" ) { - eff = ProjectRenderer::OggFile; + eff = ProjectRenderer::ExportFileFormat::Ogg; } #endif #ifdef LMMS_HAVE_MP3LAME else if( ext == "mp3" ) { - eff = ProjectRenderer::MP3File; + eff = ProjectRenderer::ExportFileFormat::MP3; } #endif else if (ext == "flac") { - eff = ProjectRenderer::FlacFile; + eff = ProjectRenderer::ExportFileFormat::Flac; } else { @@ -596,15 +596,15 @@ int main( int argc, char * * argv ) if( mode == "s" ) { - os.setStereoMode(OutputSettings::StereoMode_Stereo); + os.setStereoMode(OutputSettings::StereoMode::Stereo); } else if( mode == "j" ) { - os.setStereoMode(OutputSettings::StereoMode_JointStereo); + os.setStereoMode(OutputSettings::StereoMode::JointStereo); } else if( mode == "m" ) { - os.setStereoMode(OutputSettings::StereoMode_Mono); + os.setStereoMode(OutputSettings::StereoMode::Mono); } else { @@ -613,7 +613,7 @@ int main( int argc, char * * argv ) } else if( arg =="--float" || arg == "-a" ) { - os.setBitDepth(OutputSettings::Depth_32Bit); + os.setBitDepth(OutputSettings::BitDepth::Depth32Bit); } else if( arg == "--interpolation" || arg == "-i" ) { @@ -629,19 +629,19 @@ int main( int argc, char * * argv ) if( ip == "linear" ) { - qs.interpolation = AudioEngine::qualitySettings::Interpolation_Linear; + qs.interpolation = AudioEngine::qualitySettings::Interpolation::Linear; } else if( ip == "sincfastest" ) { - qs.interpolation = AudioEngine::qualitySettings::Interpolation_SincFastest; + qs.interpolation = AudioEngine::qualitySettings::Interpolation::SincFastest; } else if( ip == "sincmedium" ) { - qs.interpolation = AudioEngine::qualitySettings::Interpolation_SincMedium; + qs.interpolation = AudioEngine::qualitySettings::Interpolation::SincMedium; } else if( ip == "sincbest" ) { - qs.interpolation = AudioEngine::qualitySettings::Interpolation_SincBest; + qs.interpolation = AudioEngine::qualitySettings::Interpolation::SincBest; } else { @@ -663,16 +663,16 @@ int main( int argc, char * * argv ) switch( o ) { case 1: - qs.oversampling = AudioEngine::qualitySettings::Oversampling_None; + qs.oversampling = AudioEngine::qualitySettings::Oversampling::None; break; case 2: - qs.oversampling = AudioEngine::qualitySettings::Oversampling_2x; + qs.oversampling = AudioEngine::qualitySettings::Oversampling::X2; break; case 4: - qs.oversampling = AudioEngine::qualitySettings::Oversampling_4x; + qs.oversampling = AudioEngine::qualitySettings::Oversampling::X4; break; case 8: - qs.oversampling = AudioEngine::qualitySettings::Oversampling_8x; + qs.oversampling = AudioEngine::qualitySettings::Oversampling::X8; break; default: return usageError( QString( "Invalid oversampling %1" ).arg( argv[i] ) ); diff --git a/src/core/midi/MidiAlsaSeq.cpp b/src/core/midi/MidiAlsaSeq.cpp index 760840c77..0b3bab819 100644 --- a/src/core/midi/MidiAlsaSeq.cpp +++ b/src/core/midi/MidiAlsaSeq.cpp @@ -245,16 +245,16 @@ void MidiAlsaSeq::applyPortMode( MidiPort * _port ) switch( _port->mode() ) { - case MidiPort::Duplex: + case MidiPort::Mode::Duplex: caps[1] |= SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ; - case MidiPort::Input: + case MidiPort::Mode::Input: caps[0] |= SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE; break; - case MidiPort::Output: + case MidiPort::Mode::Output: caps[1] |= SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ; break; diff --git a/src/core/midi/MidiApple.cpp b/src/core/midi/MidiApple.cpp index 01836c50b..444f093e5 100644 --- a/src/core/midi/MidiApple.cpp +++ b/src/core/midi/MidiApple.cpp @@ -259,7 +259,7 @@ void MidiApple::HandleReadCallback( const MIDIPacketList *pktlist, void *srcConn nBytes = packet->length; // Check if this is the end of a continued SysEx message if (continueSysEx) { - unsigned int lengthToCopy = qMin(nBytes, SYSEX_LENGTH - sysExLength); + unsigned int lengthToCopy = std::min(nBytes, SYSEX_LENGTH - sysExLength); // Copy the message into our SysEx message buffer, // making sure not to overrun the buffer memcpy(sysExMessage + sysExLength, packet->data, lengthToCopy); @@ -298,7 +298,7 @@ void MidiApple::HandleReadCallback( const MIDIPacketList *pktlist, void *srcConn { // MIDI SysEx then we copy the rest of the message into the SysEx message buffer unsigned int lengthLeftInMessage = nBytes - iByte; - unsigned int lengthToCopy = qMin(lengthLeftInMessage, SYSEX_LENGTH); + unsigned int lengthToCopy = std::min(lengthLeftInMessage, SYSEX_LENGTH); memcpy(sysExMessage + sysExLength, packet->data, lengthToCopy); sysExLength += lengthToCopy; @@ -403,7 +403,7 @@ void MidiApple::midiInClose( MIDIEndpointRef reference ) -char *getName( MIDIObjectRef &object ) +char *getName( const MIDIObjectRef &object ) { // Returns the name of a given MIDIObjectRef as char * CFStringRef name = nullptr; diff --git a/src/core/midi/MidiClient.cpp b/src/core/midi/MidiClient.cpp index 78691de6f..030384c5e 100644 --- a/src/core/midi/MidiClient.cpp +++ b/src/core/midi/MidiClient.cpp @@ -71,8 +71,7 @@ void MidiClient::removePort( MidiPort* port ) return; } - QVector::Iterator it = - std::find( m_midiPorts.begin(), m_midiPorts.end(), port ); + auto it = std::find(m_midiPorts.begin(), m_midiPorts.end(), port); if( it != m_midiPorts.end() ) { m_midiPorts.erase( it ); diff --git a/src/core/midi/MidiController.cpp b/src/core/midi/MidiController.cpp index fbd48e945..d7c89e940 100644 --- a/src/core/midi/MidiController.cpp +++ b/src/core/midi/MidiController.cpp @@ -33,9 +33,9 @@ namespace lmms MidiController::MidiController( Model * _parent ) : - Controller( Controller::MidiController, _parent, tr( "MIDI Controller" ) ), + Controller( ControllerType::Midi, _parent, tr( "MIDI Controller" ) ), MidiEventProcessor(), - m_midiPort( tr( "unnamed_midi_controller" ), Engine::audioEngine()->midiClient(), this, this, MidiPort::Input ), + m_midiPort( tr( "unnamed_midi_controller" ), Engine::audioEngine()->midiClient(), this, this, MidiPort::Mode::Input ), m_lastValue( 0.0f ), m_previousValue( 0.0f ) { diff --git a/src/core/midi/MidiPort.cpp b/src/core/midi/MidiPort.cpp index b656d9541..c7c947e8e 100644 --- a/src/core/midi/MidiPort.cpp +++ b/src/core/midi/MidiPort.cpp @@ -66,8 +66,8 @@ MidiPort::MidiPort( const QString& name, { m_midiClient->addPort( this ); - m_readableModel.setValue( m_mode == Input || m_mode == Duplex ); - m_writableModel.setValue( m_mode == Output || m_mode == Duplex ); + m_readableModel.setValue( m_mode == Mode::Input || m_mode == Mode::Duplex ); + m_writableModel.setValue( m_mode == Mode::Output || m_mode == Mode::Duplex ); connect( &m_readableModel, SIGNAL(dataChanged()), this, SLOT(updateMidiPortMode()), Qt::DirectConnection ); @@ -325,10 +325,10 @@ void MidiPort::subscribeWritablePort( const QString& port, bool subscribe ) void MidiPort::updateMidiPortMode() { // this small lookup-table makes everything easier - static const Modes modeTable[2][2] = + static const Mode modeTable[2][2] = { - { Disabled, Output }, - { Input, Duplex } + { Mode::Disabled, Mode::Output }, + { Mode::Input, Mode::Duplex } } ; setMode( modeTable[m_readableModel.value()][m_writableModel.value()] ); diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 93b37527c..0d15b1067 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -61,7 +61,7 @@ SET(LMMS_SRCS gui/instrument/EnvelopeAndLfoView.cpp gui/instrument/InstrumentFunctionViews.cpp gui/instrument/InstrumentMidiIOView.cpp - gui/instrument/InstrumentMiscView.cpp + gui/instrument/InstrumentTuningView.cpp gui/instrument/InstrumentSoundShapingView.cpp gui/instrument/InstrumentTrackWindow.cpp gui/instrument/InstrumentView.cpp diff --git a/src/gui/ControlLayout.cpp b/src/gui/ControlLayout.cpp index 7e0976c94..5e9a21101 100644 --- a/src/gui/ControlLayout.cpp +++ b/src/gui/ControlLayout.cpp @@ -258,8 +258,8 @@ int ControlLayout::doLayout(const QRect &rect, bool testOnly) const if (first) { // for the search bar, only show it if there are at least - // two control widgets (i.e. at least 3 widgets) - if (m_itemMap.size() > 2) { wid->show(); } + // five control widgets (i.e. at least 6 widgets) + if (m_itemMap.size() > 5) { wid->show(); } else { wid->hide(); } } else { wid->show(); } diff --git a/src/gui/ControllerView.cpp b/src/gui/ControllerView.cpp index 3e3f4b9d1..d32e8d49c 100644 --- a/src/gui/ControllerView.cpp +++ b/src/gui/ControllerView.cpp @@ -149,7 +149,7 @@ void ControllerView::renameController() if( ok && !new_name.isEmpty() ) { c->setName( new_name ); - if( getController()->type() == Controller::LfoController ) + if( getController()->type() == Controller::ControllerType::Lfo ) { m_controllerDlg->setWindowTitle( tr( "LFO" ) + " (" + new_name + ")" ); } diff --git a/src/gui/Controls.cpp b/src/gui/Controls.cpp index 8c007ee99..209b0fce1 100644 --- a/src/gui/Controls.cpp +++ b/src/gui/Controls.cpp @@ -95,7 +95,7 @@ AutomatableModelView* CheckControl::modelView() { return m_checkBox; } CheckControl::CheckControl(QWidget *parent) : m_widget(new QWidget(parent)), - m_checkBox(new LedCheckBox(nullptr, QString(), LedCheckBox::Green)), + m_checkBox(new LedCheckBox(nullptr, QString(), LedCheckBox::LedColor::Green)), m_label(new QLabel(m_widget)) { auto vbox = new QVBoxLayout(m_widget); diff --git a/src/gui/EffectView.cpp b/src/gui/EffectView.cpp index f2caaadd5..7f7f9ee9d 100644 --- a/src/gui/EffectView.cpp +++ b/src/gui/EffectView.cpp @@ -56,28 +56,28 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) : // Disable effects that are of type "DummyEffect" bool isEnabled = !dynamic_cast( effect() ); - m_bypass = new LedCheckBox( this, "", isEnabled ? LedCheckBox::Green : LedCheckBox::Red ); + m_bypass = new LedCheckBox( this, "", isEnabled ? LedCheckBox::LedColor::Green : LedCheckBox::LedColor::Red ); m_bypass->move( 3, 3 ); m_bypass->setEnabled( isEnabled ); m_bypass->setToolTip(tr("On/Off")); - m_wetDry = new Knob( knobBright_26, this ); + m_wetDry = new Knob( KnobType::Bright26, this ); m_wetDry->setLabel( tr( "W/D" ) ); m_wetDry->move( 40 - m_wetDry->width() / 2, 5 ); m_wetDry->setEnabled( isEnabled ); m_wetDry->setHintText( tr( "Wet Level:" ), "" ); - m_autoQuit = new TempoSyncKnob( knobBright_26, this ); + m_autoQuit = new TempoSyncKnob( KnobType::Bright26, this ); m_autoQuit->setLabel( tr( "DECAY" ) ); m_autoQuit->move( 78 - m_autoQuit->width() / 2, 5 ); m_autoQuit->setEnabled( isEnabled && !effect()->m_autoQuitDisabled ); m_autoQuit->setHintText( tr( "Time:" ), "ms" ); - m_gate = new Knob( knobBright_26, this ); + m_gate = new Knob( KnobType::Bright26, this ); m_gate->setLabel( tr( "GATE" ) ); m_gate->move( 116 - m_gate->width() / 2, 5 ); m_gate->setEnabled( isEnabled && !effect()->m_autoQuitDisabled ); diff --git a/src/gui/FileBrowser.cpp b/src/gui/FileBrowser.cpp index 0672cd347..c0763d542 100644 --- a/src/gui/FileBrowser.cpp +++ b/src/gui/FileBrowser.cpp @@ -440,7 +440,7 @@ void FileBrowserTreeWidget::keyPressEvent(QKeyEvent * ke ) if (file == nullptr) { return; } // When moving to a new sound, preview it. Skip presets, they can play forever - if (vertical && file->type() == FileItem::SampleFile) + if (vertical && file->type() == FileItem::FileType::Sample) { previewFileItem(file); } @@ -535,7 +535,7 @@ void FileBrowserTreeWidget::contextMenuEvent(QContextMenuEvent * e ) QList FileBrowserTreeWidget::getContextActions(FileItem* file, bool songEditor) { QList result = QList(); - const bool fileIsSample = file->type() == FileItem::SampleFile; + const bool fileIsSample = file->type() == FileItem::FileType::Sample; QString instrumentAction = fileIsSample ? tr("Send to new AudioFileProcessor instance") : @@ -603,7 +603,7 @@ void FileBrowserTreeWidget::previewFileItem(FileItem* file) // In special case of sample-files we do not care about // handling() rather than directly creating a SamplePlayHandle - if (file->type() == FileItem::SampleFile) + if (file->type() == FileItem::FileType::Sample) { TextFloat * tf = TextFloat::displayMessage( tr("Loading sample"), @@ -621,15 +621,15 @@ void FileBrowserTreeWidget::previewFileItem(FileItem* file) ext == "gig" || ext == "pat") && !getPluginFactory()->pluginSupportingExtension(ext).isNull()) { - const bool isPlugin = file->handling() == FileItem::LoadByPlugin; + const bool isPlugin = file->handling() == FileItem::FileHandling::LoadByPlugin; newPPH = new PresetPreviewPlayHandle(fileName, isPlugin); } - else if (file->type() != FileItem::VstPluginFile && file->isTrack()) + else if (file->type() != FileItem::FileType::VstPlugin && file->isTrack()) { DataFile dataFile(fileName); if (dataFile.validate(ext)) { - const bool isPlugin = file->handling() == FileItem::LoadByPlugin; + const bool isPlugin = file->handling() == FileItem::FileHandling::LoadByPlugin; newPPH = new PresetPreviewPlayHandle(fileName, isPlugin, &dataFile); } else @@ -681,34 +681,34 @@ void FileBrowserTreeWidget::mouseMoveEvent( QMouseEvent * me ) { switch( f->type() ) { - case FileItem::PresetFile: - new StringPairDrag( f->handling() == FileItem::LoadAsPreset ? + case FileItem::FileType::Preset: + new StringPairDrag( f->handling() == FileItem::FileHandling::LoadAsPreset ? "presetfile" : "pluginpresetfile", f->fullName(), embed::getIconPixmap( "preset_file" ), this ); break; - case FileItem::SampleFile: + case FileItem::FileType::Sample: new StringPairDrag( "samplefile", f->fullName(), embed::getIconPixmap( "sample_file" ), this ); break; - case FileItem::SoundFontFile: + case FileItem::FileType::SoundFont: new StringPairDrag( "soundfontfile", f->fullName(), embed::getIconPixmap( "soundfont_file" ), this ); break; - case FileItem::PatchFile: + case FileItem::FileType::Patch: new StringPairDrag( "patchfile", f->fullName(), embed::getIconPixmap( "sample_file" ), this ); break; - case FileItem::VstPluginFile: + case FileItem::FileType::VstPlugin: new StringPairDrag( "vstpluginfile", f->fullName(), embed::getIconPixmap( "vst_plugin_file" ), this ); break; - case FileItem::MidiFile: + case FileItem::FileType::Midi: new StringPairDrag( "importedproject", f->fullName(), embed::getIconPixmap( "midi_file" ), this ); break; - case FileItem::ProjectFile: + case FileItem::FileType::Project: new StringPairDrag( "projectfile", f->fullName(), embed::getIconPixmap( "project_file" ), this ); break; @@ -732,7 +732,7 @@ void FileBrowserTreeWidget::mouseReleaseEvent(QMouseEvent * me ) if (m_previewPlayHandle == nullptr) { return; } // Only sample previews may continue after mouse up. Is this a sample preview? - bool isSample = m_previewPlayHandle->type() == PlayHandle::TypeSamplePlayHandle; + bool isSample = m_previewPlayHandle->type() == PlayHandle::Type::SamplePlayHandle; // Even sample previews should only continue if the user wants them to. Do they? bool shouldContinue = ConfigManager::inst()->value("ui", "letpreviewsfinish").toInt(); // If both are true the preview may continue, otherwise we stop it @@ -747,14 +747,14 @@ void FileBrowserTreeWidget::handleFile(FileItem * f, InstrumentTrack * it) Engine::audioEngine()->requestChangeInModel(); switch( f->handling() ) { - case FileItem::LoadAsProject: + case FileItem::FileHandling::LoadAsProject: if( getGUI()->mainWindow()->mayChangeProject(true) ) { Engine::getSong()->loadProject( f->fullName() ); } break; - case FileItem::LoadByPlugin: + case FileItem::FileHandling::LoadByPlugin: { const QString e = f->extension(); Instrument * i = it->instrument(); @@ -769,17 +769,17 @@ void FileBrowserTreeWidget::handleFile(FileItem * f, InstrumentTrack * it) break; } - case FileItem::LoadAsPreset: { + case FileItem::FileHandling::LoadAsPreset: { DataFile dataFile(f->fullName()); it->replaceInstrument(dataFile); break; } - case FileItem::ImportAsProject: + case FileItem::FileHandling::ImportAsProject: ImportFilter::import( f->fullName(), Engine::getSong() ); break; - case FileItem::NotSupported: + case FileItem::FileHandling::NotSupported: default: break; @@ -799,14 +799,14 @@ void FileBrowserTreeWidget::activateListItem(QTreeWidgetItem * item, return; } - if( f->handling() == FileItem::LoadAsProject || - f->handling() == FileItem::ImportAsProject ) + if( f->handling() == FileItem::FileHandling::LoadAsProject || + f->handling() == FileItem::FileHandling::ImportAsProject ) { handleFile( f, nullptr ); } - else if( f->handling() != FileItem::NotSupported ) + else if( f->handling() != FileItem::FileHandling::NotSupported ) { - auto it = dynamic_cast(Track::create(Track::InstrumentTrack, Engine::patternStore())); + auto it = dynamic_cast(Track::create(Track::Type::Instrument, Engine::patternStore())); handleFile( f, it ); } } @@ -818,7 +818,7 @@ void FileBrowserTreeWidget::openInNewInstrumentTrack(TrackContainer* tc, FileIte { if(item->isTrack()) { - auto it = dynamic_cast(Track::create(Track::InstrumentTrack, tc)); + auto it = dynamic_cast(Track::create(Track::Type::Instrument, tc)); handleFile(item, it); } } @@ -840,10 +840,10 @@ void FileBrowserTreeWidget::openInNewInstrumentTrack(FileItem* item, bool songEd bool FileBrowserTreeWidget::openInNewSampleTrack(FileItem* item) { // Can't add non-samples to a sample track - if (item->type() != FileItem::SampleFile) { return false; } + if (item->type() != FileItem::FileType::Sample) { return false; } // Create a new sample track for this sample - auto sampleTrack = static_cast(Track::create(Track::SampleTrack, Engine::getSong())); + auto sampleTrack = static_cast(Track::create(Track::Type::Sample, Engine::getSong())); // Add the sample clip to the track Engine::audioEngine()->requestChangeInModel(); @@ -1113,26 +1113,26 @@ void FileItem::initPixmaps() switch( m_type ) { - case ProjectFile: + case FileType::Project: setIcon( 0, *s_projectFilePixmap ); break; - case PresetFile: + case FileType::Preset: setIcon( 0, *s_presetFilePixmap ); break; - case SoundFontFile: + case FileType::SoundFont: setIcon( 0, *s_soundfontFilePixmap ); break; - case VstPluginFile: + case FileType::VstPlugin: setIcon( 0, *s_vstPluginFilePixmap ); break; - case SampleFile: - case PatchFile: // TODO + case FileType::Sample: + case FileType::Patch: // TODO setIcon( 0, *s_sampleFilePixmap ); break; - case MidiFile: + case FileType::Midi: setIcon( 0, *s_midiFilePixmap ); break; - case UnknownFile: + case FileType::Unknown: default: setIcon( 0, *s_unknownFilePixmap ); break; @@ -1144,36 +1144,36 @@ void FileItem::initPixmaps() void FileItem::determineFileType() { - m_handling = NotSupported; + m_handling = FileHandling::NotSupported; const QString ext = extension(); if( ext == "mmp" || ext == "mpt" || ext == "mmpz" ) { - m_type = ProjectFile; - m_handling = LoadAsProject; + m_type = FileType::Project; + m_handling = FileHandling::LoadAsProject; } else if( ext == "xpf" || ext == "xml" ) { - m_type = PresetFile; - m_handling = LoadAsPreset; + m_type = FileType::Preset; + m_handling = FileHandling::LoadAsPreset; } else if( ext == "xiz" && ! getPluginFactory()->pluginSupportingExtension(ext).isNull() ) { - m_type = PresetFile; - m_handling = LoadByPlugin; + m_type = FileType::Preset; + m_handling = FileHandling::LoadByPlugin; } else if( ext == "sf2" || ext == "sf3" ) { - m_type = SoundFontFile; + m_type = FileType::SoundFont; } else if( ext == "pat" ) { - m_type = PatchFile; + m_type = FileType::Patch; } else if( ext == "mid" || ext == "midi" || ext == "rmi" ) { - m_type = MidiFile; - m_handling = ImportAsProject; + m_type = FileType::Midi; + m_handling = FileHandling::ImportAsProject; } else if( ext == "dll" #ifdef LMMS_BUILD_LINUX @@ -1181,28 +1181,28 @@ void FileItem::determineFileType() #endif ) { - m_type = VstPluginFile; - m_handling = LoadByPlugin; + m_type = FileType::VstPlugin; + m_handling = FileHandling::LoadByPlugin; } else if ( ext == "lv2" ) { - m_type = PresetFile; - m_handling = LoadByPlugin; + m_type = FileType::Preset; + m_handling = FileHandling::LoadByPlugin; } else { - m_type = UnknownFile; + m_type = FileType::Unknown; } - if( m_handling == NotSupported && + if( m_handling == FileHandling::NotSupported && !ext.isEmpty() && ! getPluginFactory()->pluginSupportingExtension(ext).isNull() ) { - m_handling = LoadByPlugin; + m_handling = FileHandling::LoadByPlugin; // classify as sample if not classified by anything yet but can // be handled by a certain plugin - if( m_type == UnknownFile ) + if( m_type == FileType::Unknown ) { - m_type = SampleFile; + m_type = FileType::Sample; } } } diff --git a/src/gui/LadspaControlView.cpp b/src/gui/LadspaControlView.cpp index 46e208d2e..dbc3b8059 100644 --- a/src/gui/LadspaControlView.cpp +++ b/src/gui/LadspaControlView.cpp @@ -60,9 +60,9 @@ LadspaControlView::LadspaControlView( QWidget * _parent, switch( m_ctl->port()->data_type ) { - case TOGGLED: + case BufferDataType::Toggled: { - auto toggle = new LedCheckBox(m_ctl->port()->name, this, QString(), LedCheckBox::Green); + auto toggle = new LedCheckBox(m_ctl->port()->name, this, QString(), LedCheckBox::LedColor::Green); toggle->setModel( m_ctl->toggledModel() ); layout->addWidget( toggle ); if( link != nullptr ) @@ -78,14 +78,14 @@ LadspaControlView::LadspaControlView( QWidget * _parent, break; } - case INTEGER: - case ENUM: - case FLOATING: - knb = new Knob( knobBright_26, this, m_ctl->port()->name ); + case BufferDataType::Integer: + case BufferDataType::Enum: + case BufferDataType::Floating: + knb = new Knob( KnobType::Bright26, this, m_ctl->port()->name ); break; - case TIME: - knb = new TempoSyncKnob( knobBright_26, this, m_ctl->port()->name ); + case BufferDataType::Time: + knb = new TempoSyncKnob( KnobType::Bright26, this, m_ctl->port()->name ); break; default: @@ -94,7 +94,7 @@ LadspaControlView::LadspaControlView( QWidget * _parent, if( knb != nullptr ) { - if( m_ctl->port()->data_type != TIME ) + if( m_ctl->port()->data_type != BufferDataType::Time ) { knb->setModel( m_ctl->knobModel() ); } diff --git a/src/gui/LfoControllerDialog.cpp b/src/gui/LfoControllerDialog.cpp index 64602cd74..77362b169 100644 --- a/src/gui/LfoControllerDialog.cpp +++ b/src/gui/LfoControllerDialog.cpp @@ -61,22 +61,22 @@ LfoControllerDialog::LfoControllerDialog( Controller * _model, QWidget * _parent setWindowIcon( embed::getIconPixmap( "controller" ) ); setFixedSize( 240, 58 ); - m_baseKnob = new Knob( knobBright_26, this ); + m_baseKnob = new Knob( KnobType::Bright26, this ); m_baseKnob->setLabel( tr( "BASE" ) ); m_baseKnob->move( CD_LFO_BASE_CD_KNOB_X, CD_LFO_CD_KNOB_Y ); m_baseKnob->setHintText( tr( "Base:" ), "" ); - m_speedKnob = new TempoSyncKnob( knobBright_26, this ); + m_speedKnob = new TempoSyncKnob( KnobType::Bright26, this ); m_speedKnob->setLabel( tr( "FREQ" ) ); m_speedKnob->move( CD_LFO_SPEED_CD_KNOB_X, CD_LFO_CD_KNOB_Y ); m_speedKnob->setHintText( tr( "LFO frequency:" ), "" ); - m_amountKnob = new Knob( knobBright_26, this ); + m_amountKnob = new Knob( KnobType::Bright26, this ); m_amountKnob->setLabel( tr( "AMNT" ) ); m_amountKnob->move( CD_LFO_AMOUNT_CD_KNOB_X, CD_LFO_CD_KNOB_Y ); m_amountKnob->setHintText( tr( "Modulation amount:" ), "" ); - m_phaseKnob = new Knob( knobBright_26, this ); + m_phaseKnob = new Knob( KnobType::Bright26, this ); m_phaseKnob->setLabel( tr( "PHS" ) ); m_phaseKnob->move( CD_LFO_PHASE_CD_KNOB_X, CD_LFO_CD_KNOB_Y ); m_phaseKnob->setHintText( tr( "Phase offset:" ) , "" + tr( " degrees" ) ); diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 40c8334ba..10805fe01 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -84,7 +84,7 @@ MainWindow::MainWindow() : m_autoSaveTimer( this ), m_viewMenu( nullptr ), m_metronomeToggle( 0 ), - m_session( Normal ) + m_session( SessionState::Normal ) { setAttribute( Qt::WA_DeleteOnClose ); @@ -363,10 +363,12 @@ void MainWindow::finalize() } edit_menu->addSeparator(); - edit_menu->addAction( embed::getIconPixmap( "setup_general" ), - tr( "Settings" ), - this, SLOT(showSettingsDialog())); - connect( edit_menu, SIGNAL(aboutToShow()), this, SLOT(updateUndoRedoButtons())); + edit_menu->addAction(embed::getIconPixmap("microtuner"), tr("Scales and keymaps"), + this, SLOT(toggleMicrotunerWin())); + edit_menu->addAction(embed::getIconPixmap("setup_general"), tr("Settings"), + this, SLOT(showSettingsDialog())); + + connect(edit_menu, SIGNAL(aboutToShow()), this, SLOT(updateUndoRedoButtons())); m_viewMenu = new QMenu( this ); menuBar()->addMenu( m_viewMenu )->setText( tr( "&View" ) ); @@ -377,7 +379,7 @@ void MainWindow::finalize() m_toolsMenu = new QMenu( this ); - for( const Plugin::Descriptor* desc : getPluginFactory()->descriptors(Plugin::Tool) ) + for( const Plugin::Descriptor* desc : getPluginFactory()->descriptors(Plugin::Type::Tool) ) { m_toolsMenu->addAction( desc->logo->pixmap(), desc->displayName ); m_tools.push_back( ToolPlugin::instantiate( desc->name, /*this*/nullptr ) @@ -485,10 +487,6 @@ void MainWindow::finalize() tr("Show/hide project notes") + " (Ctrl+7)", this, SLOT(toggleProjectNotesWin()), m_toolBar); project_notes_window->setShortcut( Qt::CTRL + Qt::Key_7 ); - auto microtuner_window = new ToolButton(embed::getIconPixmap("microtuner"), - tr("Microtuner configuration") + " (Ctrl+8)", this, SLOT(toggleMicrotunerWin()), m_toolBar); - microtuner_window->setShortcut( Qt::CTRL + Qt::Key_8 ); - m_toolBarLayout->addWidget( song_editor_window, 1, 1 ); m_toolBarLayout->addWidget( pattern_editor_window, 1, 2 ); m_toolBarLayout->addWidget( piano_roll_window, 1, 3 ); @@ -496,7 +494,6 @@ void MainWindow::finalize() m_toolBarLayout->addWidget( mixer_window, 1, 5 ); m_toolBarLayout->addWidget( controllers_window, 1, 6 ); m_toolBarLayout->addWidget( project_notes_window, 1, 7 ); - m_toolBarLayout->addWidget( microtuner_window, 1, 8 ); m_toolBarLayout->setColumnStretch( 100, 1 ); // setup-dialog opened before? @@ -514,7 +511,7 @@ void MainWindow::finalize() ConfigManager::inst()->value( "audioengine", "audiodev" ) ) ) { // if so, offer the audio settings section of the setup dialog - SetupDialog sd( SetupDialog::AudioSettings ); + SetupDialog sd( SetupDialog::ConfigTab::AudioSettings ); sd.exec(); } @@ -600,7 +597,7 @@ void MainWindow::resetWindowTitle() title += '*'; } - if( getSession() == Recover ) + if( getSession() == SessionState::Recover ) { title += " - " + tr( "Recover session. Please save your work!" ); } @@ -618,7 +615,7 @@ bool MainWindow::mayChangeProject(bool stopPlayback) Engine::getSong()->stop(); } - if( !Engine::getSong()->isModified() && getSession() != Recover ) + if( !Engine::getSong()->isModified() && getSession() != SessionState::Recover ) { return( true ); } @@ -635,9 +632,9 @@ bool MainWindow::mayChangeProject(bool stopPlayback) "last saving. Do you want to save it " "now?" ); - QMessageBox mb( ( getSession() == Recover ? + QMessageBox mb( ( getSession() == SessionState::Recover ? messageTitleRecovered : messageTitleUnsaved ), - ( getSession() == Recover ? + ( getSession() == SessionState::Recover ? messageRecovered : messageUnsaved ), QMessageBox::Question, QMessageBox::Save, @@ -652,7 +649,7 @@ bool MainWindow::mayChangeProject(bool stopPlayback) } else if( answer == QMessageBox::Discard ) { - if( getSession() == Recover ) + if( getSession() == SessionState::Recover ) { sessionCleanup(); } @@ -795,7 +792,7 @@ bool MainWindow::saveProject() } else if( this->guiSaveProject() ) { - if( getSession() == Recover ) + if( getSession() == SessionState::Recover ) { sessionCleanup(); } @@ -850,7 +847,7 @@ bool MainWindow::saveProjectAs() } if( this->guiSaveProjectAs( fname ) ) { - if( getSession() == Recover ) + if( getSession() == SessionState::Recover ) { sessionCleanup(); } @@ -1100,10 +1097,6 @@ void MainWindow::updateViewMenu() tr( "Project Notes" ) + "\tCtrl+7", this, SLOT(toggleProjectNotesWin()) ); - m_viewMenu->addAction(embed::getIconPixmap( "microtuner" ), - tr( "Microtuner" ) + "\tCtrl+8", - this, SLOT(toggleMicrotunerWin()) - ); m_viewMenu->addSeparator(); @@ -1214,19 +1207,19 @@ void MainWindow::updatePlayPauseIcons() { switch( Engine::getSong()->playMode() ) { - case Song::Mode_PlaySong: + case Song::PlayMode::Song: getGUI()->songEditor()->setPauseIcon( true ); break; - case Song::Mode_PlayAutomationClip: + case Song::PlayMode::AutomationClip: getGUI()->automationEditor()->setPauseIcon( true ); break; - case Song::Mode_PlayPattern: + case Song::PlayMode::Pattern: getGUI()->patternEditor()->setPauseIcon( true ); break; - case Song::Mode_PlayMidiClip: + case Song::PlayMode::MidiClip: getGUI()->pianoRoll()->setPauseIcon( true ); break; @@ -1288,7 +1281,7 @@ void MainWindow::sessionCleanup() { // delete recover session files QFile::remove( ConfigManager::inst()->recoveryFile() ); - setSession( Normal ); + setSession( SessionState::Normal ); } @@ -1480,7 +1473,7 @@ void MainWindow::exportProject(bool multiExport) efd.setFileMode( FileDialog::AnyFile ); int idx = 0; QStringList types; - while( ProjectRenderer::fileEncodeDevices[idx].m_fileFormat != ProjectRenderer::NumFileFormats) + while( ProjectRenderer::fileEncodeDevices[idx].m_fileFormat != ProjectRenderer::ExportFileFormat::Count) { if(ProjectRenderer::fileEncodeDevices[idx].isAvailable()) { types << tr(ProjectRenderer::fileEncodeDevices[idx].m_description); @@ -1625,17 +1618,17 @@ void MainWindow::onSongStopped() SongEditorWindow* songEditor = getGUI()->songEditor(); switch( tl->behaviourAtStop() ) { - case TimeLineWidget::BackToZero: - if( songEditor && ( tl->autoScroll() == TimeLineWidget::AutoScrollEnabled ) ) + case TimeLineWidget::BehaviourAtStopState::BackToZero: + if( songEditor && ( tl->autoScroll() == TimeLineWidget::AutoScrollState::Enabled ) ) { songEditor->m_editor->updatePosition(0); } break; - case TimeLineWidget::BackToStart: + case TimeLineWidget::BehaviourAtStopState::BackToStart: if( tl->savedPos() >= 0 ) { - if(songEditor && ( tl->autoScroll() == TimeLineWidget::AutoScrollEnabled ) ) + if(songEditor && ( tl->autoScroll() == TimeLineWidget::AutoScrollState::Enabled ) ) { songEditor->m_editor->updatePosition( TimePos(tl->savedPos().getTicks() ) ); } @@ -1643,7 +1636,7 @@ void MainWindow::onSongStopped() } break; - case TimeLineWidget::KeepStopPosition: + case TimeLineWidget::BehaviourAtStopState::KeepStopPosition: break; } } diff --git a/src/gui/MicrotunerConfig.cpp b/src/gui/MicrotunerConfig.cpp index 316bf54d6..4156b9e79 100644 --- a/src/gui/MicrotunerConfig.cpp +++ b/src/gui/MicrotunerConfig.cpp @@ -56,16 +56,26 @@ namespace lmms::gui MicrotunerConfig::MicrotunerConfig() : QWidget(), - m_scaleComboModel(nullptr, tr("Selected scale")), - m_keymapComboModel(nullptr, tr("Selected keymap")), + m_scaleComboModel(nullptr, tr("Selected scale slot")), + m_keymapComboModel(nullptr, tr("Selected keymap slot")), m_firstKeyModel(0, 0, NumKeys - 1, nullptr, tr("First key")), m_lastKeyModel(NumKeys - 1, 0, NumKeys - 1, nullptr, tr("Last key")), m_middleKeyModel(DefaultMiddleKey, 0, NumKeys - 1, nullptr, tr("Middle key")), m_baseKeyModel(DefaultBaseKey, 0, NumKeys - 1, nullptr, tr("Base key")), m_baseFreqModel(DefaultBaseFreq, 0.1f, 9999.999f, 0.001f, nullptr, tr("Base note frequency")) { +#if QT_VERSION < 0x50C00 + // Workaround for a bug in Qt versions below 5.12, + // where argument-dependent-lookup fails for QFlags operators + // declared inside a namepsace. + // This affects the Q_DECLARE_OPERATORS_FOR_FLAGS macro in Instrument.h + // See also: https://codereview.qt-project.org/c/qt/qtbase/+/225348 + + using ::operator|; +#endif + setWindowIcon(embed::getIconPixmap("microtuner")); - setWindowTitle(tr("Microtuner")); + setWindowTitle(tr("Microtuner Configuration")); // Organize into 2 main columns: scales and keymaps auto microtunerLayout = new QGridLayout(); @@ -74,7 +84,7 @@ MicrotunerConfig::MicrotunerConfig() : // ---------------------------------- // Scale sub-column // - auto scaleLabel = new QLabel(tr("Scale:")); + auto scaleLabel = new QLabel(tr("Scale slot to edit:")); microtunerLayout->addWidget(scaleLabel, 0, 0, 1, 2, Qt::AlignBottom); for (unsigned int i = 0; i < MaxScaleCount; i++) @@ -92,6 +102,8 @@ MicrotunerConfig::MicrotunerConfig() : auto loadScaleButton = new QPushButton(tr("Load")); auto saveScaleButton = new QPushButton(tr("Save")); + loadScaleButton->setToolTip(tr("Load scale definition from a file.")); + saveScaleButton->setToolTip(tr("Save scale definition to a file.")); microtunerLayout->addWidget(loadScaleButton, 3, 0, 1, 1); microtunerLayout->addWidget(saveScaleButton, 3, 1, 1, 1); connect(loadScaleButton, &QPushButton::clicked, [=] {loadScaleFromFile();}); @@ -102,14 +114,15 @@ MicrotunerConfig::MicrotunerConfig() : m_scaleTextEdit->setToolTip(tr("Enter intervals on separate lines. Numbers containing a decimal point are treated as cents.\nOther inputs are treated as integer ratios and must be in the form of \'a/b\' or \'a\'.\nUnity (0.0 cents or ratio 1/1) is always present as a hidden first value; do not enter it manually.")); microtunerLayout->addWidget(m_scaleTextEdit, 4, 0, 2, 2); - auto applyScaleButton = new QPushButton(tr("Apply scale")); + auto applyScaleButton = new QPushButton(tr("Apply scale changes")); + applyScaleButton->setToolTip(tr("Verify and apply changes made to the selected scale. To use the scale, select it in the settings of a supported instrument.")); microtunerLayout->addWidget(applyScaleButton, 6, 0, 1, 2); connect(applyScaleButton, &QPushButton::clicked, [=] {applyScale();}); // ---------------------------------- // Mapping sub-column // - auto keymapLabel = new QLabel(tr("Keymap:")); + auto keymapLabel = new QLabel(tr("Keymap slot to edit:")); microtunerLayout->addWidget(keymapLabel, 0, 2, 1, 2, Qt::AlignBottom); for (unsigned int i = 0; i < MaxKeymapCount; i++) @@ -127,6 +140,8 @@ MicrotunerConfig::MicrotunerConfig() : auto loadKeymapButton = new QPushButton(tr("Load")); auto saveKeymapButton = new QPushButton(tr("Save")); + loadKeymapButton->setToolTip(tr("Load key mapping definition from a file.")); + saveKeymapButton->setToolTip(tr("Save key mapping definition to a file.")); microtunerLayout->addWidget(loadKeymapButton, 3, 2, 1, 1); microtunerLayout->addWidget(saveKeymapButton, 3, 3, 1, 1); connect(loadKeymapButton, &QPushButton::clicked, [=] {loadKeymapFromFile();}); @@ -171,7 +186,8 @@ MicrotunerConfig::MicrotunerConfig() : baseFreqSpin->setToolTip(tr("Base note frequency")); keymapRangeLayout->addWidget(baseFreqSpin, 1, 1, 1, 2); - auto applyKeymapButton = new QPushButton(tr("Apply keymap")); + auto applyKeymapButton = new QPushButton(tr("Apply keymap changes")); + applyKeymapButton->setToolTip(tr("Verify and apply changes made to the selected key mapping. To use the mapping, select it in the settings of a supported instrument.")); microtunerLayout->addWidget(applyKeymapButton, 6, 2, 1, 2); connect(applyKeymapButton, &QPushButton::clicked, [=] {applyKeymap();}); diff --git a/src/gui/MidiCCRackView.cpp b/src/gui/MidiCCRackView.cpp index 7e0d71f78..a0b1496fb 100644 --- a/src/gui/MidiCCRackView.cpp +++ b/src/gui/MidiCCRackView.cpp @@ -89,7 +89,7 @@ MidiCCRackView::MidiCCRackView(InstrumentTrack * track) : // Adds the controller knobs for (int i = 0; i < MidiControllerCount; ++i) { - m_controllerKnob[i] = new Knob(knobBright_26); + m_controllerKnob[i] = new Knob(KnobType::Bright26); m_controllerKnob[i]->setLabel(tr("CC %1").arg(i)); knobsAreaLayout->addWidget(m_controllerKnob[i], i/4, i%4); } diff --git a/src/gui/MixerLine.cpp b/src/gui/MixerLine.cpp index 030ea892e..a90f13f83 100644 --- a/src/gui/MixerLine.cpp +++ b/src/gui/MixerLine.cpp @@ -96,7 +96,7 @@ MixerLine::MixerLine( QWidget * _parent, MixerView * _mv, int _channelIndex ) : setCursor( QCursor( embed::getIconPixmap( "hand" ), 3, 3 ) ); // mixer sends knob - m_sendKnob = new Knob( knobBright_26, this, tr( "Channel send amount" ) ); + m_sendKnob = new Knob( KnobType::Bright26, this, tr( "Channel send amount" ) ); m_sendKnob->move( 3, 22 ); m_sendKnob->setVisible( false ); diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index a9582b4e2..dff19ca3e 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -57,6 +57,16 @@ MixerView::MixerView() : ModelView( nullptr, this ), SerializingObjectHook() { +#if QT_VERSION < 0x50C00 + // Workaround for a bug in Qt versions below 5.12, + // where argument-dependent-lookup fails for QFlags operators + // declared inside a namepsace. + // This affects the Q_DECLARE_OPERATORS_FOR_FLAGS macro in Instrument.h + // See also: https://codereview.qt-project.org/c/qt/qtbase/+/225348 + + using ::operator|; +#endif + Mixer * m = Engine::mixer(); m->setHook( this ); @@ -238,20 +248,20 @@ void MixerView::refreshDisplay() // update the and max. channel number for every instrument void MixerView::updateMaxChannelSelector() { - TrackContainer::TrackList songTracks = Engine::getSong()->tracks(); - TrackContainer::TrackList patternStoreTracks = Engine::patternStore()->tracks(); + const TrackContainer::TrackList& songTracks = Engine::getSong()->tracks(); + const TrackContainer::TrackList& patternStoreTracks = Engine::patternStore()->tracks(); for (const auto& trackList : {songTracks, patternStoreTracks}) { for (const auto& track : trackList) { - if (track->type() == Track::InstrumentTrack) + if (track->type() == Track::Type::Instrument) { auto inst = (InstrumentTrack*)track; inst->mixerChannelModel()->setRange(0, m_mixerChannelViews.size()-1,1); } - else if (track->type() == Track::SampleTrack) + else if (track->type() == Track::Type::Sample) { auto strk = (SampleTrack*)track; strk->mixerChannelModel()->setRange(0, diff --git a/src/gui/PluginBrowser.cpp b/src/gui/PluginBrowser.cpp index b59064f05..7ba8bcc53 100644 --- a/src/gui/PluginBrowser.cpp +++ b/src/gui/PluginBrowser.cpp @@ -161,7 +161,7 @@ void PluginBrowser::addPlugins() m_descTree->clear(); // Fetch and sort all instrument plugin descriptors - auto descs = getPluginFactory()->descriptors(Plugin::Instrument); + auto descs = getPluginFactory()->descriptors(Plugin::Type::Instrument); std::sort(descs.begin(), descs.end(), [](auto d1, auto d2) { @@ -305,7 +305,7 @@ void PluginDescWidget::contextMenuEvent(QContextMenuEvent* e) void PluginDescWidget::openInNewInstrumentTrack(QString value) { TrackContainer* tc = Engine::getSong(); - auto it = dynamic_cast(Track::create(Track::InstrumentTrack, tc)); + auto it = dynamic_cast(Track::create(Track::Type::Instrument, tc)); auto ilt = new InstrumentLoaderThread(this, it, value); ilt->start(); } diff --git a/src/gui/SampleTrackWindow.cpp b/src/gui/SampleTrackWindow.cpp index 6fe70bf41..68b5eb8a2 100644 --- a/src/gui/SampleTrackWindow.cpp +++ b/src/gui/SampleTrackWindow.cpp @@ -54,6 +54,16 @@ SampleTrackWindow::SampleTrackWindow(SampleTrackView * tv) : m_track(tv->model()), m_stv(tv) { +#if QT_VERSION < 0x50C00 + // Workaround for a bug in Qt versions below 5.12, + // where argument-dependent-lookup fails for QFlags operators + // declared inside a namepsace. + // This affects the Q_DECLARE_OPERATORS_FOR_FLAGS macro in Instrument.h + // See also: https://codereview.qt-project.org/c/qt/qtbase/+/225348 + + using ::operator|; +#endif + // init own layout + widgets setFocusPolicy(Qt::StrongFocus); auto vlayout = new QVBoxLayout(this); @@ -94,7 +104,7 @@ SampleTrackWindow::SampleTrackWindow(SampleTrackView * tv) : Qt::Alignment widgetAlignment = Qt::AlignHCenter | Qt::AlignCenter; // set up volume knob - m_volumeKnob = new Knob(knobBright_26, nullptr, tr("Sample volume")); + m_volumeKnob = new Knob(KnobType::Bright26, nullptr, tr("Sample volume")); m_volumeKnob->setVolumeKnob(true); m_volumeKnob->setHintText(tr("Volume:"), "%"); @@ -108,7 +118,7 @@ SampleTrackWindow::SampleTrackWindow(SampleTrackView * tv) : // set up panning knob - m_panningKnob = new Knob(knobBright_26, nullptr, tr("Panning")); + m_panningKnob = new Knob(KnobType::Bright26, nullptr, tr("Panning")); m_panningKnob->setHintText(tr("Panning:"), ""); basicControlsLayout->addWidget(m_panningKnob, 0, 1); diff --git a/src/gui/SideBarWidget.cpp b/src/gui/SideBarWidget.cpp index 60760ba59..c218bedd3 100644 --- a/src/gui/SideBarWidget.cpp +++ b/src/gui/SideBarWidget.cpp @@ -62,16 +62,16 @@ void SideBarWidget::paintEvent( QPaintEvent * ) QFont f = p.font(); f.setBold( true ); - f.setUnderline( true ); + f.setUnderline(false); f.setPointSize( f.pointSize() + 2 ); p.setFont( f ); p.setPen( palette().highlightedText().color() ); - const int tx = m_icon.width()+4; + const int tx = m_icon.width() + 8; QFontMetrics metrics( f ); - const int ty = metrics.ascent(); + const int ty = (metrics.ascent() + m_icon.height()) / 2; p.drawText( tx, ty, m_title ); p.drawPixmap( 2, 2, m_icon.transformed( QTransform().rotate( -90 ) ) ); diff --git a/src/gui/clips/AutomationClipView.cpp b/src/gui/clips/AutomationClipView.cpp index 6fa91efdb..3e0e12b75 100644 --- a/src/gui/clips/AutomationClipView.cpp +++ b/src/gui/clips/AutomationClipView.cpp @@ -191,10 +191,10 @@ void AutomationClipView::constructContextMenu( QMenu * _cm ) _cm->addAction( embed::getIconPixmap( "flip_x" ), tr( "Flip Horizontally (Visible)" ), this, SLOT(flipX())); - if( !m_clip->m_objects.isEmpty() ) + if (!m_clip->m_objects.empty()) { _cm->addSeparator(); - auto m = new QMenu(tr("%1 Connections").arg(m_clip->m_objects.count()), _cm); + auto m = new QMenu(tr("%1 Connections").arg(m_clip->m_objects.size()), _cm); for (const auto& object : m_clip->m_objects) { if (object) @@ -321,7 +321,7 @@ void AutomationClipView::paintEvent( QPaintEvent * ) // the value of the end of the shape between the two nodes will be the inValue of // the next node. float nextValue; - if( m_clip->progressionType() == AutomationClip::DiscreteProgression ) + if( m_clip->progressionType() == AutomationClip::ProgressionType::Discrete ) { nextValue = OUTVAL(it); } diff --git a/src/gui/clips/ClipView.cpp b/src/gui/clips/ClipView.cpp index 8c4f704bc..de7690d26 100644 --- a/src/gui/clips/ClipView.cpp +++ b/src/gui/clips/ClipView.cpp @@ -25,6 +25,7 @@ #include "ClipView.h" #include +#include #include #include @@ -87,7 +88,7 @@ ClipView::ClipView( Clip * clip, m_initialClipPos( TimePos(0) ), m_initialClipEnd( TimePos(0) ), m_clip( clip ), - m_action( NoAction ), + m_action( Action::None ), m_initialMousePos( QPoint( 0, 0 ) ), m_initialMouseGlobalPos( QPoint( 0, 0 ) ), m_initialOffsets( QVector() ), @@ -125,7 +126,7 @@ ClipView::ClipView( Clip * clip, connect( m_clip, SIGNAL(lengthChanged()), this, SLOT(updateLength())); - connect( getGUI()->songEditor()->m_editor->zoomingModel(), SIGNAL(dataChanged()), this, SLOT(updateLength())); + connect(getGUI()->songEditor()->m_editor, &SongEditor::pixelsPerBarChanged, this, &ClipView::updateLength); connect( m_clip, SIGNAL(positionChanged()), this, SLOT(updatePosition())); connect( m_clip, SIGNAL(destroyedClip()), this, SLOT(close())); @@ -314,10 +315,9 @@ void ClipView::updateLength() } else { - setFixedWidth( - static_cast( m_clip->length() * pixelsPerBar() / - TimePos::ticksPerBar() ) + 1 /*+ - BORDER_WIDTH * 2-1*/ ); + // this std::max function is needed for clips that do not start or end on the beat, otherwise, they "disappear" when zooming to min + // 3 is the minimun width needed to make a clip visible + setFixedWidth(std::max(static_cast(m_clip->length() * pixelsPerBar() / TimePos::ticksPerBar() + 1), 3)); } m_trackView->trackContainerView()->update(); } @@ -436,7 +436,7 @@ void ClipView::dragEnterEvent( QDragEnterEvent * dee ) else { StringPairDrag::processDragEnterEvent( dee, "clip_" + - QString::number( m_clip->getTrack()->type() ) ); + QString::number( static_cast(m_clip->getTrack()->type()) ) ); } } @@ -458,7 +458,7 @@ void ClipView::dropEvent( QDropEvent * de ) QString value = StringPairDrag::decodeValue( de ); // Track must be the same type to paste into - if( type != ( "clip_" + QString::number( m_clip->getTrack()->type() ) ) ) + if( type != ( "clip_" + QString::number( static_cast(m_clip->getTrack()->type()) ) ) ) { return; } @@ -538,17 +538,18 @@ DataFile ClipView::createClipDataFiles( { Track * t = m_trackView->getTrack(); TrackContainer * tc = t->trackContainer(); - DataFile dataFile( DataFile::DragNDropData ); + DataFile dataFile( DataFile::Type::DragNDropData ); QDomElement clipParent = dataFile.createElement("clips"); for (const auto& clipView : clipViews) { // Insert into the dom under the "clips" element Track* clipTrack = clipView->m_trackView->getTrack(); - int trackIndex = tc->tracks().indexOf( clipTrack ); + int trackIndex = std::distance(tc->tracks().begin(), std::find(tc->tracks().begin(), tc->tracks().end(), clipTrack)); + assert(trackIndex != tc->tracks().size()); QDomElement clipElement = dataFile.createElement("clip"); clipElement.setAttribute( "trackIndex", trackIndex ); - clipElement.setAttribute( "trackType", clipTrack->type() ); + clipElement.setAttribute( "trackType", static_cast(clipTrack->type()) ); clipElement.setAttribute( "trackName", clipTrack->name() ); clipView->m_clip->saveState(dataFile, clipElement); clipParent.appendChild( clipElement ); @@ -557,12 +558,15 @@ DataFile ClipView::createClipDataFiles( dataFile.content().appendChild( clipParent ); // Add extra metadata needed for calculations later - int initialTrackIndex = tc->tracks().indexOf( t ); - if( initialTrackIndex < 0 ) + + const auto initialTrackIt = std::find(tc->tracks().begin(), tc->tracks().end(), t); + if (initialTrackIt == tc->tracks().end()) { printf("Failed to find selected track in the TrackContainer.\n"); return dataFile; } + + const int initialTrackIndex = std::distance(tc->tracks().begin(), initialTrackIt); QDomElement metadata = dataFile.createElement( "copyMetadata" ); // initialTrackIndex is the index of the track that was touched metadata.setAttribute( "initialTrackIndex", initialTrackIndex ); @@ -643,27 +647,27 @@ void ClipView::mousePressEvent( QMouseEvent * me ) { if( isSelected() ) { - m_action = CopySelection; + m_action = Action::CopySelection; } else { - m_action = ToggleSelected; + m_action = Action::ToggleSelected; } } else { if( isSelected() ) { - m_action = MoveSelection; + m_action = Action::MoveSelection; } else { getGUI()->songEditor()->m_editor->selectAllClips( false ); m_clip->addJournalCheckPoint(); - // Move, Resize and ResizeLeft - // Split action doesn't disable Clip journalling - if (m_action == Move || m_action == Resize || m_action == ResizeLeft) + // Action::Move, Action::Resize and Action::ResizeLeft + // Action::Split action doesn't disable Clip journalling + if (m_action == Action::Move || m_action == Action::Resize || m_action == Action::ResizeLeft) { m_clip->setJournalling(false); } @@ -673,22 +677,22 @@ void ClipView::mousePressEvent( QMouseEvent * me ) if( m_clip->getAutoResize() ) { // Always move clips that can't be manually resized - m_action = Move; + m_action = Action::Move; setCursor( Qt::SizeAllCursor ); } else if( me->x() >= width() - RESIZE_GRIP_WIDTH ) { - m_action = Resize; + m_action = Action::Resize; setCursor( Qt::SizeHorCursor ); } else if( me->x() < RESIZE_GRIP_WIDTH && (sClip || pClip) ) { - m_action = ResizeLeft; + m_action = Action::ResizeLeft; setCursor( Qt::SizeHorCursor ); } else if( sClip && knifeMode ) { - m_action = Split; + m_action = Action::Split; setCursor( m_cursorKnife ); setMarkerPos( knifeMarkerPos( me ) ); setMarkerEnabled( true ); @@ -696,11 +700,11 @@ void ClipView::mousePressEvent( QMouseEvent * me ) } else { - m_action = Move; + m_action = Action::Move; setCursor( Qt::SizeAllCursor ); } - if( m_action == Move ) + if( m_action == Action::Move ) { s_textFloat->setTitle( tr( "Current position" ) ); s_textFloat->setText( QString( "%1:%2" ). @@ -708,7 +712,7 @@ void ClipView::mousePressEvent( QMouseEvent * me ) arg( m_clip->startPosition().getTicks() % TimePos::ticksPerBar() ) ); } - else if( m_action == Resize || m_action == ResizeLeft ) + else if( m_action == Action::Resize || m_action == Action::ResizeLeft ) { s_textFloat->setTitle( tr( "Current length" ) ); s_textFloat->setText( tr( "%1:%2 (%3:%4 to %5:%6)" ). @@ -725,11 +729,11 @@ void ClipView::mousePressEvent( QMouseEvent * me ) // s_textFloat->reparent( this ); // setup text-float as if Clip was already moved/resized s_textFloat->moveGlobal( this, QPoint( width() + 2, height() + 2) ); - if ( m_action != Split) { s_textFloat->show(); } + if ( m_action != Action::Split) { s_textFloat->show(); } } delete m_hint; - QString hint = m_action == Move || m_action == MoveSelection + QString hint = m_action == Action::Move || m_action == Action::MoveSelection ? tr( "Press <%1> and drag to make a copy." ) : tr( "Press <%1> for free resizing." ); m_hint = TextFloat::displayMessage( tr( "Hint" ), hint.arg(UI_CTRL_KEY), @@ -746,9 +750,9 @@ void ClipView::mousePressEvent( QMouseEvent * me ) { remove( active ); } - if (m_action == Split) + if (m_action == Action::Split) { - m_action = NoAction; + m_action = Action::None; auto sClip = dynamic_cast(m_clip); if (sClip) { @@ -788,12 +792,12 @@ void ClipView::mousePressEvent( QMouseEvent * me ) */ void ClipView::mouseMoveEvent( QMouseEvent * me ) { - if( m_action == CopySelection || m_action == ToggleSelected ) + if( m_action == Action::CopySelection || m_action == Action::ToggleSelected ) { if( mouseMovedDistance( me, 2 ) == true ) { QVector clipViews; - if( m_action == CopySelection ) + if( m_action == Action::CopySelection ) { // Collect all selected Clips QVector so = @@ -814,7 +818,7 @@ void ClipView::mouseMoveEvent( QMouseEvent * me ) } // Clear the action here because mouseReleaseEvent will not get // triggered once we go into drag. - m_action = NoAction; + m_action = Action::None; // Write the Clips to the DataFile for copying DataFile dataFile = createClipDataFiles( clipViews ); @@ -825,7 +829,7 @@ void ClipView::mouseMoveEvent( QMouseEvent * me ) Qt::KeepAspectRatio, Qt::SmoothTransformation ); new StringPairDrag( QString( "clip_%1" ).arg( - m_clip->getTrack()->type() ), + static_cast(m_clip->getTrack()->type()) ), dataFile.toString(), thumbnail, this ); } } @@ -837,7 +841,7 @@ void ClipView::mouseMoveEvent( QMouseEvent * me ) } const float ppb = m_trackView->trackContainerView()->pixelsPerBar(); - if( m_action == Move ) + if( m_action == Action::Move ) { TimePos newPos = draggedClipPos( me ); m_clip->movePosition(newPos); @@ -849,7 +853,7 @@ void ClipView::mouseMoveEvent( QMouseEvent * me ) TimePos::ticksPerBar() ) ); s_textFloat->moveGlobal( this, QPoint( width() + 2, height() + 2 ) ); } - else if( m_action == MoveSelection ) + else if( m_action == Action::MoveSelection ) { // 1: Find the position we want to move the grabbed Clip to TimePos newPos = draggedClipPos( me ); @@ -879,13 +883,13 @@ void ClipView::mouseMoveEvent( QMouseEvent * me ) ( *it )->movePosition( newPos + m_initialOffsets[index] ); } } - else if( m_action == Resize || m_action == ResizeLeft ) + else if( m_action == Action::Resize || m_action == Action::ResizeLeft ) { const float snapSize = getGUI()->songEditor()->m_editor->getSnapSize(); // Length in ticks of one snap increment const TimePos snapLength = TimePos( (int)(snapSize * TimePos::ticksPerBar()) ); - if( m_action == Resize ) + if( m_action == Action::Resize ) { // The clip's new length TimePos l = static_cast( me->x() * TimePos::ticksPerBar() / ppb ); @@ -988,7 +992,7 @@ void ClipView::mouseMoveEvent( QMouseEvent * me ) TimePos::ticksPerBar() ) ); s_textFloat->moveGlobal( this, QPoint( width() + 2, height() + 2) ); } - else if( m_action == Split ) + else if( m_action == Action::Split ) { auto sClip = dynamic_cast(m_clip); if (sClip) { @@ -1013,21 +1017,21 @@ void ClipView::mouseMoveEvent( QMouseEvent * me ) */ void ClipView::mouseReleaseEvent( QMouseEvent * me ) { - // If the CopySelection was chosen as the action due to mouse movement, + // If the Action::CopySelection was chosen as the action due to mouse movement, // it will have been cleared. At this point Toggle is the desired action. // An active StringPairDrag will prevent this method from being called, - // so a real CopySelection would not have occurred. - if( m_action == CopySelection || - ( m_action == ToggleSelected && mouseMovedDistance( me, 2 ) == false ) ) + // so a real Action::CopySelection would not have occurred. + if( m_action == Action::CopySelection || + ( m_action == Action::ToggleSelected && mouseMovedDistance( me, 2 ) == false ) ) { setSelected( !isSelected() ); } - else if( m_action == Move || m_action == Resize || m_action == ResizeLeft ) + else if( m_action == Action::Move || m_action == Action::Resize || m_action == Action::ResizeLeft ) { // TODO: Fix m_clip->setJournalling() consistency m_clip->setJournalling( true ); } - else if( m_action == Split ) + else if( m_action == Action::Split ) { const float ppb = m_trackView->trackContainerView()->pixelsPerBar(); const TimePos relPos = me->pos().x() * TimePos::ticksPerBar() / ppb; @@ -1037,7 +1041,7 @@ void ClipView::mouseReleaseEvent( QMouseEvent * me ) ); } - m_action = NoAction; + m_action = Action::None; delete m_hint; m_hint = nullptr; s_textFloat->hide(); @@ -1077,7 +1081,7 @@ void ClipView::contextMenuEvent( QContextMenuEvent * cme ) individualClip ? tr("Delete (middle mousebutton)") : tr("Delete selection (middle mousebutton)"), - [this](){ contextMenuAction( Remove ); } ); + [this](){ contextMenuAction( ContextMenuAction::Remove ); } ); contextMenu.addSeparator(); @@ -1086,14 +1090,14 @@ void ClipView::contextMenuEvent( QContextMenuEvent * cme ) individualClip ? tr("Cut") : tr("Cut selection"), - [this](){ contextMenuAction( Cut ); } ); + [this](){ contextMenuAction( ContextMenuAction::Cut ); } ); if (canMergeSelection(selectedClips)) { contextMenu.addAction( embed::getIconPixmap("edit_merge"), tr("Merge Selection"), - [this]() { contextMenuAction(Merge); } + [this]() { contextMenuAction(ContextMenuAction::Merge); } ); } } @@ -1103,12 +1107,12 @@ void ClipView::contextMenuEvent( QContextMenuEvent * cme ) individualClip ? tr("Copy") : tr("Copy selection"), - [this](){ contextMenuAction( Copy ); } ); + [this](){ contextMenuAction( ContextMenuAction::Copy ); } ); contextMenu.addAction( embed::getIconPixmap( "edit_paste" ), tr( "Paste" ), - [this](){ contextMenuAction( Paste ); } ); + [this](){ contextMenuAction( ContextMenuAction::Paste ); } ); contextMenu.addSeparator(); @@ -1117,7 +1121,7 @@ void ClipView::contextMenuEvent( QContextMenuEvent * cme ) (individualClip ? tr("Mute/unmute (<%1> + middle click)") : tr("Mute/unmute selection (<%1> + middle click)")).arg(UI_CTRL_KEY), - [this](){ contextMenuAction( Mute ); } ); + [this](){ contextMenuAction( ContextMenuAction::Mute ); } ); contextMenu.addSeparator(); @@ -1141,22 +1145,22 @@ void ClipView::contextMenuAction( ContextMenuAction action ) switch( action ) { - case Remove: + case ContextMenuAction::Remove: remove( active ); break; - case Cut: + case ContextMenuAction::Cut: cut( active ); break; - case Copy: + case ContextMenuAction::Copy: copy( active ); break; - case Paste: + case ContextMenuAction::Paste: paste(); break; - case Mute: + case ContextMenuAction::Mute: toggleMute( active ); break; - case Merge: + case ContextMenuAction::Merge: mergeClips(active); break; } @@ -1203,7 +1207,7 @@ void ClipView::copy( QVector clipvs ) DataFile dataFile = createClipDataFiles( clipvs ); // Copy the Clip type as a key and the Clip data file to the clipboard - copyStringPair( QString( "clip_%1" ).arg( m_clip->getTrack()->type() ), + copyStringPair( QString( "clip_%1" ).arg( static_cast(m_clip->getTrack()->type()) ), dataFile.toString() ); } @@ -1306,7 +1310,7 @@ void ClipView::mergeClips(QVector clipvs) continue; } - NoteVector currentClipNotes = mcView->getMidiClip()->notes(); + const NoteVector& currentClipNotes = mcView->getMidiClip()->notes(); TimePos mcViewPos = mcView->getMidiClip()->startPosition(); for (Note* note: currentClipNotes) diff --git a/src/gui/clips/MidiClipView.cpp b/src/gui/clips/MidiClipView.cpp index e3ef9fd20..79c4cd73d 100644 --- a/src/gui/clips/MidiClipView.cpp +++ b/src/gui/clips/MidiClipView.cpp @@ -204,7 +204,7 @@ void MidiClipView::transposeSelection() void MidiClipView::constructContextMenu( QMenu * _cm ) { - bool isBeat = m_clip->type() == MidiClip::BeatClip; + bool isBeat = m_clip->type() == MidiClip::Type::BeatClip; auto a = new QAction(embed::getIconPixmap("piano"), tr("Open in piano-roll"), _cm); _cm->insertAction( _cm->actions()[0], a ); @@ -253,7 +253,7 @@ void MidiClipView::mousePressEvent( QMouseEvent * _me ) { bool displayPattern = fixedClips() || (pixelsPerBar() >= 96 && m_legacySEPattern); if( _me->button() == Qt::LeftButton && - m_clip->m_clipType == MidiClip::BeatClip && + m_clip->m_clipType == MidiClip::Type::BeatClip && displayPattern && _me->y() > height() - s_stepBtnOff->height() ) // when mouse button is pressed in pattern mode @@ -311,7 +311,7 @@ void MidiClipView::mouseDoubleClickEvent(QMouseEvent *_me) _me->ignore(); return; } - if( m_clip->m_clipType == MidiClip::MelodyClip || !fixedClips() ) + if( m_clip->m_clipType == MidiClip::Type::MelodyClip || !fixedClips() ) { openInPianoRoll(); } @@ -322,7 +322,7 @@ void MidiClipView::mouseDoubleClickEvent(QMouseEvent *_me) void MidiClipView::wheelEvent(QWheelEvent * we) { - if(m_clip->m_clipType == MidiClip::BeatClip && + if(m_clip->m_clipType == MidiClip::Type::BeatClip && (fixedClips() || pixelsPerBar() >= 96) && position(we).y() > height() - s_stepBtnOff->height()) { @@ -400,7 +400,7 @@ void MidiClipView::paintEvent( QPaintEvent * ) QColor c; bool const muted = m_clip->getTrack()->isMuted() || m_clip->isMuted(); bool current = getGUI()->pianoRoll()->currentMidiClip() == m_clip; - bool beatClip = m_clip->m_clipType == MidiClip::BeatClip; + bool beatClip = m_clip->m_clipType == MidiClip::Type::BeatClip; if( beatClip ) { @@ -460,7 +460,7 @@ void MidiClipView::paintEvent( QPaintEvent * ) bool displayPattern = fixedClips() || (pixelsPerBar >= 96 && m_legacySEPattern); // melody clip paint event NoteVector const & noteCollection = m_clip->m_notes; - if( m_clip->m_clipType == MidiClip::MelodyClip && !noteCollection.empty() ) + if( m_clip->m_clipType == MidiClip::Type::MelodyClip && !noteCollection.empty() ) { // Compute the minimum and maximum key in the clip // so that we know how much there is to draw. diff --git a/src/gui/editors/AutomationEditor.cpp b/src/gui/editors/AutomationEditor.cpp index db56557a4..a24165332 100644 --- a/src/gui/editors/AutomationEditor.cpp +++ b/src/gui/editors/AutomationEditor.cpp @@ -72,7 +72,7 @@ QPixmap * AutomationEditor::s_toolMove = nullptr; QPixmap * AutomationEditor::s_toolYFlip = nullptr; QPixmap * AutomationEditor::s_toolXFlip = nullptr; -const QVector AutomationEditor::m_zoomXLevels = +const std::array AutomationEditor::m_zoomXLevels = { 0.125f, 0.25f, 0.5f, 1.0f, 2.0f, 4.0f, 8.0f }; @@ -90,13 +90,13 @@ AutomationEditor::AutomationEditor() : m_bottomLevel( 0 ), m_topLevel( 0 ), m_currentPosition(), - m_action( NONE ), + m_action( Action::None ), m_drawLastLevel( 0.0f ), m_drawLastTick( 0 ), m_ppb( DEFAULT_PPB ), m_y_delta( DEFAULT_Y_DELTA ), m_y_auto( true ), - m_editMode( DRAW ), + m_editMode( EditMode::Draw ), m_mouseDownLeft(false), m_mouseDownRight( false ), m_scrollBack( false ), @@ -147,9 +147,9 @@ AutomationEditor::AutomationEditor() : // add time-line m_timeLine = new TimeLineWidget( VALUES_WIDTH, 0, m_ppb, Engine::getSong()->getPlayPos( - Song::Mode_PlayAutomationClip ), + Song::PlayMode::AutomationClip ), m_currentPosition, - Song::Mode_PlayAutomationClip, this ); + Song::PlayMode::AutomationClip, this ); connect( this, SIGNAL( positionChanged( const lmms::TimePos& ) ), m_timeLine, SLOT( updatePosition( const lmms::TimePos& ) ) ); connect( m_timeLine, SIGNAL( positionChanged( const lmms::TimePos& ) ), @@ -492,15 +492,15 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent ) // a node, while others require that we know if we clicked the outValue // of a node. bool editingOutValue = ( - m_editMode == DRAW_OUTVALUES - || (m_editMode == ERASE && m_mouseDownRight) + m_editMode == EditMode::DrawOutValues + || (m_editMode == EditMode::Erase && m_mouseDownRight) ); timeMap::iterator clickedNode = getNodeAt(mouseEvent->x(), mouseEvent->y(), editingOutValue); switch (m_editMode) { - case DRAW: + case EditMode::Draw: { m_clip->addJournalCheckPoint(); @@ -518,7 +518,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent ) m_drawLastLevel = level; // Changes the action to drawing a line of nodes - m_action = DRAW_LINE; + m_action = Action::DrawLine; } else // No shift, we are just creating/moving nodes { @@ -540,8 +540,8 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent ) // is being dragged, so if we don't update it we have a bogus iterator clickedNode = tm.find(newTime); - // Set the action to MOVE_VALUE so moveMouseEvent() knows we are moving a node - m_action = MOVE_VALUE; + // Set the action to Action::MoveValue so moveMouseEvent() knows we are moving a node + m_action = Action::MoveValue; // Calculate the offset from the place the mouse click happened in comparison // to the center of the node @@ -559,7 +559,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent ) Engine::getSong()->setModified(); } - else if (m_mouseDownRight) // Right click on DRAW mode erases values + else if (m_mouseDownRight) // Right click on EditMode::Draw mode erases values { // Update the last clicked position so we remove all nodes from // that point up to the point we release the mouse button @@ -568,11 +568,11 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent ) // If we right-clicked a node, remove it eraseNode(clickedNode); - m_action = ERASE_VALUES; + m_action = Action::EraseValues; } break; } - case ERASE: + case EditMode::Erase: { m_clip->addJournalCheckPoint(); @@ -586,7 +586,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent ) // If we right-clicked a node, remove it eraseNode(clickedNode); - m_action = ERASE_VALUES; + m_action = Action::EraseValues; } else if (m_mouseDownRight) // And right click resets outValues { @@ -597,11 +597,11 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent ) // that point up to the point we release the mouse button m_drawLastTick = posTicks; - m_action = RESET_OUTVALUES; + m_action = Action::ResetOutValues; } break; } - case DRAW_OUTVALUES: + case EditMode::DrawOutValues: { m_clip->addJournalCheckPoint(); @@ -615,7 +615,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent ) clickedNode.value().setOutValue(level); - m_action = MOVE_OUTVALUE; + m_action = Action::MoveOutValue; Engine::getSong()->setModified(); } @@ -635,7 +635,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent ) m_draggedOutValueKey = POS(clickedNode); clickedNode.value().setOutValue(level); - m_action = MOVE_OUTVALUE; + m_action = Action::MoveOutValue; Engine::getSong()->setModified(); } @@ -650,7 +650,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent ) // that point up to the point we release the mouse button m_drawLastTick = posTicks; - m_action = RESET_OUTVALUES; + m_action = Action::ResetOutValues; } break; } @@ -671,13 +671,13 @@ void AutomationEditor::mouseDoubleClickEvent(QMouseEvent * mouseEvent) if (mouseEvent->y() <= TOP_MARGIN || mouseEvent->x() < VALUES_WIDTH) { return; } // Are we fine tuning the inValue or outValue? - const bool isOutVal = (m_editMode == DRAW_OUTVALUES); + const bool isOutVal = (m_editMode == EditMode::DrawOutValues); timeMap::iterator clickedNode = getNodeAt(mouseEvent->x(), mouseEvent->y(), isOutVal); switch (m_editMode) { - case DRAW: - case DRAW_OUTVALUES: + case EditMode::Draw: + case EditMode::DrawOutValues: if (fineTuneValue(clickedNode, isOutVal)) { update(); } break; default: @@ -703,9 +703,9 @@ void AutomationEditor::mouseReleaseEvent(QMouseEvent * mouseEvent ) mustRepaint = true; } - if (m_editMode == DRAW) + if (m_editMode == EditMode::Draw) { - if (m_action == MOVE_VALUE) + if (m_action == Action::MoveValue) { // Actually apply the value of the node being dragged m_clip->applyDragValue(); @@ -714,7 +714,7 @@ void AutomationEditor::mouseReleaseEvent(QMouseEvent * mouseEvent ) QApplication::restoreOverrideCursor(); } - m_action = NONE; + m_action = Action::None; if (mustRepaint) { repaint(); } } @@ -742,12 +742,12 @@ void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent ) switch (m_editMode) { - case DRAW: + case EditMode::Draw: { // We are dragging a node if (m_mouseDownLeft) { - if (m_action == MOVE_VALUE) + if (m_action == Action::MoveValue) { // When we clicked the node, we might have clicked slightly off // so we account for that offset for a smooth drag @@ -770,7 +770,7 @@ void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent ) Engine::getSong()->setModified(); } - /* else if (m_action == DRAW_LINE) + /* else if (m_action == Action::DrawLine) { // We are drawing a line. For now do nothing (as before), but later logic // could be added here so the line is updated according to the new mouse position @@ -779,7 +779,7 @@ void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent ) } else if (m_mouseDownRight) // We are removing nodes { - if (m_action == ERASE_VALUES) + if (m_action == Action::EraseValues) { // If we moved the mouse past the beginning correct the position in ticks posTicks = qMax(posTicks, 0); @@ -794,7 +794,7 @@ void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent ) } break; } - case ERASE: + case EditMode::Erase: { // If we moved the mouse past the beginning correct the position in ticks posTicks = qMax(posTicks, 0); @@ -802,7 +802,7 @@ void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent ) // Left button removes nodes if (m_mouseDownLeft) { - if (m_action == ERASE_VALUES) + if (m_action == Action::EraseValues) { // Removing automation nodes @@ -814,7 +814,7 @@ void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent ) } else if (m_mouseDownRight) // Right button resets outValues { - if (m_action == RESET_OUTVALUES) + if (m_action == Action::ResetOutValues) { // Reseting outValues @@ -826,7 +826,7 @@ void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent ) } break; } - case DRAW_OUTVALUES: + case EditMode::DrawOutValues: { // If we moved the mouse past the beginning correct the position in ticks posTicks = qMax(posTicks, 0); @@ -834,7 +834,7 @@ void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent ) // Left button moves outValues if (m_mouseDownLeft) { - if (m_action == MOVE_OUTVALUE) + if (m_action == Action::MoveOutValue) { // We are moving the outValue of the node timeMap & tm = m_clip->getTimeMap(); @@ -850,7 +850,7 @@ void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent ) } else if (m_mouseDownRight) // Right button resets them { - if (m_action == RESET_OUTVALUES) + if (m_action == Action::ResetOutValues) { // Reseting outValues @@ -1172,7 +1172,7 @@ void AutomationEditor::paintEvent(QPaintEvent * pe ) // the value of the end of the shape between the two nodes will be the inValue of // the next node. float nextValue; - if( m_clip->progressionType() == AutomationClip::DiscreteProgression ) + if( m_clip->progressionType() == AutomationClip::ProgressionType::Discrete ) { nextValue = OUTVAL(it); } @@ -1248,22 +1248,22 @@ void AutomationEditor::paintEvent(QPaintEvent * pe ) // draw current edit-mode-icon below the cursor switch( m_editMode ) { - case DRAW: + case EditMode::Draw: { - if (m_action == ERASE_VALUES) { cursor = s_toolErase; } - else if (m_action == MOVE_VALUE) { cursor = s_toolMove; } + if (m_action == Action::EraseValues) { cursor = s_toolErase; } + else if (m_action == Action::MoveValue) { cursor = s_toolMove; } else { cursor = s_toolDraw; } break; } - case ERASE: + case EditMode::Erase: { cursor = s_toolErase; break; } - case DRAW_OUTVALUES: + case EditMode::DrawOutValues: { - if (m_action == RESET_OUTVALUES) { cursor = s_toolErase; } - else if (m_action == MOVE_OUTVALUE) { cursor = s_toolMove; } + if (m_action == Action::ResetOutValues) { cursor = s_toolErase; } + else if (m_action == Action::MoveOutValue) { cursor = s_toolMove; } else { cursor = s_toolDrawOut; } break; } @@ -1400,7 +1400,7 @@ void AutomationEditor::resizeEvent(QResizeEvent * re) if( Engine::getSong() ) { - Engine::getSong()->getPlayPos( Song::Mode_PlayAutomationClip + Engine::getSong()->getPlayPos( Song::PlayMode::AutomationClip ).m_timeLine->setFixedWidth( width() ); } @@ -1525,7 +1525,7 @@ void AutomationEditor::play() if( !m_clip->getTrack() ) { - if( Engine::getSong()->playMode() != Song::Mode_PlayMidiClip ) + if( Engine::getSong()->playMode() != Song::PlayMode::MidiClip ) { Engine::getSong()->stop(); Engine::getSong()->playMidiClip( getGUI()->pianoRoll()->currentMidiClip() ); @@ -1599,7 +1599,7 @@ void AutomationEditor::verScrolled(int new_pos ) -void AutomationEditor::setEditMode(AutomationEditor::EditModes mode) +void AutomationEditor::setEditMode(AutomationEditor::EditMode mode) { if (m_editMode == mode) return; @@ -1614,13 +1614,13 @@ void AutomationEditor::setEditMode(AutomationEditor::EditModes mode) void AutomationEditor::setEditMode(int mode) { - setEditMode((AutomationEditor::EditModes) mode); + setEditMode((AutomationEditor::EditMode) mode); } -void AutomationEditor::setProgressionType(AutomationClip::ProgressionTypes type) +void AutomationEditor::setProgressionType(AutomationClip::ProgressionType type) { if (validClip()) { @@ -1633,7 +1633,7 @@ void AutomationEditor::setProgressionType(AutomationClip::ProgressionTypes type) void AutomationEditor::setProgressionType(int type) { - setProgressionType((AutomationClip::ProgressionTypes) type); + setProgressionType((AutomationClip::ProgressionType) type); } @@ -1655,7 +1655,7 @@ void AutomationEditor::updatePosition(const TimePos & t ) { if( ( Engine::getSong()->isPlaying() && Engine::getSong()->playMode() == - Song::Mode_PlayAutomationClip ) || + Song::PlayMode::AutomationClip ) || m_scrollBack == true ) { const int w = width() - VALUES_WIDTH; @@ -1877,7 +1877,7 @@ AutomationEditorWindow::AutomationEditorWindow() : connect(progression_type_group, SIGNAL(triggered(int)), m_editor, SLOT(setProgressionType(int))); // setup tension-stuff - m_tensionKnob = new Knob( knobSmall_17, this, "Tension" ); + m_tensionKnob = new Knob( KnobType::Small17, this, "Tension" ); m_tensionKnob->setModel(m_editor->m_tensionModel); m_tensionKnob->setToolTip(tr("Tension value for spline")); @@ -1989,15 +1989,15 @@ void AutomationEditorWindow::setCurrentClip(AutomationClip* clip) switch(m_editor->m_clip->progressionType()) { - case AutomationClip::DiscreteProgression: + case AutomationClip::ProgressionType::Discrete: m_discreteAction->setChecked(true); m_tensionKnob->setEnabled(false); break; - case AutomationClip::LinearProgression: + case AutomationClip::ProgressionType::Linear: m_linearAction->setChecked(true); m_tensionKnob->setEnabled(false); break; - case AutomationClip::CubicHermiteProgression: + case AutomationClip::ProgressionType::CubicHermite: m_cubicHermiteAction->setChecked(true); m_tensionKnob->setEnabled(true); break; diff --git a/src/gui/editors/PatternEditor.cpp b/src/gui/editors/PatternEditor.cpp index b2d2f5c3f..5237690a7 100644 --- a/src/gui/editors/PatternEditor.cpp +++ b/src/gui/editors/PatternEditor.cpp @@ -69,11 +69,11 @@ void PatternEditor::cloneSteps() void PatternEditor::removeSteps() { - TrackContainer::TrackList tl = model()->tracks(); + const TrackContainer::TrackList& tl = model()->tracks(); for (const auto& track : tl) { - if (track->type() == Track::InstrumentTrack) + if (track->type() == Track::Type::Instrument) { auto p = static_cast(track->getClip(m_ps->currentPattern())); p->removeSteps(); @@ -86,7 +86,7 @@ void PatternEditor::removeSteps() void PatternEditor::addSampleTrack() { - (void) Track::create( Track::SampleTrack, model() ); + (void) Track::create( Track::Type::Sample, model() ); } @@ -94,7 +94,7 @@ void PatternEditor::addSampleTrack() void PatternEditor::addAutomationTrack() { - (void) Track::create( Track::AutomationTrack, model() ); + (void) Track::create( Track::Type::Automation, model() ); } @@ -176,11 +176,11 @@ void PatternEditor::updatePosition() void PatternEditor::makeSteps( bool clone ) { - TrackContainer::TrackList tl = model()->tracks(); + const TrackContainer::TrackList& tl = model()->tracks(); for (const auto& track : tl) { - if (track->type() == Track::InstrumentTrack) + if (track->type() == Track::Type::Instrument) { auto p = static_cast(track->getClip(m_ps->currentPattern())); if( clone ) @@ -306,7 +306,7 @@ QSize PatternEditorWindow::sizeHint() const void PatternEditorWindow::play() { - if (Engine::getSong()->playMode() != Song::Mode_PlayPattern) + if (Engine::getSong()->playMode() != Song::PlayMode::Pattern) { Engine::getSong()->playPattern(); } diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index adc1997b9..b38335995 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -113,7 +113,7 @@ const int RESIZE_AREA_WIDTH = 9; const int NOTE_EDIT_LINE_WIDTH = 3; // key where to start -const int INITIAL_START_KEY = Key_C + Octave_4 * KeysPerOctave; +const int INITIAL_START_KEY = Octave::Octave_4 + Key::C; // number of each note to provide in quantization and note lengths const int NUM_EVEN_LENGTHS = 6; @@ -138,25 +138,24 @@ static QString getNoteString(int key) } // used for drawing of piano -std::array PianoRoll::prKeyOrder +std::array PianoRoll::prKeyOrder { - PR_WHITE_KEY_SMALL, PR_BLACK_KEY, PR_WHITE_KEY_BIG, PR_BLACK_KEY, - PR_WHITE_KEY_SMALL, PR_WHITE_KEY_SMALL, PR_BLACK_KEY, PR_WHITE_KEY_BIG, - PR_BLACK_KEY, PR_WHITE_KEY_BIG, PR_BLACK_KEY, PR_WHITE_KEY_SMALL + KeyType::WhiteSmall, KeyType::Black, KeyType::WhiteBig, KeyType::Black, + KeyType::WhiteSmall, KeyType::WhiteSmall, KeyType::Black, KeyType::WhiteBig, + KeyType::Black, KeyType::WhiteBig, KeyType::Black, KeyType::WhiteSmall } ; const int DEFAULT_PR_PPB = DEFAULT_CELL_WIDTH * DefaultStepsPerBar; -const QVector PianoRoll::m_zoomLevels = +const std::vector PianoRoll::m_zoomLevels = {0.125f, 0.25f, 0.5f, 1.0f, 1.5f, 2.0f, 4.0f, 8.0f}; -const QVector PianoRoll::m_zoomYLevels = +const std::vector PianoRoll::m_zoomYLevels = {0.25f, 0.5f, 1.0f, 1.5f, 2.0f, 2.5f, 3.0f, 4.0f}; PianoRoll::PianoRoll() : - m_nemStr( QVector() ), m_noteEditMenu( nullptr ), m_semiToneMarkerMenu( nullptr ), m_zoomingModel(), @@ -169,8 +168,8 @@ PianoRoll::PianoRoll() : m_currentPosition(), m_recording( false ), m_currentNote( nullptr ), - m_action( ActionNone ), - m_noteEditMode( NoteEditVolume ), + m_action( Action::None ), + m_noteEditMode( NoteEditMode::Volume ), m_moveBoundaryLeft( 0 ), m_moveBoundaryTop( 0 ), m_moveBoundaryRight( 0 ), @@ -192,8 +191,8 @@ PianoRoll::PianoRoll() : m_minResizeLen( 0 ), m_startKey( INITIAL_START_KEY ), m_lastKey( 0 ), - m_editMode( ModeDraw ), - m_ctrlMode( ModeDraw ), + m_editMode( EditMode::Draw ), + m_ctrlMode( EditMode::Draw ), m_mouseDownRight( false ), m_scrollBack( false ), m_stepRecorderWidget(this, DEFAULT_PR_PPB, PR_TOP_MARGIN, PR_BOTTOM_MARGIN + m_notesEditHeight, WHITE_KEY_WIDTH, 0), @@ -242,12 +241,12 @@ PianoRoll::PianoRoll() : auto unmarkAllAction = new QAction(tr("Unmark all"), this); auto copyAllNotesAction = new QAction(tr("Select all notes on this key"), this); - connect( markSemitoneAction, &QAction::triggered, [this](){ markSemiTone(stmaMarkCurrentSemiTone); }); - connect( markAllOctaveSemitonesAction, &QAction::triggered, [this](){ markSemiTone(stmaMarkAllOctaveSemiTones); }); - connect( markScaleAction, &QAction::triggered, [this](){ markSemiTone(stmaMarkCurrentScale); }); - connect( markChordAction, &QAction::triggered, [this](){ markSemiTone(stmaMarkCurrentChord); }); - connect( unmarkAllAction, &QAction::triggered, [this](){ markSemiTone(stmaUnmarkAll); }); - connect( copyAllNotesAction, &QAction::triggered, [this](){ markSemiTone(stmaCopyAllNotesOnKey); }); + connect( markSemitoneAction, &QAction::triggered, [this](){ markSemiTone(SemiToneMarkerAction::MarkCurrentSemiTone); }); + connect( markAllOctaveSemitonesAction, &QAction::triggered, [this](){ markSemiTone(SemiToneMarkerAction::MarkAllOctaveSemiTones); }); + connect( markScaleAction, &QAction::triggered, [this](){ markSemiTone(SemiToneMarkerAction::MarkCurrentScale); }); + connect( markChordAction, &QAction::triggered, [this](){ markSemiTone(SemiToneMarkerAction::MarkCurrentChord); }); + connect( unmarkAllAction, &QAction::triggered, [this](){ markSemiTone(SemiToneMarkerAction::UnmarkAll); }); + connect( copyAllNotesAction, &QAction::triggered, [this](){ markSemiTone(SemiToneMarkerAction::CopyAllNotesOnKey); }); markScaleAction->setEnabled( false ); markChordAction->setEnabled( false ); @@ -299,9 +298,9 @@ PianoRoll::PianoRoll() : // add time-line m_timeLine = new TimeLineWidget(m_whiteKeyWidth, 0, m_ppb, Engine::getSong()->getPlayPos( - Song::Mode_PlayMidiClip ), + Song::PlayMode::MidiClip ), m_currentPosition, - Song::Mode_PlayMidiClip, this ); + Song::PlayMode::MidiClip, this ); connect( this, SIGNAL( positionChanged( const lmms::TimePos& ) ), m_timeLine, SLOT( updatePosition( const lmms::TimePos& ) ) ); connect( m_timeLine, SIGNAL( positionChanged( const lmms::TimePos& ) ), @@ -315,12 +314,12 @@ PianoRoll::PianoRoll() : this, SLOT( updatePositionStepRecording( const lmms::TimePos& ) ) ); // update timeline when in record-accompany mode - connect( Engine::getSong()->getPlayPos( Song::Mode_PlaySong ).m_timeLine, + connect( Engine::getSong()->getPlayPos( Song::PlayMode::Song ).m_timeLine, SIGNAL( positionChanged( const lmms::TimePos& ) ), this, SLOT( updatePositionAccompany( const lmms::TimePos& ) ) ); // TODO -/* connect( engine::getSong()->getPlayPos( Song::Mode_PlayPattern ).m_timeLine, +/* connect( engine::getSong()->getPlayPos( Song::PlayMode::Pattern ).m_timeLine, SIGNAL( positionChanged( const lmms::TimePos& ) ), this, SLOT( updatePositionAccompany( const lmms::TimePos& ) ) );*/ @@ -406,7 +405,7 @@ PianoRoll::PianoRoll() : InstrumentFunctionNoteStacking::ChordTable::getInstance(); m_scaleModel.addItem( tr("No scale") ); - for( const InstrumentFunctionNoteStacking::Chord& chord : chord_table ) + for (const InstrumentFunctionNoteStacking::Chord& chord : chord_table.chords()) { if( chord.isScale() ) { @@ -423,7 +422,7 @@ PianoRoll::PianoRoll() : // Set up chord model m_chordModel.addItem( tr("No chord") ); - for( const InstrumentFunctionNoteStacking::Chord& chord : chord_table ) + for (const InstrumentFunctionNoteStacking::Chord& chord : chord_table.chords()) { if( ! chord.isScale() ) { @@ -525,7 +524,7 @@ void PianoRoll::changeNoteEditMode( int i ) } -void PianoRoll::markSemiTone(int i, bool fromMenu) +void PianoRoll::markSemiTone(SemiToneMarkerAction i, bool fromMenu) { const int key = fromMenu ? getKey(mapFromGlobal(m_semiToneMarkerMenu->pos()).y()) @@ -534,14 +533,14 @@ void PianoRoll::markSemiTone(int i, bool fromMenu) // if "No key" is selected, key is -1, unmark all semitones // or if scale changed from toolbar to "No scale", unmark all semitones - if (!fromMenu && (key < 0 || m_scaleModel.value() == 0)) { i = stmaUnmarkAll; } + if (!fromMenu && (key < 0 || m_scaleModel.value() == 0)) { i = SemiToneMarkerAction::UnmarkAll; } - switch( static_cast( i ) ) + switch(i) { - case stmaUnmarkAll: + case SemiToneMarkerAction::UnmarkAll: m_markedSemiTones.clear(); break; - case stmaMarkCurrentSemiTone: + case SemiToneMarkerAction::MarkCurrentSemiTone: { QList::iterator it = std::find( m_markedSemiTones.begin(), m_markedSemiTones.end(), key ); if( it != m_markedSemiTones.end() ) @@ -554,7 +553,7 @@ void PianoRoll::markSemiTone(int i, bool fromMenu) } break; } - case stmaMarkAllOctaveSemiTones: + case SemiToneMarkerAction::MarkAllOctaveSemiTones: { QList aok = getAllOctavesForKey(key); @@ -579,10 +578,10 @@ void PianoRoll::markSemiTone(int i, bool fromMenu) break; } - case stmaMarkCurrentScale: + case SemiToneMarkerAction::MarkCurrentScale: chord = & InstrumentFunctionNoteStacking::ChordTable::getInstance() .getScaleByName( m_scaleModel.currentText() ); - case stmaMarkCurrentChord: + case SemiToneMarkerAction::MarkCurrentChord: { if( ! chord ) { @@ -612,7 +611,7 @@ void PianoRoll::markSemiTone(int i, bool fromMenu) } break; } - case stmaCopyAllNotesOnKey: + case SemiToneMarkerAction::CopyAllNotesOnKey: { selectNotesOnKey(); break; @@ -742,10 +741,10 @@ void PianoRoll::fitNoteLengths(bool fill) { if (!hasValidMidiClip()) { return; } m_midiClip->addJournalCheckPoint(); + m_midiClip->rearrangeAllNotes(); // Reference notes - NoteVector refNotes = m_midiClip->notes(); - std::sort(refNotes.begin(), refNotes.end(), Note::lessThan); + const NoteVector& refNotes = m_midiClip->notes(); // Notes to edit NoteVector notes = getSelectedNotes(); @@ -763,7 +762,7 @@ void PianoRoll::fitNoteLengths(bool fill) } int length; - NoteVector::iterator ref = refNotes.begin(); + auto ref = refNotes.begin(); for (Note* note : notes) { // Fast forward to next reference note @@ -775,7 +774,7 @@ void PianoRoll::fitNoteLengths(bool fill) { if (!fill) { break; } // Last notes stretch to end of last bar - length = notes.last()->endPos().nextFullBar() * TimePos::ticksPerBar() - note->pos(); + length = notes.back()->endPos().nextFullBar() * TimePos::ticksPerBar() - note->pos(); } else { @@ -798,14 +797,11 @@ void PianoRoll::constrainNoteLengths(bool constrainMax) if (!hasValidMidiClip()) { return; } m_midiClip->addJournalCheckPoint(); - NoteVector notes = getSelectedNotes(); - if (notes.empty()) - { - notes = m_midiClip->notes(); - } + const NoteVector selectedNotes = getSelectedNotes(); + const auto& notes = selectedNotes.empty() ? m_midiClip->notes() : selectedNotes; - TimePos bound = m_lenOfNewNotes; // will be length of last note - for (Note* note : notes) + TimePos bound = m_lenOfNewNotes; // will be length of last note + for (auto note : notes) { if (constrainMax ? note->length() > bound : note->length() < bound) { @@ -859,7 +855,7 @@ void PianoRoll::setCurrentMidiClip( MidiClip* newMidiClip ) } // force the song-editor to stop playing if it played a MIDI clip before - if (Engine::getSong()->playMode() == Song::Mode_PlayMidiClip) + if (Engine::getSong()->playMode() == Song::PlayMode::MidiClip) { Engine::getSong()->playMidiClip( nullptr ); } @@ -1147,12 +1143,12 @@ void PianoRoll::drawDetuningInfo( QPainter & _p, const Note * _n, int _x, // node to the other switch (_n->detuning()->automationClip()->progressionType()) { - case AutomationClip::DiscreteProgression: + case AutomationClip::ProgressionType::Discrete: _p.drawLine(old_x, pre_y, cur_x, pre_y); _p.drawLine(cur_x, pre_y, cur_x, cur_y); break; - case AutomationClip::CubicHermiteProgression: /* TODO */ - case AutomationClip::LinearProgression: + case AutomationClip::ProgressionType::CubicHermite: /* TODO */ + case AutomationClip::ProgressionType::Linear: _p.drawLine(old_x, pre_y, cur_x, cur_y); break; } @@ -1208,11 +1204,11 @@ void PianoRoll::shiftSemiTone(int amount) //Shift notes by amount semitones auto selectedNotes = getSelectedNotes(); //If no notes are selected, shift all of them, otherwise shift selection - if (selectedNotes.empty()) { return shiftSemiTone(m_midiClip->notes(), amount); } - else { return shiftSemiTone(selectedNotes, amount); } + if (selectedNotes.empty()) { shiftSemiTone(m_midiClip->notes(), amount); } + else { shiftSemiTone(selectedNotes, amount); } } -void PianoRoll::shiftSemiTone(NoteVector notes, int amount) +void PianoRoll::shiftSemiTone(const NoteVector& notes, int amount) { m_midiClip->addJournalCheckPoint(); for (Note *note : notes) { note->setKey( note->key() + amount ); } @@ -1233,19 +1229,19 @@ void PianoRoll::shiftPos(int amount) //Shift notes pos by amount auto selectedNotes = getSelectedNotes(); //If no notes are selected, shift all of them, otherwise shift selection - if (selectedNotes.empty()) { return shiftPos(m_midiClip->notes(), amount); } - else { return shiftPos(selectedNotes, amount); } + if (selectedNotes.empty()) { shiftPos(m_midiClip->notes(), amount); } + else { shiftPos(selectedNotes, amount); } } -void PianoRoll::shiftPos(NoteVector notes, int amount) +void PianoRoll::shiftPos(const NoteVector& notes, int amount) { m_midiClip->addJournalCheckPoint(); - if (notes.isEmpty()) { + if (notes.empty()) { return; } - auto leftMostPos = notes.first()->pos(); + auto leftMostPos = notes.front()->pos(); //Limit leftwards shifts to prevent moving left of clip start auto shiftAmount = (leftMostPos > -amount) ? amount : -leftMostPos; if (shiftAmount == 0) { return; } @@ -1300,7 +1296,7 @@ void PianoRoll::keyPressEvent(QKeyEvent* ke) if( hasValidMidiClip() && ke->modifiers() == Qt::NoModifier ) { - const int key_num = PianoView::getKeyFromKeyEvent( ke ) + ( DefaultOctave - 1 ) * KeysPerOctave; + const int key_num = PianoView::getKeyFromKeyEvent( ke ); if (!ke->isAutoRepeat() && key_num > -1) { @@ -1317,7 +1313,7 @@ void PianoRoll::keyPressEvent(QKeyEvent* ke) case Qt::Key_Down: { int direction = (ke->key() == Qt::Key_Up ? +1 : -1); - if( ( ke->modifiers() & Qt::ControlModifier ) && m_action == ActionNone ) + if( ( ke->modifiers() & Qt::ControlModifier ) && m_action == Action::None ) { // shift selection by one octave // if nothing selected, shift _everything_ @@ -1335,7 +1331,7 @@ void PianoRoll::keyPressEvent(QKeyEvent* ke) } } } - else if((ke->modifiers() & Qt::ShiftModifier) && m_action == ActionNone) + else if((ke->modifiers() & Qt::ShiftModifier) && m_action == Action::None) { // Move selected notes by one semitone if (hasValidMidiClip()) @@ -1351,8 +1347,8 @@ void PianoRoll::keyPressEvent(QKeyEvent* ke) // if they are moving notes around or resizing, // recalculate the note/resize position - if( m_action == ActionMoveNote || - m_action == ActionResizeNote ) + if( m_action == Action::MoveNote || + m_action == Action::ResizeNote ) { dragNotes( m_lastMouseX, @@ -1371,7 +1367,7 @@ void PianoRoll::keyPressEvent(QKeyEvent* ke) case Qt::Key_Left: { int direction = (ke->key() == Qt::Key_Right ? +1 : -1); - if( ke->modifiers() & Qt::ControlModifier && m_action == ActionNone ) + if( ke->modifiers() & Qt::ControlModifier && m_action == Action::None ) { // Move selected notes by one bar to the left if (hasValidMidiClip()) @@ -1379,7 +1375,7 @@ void PianoRoll::keyPressEvent(QKeyEvent* ke) shiftPos( direction * TimePos::ticksPerBar() ); } } - else if( ke->modifiers() & Qt::ShiftModifier && m_action == ActionNone) + else if( ke->modifiers() & Qt::ShiftModifier && m_action == Action::None) { // move notes if (hasValidMidiClip()) @@ -1410,8 +1406,8 @@ void PianoRoll::keyPressEvent(QKeyEvent* ke) // if they are moving notes around or resizing, // recalculate the note/resize position - if( m_action == ActionMoveNote || - m_action == ActionResizeNote ) + if( m_action == Action::MoveNote || + m_action == Action::ResizeNote ) { dragNotes( m_lastMouseX, @@ -1447,7 +1443,7 @@ void PianoRoll::keyPressEvent(QKeyEvent* ke) case Qt::Key_Escape: // On the Knife mode, ESC cancels it - if (m_editMode == ModeEditKnife) + if (m_editMode == EditMode::Knife) { cancelKnifeAction(); } @@ -1502,7 +1498,7 @@ void PianoRoll::keyPressEvent(QKeyEvent* ke) case Qt::Key_Control: // Ctrl will not enter selection mode if we are // in Knife mode, but unquantize it - if (m_editMode == ModeEditKnife) + if (m_editMode == EditMode::Knife) { break; } @@ -1513,7 +1509,7 @@ void PianoRoll::keyPressEvent(QKeyEvent* ke) if ( !( ke->modifiers() & Qt::ShiftModifier ) && isActiveWindow() ) { m_ctrlMode = m_editMode; - m_editMode = ModeSelect; + m_editMode = EditMode::Select; setCursor( Qt::ArrowCursor ); ke->accept(); } @@ -1532,7 +1528,7 @@ void PianoRoll::keyReleaseEvent(QKeyEvent* ke ) { if( hasValidMidiClip() && ke->modifiers() == Qt::NoModifier ) { - const int key_num = PianoView::getKeyFromKeyEvent( ke ) + ( DefaultOctave - 1 ) * KeysPerOctave; + const int key_num = PianoView::getKeyFromKeyEvent( ke ); if (!ke->isAutoRepeat() && key_num > -1) { m_midiClip->instrumentTrack()->pianoModel()->handleKeyRelease(key_num); @@ -1545,7 +1541,7 @@ void PianoRoll::keyReleaseEvent(QKeyEvent* ke ) switch( ke->key() ) { case Qt::Key_Control: - if (m_editMode == ModeEditKnife) + if (m_editMode == EditMode::Knife) { break; } @@ -1638,14 +1634,14 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) } // -- Knife - if (m_editMode == ModeEditKnife && me->button() == Qt::LeftButton) + if (m_editMode == EditMode::Knife && me->button() == Qt::LeftButton) { NoteVector n; Note* note = noteUnderMouse(); if (note) { - n.append(note); + n.push_back(note); updateKnifePos(me); @@ -1657,7 +1653,7 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) return; } - if( m_editMode == ModeEditDetuning && noteUnderMouse() ) + if( m_editMode == EditMode::Detuning && noteUnderMouse() ) { static QPointer detuningClip = nullptr; if (detuningClip.data() != nullptr) @@ -1676,10 +1672,10 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) } // if holding control, go to selection mode unless shift is also pressed - if( me->modifiers() & Qt::ControlModifier && m_editMode != ModeSelect ) + if( me->modifiers() & Qt::ControlModifier && m_editMode != EditMode::Select ) { m_ctrlMode = m_editMode; - m_editMode = ModeSelect; + m_editMode = EditMode::Select; setCursor( Qt::ArrowCursor ); update(); } @@ -1695,7 +1691,7 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) me->y() > keyAreaBottom() && me->y() < noteEditTop()) { // resizing the note edit area - m_action = ActionResizeNoteEditArea; + m_action = Action::ResizeNoteEditArea; return; } @@ -1723,7 +1719,7 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) const NoteVector & notes = m_midiClip->notes(); // will be our iterator in the following loop - NoteVector::ConstIterator it = notes.begin()+notes.size()-1; + auto it = notes.begin() + notes.size() - 1; // loop through whole note-vector... for( int i = 0; i < notes.size(); ++i ) @@ -1765,7 +1761,7 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) } // left button?? else if( me->button() == Qt::LeftButton && - m_editMode == ModeDraw ) + m_editMode == EditMode::Draw ) { // whether this action creates new note(s) or not bool is_new_note = false; @@ -1846,9 +1842,9 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) auto selectedNotes = getSelectedNotes(); - m_moveBoundaryLeft = selectedNotes.first()->pos().getTicks(); - m_moveBoundaryRight = selectedNotes.first()->endPos(); - m_moveBoundaryBottom = selectedNotes.first()->key(); + m_moveBoundaryLeft = selectedNotes.front()->pos().getTicks(); + m_moveBoundaryRight = selectedNotes.front()->endPos(); + m_moveBoundaryBottom = selectedNotes.front()->key(); m_moveBoundaryTop = m_moveBoundaryBottom; //Figure out the bounding box of all the selected notes @@ -1872,7 +1868,7 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) { m_midiClip->addJournalCheckPoint(); // then resize the note - m_action = ActionResizeNote; + m_action = Action::ResizeNote; //Calculate the minimum length we should allow when resizing //each note, and let all notes use the smallest one found @@ -1902,7 +1898,7 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) } // otherwise move it - m_action = ActionMoveNote; + m_action = Action::MoveNote; // set move-cursor setCursor( Qt::SizeAllCursor ); @@ -1932,8 +1928,8 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) Engine::getSong()->setModified(); } else if( ( me->buttons() == Qt::RightButton && - m_editMode == ModeDraw ) || - m_editMode == ModeErase ) + m_editMode == EditMode::Draw ) || + m_editMode == EditMode::Erase ) { // erase single note m_mouseDownRight = true; @@ -1945,7 +1941,7 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) } } else if( me->button() == Qt::LeftButton && - m_editMode == ModeSelect ) + m_editMode == EditMode::Select ) { // select an area of notes @@ -1953,7 +1949,7 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) m_selectedTick = 0; m_selectStartKey = key_num; m_selectedKeys = 1; - m_action = ActionSelectNotes; + m_action = Action::SelectNotes; // call mousemove to fix glitch where selection // appears in wrong spot on mousedown @@ -1991,7 +1987,7 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) { // clicked in the box below the keys to the left of note edit area m_noteEditMode = (NoteEditMode)(((int)m_noteEditMode)+1); - if( m_noteEditMode == NoteEditCount ) + if( m_noteEditMode == NoteEditMode::Count ) { m_noteEditMode = (NoteEditMode) 0; } @@ -2036,7 +2032,7 @@ void PianoRoll::mouseDoubleClickEvent(QMouseEvent * me ) { if( i->withinRange( ticks_start, ticks_end ) || ( i->selected() && !altPressed ) ) { - nv += i; + nv.push_back(i); } } // make sure we're on a note @@ -2054,8 +2050,8 @@ void PianoRoll::mouseDoubleClickEvent(QMouseEvent * me ) if( dist < closest_dist ) { closest = i; closest_dist = dist; } } // ... then remove all notes from the vector that aren't on the same exact time - NoteVector::Iterator it = nv.begin(); - while( it != nv.end() ) + auto it = nv.begin(); + while (it != nv.end()) { const Note *note = *it; if( note->pos().getTicks() != closest->pos().getTicks() ) @@ -2164,11 +2160,11 @@ void PianoRoll::pauseChordNotes(int key) void PianoRoll::setKnifeAction() { - if (m_editMode != ModeEditKnife) + if (m_editMode != EditMode::Knife) { m_knifeMode = m_editMode; - m_editMode = ModeEditKnife; - m_action = ActionKnife; + m_editMode = EditMode::Knife; + m_action = Action::Knife; setCursor(Qt::ArrowCursor); update(); } @@ -2177,7 +2173,7 @@ void PianoRoll::setKnifeAction() void PianoRoll::cancelKnifeAction() { m_editMode = m_knifeMode; - m_action = ActionNone; + m_action = Action::None; update(); } @@ -2282,7 +2278,7 @@ void PianoRoll::mouseReleaseEvent( QMouseEvent * me ) s_textFloat->hide(); // Quit knife mode if we pressed and released the right mouse button - if (m_editMode == ModeEditKnife && me->button() == Qt::RightButton) + if (m_editMode == EditMode::Knife && me->button() == Qt::RightButton) { cancelKnifeAction(); } @@ -2291,14 +2287,14 @@ void PianoRoll::mouseReleaseEvent( QMouseEvent * me ) { mustRepaint = true; - if( m_action == ActionSelectNotes && m_editMode == ModeSelect ) + if( m_action == Action::SelectNotes && m_editMode == EditMode::Select ) { // select the notes within the selection rectangle and // then destroy the selection rectangle computeSelectedNotes( me->modifiers() & Qt::ShiftModifier ); } - else if( m_action == ActionMoveNote ) + else if( m_action == Action::MoveNote ) { // we moved one or more notes so they have to be // moved properly according to new starting- @@ -2307,7 +2303,7 @@ void PianoRoll::mouseReleaseEvent( QMouseEvent * me ) } - if( m_action == ActionMoveNote || m_action == ActionResizeNote ) + if( m_action == Action::MoveNote || m_action == Action::ResizeNote ) { // if we only moved one note, deselect it so we can // edit the notes in the note edit area @@ -2346,12 +2342,12 @@ void PianoRoll::mouseReleaseEvent( QMouseEvent * me ) m_currentNote = nullptr; - if (m_action != ActionKnife) + if (m_action != Action::Knife) { - m_action = ActionNone; + m_action = Action::None; } - if( m_editMode == ModeDraw ) + if( m_editMode == EditMode::Draw ) { setCursor( Qt::ArrowCursor ); } @@ -2373,7 +2369,7 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) return; } - if( m_action == ActionNone && me->buttons() == 0 ) + if( m_action == Action::None && me->buttons() == 0 ) { // When cursor is between note editing area and volume/panning // area show vertical size cursor. @@ -2383,7 +2379,7 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) return; } } - else if( m_action == ActionResizeNoteEditArea ) + else if( m_action == Action::ResizeNoteEditArea ) { // Don't try to show more keys than the full keyboard, bail if trying to if (m_pianoKeysVisible == NumKeys && me->y() > m_moveStartY) @@ -2407,22 +2403,22 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) } // Update Knife position if we are on knife mode - if (m_editMode == ModeEditKnife) + if (m_editMode == EditMode::Knife) { updateKnifePos(me); } - if( me->y() > PR_TOP_MARGIN || m_action != ActionNone ) + if( me->y() > PR_TOP_MARGIN || m_action != Action::None ) { bool edit_note = ( me->y() > noteEditTop() ) - && m_action != ActionSelectNotes; + && m_action != Action::SelectNotes; int key_num = getKey( me->y() ); int x = me->x(); // see if they clicked on the keyboard on the left - if (x < m_whiteKeyWidth && m_action == ActionNone + if (x < m_whiteKeyWidth && m_action == Action::None && ! edit_note && key_num != m_lastKey && me->buttons() & Qt::LeftButton ) { @@ -2435,14 +2431,14 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) x -= m_whiteKeyWidth; if( me->buttons() & Qt::LeftButton - && m_editMode == ModeDraw - && (m_action == ActionMoveNote || m_action == ActionResizeNote ) ) + && m_editMode == EditMode::Draw + && (m_action == Action::MoveNote || m_action == Action::ResizeNote ) ) { // handle moving notes and resizing them bool replay_note = key_num != m_lastKey - && m_action == ActionMoveNote; + && m_action == Action::MoveNote; - if( replay_note || ( m_action == ActionMoveNote && ( me->modifiers() & Qt::ShiftModifier ) && ! m_startedWithShift ) ) + if( replay_note || ( m_action == Action::MoveNote && ( me->modifiers() & Qt::ShiftModifier ) && ! m_startedWithShift ) ) { pauseTestNotes(); } @@ -2455,13 +2451,13 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) me->modifiers() & Qt::ControlModifier ); - if( replay_note && m_action == ActionMoveNote && ! ( ( me->modifiers() & Qt::ShiftModifier ) && ! m_startedWithShift ) ) + if( replay_note && m_action == Action::MoveNote && ! ( ( me->modifiers() & Qt::ShiftModifier ) && ! m_startedWithShift ) ) { pauseTestNotes( false ); } } - else if( m_editMode != ModeErase && - ( edit_note || m_action == ActionChangeNoteProperty ) && + else if( m_editMode != EditMode::Erase && + ( edit_note || m_action == Action::ChangeNoteProperty ) && ( me->buttons() & Qt::LeftButton || me->buttons() & Qt::MiddleButton || ( me->buttons() & Qt::RightButton && me->modifiers() & Qt::ShiftModifier ) ) ) { @@ -2502,12 +2498,12 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) PanningRight); } - if( m_noteEditMode == NoteEditVolume ) + if( m_noteEditMode == NoteEditMode::Volume ) { m_lastNoteVolume = vol; showVolTextFloat( vol, me->pos() ); } - else if( m_noteEditMode == NoteEditPanning ) + else if( m_noteEditMode == NoteEditMode::Panning ) { m_lastNotePanning = pan; showPanTextFloat( pan, me->pos() ); @@ -2517,7 +2513,7 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) bool altPressed = me->modifiers() & Qt::AltModifier; // We iterate from last note in MIDI clip to the first, // chronologically - NoteVector::ConstIterator it = notes.begin()+notes.size()-1; + auto it = notes.begin() + notes.size() - 1; for( int i = 0; i < notes.size(); ++i ) { Note* n = *it; @@ -2534,7 +2530,7 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) ( isUnderPosition && n->selected() && altPressed ) ) { - if( m_noteEditMode == NoteEditVolume ) + if( m_noteEditMode == NoteEditMode::Volume ) { n->setVolume( vol ); @@ -2542,7 +2538,7 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) m_midiClip->instrumentTrack()->processInEvent( MidiEvent( MidiKeyPressure, -1, n->key(), n->midiVelocity( baseVelocity ) ) ); } - else if( m_noteEditMode == NoteEditPanning ) + else if( m_noteEditMode == NoteEditMode::Panning ) { n->setPanning( pan ); MidiEvent evt( MidiMetaEvent, -1, n->key(), panningToMidi( pan ) ); @@ -2567,7 +2563,7 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) m_midiClip->dataChanged(); } - else if( me->buttons() == Qt::NoButton && m_editMode == ModeDraw ) + else if( me->buttons() == Qt::NoButton && m_editMode == EditMode::Draw ) { // set move- or resize-cursor @@ -2579,7 +2575,7 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) const NoteVector & notes = m_midiClip->notes(); // will be our iterator in the following loop - NoteVector::ConstIterator it = notes.begin()+notes.size()-1; + auto it = notes.begin() + notes.size() - 1; // loop through whole note-vector... for( int i = 0; i < notes.size(); ++i ) @@ -2620,8 +2616,8 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) } } else if( me->buttons() & Qt::LeftButton && - m_editMode == ModeSelect && - m_action == ActionSelectNotes ) + m_editMode == EditMode::Select && + m_action == Action::SelectNotes ) { // change size of selection @@ -2641,8 +2637,8 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) --m_selectedKeys; } } - else if( ( m_editMode == ModeDraw && me->buttons() & Qt::RightButton ) - || ( m_editMode == ModeErase && me->buttons() ) ) + else if( ( m_editMode == EditMode::Draw && me->buttons() & Qt::RightButton ) + || ( m_editMode == EditMode::Erase && me->buttons() ) ) { // holding down right-click to delete notes or holding down // any key if in erase mode @@ -2656,7 +2652,7 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) const NoteVector & notes = m_midiClip->notes(); // will be our iterator in the following loop - NoteVector::ConstIterator it = notes.begin(); + auto it = notes.begin(); // loop through whole note-vector... while( it != notes.end() ) @@ -2694,7 +2690,7 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) } } } - else if (me->buttons() == Qt::NoButton && m_editMode != ModeDraw && m_editMode != ModeEditKnife) + else if (me->buttons() == Qt::NoButton && m_editMode != EditMode::Draw && m_editMode != EditMode::Knife) { // Is needed to restore cursor when it previously was set to // Qt::SizeVerCursor (between keyAreaBottom and noteEditTop) @@ -2704,8 +2700,8 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) else { if( me->buttons() & Qt::LeftButton && - m_editMode == ModeSelect && - m_action == ActionSelectNotes ) + m_editMode == EditMode::Select && + m_action == Action::SelectNotes ) { int x = me->x() - m_whiteKeyWidth; @@ -2824,11 +2820,11 @@ void PianoRoll::dragNotes(int x, int y, bool alt, bool shift, bool ctrl) // get note-vector of current MIDI clip const NoteVector & notes = m_midiClip->notes(); - if (m_action == ActionMoveNote) + if (m_action == Action::MoveNote) { // Calculate the offset for either Nudge or Snap modes int noteOffset = off_ticks; - if (m_gridMode == gridSnap && quantization () > 1) + if (m_gridMode == GridMode::Snap && quantization () > 1) { // Get the mouse timeline absolute position TimePos mousePos(m_currentNote->oldPos().getTicks() + off_ticks); @@ -2850,7 +2846,7 @@ void PianoRoll::dragNotes(int x, int y, bool alt, bool shift, bool ctrl) ? mousePosEndQ.getTicks() - m_currentNote->oldPos().getTicks() - m_currentNote->oldLength().getTicks() : mousePosQ.getTicks() - m_currentNote->oldPos().getTicks(); } - else if (m_gridMode == gridNudge) + else if (m_gridMode == GridMode::Nudge) { // if they're not holding alt, quantize the offset if (!alt) @@ -2878,7 +2874,7 @@ void PianoRoll::dragNotes(int x, int y, bool alt, bool shift, bool ctrl) { // Quick resize is only enabled on Nudge mode, since resizing the note // while in Snap mode breaks the calculation of the note offset - if (shift && ! m_startedWithShift && m_gridMode == gridNudge) + if (shift && ! m_startedWithShift && m_gridMode == GridMode::Nudge) { // quick resize, toggled by holding shift after starting a note move, but not before int ticks_new = note->oldLength().getTicks() + noteOffset; @@ -2902,7 +2898,7 @@ void PianoRoll::dragNotes(int x, int y, bool alt, bool shift, bool ctrl) } } } - else if (m_action == ActionResizeNote) + else if (m_action == Action::ResizeNote) { // When resizing notes: // If shift is not pressed, resize the selected notes but do not rearrange them @@ -3003,7 +2999,7 @@ void PianoRoll::dragNotes(int x, int y, bool alt, bool shift, bool ctrl) // shift is not pressed; stretch length of selected notes but not their position int minLength = alt ? 1 : m_minResizeLen.getTicks(); - if (m_gridMode == gridSnap) + if (m_gridMode == GridMode::Snap) { // Calculate the end point of the note being dragged TimePos oldEndPoint = m_currentNote->oldPos() + m_currentNote->oldLength(); @@ -3100,7 +3096,7 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) topKey = qBound(0, m_startKey + m_pianoKeysVisible - 1, NumKeys - 1); topNote = topKey % KeysPerOctave; // if not resizing the note edit area, we can change m_notesEditHeight - if (m_action != ActionResizeNoteEditArea && partialKeyVisible != 0) + if (m_action != Action::ResizeNoteEditArea && partialKeyVisible != 0) { // calculate the height change adding and subtracting the partial key int noteAreaPlus = (m_notesEditHeight + partialKeyVisible) - m_userSetNotesEditHeight; @@ -3154,11 +3150,11 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) { switch (prKeyOrder[key % KeysPerOctave]) { - case PR_WHITE_KEY_BIG: + case KeyType::WhiteBig: return m_whiteKeyBigHeight; - case PR_WHITE_KEY_SMALL: + case KeyType::WhiteSmall: return m_whiteKeySmallHeight; - case PR_BLACK_KEY: + case KeyType::Black: return m_blackKeyHeight; } return 0; // should never happen @@ -3171,15 +3167,15 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) const int keyCode = key % KeysPerOctave; switch (prKeyOrder[keyCode]) { - case PR_WHITE_KEY_BIG: + case KeyType::WhiteBig: return m_whiteKeySmallHeight; - case PR_WHITE_KEY_SMALL: + case KeyType::WhiteSmall: // These two keys need to adjust up small height instead of only key line height - if (keyCode == Key_C || keyCode == Key_F) + if (static_cast(keyCode) == Key::C || static_cast(keyCode) == Key::F) { return m_whiteKeySmallHeight; } - case PR_BLACK_KEY: + case KeyType::Black: return m_blackKeyHeight; } return 0; // should never happen @@ -3190,10 +3186,10 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) { switch (prKeyOrder[key % KeysPerOctave]) { - case PR_WHITE_KEY_SMALL: - case PR_WHITE_KEY_BIG: + case KeyType::WhiteSmall: + case KeyType::WhiteBig: return m_whiteKeyWidth; - case PR_BLACK_KEY: + case KeyType::Black: return m_blackKeyWidth; } return 0; // should never happen @@ -3213,8 +3209,8 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) p.setPen(QColor(0, 0, 0)); switch (prKeyOrder[keyCode]) { - case PR_WHITE_KEY_SMALL: - case PR_WHITE_KEY_BIG: + case KeyType::WhiteSmall: + case KeyType::WhiteBig: if (mapped) { if (pressed) { p.setBrush(m_whiteKeyActiveBackground); } @@ -3225,7 +3221,7 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) p.setBrush(m_whiteKeyDisabledBackground); } break; - case PR_BLACK_KEY: + case KeyType::Black: if (mapped) { if (pressed) { p.setBrush(m_blackKeyActiveBackground); } @@ -3239,7 +3235,7 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) // draw key p.drawRect(PIANO_X, yt, kw, kh); // draw note name - if (keyCode == Key_C || (drawNoteNames && Piano::isWhiteKey(key))) + if (static_cast(keyCode) == Key::C || (drawNoteNames && Piano::isWhiteKey(key))) { // small font sizes have 1 pixel offset instead of 2 auto zoomOffset = m_zoomYLevels[m_zoomingYModel.value()] > 1.0f ? 2 : 1; @@ -3253,7 +3249,7 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) p.setPen(pressed ? m_whiteKeyActiveTextShadow : m_whiteKeyInactiveTextShadow); p.drawText(textRect.adjusted(0, 1, 1, 0), Qt::AlignRight | Qt::AlignHCenter, noteString); p.setPen(pressed ? m_whiteKeyActiveTextColor : m_whiteKeyInactiveTextColor); - // if (keyCode == Key_C) { p.setPen(textColor()); } + // if (static_cast(keyCode) == Key::C) { p.setPen(textColor()); } // else { p.setPen(textColorLight()); } p.drawText(textRect, Qt::AlignRight | Qt::AlignHCenter, noteString); } @@ -3264,17 +3260,17 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) const int y ) { - if (key % KeysPerOctave == Key_C) { p.setPen(m_beatLineColor); } + if (static_cast(key % KeysPerOctave) == Key::C) { p.setPen(m_beatLineColor); } else { p.setPen(m_lineColor); } p.drawLine(m_whiteKeyWidth, y, width(), y); }; // correct y offset of the top key switch (prKeyOrder[topNote]) { - case PR_WHITE_KEY_SMALL: - case PR_WHITE_KEY_BIG: + case KeyType::WhiteSmall: + case KeyType::WhiteBig: break; - case PR_BLACK_KEY: + case KeyType::Black: // draw extra white key drawKey(topKey + 1, grid_line_y - m_keyLineHeight); } @@ -3355,11 +3351,11 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) for(x = 0; x < m_markedSemiTones.size(); ++x) { const int key_num = m_markedSemiTones.at(x); - const int y = keyAreaBottom() + 5 - m_keyLineHeight * + const int y = keyAreaBottom() - 1 - m_keyLineHeight * (key_num - m_startKey + 1); - if(y > keyAreaBottom()) { break; } + if(y >= keyAreaBottom() - 1) { break; } p.fillRect(m_whiteKeyWidth + 1, - y - m_keyLineHeight / 2, + y, width() - 10, m_keyLineHeight + 1, m_markedSemitoneColor); @@ -3382,7 +3378,7 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) p.drawText( QRect( 0, keyAreaBottom(), m_whiteKeyWidth, noteEditBottom() - keyAreaBottom()), Qt::AlignCenter | Qt::TextWordWrap, - m_nemStr.at( m_noteEditMode ) + ":" ); + m_nemStr.at(static_cast(m_noteEditMode)) + ":" ); // set clipping area, because we are not allowed to paint over // keyboard... @@ -3508,7 +3504,7 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) // draw note editing stuff int editHandleTop = 0; - if( m_noteEditMode == NoteEditVolume ) + if( m_noteEditMode == NoteEditMode::Volume ) { QColor color = m_barColor.lighter(30 + (note->getVolume() * 90 / MaxVolume)); if( note->selected() ) @@ -3526,7 +3522,7 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) noteEditLeft() + x + 0.5, noteEditBottom() + 0.5 ) ); } - else if( m_noteEditMode == NoteEditPanning ) + else if( m_noteEditMode == NoteEditMode::Panning ) { QColor color = m_noteColor; if( note->selected() ) @@ -3560,7 +3556,7 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) } // -- Knife tool (draw cut line) - if (m_action == ActionKnife) + if (m_action == Action::Knife) { auto xCoordOfTick = [this](int tick) { return m_whiteKeyWidth + ( @@ -3697,12 +3693,12 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) // draw current edit-mode-icon below the cursor switch( m_editMode ) { - case ModeDraw: + case EditMode::Draw: if( m_mouseDownRight ) { cursor = s_toolErase; } - else if( m_action == ActionMoveNote ) + else if( m_action == Action::MoveNote ) { cursor = s_toolMove; } @@ -3711,10 +3707,10 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) cursor = s_toolDraw; } break; - case ModeErase: cursor = s_toolErase; break; - case ModeSelect: cursor = s_toolSelect; break; - case ModeEditDetuning: cursor = s_toolOpen; break; - case ModeEditKnife: cursor = s_toolKnife; break; + case EditMode::Erase: cursor = s_toolErase; break; + case EditMode::Select: cursor = s_toolSelect; break; + case EditMode::Detuning: cursor = s_toolOpen; break; + case EditMode::Knife: cursor = s_toolKnife; break; } QPoint mousePosition = mapFromGlobal( QCursor::pos() ); if( cursor != nullptr && mousePosition.y() > keyAreaTop() && mousePosition.x() > noteEditLeft()) @@ -3757,7 +3753,7 @@ void PianoRoll::resizeEvent(QResizeEvent* re) { updatePositionLineHeight(); updateScrollbars(); - Engine::getSong()->getPlayPos(Song::Mode_PlayMidiClip) + Engine::getSong()->getPlayPos(Song::PlayMode::MidiClip) .m_timeLine->setFixedWidth(width()); update(); } @@ -3789,13 +3785,13 @@ void PianoRoll::wheelEvent(QWheelEvent * we ) { if( i->withinRange( ticks_start, ticks_end ) || ( i->selected() && !altPressed ) ) { - nv += i; + nv.push_back(i); } } if( nv.size() > 0 ) { const int step = we->angleDelta().y() > 0 ? 1 : -1; - if( m_noteEditMode == NoteEditVolume ) + if( m_noteEditMode == NoteEditMode::Volume ) { for ( Note * n : nv ) { @@ -3814,7 +3810,7 @@ void PianoRoll::wheelEvent(QWheelEvent * we ) showVolTextFloat(nv[0]->getVolume(), position(we), 1000); } } - else if( m_noteEditMode == NoteEditPanning ) + else if( m_noteEditMode == NoteEditMode::Panning ) { for ( Note * n : nv ) { @@ -3922,9 +3918,9 @@ void PianoRoll::focusOutEvent( QFocusEvent * ) m_midiClip->instrumentTrack()->pianoModel()->setKeyState( i, false ); } } - if (m_editMode == ModeEditKnife) { + if (m_editMode == EditMode::Knife) { m_editMode = m_knifeMode; - m_action = ActionNone; + m_action = Action::None; } else { m_editMode = m_ctrlMode; } @@ -3969,13 +3965,13 @@ QList PianoRoll::getAllOctavesForKey( int keyToMirror ) const return keys; } -Song::PlayModes PianoRoll::desiredPlayModeForAccompany() const +Song::PlayMode PianoRoll::desiredPlayModeForAccompany() const { if (m_midiClip->getTrack()->trackContainer() == Engine::patternStore()) { - return Song::Mode_PlayPattern; + return Song::PlayMode::Pattern; } - return Song::Mode_PlaySong; + return Song::PlayMode::Song; } @@ -3988,7 +3984,7 @@ void PianoRoll::play() return; } - if( Engine::getSong()->playMode() != Song::Mode_PlayMidiClip ) + if( Engine::getSong()->playMode() != Song::PlayMode::MidiClip ) { Engine::getSong()->playMidiClip( m_midiClip ); } @@ -4066,7 +4062,7 @@ bool PianoRoll::toggleStepRecording() { m_stepRecorder.start( Engine::getSong()->getPlayPos( - Song::Mode_PlayMidiClip), newNoteLen()); + Song::PlayMode::MidiClip), newNoteLen()); } } } @@ -4081,7 +4077,7 @@ void PianoRoll::stop() { Engine::getSong()->stop(); m_recording = false; - m_scrollBack = ( m_timeLine->autoScroll() == TimeLineWidget::AutoScrollEnabled ); + m_scrollBack = ( m_timeLine->autoScroll() == TimeLineWidget::AutoScrollState::Enabled ); } @@ -4094,10 +4090,10 @@ void PianoRoll::startRecordNote(const Note & n ) if( m_recording && Engine::getSong()->isPlaying() && (Engine::getSong()->playMode() == desiredPlayModeForAccompany() || - Engine::getSong()->playMode() == Song::Mode_PlayMidiClip )) + Engine::getSong()->playMode() == Song::PlayMode::MidiClip )) { TimePos sub; - if( Engine::getSong()->playMode() == Song::Mode_PlaySong ) + if( Engine::getSong()->playMode() == Song::PlayMode::Song ) { sub = m_midiClip->startPosition(); } @@ -4128,16 +4124,16 @@ void PianoRoll::finishRecordNote(const Note & n ) ( Engine::getSong()->playMode() == desiredPlayModeForAccompany() || Engine::getSong()->playMode() == - Song::Mode_PlayMidiClip ) ) + Song::PlayMode::MidiClip ) ) { for( QList::Iterator it = m_recordingNotes.begin(); it != m_recordingNotes.end(); ++it ) { if( it->key() == n.key() ) { - Note n1( n.length(), it->pos(), + Note n1(n.length(), it->pos(), it->key(), it->getVolume(), - it->getPanning() ); + it->getPanning(), n.detuning()); n1.quantizeLength( quantization() ); m_midiClip->addNote( n1 ); update(); @@ -4180,7 +4176,7 @@ void PianoRoll::verScrolled( int new_pos ) void PianoRoll::setEditMode(int mode) { - m_ctrlMode = m_editMode = (EditModes) mode; + m_ctrlMode = m_editMode = (EditMode) mode; } @@ -4272,7 +4268,7 @@ void PianoRoll::selectNotesOnKey() void PianoRoll::enterValue( NoteVector* nv ) { - if( m_noteEditMode == NoteEditVolume ) + if( m_noteEditMode == NoteEditMode::Volume ) { bool ok; int new_val; @@ -4291,7 +4287,7 @@ void PianoRoll::enterValue( NoteVector* nv ) m_lastNoteVolume = new_val; } } - else if( m_noteEditMode == NoteEditPanning ) + else if( m_noteEditMode == NoteEditMode::Panning ) { bool ok; int new_val; @@ -4339,7 +4335,7 @@ void PianoRoll::copyToClipboard( const NoteVector & notes ) const // For copyString() and MimeType enum class using namespace Clipboard; - DataFile dataFile( DataFile::ClipboardData ); + DataFile dataFile( DataFile::Type::ClipboardData ); QDomElement note_list = dataFile.createElement( "note-list" ); dataFile.content().appendChild( note_list ); @@ -4496,8 +4492,8 @@ void PianoRoll::autoScroll( const TimePos & t ) void PianoRoll::updatePosition( const TimePos & t ) { if( ( Engine::getSong()->isPlaying() - && Engine::getSong()->playMode() == Song::Mode_PlayMidiClip - && m_timeLine->autoScroll() == TimeLineWidget::AutoScrollEnabled + && Engine::getSong()->playMode() == Song::PlayMode::MidiClip + && m_timeLine->autoScroll() == TimeLineWidget::AutoScrollState::Enabled ) || m_scrollBack ) { autoScroll( t ); @@ -4533,16 +4529,16 @@ void PianoRoll::updatePositionAccompany( const TimePos & t ) Song * s = Engine::getSong(); if( m_recording && hasValidMidiClip() && - s->playMode() != Song::Mode_PlayMidiClip ) + s->playMode() != Song::PlayMode::MidiClip ) { TimePos pos = t; - if (s->playMode() != Song::Mode_PlayPattern) + if (s->playMode() != Song::PlayMode::Pattern) { pos -= m_midiClip->startPosition(); } if( (int) pos > 0 ) { - s->getPlayPos( Song::Mode_PlayMidiClip ).setTicks( pos ); + s->getPlayPos( Song::PlayMode::MidiClip ).setTicks( pos ); autoScroll( pos ); } } @@ -4597,7 +4593,7 @@ void PianoRoll::noteLengthChanged() void PianoRoll::keyChanged() { - markSemiTone(stmaMarkCurrentScale, false); + markSemiTone(SemiToneMarkerAction::MarkCurrentScale, false); } int PianoRoll::quantization() const @@ -4618,7 +4614,7 @@ int PianoRoll::quantization() const } -void PianoRoll::quantizeNotes(QuantizeActions mode) +void PianoRoll::quantizeNotes(QuantizeAction mode) { if( ! hasValidMidiClip() ) { @@ -4646,11 +4642,11 @@ void PianoRoll::quantizeNotes(QuantizeActions mode) Note copy(*n); m_midiClip->removeNote( n ); - if (mode == QuantizeBoth || mode == QuantizePos) + if (mode == QuantizeAction::Both || mode == QuantizeAction::Pos) { copy.quantizePos(quantization()); } - if (mode == QuantizeBoth || mode == QuantizeLength) + if (mode == QuantizeAction::Both || mode == QuantizeAction::Length) { copy.quantizeLength(quantization()); } @@ -4738,9 +4734,9 @@ Note * PianoRoll::noteUnderMouse() void PianoRoll::changeSnapMode() { - // gridNudge, - // gridSnap, - // gridFree - to be implemented + // GridMode::Nudge, + // GridMode::Snap, + // GridMode::Free - to be implemented m_gridMode = static_cast(m_snapModel.value()); } @@ -4784,8 +4780,8 @@ PianoRollWindow::PianoRollWindow() : auto quantizeLengthAction = new QAction(tr("Quantize lengths"), this); connect(quantizeAction, &QAction::triggered, [this](){ m_editor->quantizeNotes(); }); - connect(quantizePosAction, &QAction::triggered, [this](){ m_editor->quantizeNotes(PianoRoll::QuantizePos); }); - connect(quantizeLengthAction, &QAction::triggered, [this](){ m_editor->quantizeNotes(PianoRoll::QuantizeLength); }); + connect(quantizePosAction, &QAction::triggered, [this](){ m_editor->quantizeNotes(PianoRoll::QuantizeAction::Pos); }); + connect(quantizeLengthAction, &QAction::triggered, [this](){ m_editor->quantizeNotes(PianoRoll::QuantizeAction::Length); }); quantizeButton->setPopupMode(QToolButton::MenuButtonPopup); quantizeButton->setDefaultAction(quantizeAction); @@ -5190,7 +5186,7 @@ void PianoRollWindow::saveSettings( QDomDocument & doc, QDomElement & de ) de.appendChild(markedSemiTonesRoot); } - de.setAttribute("stopbehaviour", m_editor->m_timeLine->behaviourAtStop()); + de.setAttribute("stopbehaviour", static_cast(m_editor->m_timeLine->behaviourAtStop())); MainWindow::saveWidgetState( this, de ); } @@ -5282,7 +5278,7 @@ void PianoRollWindow::exportMidiClip() exportDialog.setDefaultSuffix(suffix); const QString fullPath = exportDialog.selectedFiles()[0]; - DataFile dataFile(DataFile::MidiClip); + DataFile dataFile(DataFile::Type::MidiClip); m_editor->m_midiClip->saveSettings(dataFile, dataFile.content()); if (dataFile.writeFile(fullPath)) diff --git a/src/gui/editors/PositionLine.cpp b/src/gui/editors/PositionLine.cpp index 7dd8b3b13..8b938443d 100644 --- a/src/gui/editors/PositionLine.cpp +++ b/src/gui/editors/PositionLine.cpp @@ -64,8 +64,8 @@ void PositionLine::paintEvent(QPaintEvent* pe) // If gradient is enabled, we're in focus and we're playing, enable gradient if (m_hasTailGradient && Engine::getSong()->isPlaying() && - (Engine::getSong()->playMode() == Song::Mode_PlaySong || - Engine::getSong()->playMode() == Song::Mode_PlayMidiClip)) + (Engine::getSong()->playMode() == Song::PlayMode::Song || + Engine::getSong()->playMode() == Song::PlayMode::MidiClip)) { c.setAlpha(60); gradient.setColorAt(w, c); diff --git a/src/gui/editors/SongEditor.cpp b/src/gui/editors/SongEditor.cpp index 3e62cc238..518068759 100644 --- a/src/gui/editors/SongEditor.cpp +++ b/src/gui/editors/SongEditor.cpp @@ -24,11 +24,14 @@ #include "SongEditor.h" +#include + #include #include #include #include #include +#include #include #include "ActionGroup.h" @@ -57,25 +60,35 @@ namespace lmms::gui { +namespace +{ + +constexpr int MIN_PIXELS_PER_BAR = 2; +constexpr int MAX_PIXELS_PER_BAR = 400; +constexpr int ZOOM_STEPS = 200; + +constexpr std::array SNAP_SIZES{8.f, 4.f, 2.f, 1.f, 1/2.f, 1/4.f, 1/8.f, 1/16.f}; +constexpr std::array PROPORTIONAL_SNAP_SIZES{64.f, 32.f, 16.f, 8.f, 4.f, 2.f, 1.f, 1/2.f, 1/4.f, 1/8.f, 1/16.f, 1/32.f, 1/64.f}; + +} + -const QVector SongEditor::m_zoomLevels = - { 0.125f, 0.25f, 0.5f, 1.0f, 2.0f, 4.0f, 8.0f, 16.0f }; SongEditor::SongEditor( Song * song ) : TrackContainerView( song ), m_song( song ), - m_zoomingModel(new ComboBoxModel()), + m_zoomingModel(new IntModel(calculateZoomSliderValue(DEFAULT_PIXELS_PER_BAR), 0, ZOOM_STEPS, nullptr, tr("Zoom"))), m_snappingModel(new ComboBoxModel()), m_proportionalSnap( false ), m_scrollBack( false ), m_smoothScroll( ConfigManager::inst()->value( "ui", "smoothscroll" ).toInt() ), - m_mode(DrawMode), + m_mode(EditMode::Draw), m_origin(), m_scrollPos(), m_mousePos(), m_rubberBandStartTrackview(0), m_rubberbandStartTimePos(0), - m_currentZoomingValue(m_zoomingModel->value()), + m_rubberbandPixelsPerBar(DEFAULT_PIXELS_PER_BAR), m_trackHeadWidth(ConfigManager::inst()->value("ui", "compacttrackbuttons").toInt()==1 ? DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT + TRACK_OP_WIDTH_COMPACT : DEFAULT_SETTINGS_WIDGET_WIDTH + TRACK_OP_WIDTH), @@ -83,13 +96,14 @@ SongEditor::SongEditor( Song * song ) : { m_zoomingModel->setParent(this); m_snappingModel->setParent(this); + m_timeLine = new TimeLineWidget( m_trackHeadWidth, 32, pixelsPerBar(), - m_song->m_playPos[Song::Mode_PlaySong], + m_song->getPlayPos(Song::PlayMode::Song), m_currentPosition, - Song::Mode_PlaySong, this ); + Song::PlayMode::Song, this ); connect( this, SIGNAL( positionChanged( const lmms::TimePos& ) ), - m_song->m_playPos[Song::Mode_PlaySong].m_timeLine, + m_song->getPlayPos(Song::PlayMode::Song).m_timeLine, SLOT( updatePosition( const lmms::TimePos& ) ) ); connect( m_timeLine, SIGNAL( positionChanged( const lmms::TimePos& ) ), this, SLOT( updatePosition( const lmms::TimePos& ) ) ); @@ -103,12 +117,15 @@ SongEditor::SongEditor( Song * song ) : m_positionLine = new PositionLine(this); static_cast( layout() )->insertWidget( 1, m_timeLine ); - + connect( m_song, SIGNAL(playbackStateChanged()), m_positionLine, SLOT(update())); - connect( this, SIGNAL(zoomingValueChanged(float)), - m_positionLine, SLOT(zoomChange(float))); - + + // When zoom changes, update position line + // But we must convert pixels per bar to a zoom factor where 1.0 is 100% + connect(this, &SongEditor::pixelsPerBarChanged, m_positionLine, + [this]() { m_positionLine->zoomChange(pixelsPerBar() / float(DEFAULT_PIXELS_PER_BAR)); }); + // Ensure loop markers snap to same increments as clips. Zoom & proportional // snap changes are handled in zoomingChanged() and toggleProportionalSnap() connect(m_snappingModel, &ComboBoxModel::dataChanged, @@ -171,8 +188,8 @@ SongEditor::SongEditor( Song * song ) : SLOT(hideMasterVolumeFloat())); m_mvsStatus = new TextFloat; - m_mvsStatus->setTitle( tr( "Master volume" ) ); - m_mvsStatus->setPixmap( embed::getIconPixmap( "master_volume" ) ); + m_mvsStatus->setTitle(tr("Master volume")); + m_mvsStatus->setPixmap(embed::getIconPixmap("master_volume")); getGUI()->mainWindow()->addWidgetToToolBar( master_vol_lbl ); getGUI()->mainWindow()->addWidgetToToolBar( m_masterVolumeSlider ); @@ -240,33 +257,23 @@ SongEditor::SongEditor( Song * song ) : connect(contentWidget()->verticalScrollBar(), SIGNAL(valueChanged(int)),this, SLOT(updateRubberband())); connect(m_timeLine, SIGNAL(selectionFinished()), this, SLOT(stopSelectRegion())); + //zoom connects + connect(m_zoomingModel, SIGNAL(dataChanged()), this, SLOT(zoomingChanged())); - //Set up zooming model - for( float const & zoomLevel : m_zoomLevels ) + // Set up snapping model + for (float bars : SNAP_SIZES) { - m_zoomingModel->addItem( QString( "%1\%" ).arg( zoomLevel * 100 ) ); - } - m_zoomingModel->setInitValue( - m_zoomingModel->findText( "100%" ) ); - connect( m_zoomingModel, SIGNAL(dataChanged()), - this, SLOT(zoomingChanged())); - connect( m_zoomingModel, SIGNAL(dataChanged()), - m_positionLine, SLOT(update())); - - //Set up snapping model, 2^i - for ( int i = 3; i >= -4; i-- ) - { - if ( i > 0 ) + if (bars > 1.0f) { - m_snappingModel->addItem( QString( "%1 Bars").arg( 1 << i ) ); + m_snappingModel->addItem(QString("%1 Bars").arg(bars)); } - else if ( i == 0 ) + else if (bars == 1.0f) { m_snappingModel->addItem( "1 Bar" ); } else { - m_snappingModel->addItem( QString( "1/%1 Bar" ).arg( 1 << (-i) ) ); + m_snappingModel->addItem(QString("1/%1 Bar").arg(1 / bars)); } } m_snappingModel->setInitValue( m_snappingModel->findText( "1 Bar" ) ); @@ -291,42 +298,40 @@ void SongEditor::loadSettings( const QDomElement& element ) +/*! \brief Return grid size as number of bars */ float SongEditor::getSnapSize() const { - // 1 Bar is the third value in the snapping dropdown - int val = -m_snappingModel->value() + 3; + float snapSize = SNAP_SIZES[m_snappingModel->value()]; + // If proportional snap is on, we snap to finer values when zoomed in if (m_proportionalSnap) { - val = val - m_zoomingModel->value() + 3; + // Finds the closest available snap size + const float optimalSize = snapSize * DEFAULT_PIXELS_PER_BAR / pixelsPerBar(); + return *std::min_element(PROPORTIONAL_SNAP_SIZES.begin(), PROPORTIONAL_SNAP_SIZES.end(), [optimalSize](float a, float b) + { + return std::abs(a - optimalSize) < std::abs(b - optimalSize); + }); } - val = std::max(val, -6); // -6 gives 1/64th bar snapping. Lower values cause crashing. - if ( val >= 0 ){ - return 1 << val; - } - else { - return 1.0 / ( 1 << -val ); - } + return snapSize; } QString SongEditor::getSnapSizeString() const { - int val = -m_snappingModel->value() + 3; - val = val - m_zoomingModel->value() + 3; - val = std::max(val, -6); // -6 gives 1/64th bar snapping. Lower values cause crashing. + float bars = getSnapSize(); - if ( val >= 0 ){ - int bars = 1 << val; - if ( bars == 1 ) { return QString("1 Bar"); } - else - { - return QString( "%1 Bars" ).arg(bars); - } + if (bars < 1) + { + return QString(tr("1/%1 Bar")).arg(round(1 / bars)); } - else { - int div = ( 1 << -val ); - return QString( "1/%1 Bar" ).arg(div); + else if (bars >= 2) + { + return QString(tr("%1 Bars")).arg(bars); + } + else + { + return QString("1 Bar"); } } @@ -336,8 +341,8 @@ QString SongEditor::getSnapSizeString() const void SongEditor::setHighQuality( bool hq ) { Engine::audioEngine()->changeQuality( AudioEngine::qualitySettings( - hq ? AudioEngine::qualitySettings::Mode_HighQuality : - AudioEngine::qualitySettings::Mode_Draft ) ); + hq ? AudioEngine::qualitySettings::Mode::HighQuality : + AudioEngine::qualitySettings::Mode::Draft ) ); } @@ -367,7 +372,7 @@ void SongEditor::selectRegionFromPixels(int xStart, int xEnd) //we save the position of scrollbars, mouse position and zooming level m_origin = QPoint(xStart, 0); m_scrollPos = QPoint(m_leftRightScroll->value(), contentWidget()->verticalScrollBar()->value()); - m_currentZoomingValue = zoomingModel()->value(); + m_rubberbandPixelsPerBar = pixelsPerBar(); //calculate the song position where the mouse was clicked m_rubberbandStartTimePos = TimePos((xStart - m_trackHeadWidth) @@ -399,10 +404,9 @@ void SongEditor::updateRubberband() int originX = m_origin.x(); //take care of the zooming - if (m_currentZoomingValue != m_zoomingModel->value()) + if (m_rubberbandPixelsPerBar != pixelsPerBar()) { - originX = m_trackHeadWidth + (originX - m_trackHeadWidth) - * m_zoomLevels[m_zoomingModel->value()] / m_zoomLevels[m_currentZoomingValue]; + originX = m_trackHeadWidth + (originX - m_trackHeadWidth) * pixelsPerBar() / m_rubberbandPixelsPerBar; } //take care of the scrollbar position @@ -452,17 +456,17 @@ void SongEditor::setEditMode( EditMode mode ) void SongEditor::setEditModeDraw() { - setEditMode(DrawMode); + setEditMode(EditMode::Draw); } void SongEditor::setEditModeKnife() { - setEditMode(KnifeMode); + setEditMode(EditMode::Knife); } void SongEditor::setEditModeSelect() { - setEditMode(SelectMode); + setEditMode(EditMode::Select); } void SongEditor::toggleProportionalSnap() @@ -492,7 +496,7 @@ void SongEditor::keyPressEvent( QKeyEvent * ke ) tick_t t = m_song->currentTick() - TimePos::ticksPerBar(); if( t >= 0 ) { - m_song->setPlayPos( t, Song::Mode_PlaySong ); + m_song->setPlayPos( t, Song::PlayMode::Song ); } } else if( ke->key() == Qt::Key_Right ) @@ -500,12 +504,12 @@ void SongEditor::keyPressEvent( QKeyEvent * ke ) tick_t t = m_song->currentTick() + TimePos::ticksPerBar(); if( t < MaxSongLength ) { - m_song->setPlayPos( t, Song::Mode_PlaySong ); + m_song->setPlayPos( t, Song::PlayMode::Song ); } } else if( ke->key() == Qt::Key_Home ) { - m_song->setPlayPos( 0, Song::Mode_PlaySong ); + m_song->setPlayPos( 0, Song::PlayMode::Song ); } else if( ke->key() == Qt::Key_Delete || ke->key() == Qt::Key_Backspace ) { @@ -524,9 +528,13 @@ void SongEditor::keyPressEvent( QKeyEvent * ke ) { selectAllClips( false ); } + else if (ke->key() == Qt::Key_0 && ke->modifiers() & Qt::ControlModifier) + { + m_zoomingModel->reset(); + } else { - QWidget::keyPressEvent( ke ); + QWidget::keyPressEvent(ke); } } @@ -535,35 +543,24 @@ void SongEditor::keyPressEvent( QKeyEvent * ke ) void SongEditor::wheelEvent( QWheelEvent * we ) { - if( we->modifiers() & Qt::ControlModifier ) + if ((we->modifiers() & Qt::ControlModifier) && (position(we).x() > m_trackHeadWidth)) { - int z = m_zoomingModel->value(); - - if(we->angleDelta().y() > 0) - { - z++; - } - else if(we->angleDelta().y() < 0) - { - z--; - } - z = qBound( 0, z, m_zoomingModel->size() - 1 ); - - int x = position(we).x() - m_trackHeadWidth; // bar based on the mouse x-position where the scroll wheel was used int bar = x / pixelsPerBar(); - // what would be the bar in the new zoom level on the very same mouse x - int newBar = x / DEFAULT_PIXELS_PER_BAR / m_zoomLevels[z]; - // scroll so the bar "selected" by the mouse x doesn't move on the screen + + // move zoom slider (pixelsPerBar will change automatically) + int step = we->modifiers() & Qt::ShiftModifier ? 1 : 5; + // when Alt is pressed, wheelEvent returns delta for x coordinate (mimics horizontal mouse wheel) + int direction = (we->angleDelta().y() + we->angleDelta().x()) > 0 ? 1 : -1; + m_zoomingModel->incValue(step * direction); + + // scroll to zooming around cursor's bar + int newBar = static_cast(x / pixelsPerBar()); m_leftRightScroll->setValue(m_leftRightScroll->value() + bar - newBar); - // update combobox with zooming-factor - m_zoomingModel->setValue( z ); - // update timeline - m_song->m_playPos[Song::Mode_PlaySong].m_timeLine-> - setPixelsPerBar( pixelsPerBar() ); + m_song->getPlayPos(Song::PlayMode::Song).m_timeLine->setPixelsPerBar(pixelsPerBar()); // and make sure, all Clip's are resized and relocated realignTracks(); } @@ -612,7 +609,7 @@ void SongEditor::mousePressEvent(QMouseEvent *me) //we save the position of scrollbars, mouse position and zooming level m_scrollPos = QPoint(m_leftRightScroll->value(), contentWidget()->verticalScrollBar()->value()); m_origin = contentWidget()->mapFromParent(QPoint(me->pos().x(), me->pos().y())); - m_currentZoomingValue = zoomingModel()->value(); + m_rubberbandPixelsPerBar = pixelsPerBar(); //paint the rubberband rubberBand()->setEnabled(true); @@ -655,12 +652,12 @@ void SongEditor::setMasterVolume( int new_val ) { updateMasterVolumeFloat( new_val ); - if( !m_mvsStatus->isVisible() && !m_song->m_loadingProject + if (!m_mvsStatus->isVisible() && !m_song->m_loadingProject && m_masterVolumeSlider->showStatus() ) { - m_mvsStatus->moveGlobal( m_masterVolumeSlider, + m_mvsStatus->moveGlobal(m_masterVolumeSlider, QPoint( m_masterVolumeSlider->width() + 2, -2 ) ); - m_mvsStatus->setVisibilityTimeOut( 1000 ); + m_mvsStatus->setVisibilityTimeOut(1000); } Engine::audioEngine()->setMasterGain( new_val / 100.0f ); } @@ -670,7 +667,7 @@ void SongEditor::setMasterVolume( int new_val ) void SongEditor::showMasterVolumeFloat( void ) { - m_mvsStatus->moveGlobal( m_masterVolumeSlider, + m_mvsStatus->moveGlobal(m_masterVolumeSlider, QPoint( m_masterVolumeSlider->width() + 2, -2 ) ); m_mvsStatus->show(); updateMasterVolumeFloat( m_song->m_masterVolumeModel.value() ); @@ -681,7 +678,7 @@ void SongEditor::showMasterVolumeFloat( void ) void SongEditor::updateMasterVolumeFloat( int new_val ) { - m_mvsStatus->setText( tr( "Value: %1%" ).arg( new_val ) ); + m_mvsStatus->setText(tr("Value: %1%").arg(new_val)); } @@ -791,8 +788,8 @@ void SongEditor::updatePosition( const TimePos & t ) trackOpWidth = TRACK_OP_WIDTH; } - if( ( m_song->isPlaying() && m_song->m_playMode == Song::Mode_PlaySong - && m_timeLine->autoScroll() == TimeLineWidget::AutoScrollEnabled) || + if( ( m_song->isPlaying() && m_song->m_playMode == Song::PlayMode::Song + && m_timeLine->autoScroll() == TimeLineWidget::AutoScrollState::Enabled) || m_scrollBack == true ) { m_smoothScroll = ConfigManager::inst()->value( "ui", "smoothscroll" ).toInt(); @@ -811,7 +808,7 @@ void SongEditor::updatePosition( const TimePos & t ) m_scrollBack = false; } - const int x = m_song->m_playPos[Song::Mode_PlaySong].m_timeLine-> + const int x = m_song->getPlayPos(Song::PlayMode::Song).m_timeLine-> markerX( t ) + 8; if( x >= trackOpWidth + widgetWidth -1 ) { @@ -837,17 +834,50 @@ void SongEditor::updatePositionLine() +//! Convert zoom slider's value to bar width in pixels +int SongEditor::calculatePixelsPerBar() const +{ + // What we need to raise 2 by to get MIN_PIXELS_PER_BAR and MAX_PIXELS_PER_BAR + static const double minExp = std::log2(MIN_PIXELS_PER_BAR); + static const double maxExp = std::log2(MAX_PIXELS_PER_BAR); + static const double stepsInv = 1 / static_cast(ZOOM_STEPS) * (maxExp - minExp); + double exponent = m_zoomingModel->value() * stepsInv + minExp; + + double ppb = std::exp2(exponent); + + return static_cast(std::round(ppb)); +} + + + + +//! Convert bar width in pixels to zoom slider value +int SongEditor::calculateZoomSliderValue(int pixelsPerBar) const +{ + // What we need to raise 2 by to get MIN_PIXELS_PER_BAR and MAX_PIXELS_PER_BAR + static const double minExp = std::log2(MIN_PIXELS_PER_BAR); + static const double maxExp = std::log2(MAX_PIXELS_PER_BAR); + double exponent = std::log2(pixelsPerBar); + + double sliderValue = (exponent - minExp) / (maxExp - minExp) * ZOOM_STEPS; + + return static_cast(std::round(sliderValue)); +} + + + + void SongEditor::zoomingChanged() { - setPixelsPerBar( m_zoomLevels[m_zoomingModel->value()] * DEFAULT_PIXELS_PER_BAR ); + int ppb = calculatePixelsPerBar(); + setPixelsPerBar(ppb); - m_song->m_playPos[Song::Mode_PlaySong].m_timeLine-> - setPixelsPerBar( pixelsPerBar() ); + m_song->getPlayPos(Song::PlayMode::Song).m_timeLine->setPixelsPerBar(ppb); realignTracks(); updateRubberband(); m_timeLine->setSnapSize(getSnapSize()); - - emit zoomingValueChanged( m_zoomLevels[m_zoomingModel->value()] ); + + emit pixelsPerBarChanged(ppb); } @@ -865,7 +895,7 @@ void SongEditor::selectAllClips( bool select ) bool SongEditor::allowRubberband() const { - return m_mode == SelectMode; + return m_mode == EditMode::Select; } @@ -873,7 +903,7 @@ bool SongEditor::allowRubberband() const bool SongEditor::knifeMode() const { - return m_mode == KnifeMode; + return m_mode == EditMode::Knife; } @@ -899,14 +929,6 @@ int SongEditor::indexOfTrackView(const TrackView *tv) -ComboBoxModel *SongEditor::zoomingModel() const -{ - return m_zoomingModel; -} - - - - ComboBoxModel *SongEditor::snappingModel() const { return m_snappingModel; @@ -991,16 +1013,19 @@ SongEditorWindow::SongEditorWindow(Song* song) : auto zoom_lbl = new QLabel(m_toolBar); zoom_lbl->setPixmap( embed::getIconPixmap( "zoom" ) ); - //Set up zooming-stuff - m_zoomingComboBox = new ComboBox( m_toolBar ); - m_zoomingComboBox->setFixedSize( 80, ComboBox::DEFAULT_HEIGHT ); - m_zoomingComboBox->move( 580, 4 ); - m_zoomingComboBox->setModel(m_editor->m_zoomingModel); - m_zoomingComboBox->setToolTip(tr("Horizontal zooming")); - connect(m_editor->zoomingModel(), SIGNAL(dataChanged()), this, SLOT(updateSnapLabel())); + // Set slider zoom + m_zoomingSlider = new AutomatableSlider(m_toolBar, tr("Zoom")); + m_zoomingSlider->setModel(m_editor->m_zoomingModel); + m_zoomingSlider->setOrientation(Qt::Horizontal); + m_zoomingSlider->setPageStep(1); + m_zoomingSlider->setFocusPolicy(Qt::NoFocus); + m_zoomingSlider->setFixedSize(100, 26); + m_zoomingSlider->setToolTip(tr("Zoom")); + m_zoomingSlider->setContextMenuPolicy(Qt::NoContextMenu); + connect(m_editor->m_zoomingModel, SIGNAL(dataChanged()), this, SLOT(updateSnapLabel())); zoomToolBar->addWidget( zoom_lbl ); - zoomToolBar->addWidget( m_zoomingComboBox ); + zoomToolBar->addWidget(m_zoomingSlider); DropToolBar *snapToolBar = addDropToolBarToTop(tr("Snap controls")); auto snap_lbl = new QLabel(m_toolBar); @@ -1034,7 +1059,7 @@ SongEditorWindow::SongEditorWindow(Song* song) : QSize SongEditorWindow::sizeHint() const { - return {720, 300}; + return {900, 300}; } void SongEditorWindow::updateSnapLabel(){ @@ -1079,7 +1104,7 @@ void SongEditorWindow::changeEvent(QEvent *event) void SongEditorWindow::play() { emit playTriggered(); - if( Engine::getSong()->playMode() != Song::Mode_PlaySong ) + if( Engine::getSong()->playMode() != Song::PlayMode::Song ) { Engine::getSong()->playSong(); } @@ -1140,3 +1165,5 @@ void SongEditorWindow::adjustUiAfterProjectLoad() } // namespace lmms::gui + + diff --git a/src/gui/editors/TimeLineWidget.cpp b/src/gui/editors/TimeLineWidget.cpp index 12b6a11f5..423485a25 100644 --- a/src/gui/editors/TimeLineWidget.cpp +++ b/src/gui/editors/TimeLineWidget.cpp @@ -22,28 +22,34 @@ * */ +#include "TimeLineWidget.h" + +#include #include -#include #include #include +#include #include - -#include "TimeLineWidget.h" #include "embed.h" -#include "NStateButton.h" #include "GuiApplication.h" +#include "NStateButton.h" #include "TextFloat.h" namespace lmms::gui { +namespace +{ + constexpr int MIN_BAR_LABEL_DISTANCE = 35; +} + QPixmap * TimeLineWidget::s_posMarkerPixmap = nullptr; TimeLineWidget::TimeLineWidget( const int xoff, const int yoff, const float ppb, - Song::PlayPos & pos, const TimePos & begin, Song::PlayModes mode, + Song::PlayPos & pos, const TimePos & begin, Song::PlayMode mode, QWidget * parent ) : QWidget( parent ), m_inactiveLoopColor( 52, 63, 53, 64 ), @@ -55,9 +61,9 @@ TimeLineWidget::TimeLineWidget( const int xoff, const int yoff, const float ppb, m_loopRectangleVerticalPadding( 1 ), m_barLineColor( 192, 192, 192 ), m_barNumberColor( m_barLineColor.darker( 120 ) ), - m_autoScroll( AutoScrollEnabled ), - m_loopPoints( LoopPointsDisabled ), - m_behaviourAtStop( BackToZero ), + m_autoScroll( AutoScrollState::Enabled ), + m_loopPoints( LoopPointState::Disabled ), + m_behaviourAtStop( BehaviourAtStopState::BackToZero ), m_changedPosition( true ), m_xOffset( xoff ), m_posMarkerX( 0 ), @@ -68,7 +74,7 @@ TimeLineWidget::TimeLineWidget( const int xoff, const int yoff, const float ppb, m_mode( mode ), m_savedPos( -1 ), m_hint( nullptr ), - m_action( NoAction ), + m_action( Action::NoAction ), m_moveXOff( 0 ) { m_loopPos[0] = 0; @@ -151,7 +157,7 @@ void TimeLineWidget::addToolButtons( QToolBar * _tool_bar ) SLOT(toggleBehaviourAtStop(int))); connect( this, SIGNAL(loadBehaviourAtStop(int)), behaviourAtStop, SLOT(changeState(int))); - behaviourAtStop->changeState( BackToStart ); + behaviourAtStop->changeState( static_cast(BehaviourAtStopState::BackToStart) ); _tool_bar->addWidget( autoScroll ); _tool_bar->addWidget( loopPoints ); @@ -165,8 +171,8 @@ void TimeLineWidget::saveSettings( QDomDocument & _doc, QDomElement & _this ) { _this.setAttribute( "lp0pos", (int) loopBegin() ); _this.setAttribute( "lp1pos", (int) loopEnd() ); - _this.setAttribute( "lpstate", m_loopPoints ); - _this.setAttribute( "stopbehaviour", m_behaviourAtStop ); + _this.setAttribute( "lpstate", static_cast(m_loopPoints) ); + _this.setAttribute( "stopbehaviour", static_cast(m_behaviourAtStop) ); } @@ -176,10 +182,10 @@ void TimeLineWidget::loadSettings( const QDomElement & _this ) { m_loopPos[0] = _this.attribute( "lp0pos" ).toInt(); m_loopPos[1] = _this.attribute( "lp1pos" ).toInt(); - m_loopPoints = static_cast( + m_loopPoints = static_cast( _this.attribute( "lpstate" ).toInt() ); update(); - emit loopPointStateLoaded( m_loopPoints ); + emit loopPointStateLoaded( static_cast(m_loopPoints) ); if( _this.hasAttribute( "stopbehaviour" ) ) { @@ -208,7 +214,7 @@ void TimeLineWidget::updatePosition( const TimePos & ) void TimeLineWidget::toggleAutoScroll( int _n ) { - m_autoScroll = static_cast( _n ); + m_autoScroll = static_cast( _n ); } @@ -216,7 +222,7 @@ void TimeLineWidget::toggleAutoScroll( int _n ) void TimeLineWidget::toggleLoopPoints( int _n ) { - m_loopPoints = static_cast( _n ); + m_loopPoints = static_cast( _n ); update(); } @@ -225,7 +231,7 @@ void TimeLineWidget::toggleLoopPoints( int _n ) void TimeLineWidget::toggleBehaviourAtStop( int _n ) { - m_behaviourAtStop = static_cast( _n ); + m_behaviourAtStop = static_cast( _n ); } @@ -270,12 +276,14 @@ void TimeLineWidget::paintEvent( QPaintEvent * ) int const x = m_xOffset + s_posMarkerPixmap->width() / 2 - ( ( static_cast( m_begin * m_ppb ) / TimePos::ticksPerBar() ) % static_cast( m_ppb ) ); + // Double the interval between bar numbers until they are far enough appart + int barLabelInterval = 1; + while (barLabelInterval * m_ppb < MIN_BAR_LABEL_DISTANCE) { barLabelInterval *= 2; } + for( int i = 0; x + i * m_ppb < width(); ++i ) { ++barNumber; - if( ( barNumber - 1 ) % - qMax( 1, qRound( 1.0f / 3.0f * - TimePos::ticksPerBar() / m_ppb ) ) == 0 ) + if ((barNumber - 1) % barLabelInterval == 0) { const int cx = x + qRound( i * m_ppb ); p.setPen( barLineColor ); @@ -319,7 +327,7 @@ void TimeLineWidget::mousePressEvent( QMouseEvent* event ) } if( event->button() == Qt::LeftButton && !(event->modifiers() & Qt::ShiftModifier) ) { - m_action = MovePositionMarker; + m_action = Action::MovePositionMarker; if( event->x() - m_xOffset < s_posMarkerPixmap->width() ) { m_moveXOff = event->x() - m_xOffset; @@ -331,7 +339,7 @@ void TimeLineWidget::mousePressEvent( QMouseEvent* event ) } else if( event->button() == Qt::LeftButton && (event->modifiers() & Qt::ShiftModifier) ) { - m_action = SelectSongClip; + m_action = Action::SelectSongClip; m_initalXSelect = event->x(); } else if( event->button() == Qt::RightButton ) @@ -340,12 +348,12 @@ void TimeLineWidget::mousePressEvent( QMouseEvent* event ) const TimePos t = m_begin + static_cast( qMax( event->x() - m_xOffset - m_moveXOff, 0 ) * TimePos::ticksPerBar() / m_ppb ); const TimePos loopMid = ( m_loopPos[0] + m_loopPos[1] ) / 2; - m_action = t < loopMid ? MoveLoopBegin : MoveLoopEnd; + m_action = t < loopMid ? Action::MoveLoopBegin : Action::MoveLoopEnd; std::sort(std::begin(m_loopPos), std::end(m_loopPos)); - m_loopPos[( m_action == MoveLoopBegin ) ? 0 : 1] = t; + m_loopPos[( m_action == Action::MoveLoopBegin ) ? 0 : 1] = t; } - if( m_action == MoveLoopBegin || m_action == MoveLoopEnd ) + if( m_action == Action::MoveLoopBegin || m_action == Action::MoveLoopEnd ) { delete m_hint; m_hint = TextFloat::displayMessage( tr( "Hint" ), @@ -365,13 +373,13 @@ void TimeLineWidget::mouseMoveEvent( QMouseEvent* event ) switch( m_action ) { - case MovePositionMarker: + case Action::MovePositionMarker: m_pos.setTicks(t.getTicks()); Engine::getSong()->setToTime(t, m_mode); if (!( Engine::getSong()->isPlaying())) { - //Song::Mode_None is used when nothing is being played. - Engine::getSong()->setToTime(t, Song::Mode_None); + //Song::PlayMode::None is used when nothing is being played. + Engine::getSong()->setToTime(t, Song::PlayMode::None); } m_pos.setCurrentFrame( 0 ); m_pos.setJumped( true ); @@ -379,10 +387,10 @@ void TimeLineWidget::mouseMoveEvent( QMouseEvent* event ) positionMarkerMoved(); break; - case MoveLoopBegin: - case MoveLoopEnd: + case Action::MoveLoopBegin: + case Action::MoveLoopEnd: { - const int i = m_action - MoveLoopBegin; // i == 0 || i == 1 + const int i = m_action == Action::MoveLoopBegin ? 0 : 1; const bool control = event->modifiers() & Qt::ControlModifier; if (control) { @@ -401,13 +409,13 @@ void TimeLineWidget::mouseMoveEvent( QMouseEvent* event ) const int offset = control ? 1 : m_snapSize * TimePos::ticksPerBar(); // Note, swap 1 and 0 below and the behavior "skips" the other // marking instead of pushing it. - if (m_action == MoveLoopBegin) { m_loopPos[0] -= offset; } + if (m_action == Action::MoveLoopBegin) { m_loopPos[0] -= offset; } else { m_loopPos[1] += offset; } } update(); break; } - case SelectSongClip: + case Action::SelectSongClip: emit regionSelectedFromPixels( m_initalXSelect , event->x() ); break; @@ -423,8 +431,8 @@ void TimeLineWidget::mouseReleaseEvent( QMouseEvent* event ) { delete m_hint; m_hint = nullptr; - if ( m_action == SelectSongClip ) { emit selectionFinished(); } - m_action = NoAction; + if ( m_action == Action::SelectSongClip ) { emit selectionFinished(); } + m_action = Action::NoAction; } diff --git a/src/gui/editors/TrackContainerView.cpp b/src/gui/editors/TrackContainerView.cpp index 38a6a36d5..60a468380 100644 --- a/src/gui/editors/TrackContainerView.cpp +++ b/src/gui/editors/TrackContainerView.cpp @@ -199,8 +199,8 @@ void TrackContainerView::moveTrackView( TrackView * trackView, int indexTo ) Track * track = m_tc->m_tracks[indexFrom]; - m_tc->m_tracks.remove( indexFrom ); - m_tc->m_tracks.insert( indexTo, track ); + m_tc->m_tracks.erase(m_tc->m_tracks.begin() + indexFrom); + m_tc->m_tracks.insert(m_tc->m_tracks.begin() + indexTo, track); m_trackViews.move( indexFrom, indexTo ); realignTracks(); @@ -372,8 +372,8 @@ void TrackContainerView::dragEnterEvent( QDragEnterEvent * _dee ) QString( "presetfile,pluginpresetfile,samplefile,instrument," "importedproject,soundfontfile,patchfile,vstpluginfile,projectfile," "track_%1,track_%2" ). - arg( Track::InstrumentTrack ). - arg( Track::SampleTrack ) ); + arg( static_cast(Track::Type::Instrument) ). + arg( static_cast(Track::Type::Sample) ) ); } @@ -394,7 +394,7 @@ void TrackContainerView::dropEvent( QDropEvent * _de ) QString value = StringPairDrag::decodeValue( _de ); if( type == "instrument" ) { - auto it = dynamic_cast(Track::create(Track::InstrumentTrack, m_tc)); + auto it = dynamic_cast(Track::create(Track::Type::Instrument, m_tc)); auto ilt = new InstrumentLoaderThread(this, it, value); ilt->start(); //it->toggledInstrumentTrackButton( true ); @@ -404,7 +404,7 @@ void TrackContainerView::dropEvent( QDropEvent * _de ) || type == "soundfontfile" || type == "vstpluginfile" || type == "patchfile" ) { - auto it = dynamic_cast(Track::create(Track::InstrumentTrack, m_tc)); + auto it = dynamic_cast(Track::create(Track::Type::Instrument, m_tc)); PluginFactory::PluginInfoAndKey piakn = getPluginFactory()->pluginSupportingExtension(FileItem::extension(value)); Instrument * i = it->loadInstrument(piakn.info.name(), &piakn.key); @@ -415,7 +415,7 @@ void TrackContainerView::dropEvent( QDropEvent * _de ) else if( type == "presetfile" ) { DataFile dataFile( value ); - auto it = dynamic_cast(Track::create(Track::InstrumentTrack, m_tc)); + auto it = dynamic_cast(Track::create(Track::Type::Instrument, m_tc)); it->setSimpleSerializing(); it->loadSettings( dataFile.content().toElement() ); //it->toggledInstrumentTrackButton( true ); diff --git a/src/gui/instrument/EnvelopeAndLfoView.cpp b/src/gui/instrument/EnvelopeAndLfoView.cpp index df0e1120d..edb6c99c7 100644 --- a/src/gui/instrument/EnvelopeAndLfoView.cpp +++ b/src/gui/instrument/EnvelopeAndLfoView.cpp @@ -99,43 +99,43 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : s_lfoGraph = new QPixmap( embed::getIconPixmap( "lfo_graph" ) ); } - m_predelayKnob = new Knob( knobBright_26, this ); + m_predelayKnob = new Knob( KnobType::Bright26, this ); m_predelayKnob->setLabel( tr( "DEL" ) ); m_predelayKnob->move( PREDELAY_KNOB_X, ENV_KNOBS_Y ); m_predelayKnob->setHintText( tr( "Pre-delay:" ), "" ); - m_attackKnob = new Knob( knobBright_26, this ); + m_attackKnob = new Knob( KnobType::Bright26, this ); m_attackKnob->setLabel( tr( "ATT" ) ); m_attackKnob->move( ATTACK_KNOB_X, ENV_KNOBS_Y ); m_attackKnob->setHintText( tr( "Attack:" ), "" ); - m_holdKnob = new Knob( knobBright_26, this ); + m_holdKnob = new Knob( KnobType::Bright26, this ); m_holdKnob->setLabel( tr( "HOLD" ) ); m_holdKnob->move( HOLD_KNOB_X, ENV_KNOBS_Y ); m_holdKnob->setHintText( tr( "Hold:" ), "" ); - m_decayKnob = new Knob( knobBright_26, this ); + m_decayKnob = new Knob( KnobType::Bright26, this ); m_decayKnob->setLabel( tr( "DEC" ) ); m_decayKnob->move( DECAY_KNOB_X, ENV_KNOBS_Y ); m_decayKnob->setHintText( tr( "Decay:" ), "" ); - m_sustainKnob = new Knob( knobBright_26, this ); + m_sustainKnob = new Knob( KnobType::Bright26, this ); m_sustainKnob->setLabel( tr( "SUST" ) ); m_sustainKnob->move( SUSTAIN_KNOB_X, ENV_KNOBS_Y ); m_sustainKnob->setHintText( tr( "Sustain:" ), "" ); - m_releaseKnob = new Knob( knobBright_26, this ); + m_releaseKnob = new Knob( KnobType::Bright26, this ); m_releaseKnob->setLabel( tr( "REL" ) ); m_releaseKnob->move( RELEASE_KNOB_X, ENV_KNOBS_Y ); m_releaseKnob->setHintText( tr( "Release:" ), "" ); - m_amountKnob = new Knob( knobBright_26, this ); + m_amountKnob = new Knob( KnobType::Bright26, this ); m_amountKnob->setLabel( tr( "AMT" ) ); m_amountKnob->move( AMOUNT_KNOB_X, ENV_GRAPH_Y ); m_amountKnob->setHintText( tr( "Modulation amount:" ), "" ); @@ -143,25 +143,25 @@ EnvelopeAndLfoView::EnvelopeAndLfoView( QWidget * _parent ) : - m_lfoPredelayKnob = new Knob( knobBright_26, this ); + m_lfoPredelayKnob = new Knob( KnobType::Bright26, this ); m_lfoPredelayKnob->setLabel( tr( "DEL" ) ); m_lfoPredelayKnob->move( LFO_PREDELAY_KNOB_X, LFO_KNOB_Y ); m_lfoPredelayKnob->setHintText( tr( "Pre-delay:" ), "" ); - m_lfoAttackKnob = new Knob( knobBright_26, this ); + m_lfoAttackKnob = new Knob( KnobType::Bright26, this ); m_lfoAttackKnob->setLabel( tr( "ATT" ) ); m_lfoAttackKnob->move( LFO_ATTACK_KNOB_X, LFO_KNOB_Y ); m_lfoAttackKnob->setHintText( tr( "Attack:" ), "" ); - m_lfoSpeedKnob = new TempoSyncKnob( knobBright_26, this ); + m_lfoSpeedKnob = new TempoSyncKnob( KnobType::Bright26, this ); m_lfoSpeedKnob->setLabel( tr( "SPD" ) ); m_lfoSpeedKnob->move( LFO_SPEED_KNOB_X, LFO_KNOB_Y ); m_lfoSpeedKnob->setHintText( tr( "Frequency:" ), "" ); - m_lfoAmountKnob = new Knob( knobBright_26, this ); + m_lfoAmountKnob = new Knob( KnobType::Bright26, this ); m_lfoAmountKnob->setLabel( tr( "AMT" ) ); m_lfoAmountKnob->move( LFO_AMOUNT_KNOB_X, LFO_KNOB_Y ); m_lfoAmountKnob->setHintText( tr( "Modulation amount:" ), "" ); @@ -310,7 +310,7 @@ void EnvelopeAndLfoView::dragEnterEvent( QDragEnterEvent * _dee ) { StringPairDrag::processDragEnterEvent( _dee, QString( "samplefile,clip_%1" ).arg( - Track::SampleTrack ) ); + static_cast(Track::Type::Sample) ) ); } @@ -325,18 +325,18 @@ void EnvelopeAndLfoView::dropEvent( QDropEvent * _de ) m_params->m_userWave.setAudioFile( StringPairDrag::decodeValue( _de ) ); m_userLfoBtn->model()->setValue( true ); - m_params->m_lfoWaveModel.setValue(EnvelopeAndLfoParameters::UserDefinedWave); + m_params->m_lfoWaveModel.setValue(static_cast(EnvelopeAndLfoParameters::LfoShape::UserDefinedWave)); _de->accept(); update(); } - else if( type == QString( "clip_%1" ).arg( Track::SampleTrack ) ) + else if( type == QString( "clip_%1" ).arg( static_cast(Track::Type::Sample) ) ) { DataFile dataFile( value.toUtf8() ); m_params->m_userWave.setAudioFile( dataFile.content(). firstChildElement().firstChildElement(). firstChildElement().attribute( "src" ) ); m_userLfoBtn->model()->setValue( true ); - m_params->m_lfoWaveModel.setValue(EnvelopeAndLfoParameters::UserDefinedWave); + m_params->m_lfoWaveModel.setValue(static_cast(EnvelopeAndLfoParameters::LfoShape::UserDefinedWave)); _de->accept(); update(); } @@ -459,29 +459,30 @@ void EnvelopeAndLfoView::paintEvent( QPaintEvent * ) float phase = ( cur_sample -= m_params->m_lfoPredelayFrames ) / osc_frames; - switch( m_params->m_lfoWaveModel.value() ) + switch( static_cast(m_params->m_lfoWaveModel.value()) ) { - case EnvelopeAndLfoParameters::SineWave: + case EnvelopeAndLfoParameters::LfoShape::SineWave: + default: val = Oscillator::sinSample( phase ); break; - case EnvelopeAndLfoParameters::TriangleWave: + case EnvelopeAndLfoParameters::LfoShape::TriangleWave: val = Oscillator::triangleSample( phase ); break; - case EnvelopeAndLfoParameters::SawWave: + case EnvelopeAndLfoParameters::LfoShape::SawWave: val = Oscillator::sawSample( phase ); break; - case EnvelopeAndLfoParameters::SquareWave: + case EnvelopeAndLfoParameters::LfoShape::SquareWave: val = Oscillator::squareSample( phase ); break; - case EnvelopeAndLfoParameters::RandomWave: + case EnvelopeAndLfoParameters::LfoShape::RandomWave: if( x % (int)( 900 * m_lfoSpeedKnob->value() + 1 ) == 0 ) { m_randomGraph = Oscillator::noiseSample( 0.0f ); } val = m_randomGraph; break; - case EnvelopeAndLfoParameters::UserDefinedWave: + case EnvelopeAndLfoParameters::LfoShape::UserDefinedWave: val = m_params->m_userWave. userWaveSample( phase ); break; @@ -516,8 +517,8 @@ void EnvelopeAndLfoView::paintEvent( QPaintEvent * ) void EnvelopeAndLfoView::lfoUserWaveChanged() { - if( m_params->m_lfoWaveModel.value() == - EnvelopeAndLfoParameters::UserDefinedWave ) + if( static_cast(m_params->m_lfoWaveModel.value()) == + EnvelopeAndLfoParameters::LfoShape::UserDefinedWave ) { if( m_params->m_userWave.frames() <= 1 ) { diff --git a/src/gui/instrument/InstrumentFunctionViews.cpp b/src/gui/instrument/InstrumentFunctionViews.cpp index a4f0e670a..c9aa04272 100644 --- a/src/gui/instrument/InstrumentFunctionViews.cpp +++ b/src/gui/instrument/InstrumentFunctionViews.cpp @@ -44,7 +44,7 @@ InstrumentFunctionNoteStackingView::InstrumentFunctionNoteStackingView( Instrume m_cc( cc ), m_chordsGroupBox( new GroupBox( tr( "STACKING" ) ) ), m_chordsComboBox( new ComboBox() ), - m_chordRangeKnob( new Knob( knobBright_26 ) ) + m_chordRangeKnob( new Knob( KnobType::Bright26 ) ) { auto topLayout = new QHBoxLayout(this); topLayout->setContentsMargins(0, 0, 0, 0); @@ -98,13 +98,13 @@ InstrumentFunctionArpeggioView::InstrumentFunctionArpeggioView( InstrumentFuncti m_a( arp ), m_arpGroupBox( new GroupBox( tr( "ARPEGGIO" ) ) ), m_arpComboBox( new ComboBox() ), - m_arpRangeKnob( new Knob( knobBright_26 ) ), - m_arpRepeatsKnob( new Knob( knobBright_26 ) ), - m_arpCycleKnob( new Knob( knobBright_26 ) ), - m_arpSkipKnob( new Knob( knobBright_26 ) ), - m_arpMissKnob( new Knob( knobBright_26 ) ), - m_arpTimeKnob( new TempoSyncKnob( knobBright_26 ) ), - m_arpGateKnob( new Knob( knobBright_26 ) ), + m_arpRangeKnob( new Knob( KnobType::Bright26 ) ), + m_arpRepeatsKnob( new Knob( KnobType::Bright26 ) ), + m_arpCycleKnob( new Knob( KnobType::Bright26 ) ), + m_arpSkipKnob( new Knob( KnobType::Bright26 ) ), + m_arpMissKnob( new Knob( KnobType::Bright26 ) ), + m_arpTimeKnob( new TempoSyncKnob( KnobType::Bright26 ) ), + m_arpGateKnob( new Knob( KnobType::Bright26 ) ), m_arpDirectionComboBox( new ComboBox() ), m_arpModeComboBox( new ComboBox() ) { diff --git a/src/gui/instrument/InstrumentSoundShapingView.cpp b/src/gui/instrument/InstrumentSoundShapingView.cpp index dd5c14a09..1bfc166b3 100644 --- a/src/gui/instrument/InstrumentSoundShapingView.cpp +++ b/src/gui/instrument/InstrumentSoundShapingView.cpp @@ -80,13 +80,13 @@ InstrumentSoundShapingView::InstrumentSoundShapingView( QWidget * _parent ) : m_filterComboBox->setFont( pointSize<8>( m_filterComboBox->font() ) ); - m_filterCutKnob = new Knob( knobBright_26, m_filterGroupBox ); + m_filterCutKnob = new Knob( KnobType::Bright26, m_filterGroupBox ); m_filterCutKnob->setLabel( tr( "FREQ" ) ); m_filterCutKnob->move( 140, 18 ); m_filterCutKnob->setHintText( tr( "Cutoff frequency:" ), " " + tr( "Hz" ) ); - m_filterResKnob = new Knob( knobBright_26, m_filterGroupBox ); + m_filterResKnob = new Knob( KnobType::Bright26, m_filterGroupBox ); m_filterResKnob->setLabel( tr( "Q/RESO" ) ); m_filterResKnob->move( 196, 18 ); m_filterResKnob->setHintText( tr( "Q/Resonance:" ), "" ); diff --git a/src/gui/instrument/InstrumentTrackWindow.cpp b/src/gui/instrument/InstrumentTrackWindow.cpp index 1d26dd9dc..28cd8c6c8 100644 --- a/src/gui/instrument/InstrumentTrackWindow.cpp +++ b/src/gui/instrument/InstrumentTrackWindow.cpp @@ -49,7 +49,7 @@ #include "InstrumentFunctions.h" #include "InstrumentFunctionViews.h" #include "InstrumentMidiIOView.h" -#include "InstrumentMiscView.h" +#include "InstrumentTuningView.h" #include "InstrumentSoundShapingView.h" #include "InstrumentTrack.h" #include "InstrumentTrackView.h" @@ -148,7 +148,7 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : Qt::Alignment widgetAlignment = Qt::AlignHCenter | Qt::AlignCenter; // set up volume knob - m_volumeKnob = new Knob( knobBright_26, nullptr, tr( "Volume" ) ); + m_volumeKnob = new Knob( KnobType::Bright26, nullptr, tr( "Volume" ) ); m_volumeKnob->setVolumeKnob( true ); m_volumeKnob->setHintText( tr( "Volume:" ), "%" ); @@ -162,7 +162,7 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : // set up panning knob - m_panningKnob = new Knob( knobBright_26, nullptr, tr( "Panning" ) ); + m_panningKnob = new Knob( KnobType::Bright26, nullptr, tr( "Panning" ) ); m_panningKnob->setHintText( tr( "Panning:" ), "" ); basicControlsLayout->addWidget( m_panningKnob, 0, 1 ); @@ -178,7 +178,7 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : // set up pitch knob - m_pitchKnob = new Knob( knobBright_26, nullptr, tr( "Pitch" ) ); + m_pitchKnob = new Knob( KnobType::Bright26, nullptr, tr( "Pitch" ) ); m_pitchKnob->setHintText( tr( "Pitch:" ), " " + tr( "cents" ) ); basicControlsLayout->addWidget( m_pitchKnob, 0, 3 ); @@ -255,25 +255,25 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : instrumentFunctionsLayout->addStretch(); // MIDI tab - m_midiView = new InstrumentMidiIOView( m_tabWidget ); + m_midiView = new InstrumentMidiIOView(m_tabWidget); // FX tab - m_effectView = new EffectRackView( m_track->m_audioPort.effects(), m_tabWidget ); + m_effectView = new EffectRackView(m_track->m_audioPort.effects(), m_tabWidget); - // MISC tab - m_miscView = new InstrumentMiscView( m_track, m_tabWidget ); + // Tuning tab + m_tuningView = new InstrumentTuningView(m_track, m_tabWidget); - m_tabWidget->addTab( m_ssView, tr( "Envelope, filter & LFO" ), "env_lfo_tab", 1 ); - m_tabWidget->addTab( instrumentFunctions, tr( "Chord stacking & arpeggio" ), "func_tab", 2 ); - m_tabWidget->addTab( m_effectView, tr( "Effects" ), "fx_tab", 3 ); - m_tabWidget->addTab( m_midiView, tr( "MIDI" ), "midi_tab", 4 ); - m_tabWidget->addTab( m_miscView, tr( "Miscellaneous" ), "misc_tab", 5 ); + m_tabWidget->addTab(m_ssView, tr("Envelope, filter & LFO"), "env_lfo_tab", 1); + m_tabWidget->addTab(instrumentFunctions, tr("Chord stacking & arpeggio"), "func_tab", 2); + m_tabWidget->addTab(m_effectView, tr("Effects"), "fx_tab", 3); + m_tabWidget->addTab(m_midiView, tr("MIDI"), "midi_tab", 4); + m_tabWidget->addTab(m_tuningView, tr("Tuning and transposition"), "tuning_tab", 5); adjustTabSize(m_ssView); adjustTabSize(instrumentFunctions); m_effectView->resize(EffectRackView::DEFAULT_WIDTH, INSTRUMENT_HEIGHT - 4 - 1); adjustTabSize(m_midiView); - adjustTabSize(m_miscView); + adjustTabSize(m_tuningView); // setup piano-widget m_pianoView = new PianoView( this ); @@ -356,7 +356,7 @@ void InstrumentTrackWindow::modelChanged() m_mixerChannelNumber->setModel( &m_track->m_mixerChannelModel ); m_pianoView->setModel( &m_track->m_piano ); - if( m_track->instrument() && m_track->instrument()->flags().testFlag( Instrument::IsNotBendable ) == false ) + if( m_track->instrument() && m_track->instrument()->flags().testFlag( Instrument::Flag::IsNotBendable ) == false ) { m_pitchKnob->setModel( &m_track->m_pitchModel ); m_pitchRangeSpinBox->setModel( &m_track->m_pitchRangeModel ); @@ -374,14 +374,16 @@ void InstrumentTrackWindow::modelChanged() m_pitchRangeLabel->hide(); } - if (m_track->instrument() && m_track->instrument()->flags().testFlag(Instrument::IsMidiBased)) + if (m_track->instrument() && m_track->instrument()->flags().testFlag(Instrument::Flag::IsMidiBased)) { - m_miscView->microtunerGroupBox()->hide(); + m_tuningView->microtunerNotSupportedLabel()->show(); + m_tuningView->microtunerGroupBox()->hide(); m_track->m_microtuner.enabledModel()->setValue(false); } else { - m_miscView->microtunerGroupBox()->show(); + m_tuningView->microtunerNotSupportedLabel()->hide(); + m_tuningView->microtunerGroupBox()->show(); } m_ssView->setModel( &m_track->m_soundShaping ); @@ -389,11 +391,11 @@ void InstrumentTrackWindow::modelChanged() m_arpeggioView->setModel( &m_track->m_arpeggio ); m_midiView->setModel( &m_track->m_midiPort ); m_effectView->setModel( m_track->m_audioPort.effects() ); - m_miscView->pitchGroupBox()->setModel(&m_track->m_useMasterPitchModel); - m_miscView->microtunerGroupBox()->setModel(m_track->m_microtuner.enabledModel()); - m_miscView->scaleCombo()->setModel(m_track->m_microtuner.scaleModel()); - m_miscView->keymapCombo()->setModel(m_track->m_microtuner.keymapModel()); - m_miscView->rangeImportCheckbox()->setModel(m_track->m_microtuner.keyRangeImportModel()); + m_tuningView->pitchGroupBox()->setModel(&m_track->m_useMasterPitchModel); + m_tuningView->microtunerGroupBox()->setModel(m_track->m_microtuner.enabledModel()); + m_tuningView->scaleCombo()->setModel(m_track->m_microtuner.scaleModel()); + m_tuningView->keymapCombo()->setModel(m_track->m_microtuner.keymapModel()); + m_tuningView->rangeImportCheckbox()->setModel(m_track->m_microtuner.keyRangeImportModel()); updateName(); } @@ -425,7 +427,7 @@ void InstrumentTrackWindow::saveSettingsBtnClicked() !sfd.selectedFiles().isEmpty() && !sfd.selectedFiles().first().isEmpty() ) { - DataFile dataFile(DataFile::InstrumentTrackSettings); + DataFile dataFile(DataFile::Type::InstrumentTrackSettings); QDomElement& content(dataFile.content()); m_track->setSimpleSerializing(); @@ -466,7 +468,7 @@ void InstrumentTrackWindow::updateInstrumentView() m_tabWidget->addTab( m_instrumentView, tr( "Plugin" ), "plugin_tab", 0 ); m_tabWidget->setActiveTab( 0 ); - m_ssView->setFunctionsHidden( m_track->m_instrument->flags().testFlag( Instrument::IsSingleStreamed ) ); + m_ssView->setFunctionsHidden( m_track->m_instrument->flags().testFlag( Instrument::Flag::IsSingleStreamed ) ); modelChanged(); // Get the instrument window to refresh m_track->dataChanged(); // Get the text on the trackButton to change diff --git a/src/gui/instrument/InstrumentMiscView.cpp b/src/gui/instrument/InstrumentTuningView.cpp similarity index 69% rename from src/gui/instrument/InstrumentMiscView.cpp rename to src/gui/instrument/InstrumentTuningView.cpp index 514db579c..355d7d18c 100644 --- a/src/gui/instrument/InstrumentMiscView.cpp +++ b/src/gui/instrument/InstrumentTuningView.cpp @@ -1,8 +1,8 @@ /* - * InstrumentMiscView.cpp - Miscellaneous instrument settings + * InstrumentTuningView.cpp - Instrument settings for tuning and transpositions * * Copyright (c) 2005-2014 Tobias Doerffel - * Copyright (c) 2020 Martin Pavelek + * Copyright (c) 2020-2022 Martin Pavelek * * This file is part of LMMS - https://lmms.io * @@ -23,24 +23,28 @@ * */ -#include "InstrumentMiscView.h" +#include "InstrumentTuningView.h" #include #include +#include #include #include "ComboBox.h" #include "GroupBox.h" +#include "GuiApplication.h" #include "gui_templates.h" #include "InstrumentTrack.h" #include "LedCheckBox.h" +#include "MainWindow.h" +#include "PixmapButton.h" namespace lmms::gui { -InstrumentMiscView::InstrumentMiscView(InstrumentTrack *it, QWidget *parent) : +InstrumentTuningView::InstrumentTuningView(InstrumentTrack *it, QWidget *parent) : QWidget(parent) { auto layout = new QVBoxLayout(this); @@ -60,6 +64,11 @@ InstrumentMiscView::InstrumentMiscView(InstrumentTrack *it, QWidget *parent) : masterPitchLayout->addWidget(tlabel); // Microtuner settings + m_microtunerNotSupportedLabel = new QLabel(tr("Microtuner is not available for MIDI-based instruments.")); + m_microtunerNotSupportedLabel->setWordWrap(true); + m_microtunerNotSupportedLabel->hide(); + layout->addWidget(m_microtunerNotSupportedLabel); + m_microtunerGroupBox = new GroupBox(tr("MICROTUNER")); m_microtunerGroupBox->setModel(it->m_microtuner.enabledModel()); layout->addWidget(m_microtunerGroupBox); @@ -67,8 +76,22 @@ InstrumentMiscView::InstrumentMiscView(InstrumentTrack *it, QWidget *parent) : auto microtunerLayout = new QVBoxLayout(m_microtunerGroupBox); microtunerLayout->setContentsMargins(8, 18, 8, 8); + auto scaleEditLayout = new QHBoxLayout(); + scaleEditLayout->setContentsMargins(0, 0, 4, 0); + microtunerLayout->addLayout(scaleEditLayout); + auto scaleLabel = new QLabel(tr("Active scale:")); - microtunerLayout->addWidget(scaleLabel); + scaleEditLayout->addWidget(scaleLabel); + + QPixmap editPixmap(embed::getIconPixmap("edit_draw_small")); + auto editPixButton = new PixmapButton(this, tr("Edit scales and keymaps")); + editPixButton->setToolTip(tr("Edit scales and keymaps")); + editPixButton->setInactiveGraphic(editPixmap); + editPixButton->setActiveGraphic(editPixmap); + editPixButton->setFixedSize(16, 16); + connect(editPixButton, SIGNAL(clicked()), getGUI()->mainWindow(), SLOT(toggleMicrotunerWin())); + + scaleEditLayout->addWidget(editPixButton); m_scaleCombo = new ComboBox(); m_scaleCombo->setModel(it->m_microtuner.scaleModel()); diff --git a/src/gui/instrument/PianoView.cpp b/src/gui/instrument/PianoView.cpp index a2df50e47..d20cbcac5 100644 --- a/src/gui/instrument/PianoView.cpp +++ b/src/gui/instrument/PianoView.cpp @@ -64,7 +64,7 @@ namespace lmms::gui */ auto WhiteKeys = std::array { - Key_C, Key_D, Key_E, Key_F, Key_G, Key_A, Key_H + Key::C, Key::D, Key::E, Key::F, Key::G, Key::A, Key::H } ; @@ -95,7 +95,7 @@ PianoView::PianoView(QWidget *parent) : QWidget(parent), /*!< Our parent */ ModelView(nullptr, this), /*!< Our view Model */ m_piano(nullptr), /*!< Our piano Model */ - m_startKey(Key_C + Octave_3*KeysPerOctave), /*!< The first key displayed? */ + m_startKey(Octave::Octave_3 + Key::C), /*!< The first key displayed? */ m_lastKey(-1), /*!< The last key displayed? */ m_movedNoteModel(nullptr) /*!< Key marker which is being moved */ { @@ -138,7 +138,7 @@ PianoView::PianoView(QWidget *parent) : m_pianoScroll = new QScrollBar( Qt::Horizontal, this ); m_pianoScroll->setSingleStep( 1 ); m_pianoScroll->setPageStep( 20 ); - m_pianoScroll->setValue(Octave_3 * Piano::WhiteKeysPerOctave); + m_pianoScroll->setValue(static_cast(Octave::Octave_3) * Piano::WhiteKeysPerOctave); // and connect it to this widget connect( m_pianoScroll, SIGNAL(valueChanged(int)), @@ -155,14 +155,10 @@ PianoView::PianoView(QWidget *parent) : connect(Engine::getSong(), SIGNAL(keymapListChanged(int)), this, SLOT(update())); } -/*! \brief Map a keyboard key being pressed to a note in our keyboard view - * - * \param _k The keyboard scan code of the key being pressed. - * \todo check the scan codes for ',' = c, 'L' = c#, '.' = d, ':' = d#, - * '/' = d, '[' = f', '=' = f'#, ']' = g' - Paul's additions - */ -int PianoView::getKeyFromKeyEvent( QKeyEvent * _ke ) +static int getKeyOffsetFromKeyEvent( QKeyEvent * _ke ) { + // TODO: check the scan codes for ',' = c, 'L' = c#, '.' = d, ':' = d#, + // '/' = d, '[' = f', '=' = f'#, ']' = g' - Paul's additions #ifdef LMMS_BUILD_APPLE const int k = _ke->nativeVirtualKey(); #else @@ -297,8 +293,14 @@ int PianoView::getKeyFromKeyEvent( QKeyEvent * _ke ) return -100; } - - +/*! \brief Map a keyboard key being pressed to a note in our keyboard view + * + */ +int PianoView::getKeyFromKeyEvent( QKeyEvent * ke ) +{ + const auto key = static_cast(getKeyOffsetFromKeyEvent(ke)); + return DefaultOctave + key - KeysPerOctave; +} /*! \brief Register a change to this piano display view * @@ -320,70 +322,65 @@ void PianoView::modelChanged() -// gets the key from the given mouse-position +// Gets the key from the given mouse position /*! \brief Get the key from the mouse position in the piano display * - * First we determine it roughly by the position of the point given in - * white key widths from our start. We then add in any black keys that - * might have been skipped over (they take a key number, but no 'white - * key' space). We then add in our starting key number. - * - * We then determine whether it was a black key that was pressed by - * checking whether it was within the vertical range of black keys. - * Black keys sit exactly between white keys on this keyboard, so - * we then shift the note down or up if we were in the left or right - * half of the white note. We only do this, of course, if the white - * note has a black key on that side, so to speak. - * - * This function returns const because there is a linear mapping from - * the point given to the key returned that never changes. - * - * \param _p The point that the mouse was pressed. + * \param p The point that the mouse was pressed. */ -int PianoView::getKeyFromMouse( const QPoint & _p ) const +int PianoView::getKeyFromMouse(const QPoint& p) const { - int offset = _p.x() % PW_WHITE_KEY_WIDTH; - if( offset < 0 ) offset += PW_WHITE_KEY_WIDTH; - int key_num = ( _p.x() - offset) / PW_WHITE_KEY_WIDTH; + // The left-most key visible in the piano display is always white + const int startingWhiteKey = m_pianoScroll->value(); - for( int i = 0; i <= key_num; ++i ) + // Adjust the mouse x position as if x == 0 was the left side of the lowest key + const int adjX = p.x() + (startingWhiteKey * PW_WHITE_KEY_WIDTH); + + // Can early return for notes too low + if (adjX <= 0) { return 0; } + + // Now we can calculate the key number (in only white keys) and the octave + const int whiteKey = adjX / PW_WHITE_KEY_WIDTH; + const int octave = whiteKey / Piano::WhiteKeysPerOctave; + + // Calculate for full octaves + int key = octave * KeysPerOctave; + + // Adjust for white notes in the current octave + // (WhiteKeys maps each white key to the number of notes to their left in the octave) + key += static_cast(WhiteKeys[whiteKey % Piano::WhiteKeysPerOctave]); + + // Might be a black key, which would require further adjustment + if (p.y() < PIANO_BASE + PW_BLACK_KEY_HEIGHT) { - if ( Piano::isBlackKey( m_startKey+i ) ) + // Maps white keys to neighboring black keys + static constexpr std::array neighboringKeyMap { + std::pair{ 0, 1 }, // C --> no B#; C# + std::pair{ 1, 1 }, // D --> C#; D# + std::pair{ 1, 0 }, // E --> D#; no E# + std::pair{ 0, 1 }, // F --> no E#; F# + std::pair{ 1, 1 }, // G --> F#; G# + std::pair{ 1, 1 }, // A --> G#; A# + std::pair{ 1, 0 }, // B --> A#; no B# + }; + + const auto neighboringBlackKeys = neighboringKeyMap[whiteKey % Piano::WhiteKeysPerOctave]; + const int offset = adjX - (whiteKey * PW_WHITE_KEY_WIDTH); // mouse X offset from white key + + if (offset < PW_BLACK_KEY_WIDTH / 2) { - ++key_num; + // At the location of a (possibly non-existent) black key on the left side + key -= neighboringBlackKeys.first; } - } - for( int i = 0; i >= key_num; --i ) - { - if ( Piano::isBlackKey( m_startKey+i ) ) + else if (offset > PW_WHITE_KEY_WIDTH - (PW_BLACK_KEY_WIDTH / 2)) { - --key_num; + // At the location of a (possibly non-existent) black key on the right side + key += neighboringBlackKeys.second; } + + // For white keys in between black keys, no further adjustment is needed } - key_num += m_startKey; - - // is it a black key? - if( _p.y() < PIANO_BASE + PW_BLACK_KEY_HEIGHT ) - { - // then do extra checking whether the mouse-cursor is over - // a black key - if( key_num > 0 && Piano::isBlackKey( key_num-1 ) && - offset <= ( PW_WHITE_KEY_WIDTH / 2 ) - - ( PW_BLACK_KEY_WIDTH / 2 ) ) - { - --key_num; - } - if( key_num < NumKeys - 1 && Piano::isBlackKey( key_num+1 ) && - offset >= ( PW_WHITE_KEY_WIDTH - - PW_BLACK_KEY_WIDTH / 2 ) ) - { - ++key_num; - } - } - - // some range-checking-stuff - return qBound( 0, key_num, NumKeys - 1 ); + return std::clamp(key, 0, NumKeys - 1); } @@ -394,12 +391,12 @@ int PianoView::getKeyFromMouse( const QPoint & _p ) const * * We need to update our start key position based on the new position. * - * \param _new_pos the new key position. + * \param newPos the new key position, counting only white keys. */ -void PianoView::pianoScrolled(int new_pos) +void PianoView::pianoScrolled(int newPos) { - m_startKey = WhiteKeys[new_pos % Piano::WhiteKeysPerOctave] + - (new_pos / Piano::WhiteKeysPerOctave) * KeysPerOctave; + m_startKey = static_cast(newPos / Piano::WhiteKeysPerOctave) + + WhiteKeys[newPos % Piano::WhiteKeysPerOctave]; update(); } @@ -625,8 +622,7 @@ void PianoView::mouseMoveEvent( QMouseEvent * _me ) */ void PianoView::keyPressEvent( QKeyEvent * _ke ) { - const int key_num = getKeyFromKeyEvent( _ke ) + - ( DefaultOctave - 1 ) * KeysPerOctave; + const int key_num = getKeyFromKeyEvent( _ke ); if( _ke->isAutoRepeat() == false && key_num > -1 ) { @@ -654,8 +650,7 @@ void PianoView::keyPressEvent( QKeyEvent * _ke ) */ void PianoView::keyReleaseEvent( QKeyEvent * _ke ) { - const int key_num = getKeyFromKeyEvent( _ke ) + - ( DefaultOctave - 1 ) * KeysPerOctave; + const int key_num = getKeyFromKeyEvent( _ke ); if( _ke->isAutoRepeat() == false && key_num > -1 ) { if( m_piano != nullptr ) @@ -913,7 +908,7 @@ void PianoView::paintEvent( QPaintEvent * ) x += PW_WHITE_KEY_WIDTH; - if ((Keys)(cur_key % KeysPerOctave) == Key_C) + if ((Key)(cur_key % KeysPerOctave) == Key::C) { // label key of note C with "C" and number of current octave p.drawText(x - PW_WHITE_KEY_WIDTH, LABEL_TEXT_SIZE + 2, @@ -927,7 +922,7 @@ void PianoView::paintEvent( QPaintEvent * ) int white_cnt = 0; int startKey = m_startKey; - if (startKey > 0 && Piano::isBlackKey(static_cast(--startKey))) + if (startKey > 0 && Piano::isBlackKey(--startKey)) { if (m_piano && m_piano->instrumentTrack()->isKeyMapped(startKey)) { diff --git a/src/gui/menus/MidiPortMenu.cpp b/src/gui/menus/MidiPortMenu.cpp index b1ddf71c9..296be3506 100644 --- a/src/gui/menus/MidiPortMenu.cpp +++ b/src/gui/menus/MidiPortMenu.cpp @@ -30,7 +30,7 @@ namespace lmms::gui { -MidiPortMenu::MidiPortMenu( MidiPort::Modes _mode ) : +MidiPortMenu::MidiPortMenu( MidiPort::Mode _mode ) : ModelView( nullptr, this ), m_mode( _mode ) { @@ -46,12 +46,12 @@ MidiPortMenu::MidiPortMenu( MidiPort::Modes _mode ) : void MidiPortMenu::modelChanged() { auto mp = castModel(); - if( m_mode == MidiPort::Input ) + if( m_mode == MidiPort::Mode::Input ) { connect( mp, SIGNAL(readablePortsChanged()), this, SLOT(updateMenu())); } - else if( m_mode == MidiPort::Output ) + else if( m_mode == MidiPort::Mode::Output ) { connect( mp, SIGNAL(writablePortsChanged()), this, SLOT(updateMenu())); @@ -64,12 +64,12 @@ void MidiPortMenu::modelChanged() void MidiPortMenu::activatedPort( QAction * _item ) { - if( m_mode == MidiPort::Input ) + if( m_mode == MidiPort::Mode::Input ) { castModel()->subscribeReadablePort( _item->text(), _item->isChecked() ); } - else if( m_mode == MidiPort::Output ) + else if( m_mode == MidiPort::Mode::Output ) { castModel()->subscribeWritablePort( _item->text(), _item->isChecked() ); @@ -82,7 +82,7 @@ void MidiPortMenu::activatedPort( QAction * _item ) void MidiPortMenu::updateMenu() { auto mp = castModel(); - const MidiPort::Map & map = ( m_mode == MidiPort::Input ) ? + const MidiPort::Map & map = ( m_mode == MidiPort::Mode::Input ) ? mp->readablePorts() : mp->writablePorts(); clear(); for( MidiPort::Map::ConstIterator it = map.begin(); diff --git a/src/gui/modals/ControllerConnectionDialog.cpp b/src/gui/modals/ControllerConnectionDialog.cpp index 06f6a5708..79daa25b5 100644 --- a/src/gui/modals/ControllerConnectionDialog.cpp +++ b/src/gui/modals/ControllerConnectionDialog.cpp @@ -169,7 +169,7 @@ ControllerConnectionDialog::ControllerConnectionDialog( QWidget * _parent, // our port-menus when being clicked if( !Engine::audioEngine()->midiClient()->isRaw() ) { - m_readablePorts = new MidiPortMenu( MidiPort::Input ); + m_readablePorts = new MidiPortMenu( MidiPort::Mode::Input ); connect( m_readablePorts, SIGNAL(triggered(QAction*)), this, SLOT(enableAutoDetect(QAction*))); auto rp_btn = new ToolButton(m_midiGroupBox); @@ -242,9 +242,9 @@ ControllerConnectionDialog::ControllerConnectionDialog( QWidget * _parent, { cc = m_targetModel->controllerConnection(); - if( cc && cc->getController()->type() != Controller::DummyController && Engine::getSong() ) + if( cc && cc->getController()->type() != Controller::ControllerType::Dummy && Engine::getSong() ) { - if ( cc->getController()->type() == Controller::MidiController ) + if ( cc->getController()->type() == Controller::ControllerType::Midi ) { m_midiGroupBox->model()->setValue( true ); // ensure controller is created @@ -258,10 +258,12 @@ ControllerConnectionDialog::ControllerConnectionDialog( QWidget * _parent, } else { - int idx = Engine::getSong()->controllers().indexOf( cc->getController() ); + auto& controllers = Engine::getSong()->controllers(); + auto it = std::find(controllers.begin(), controllers.end(), cc->getController()); - if( idx >= 0 ) + if (it != controllers.end()) { + int idx = std::distance(controllers.begin(), it); m_userGroupBox->model()->setValue( true ); m_userController->model()->setValue( idx ); } @@ -406,7 +408,7 @@ void ControllerConnectionDialog::userSelected() void ControllerConnectionDialog::autoDetectToggled() { - if( m_midiAutoDetect.value() ) + if (m_midiAutoDetect.value() && m_midiController) { m_midiController->reset(); } diff --git a/src/gui/modals/EffectSelectDialog.cpp b/src/gui/modals/EffectSelectDialog.cpp index eac5a3783..31ffd7728 100644 --- a/src/gui/modals/EffectSelectDialog.cpp +++ b/src/gui/modals/EffectSelectDialog.cpp @@ -53,7 +53,7 @@ EffectSelectDialog::EffectSelectDialog( QWidget * _parent ) : EffectKeyList subPluginEffectKeys; - for (const Plugin::Descriptor* desc: getPluginFactory()->descriptors(Plugin::Effect)) + for (const Plugin::Descriptor* desc: getPluginFactory()->descriptors(Plugin::Type::Effect)) { if( desc->subPluginFeatures ) { diff --git a/src/gui/modals/ExportProjectDialog.cpp b/src/gui/modals/ExportProjectDialog.cpp index 1f937c374..fe39082e4 100644 --- a/src/gui/modals/ExportProjectDialog.cpp +++ b/src/gui/modals/ExportProjectDialog.cpp @@ -66,7 +66,7 @@ ExportProjectDialog::ExportProjectDialog( const QString & _file_name, // Add to combo box. fileFormatCB->addItem( ProjectRenderer::tr( ProjectRenderer::fileEncodeDevices[i].m_description ), - QVariant( ProjectRenderer::fileEncodeDevices[i].m_fileFormat ) // Format tag; later used for identification. + QVariant( static_cast(ProjectRenderer::fileEncodeDevices[i].m_fileFormat) ) // Format tag; later used for identification. ); // If this is our extension, select it. @@ -142,13 +142,13 @@ OutputSettings::StereoMode mapToStereoMode(int index) switch (index) { case 0: - return OutputSettings::StereoMode_Mono; + return OutputSettings::StereoMode::Mono; case 1: - return OutputSettings::StereoMode_Stereo; + return OutputSettings::StereoMode::Stereo; case 2: - return OutputSettings::StereoMode_JointStereo; + return OutputSettings::StereoMode::JointStereo; default: - return OutputSettings::StereoMode_Stereo; + return OutputSettings::StereoMode::Stereo; } } @@ -216,27 +216,27 @@ void ExportProjectDialog::onFileFormatChanged(int index) // and adjust the UI properly. QVariant format_tag = fileFormatCB->itemData(index); bool successful_conversion = false; - auto exportFormat = static_cast( + auto exportFormat = static_cast( format_tag.toInt(&successful_conversion) ); Q_ASSERT(successful_conversion); - bool stereoModeVisible = (exportFormat == ProjectRenderer::MP3File); + bool stereoModeVisible = (exportFormat == ProjectRenderer::ExportFileFormat::MP3); - bool sampleRateControlsVisible = (exportFormat != ProjectRenderer::MP3File); + bool sampleRateControlsVisible = (exportFormat != ProjectRenderer::ExportFileFormat::MP3); bool bitRateControlsEnabled = - (exportFormat == ProjectRenderer::OggFile || - exportFormat == ProjectRenderer::MP3File); + (exportFormat == ProjectRenderer::ExportFileFormat::Ogg || + exportFormat == ProjectRenderer::ExportFileFormat::MP3); bool bitDepthControlEnabled = - (exportFormat == ProjectRenderer::WaveFile || - exportFormat == ProjectRenderer::FlacFile); + (exportFormat == ProjectRenderer::ExportFileFormat::Wave || + exportFormat == ProjectRenderer::ExportFileFormat::Flac); - bool variableBitrateVisible = !(exportFormat == ProjectRenderer::MP3File || exportFormat == ProjectRenderer::FlacFile); + bool variableBitrateVisible = !(exportFormat == ProjectRenderer::ExportFileFormat::MP3 || exportFormat == ProjectRenderer::ExportFileFormat::Flac); #ifdef LMMS_HAVE_SF_COMPLEVEL - bool compressionLevelVisible = (exportFormat == ProjectRenderer::FlacFile); + bool compressionLevelVisible = (exportFormat == ProjectRenderer::ExportFileFormat::Flac); compressionWidget->setVisible(compressionLevelVisible); #endif @@ -251,12 +251,12 @@ void ExportProjectDialog::onFileFormatChanged(int index) void ExportProjectDialog::startBtnClicked() { - m_ft = ProjectRenderer::NumFileFormats; + m_ft = ProjectRenderer::ExportFileFormat::Count; // Get file format from current menu selection. bool successful_conversion = false; QVariant tag = fileFormatCB->itemData(fileFormatCB->currentIndex()); - m_ft = static_cast( + m_ft = static_cast( tag.toInt(&successful_conversion) ); diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index 33505c399..63b84506e 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -91,7 +91,7 @@ inline void labelWidget(QWidget * w, const QString & txt) -SetupDialog::SetupDialog(ConfigTabs tab_to_open) : +SetupDialog::SetupDialog(ConfigTab tab_to_open) : m_displaydBFS(ConfigManager::inst()->value( "app", "displaydbfs").toInt()), m_tooltips(!ConfigManager::inst()->value( @@ -837,7 +837,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : tr("Paths"), 4, true, true)->setIcon( embed::getIconPixmap("setup_directories")); - m_tabBar->setActiveTab(tab_to_open); + m_tabBar->setActiveTab(static_cast(tab_to_open)); // Horizontal layout ordering. hlayout->addSpacing(2); diff --git a/src/gui/tracks/InstrumentTrackView.cpp b/src/gui/tracks/InstrumentTrackView.cpp index 17adc99a6..87c0f0449 100644 --- a/src/gui/tracks/InstrumentTrackView.cpp +++ b/src/gui/tracks/InstrumentTrackView.cpp @@ -63,7 +63,6 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV m_tlb = new TrackLabelButton( this, getTrackSettingsWidget() ); m_tlb->setCheckable( true ); m_tlb->setIcon( embed::getIconPixmap( "instrument_track" ) ); - m_tlb->move( 3, 1 ); m_tlb->show(); connect( m_tlb, SIGNAL(toggled(bool)), @@ -75,32 +74,21 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV connect(ConfigManager::inst(), SIGNAL(valueChanged(QString,QString,QString)), this, SLOT(handleConfigChange(QString,QString,QString))); - // creation of widgets for track-settings-widget - int widgetWidth; - if( ConfigManager::inst()->value( "ui", - "compacttrackbuttons" ).toInt() ) - { - widgetWidth = DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT; - } - else - { - widgetWidth = DEFAULT_SETTINGS_WIDGET_WIDTH; - } + m_mixerChannelNumber = new MixerLineLcdSpinBox(2, getTrackSettingsWidget(), tr("Mixer channel"), this); + m_mixerChannelNumber->show(); - m_volumeKnob = new Knob( knobSmall_17, getTrackSettingsWidget(), + m_volumeKnob = new Knob( KnobType::Small17, getTrackSettingsWidget(), tr( "Volume" ) ); m_volumeKnob->setVolumeKnob( true ); m_volumeKnob->setModel( &_it->m_volumeModel ); m_volumeKnob->setHintText( tr( "Volume:" ), "%" ); - m_volumeKnob->move( widgetWidth-2*24, 2 ); m_volumeKnob->setLabel( tr( "VOL" ) ); m_volumeKnob->show(); - m_panningKnob = new Knob( knobSmall_17, getTrackSettingsWidget(), + m_panningKnob = new Knob( KnobType::Small17, getTrackSettingsWidget(), tr( "Panning" ) ); m_panningKnob->setModel( &_it->m_panningModel ); m_panningKnob->setHintText(tr("Panning:"), "%"); - m_panningKnob->move( widgetWidth-24, 2 ); m_panningKnob->setLabel( tr( "PAN" ) ); m_panningKnob->show(); @@ -110,9 +98,9 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV if( !Engine::audioEngine()->midiClient()->isRaw() ) { _it->m_midiPort.m_readablePortsMenu = new MidiPortMenu( - MidiPort::Input ); + MidiPort::Mode::Input ); _it->m_midiPort.m_writablePortsMenu = new MidiPortMenu( - MidiPort::Output ); + MidiPort::Mode::Output ); _it->m_midiPort.m_readablePortsMenu->setModel( &_it->m_midiPort ); _it->m_midiPort.m_writablePortsMenu->setModel( @@ -151,9 +139,18 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV QApplication::palette().color( QPalette::Active, QPalette::BrightText).darker(), getTrackSettingsWidget() ); - m_activityIndicator->setGeometry( - widgetWidth-2*24-11, 2, 8, 28 ); + m_activityIndicator->setFixedSize(8, 28); m_activityIndicator->show(); + + auto layout = new QHBoxLayout(getTrackSettingsWidget()); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + layout->addWidget(m_tlb); + layout->addWidget(m_mixerChannelNumber); + layout->addWidget(m_activityIndicator); + layout->addWidget(m_volumeKnob); + layout->addWidget(m_panningKnob); + connect( m_activityIndicator, SIGNAL(pressed()), this, SLOT(activityIndicatorPressed())); connect( m_activityIndicator, SIGNAL(released()), @@ -268,6 +265,13 @@ void InstrumentTrackView::handleConfigChange(QString cls, QString attr, QString } } +void InstrumentTrackView::modelChanged() +{ + TrackView::modelChanged(); + auto st = castModel(); + m_mixerChannelNumber->setModel(&st->m_mixerChannelModel); +} + void InstrumentTrackView::dragEnterEvent( QDragEnterEvent * _dee ) { InstrumentTrackWindow::dragEnterEventGeneric( _dee ); diff --git a/src/gui/tracks/SampleTrackView.cpp b/src/gui/tracks/SampleTrackView.cpp index fbdd41ded..8516eb5c2 100644 --- a/src/gui/tracks/SampleTrackView.cpp +++ b/src/gui/tracks/SampleTrackView.cpp @@ -56,28 +56,24 @@ SampleTrackView::SampleTrackView( SampleTrack * _t, TrackContainerView* tcv ) : connect(m_tlb, SIGNAL(clicked(bool)), this, SLOT(showEffects())); m_tlb->setIcon(embed::getIconPixmap("sample_track")); - m_tlb->move(3, 1); m_tlb->show(); - m_volumeKnob = new Knob( knobSmall_17, getTrackSettingsWidget(), + m_mixerChannelNumber = new MixerLineLcdSpinBox(2, getTrackSettingsWidget(), tr("Mixer channel"), this); + m_mixerChannelNumber->show(); + + m_volumeKnob = new Knob( KnobType::Small17, getTrackSettingsWidget(), tr( "Track volume" ) ); m_volumeKnob->setVolumeKnob( true ); m_volumeKnob->setModel( &_t->m_volumeModel ); m_volumeKnob->setHintText( tr( "Channel volume:" ), "%" ); - int settingsWidgetWidth = ConfigManager::inst()-> - value( "ui", "compacttrackbuttons" ).toInt() - ? DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT - : DEFAULT_SETTINGS_WIDGET_WIDTH; - m_volumeKnob->move( settingsWidgetWidth - 2 * 24, 2 ); m_volumeKnob->setLabel( tr( "VOL" ) ); m_volumeKnob->show(); - m_panningKnob = new Knob( knobSmall_17, getTrackSettingsWidget(), + m_panningKnob = new Knob( KnobType::Small17, getTrackSettingsWidget(), tr( "Panning" ) ); m_panningKnob->setModel( &_t->m_panningModel ); m_panningKnob->setHintText( tr( "Panning:" ), "%" ); - m_panningKnob->move( settingsWidgetWidth - 24, 2 ); m_panningKnob->setLabel( tr( "PAN" ) ); m_panningKnob->show(); @@ -87,8 +83,18 @@ SampleTrackView::SampleTrackView( SampleTrack * _t, TrackContainerView* tcv ) : QApplication::palette().color(QPalette::Active, QPalette::BrightText).darker(), getTrackSettingsWidget() ); - m_activityIndicator->setGeometry(settingsWidgetWidth - 2 * 24 - 11, 2, 8, 28); + m_activityIndicator->setFixedSize(8, 28); m_activityIndicator->show(); + + auto layout = new QHBoxLayout(getTrackSettingsWidget()); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + layout->addWidget(m_tlb); + layout->addWidget(m_mixerChannelNumber); + layout->addWidget(m_activityIndicator); + layout->addWidget(m_volumeKnob); + layout->addWidget(m_panningKnob); + connect(_t, SIGNAL(playingChanged()), this, SLOT(updateIndicator())); setModel( _t ); @@ -170,6 +176,7 @@ void SampleTrackView::modelChanged() { auto st = castModel(); m_volumeKnob->setModel(&st->m_volumeModel); + m_mixerChannelNumber->setModel(&st->m_mixerChannelModel); TrackView::modelChanged(); } diff --git a/src/gui/tracks/TrackContentWidget.cpp b/src/gui/tracks/TrackContentWidget.cpp index 74ab016ea..619eff831 100644 --- a/src/gui/tracks/TrackContentWidget.cpp +++ b/src/gui/tracks/TrackContentWidget.cpp @@ -291,7 +291,7 @@ void TrackContentWidget::dragEnterEvent( QDragEnterEvent * dee ) else { StringPairDrag::processDragEnterEvent( dee, "clip_" + - QString::number( getTrack()->type() ) ); + QString::number( static_cast(getTrack()->type()) ) ); } } @@ -325,8 +325,7 @@ bool TrackContentWidget::canPasteSelection( TimePos clipPos, const QMimeData* md QString value = decodeValue( md ); // We can only paste into tracks of the same type - if( type != ( "clip_" + QString::number( t->type() ) ) || - m_trackView->trackContainerView()->fixedClips() == true ) + if (type != ("clip_" + QString::number(static_cast(t->type())))) { return false; } @@ -345,8 +344,9 @@ bool TrackContentWidget::canPasteSelection( TimePos clipPos, const QMimeData* md const int initialTrackIndex = tiAttr.value().toInt(); // Get the current track's index - const TrackContainer::TrackList tracks = t->trackContainer()->tracks(); - const int currentTrackIndex = tracks.indexOf( t ); + const TrackContainer::TrackList& tracks = t->trackContainer()->tracks(); + const auto currentTrackIt = std::find(tracks.begin(), tracks.end(), t); + const int currentTrackIndex = currentTrackIt != tracks.end() ? std::distance(tracks.begin(), currentTrackIt) : -1; // Don't paste if we're on the same bar and allowSameBar is false auto sourceTrackContainerId = metadata.attributeNode( "trackContainerId" ).value().toUInt(); @@ -360,6 +360,14 @@ bool TrackContentWidget::canPasteSelection( TimePos clipPos, const QMimeData* md QDomElement clipParent = dataFile.content().firstChildElement("clips"); QDomNodeList clipNodes = clipParent.childNodes(); + // If we are pasting into the PatternEditor, only a single Clip is allowed to be pasted + // so we don't have the unexpected behavior of pasting on different PatternTracks + if (m_trackView->trackContainerView()->fixedClips() == true && + clipNodes.length() > 1) + { + return false; + } + // Determine if all the Clips will land on a valid track for( int i = 0; i < clipNodes.length(); i++ ) { @@ -374,7 +382,7 @@ bool TrackContentWidget::canPasteSelection( TimePos clipPos, const QMimeData* md } // Track must be of the same type - auto startTrackType = clipElement.attributeNode("trackType").value().toInt(); + auto startTrackType = static_cast(clipElement.attributeNode("trackType").value().toInt()); Track * endTrack = tracks.at( finalTrackIndex ); if( startTrackType != endTrack->type() ) { @@ -435,8 +443,9 @@ bool TrackContentWidget::pasteSelection( TimePos clipPos, const QMimeData * md, TimePos grabbedClipPos = clipPosAttr.value().toInt(); // Snap the mouse position to the beginning of the dropped bar, in ticks - const TrackContainer::TrackList tracks = getTrack()->trackContainer()->tracks(); - const int currentTrackIndex = tracks.indexOf( getTrack() ); + const TrackContainer::TrackList& tracks = getTrack()->trackContainer()->tracks(); + const auto currentTrackIt = std::find(tracks.begin(), tracks.end(), getTrack()); + const int currentTrackIndex = currentTrackIt != tracks.end() ? std::distance(tracks.begin(), currentTrackIt) : -1; bool wasSelection = m_trackView->trackContainerView()->rubberBand()->selectedObjects().count(); @@ -529,7 +538,7 @@ void TrackContentWidget::mousePressEvent( QMouseEvent * me ) // Enable box select if control is held when clicking an empty space // (If we had clicked a Clip it would have intercepted the mouse event) if( me->modifiers() & Qt::ControlModifier ){ - getGUI()->songEditor()->m_editor->setEditMode(SongEditor::EditMode::SelectMode); + getGUI()->songEditor()->m_editor->setEditMode(SongEditor::EditMode::Select); } // Forward event to allow box select if the editor supports it and is in that mode if( m_trackView->trackContainerView()->allowRubberband() == true ) @@ -646,7 +655,7 @@ void TrackContentWidget::contextMenuEvent( QContextMenuEvent * cme ) QMenu contextMenu( this ); QAction *pasteA = contextMenu.addAction( embed::getIconPixmap( "edit_paste" ), - tr( "Paste" ), [this, cme](){ contextMenuAction( cme, Paste ); } ); + tr( "Paste" ), [this, cme](){ contextMenuAction( cme, ContextMenuAction::Paste ); } ); // If we can't paste in the current TCW for some reason, disable the action so the user knows pasteA->setEnabled( canPasteSelection( getPosition( cme->x() ), getMimeData() ) ? true : false ); @@ -660,7 +669,7 @@ void TrackContentWidget::contextMenuAction( QContextMenuEvent * cme, ContextMenu switch( action ) { - case Paste: + case ContextMenuAction::Paste: // Paste the selection on the TimePos of the context menu event TimePos clipPos = getPosition( cme->x() ); diff --git a/src/gui/tracks/TrackLabelButton.cpp b/src/gui/tracks/TrackLabelButton.cpp index 3f1b45871..2a50a4aa2 100644 --- a/src/gui/tracks/TrackLabelButton.cpp +++ b/src/gui/tracks/TrackLabelButton.cpp @@ -187,7 +187,7 @@ void TrackLabelButton::mouseReleaseEvent( QMouseEvent *_me ) void TrackLabelButton::paintEvent( QPaintEvent * _pe ) { - if( m_trackView->getTrack()->type() == Track::InstrumentTrack ) + if( m_trackView->getTrack()->type() == Track::Type::Instrument ) { auto it = dynamic_cast(m_trackView->getTrack()); const PixmapLoader * pl; diff --git a/src/gui/tracks/TrackOperationsWidget.cpp b/src/gui/tracks/TrackOperationsWidget.cpp index ddbd2eacd..ce6177d76 100644 --- a/src/gui/tracks/TrackOperationsWidget.cpp +++ b/src/gui/tracks/TrackOperationsWidget.cpp @@ -137,12 +137,12 @@ void TrackOperationsWidget::mousePressEvent( QMouseEvent * me ) { if( me->button() == Qt::LeftButton && me->modifiers() & Qt::ControlModifier && - m_trackView->getTrack()->type() != Track::PatternTrack) + m_trackView->getTrack()->type() != Track::Type::Pattern) { - DataFile dataFile( DataFile::DragNDropData ); + DataFile dataFile( DataFile::Type::DragNDropData ); m_trackView->getTrack()->saveState( dataFile, dataFile.content() ); new StringPairDrag( QString( "track_%1" ).arg( - m_trackView->getTrack()->type() ), + static_cast(m_trackView->getTrack()->type()) ), dataFile.toString(), m_trackView->getTrackSettingsWidget()->grab(), this ); } diff --git a/src/gui/tracks/TrackView.cpp b/src/gui/tracks/TrackView.cpp index 3e9257a0d..426be7e36 100644 --- a/src/gui/tracks/TrackView.cpp +++ b/src/gui/tracks/TrackView.cpp @@ -65,7 +65,7 @@ TrackView::TrackView( Track * track, TrackContainerView * tcv ) : m_trackOperationsWidget( this ), /*!< Our trackOperationsWidget */ m_trackSettingsWidget( this ), /*!< Our trackSettingsWidget */ m_trackContentWidget( this ), /*!< Our trackContentWidget */ - m_action( NoAction ) /*!< The action we're currently performing */ + m_action( Action::None ) /*!< The action we're currently performing */ { setAutoFillBackground( true ); QPalette pal; @@ -207,7 +207,7 @@ void TrackView::modelChanged() void TrackView::dragEnterEvent( QDragEnterEvent * dee ) { StringPairDrag::processDragEnterEvent( dee, "track_" + - QString::number( m_track->type() ) ); + QString::number( static_cast(m_track->type()) ) ); } @@ -225,7 +225,7 @@ void TrackView::dropEvent( QDropEvent * de ) { QString type = StringPairDrag::decodeKey( de ); QString value = StringPairDrag::decodeValue( de ); - if( type == ( "track_" + QString::number( m_track->type() ) ) ) + if( type == ( "track_" + QString::number( static_cast(m_track->type()) ) ) ) { // value contains our XML-data so simply create a // DataFile which does the rest for us... @@ -278,7 +278,7 @@ void TrackView::mousePressEvent( QMouseEvent * me ) { if( me->modifiers() & Qt::ShiftModifier ) { - m_action = ResizeTrack; + m_action = Action::Resize; QCursor::setPos( mapToGlobal( QPoint( me->x(), height() ) ) ); QCursor c( Qt::SizeVerCursor); @@ -292,7 +292,7 @@ void TrackView::mousePressEvent( QMouseEvent * me ) return; } - m_action = MoveTrack; + m_action = Action::Move; QCursor c( Qt::SizeVerCursor ); QApplication::setOverrideCursor( c ); @@ -338,7 +338,7 @@ void TrackView::mouseMoveEvent( QMouseEvent * me ) { QWidget::mouseMoveEvent( me ); } - else if( m_action == MoveTrack ) + else if( m_action == Action::Move ) { // look which track-widget the mouse-cursor is over const int yPos = @@ -362,7 +362,7 @@ void TrackView::mouseMoveEvent( QMouseEvent * me ) } } } - else if( m_action == ResizeTrack ) + else if( m_action == Action::Resize ) { setFixedHeight( qMax( me->y(), MINIMAL_TRACK_HEIGHT ) ); m_trackContainerView->realignTracks(); @@ -383,7 +383,7 @@ void TrackView::mouseMoveEvent( QMouseEvent * me ) */ void TrackView::mouseReleaseEvent( QMouseEvent * me ) { - m_action = NoAction; + m_action = Action::None; while( QApplication::overrideCursor() != nullptr ) { QApplication::restoreOverrideCursor(); diff --git a/src/gui/widgets/CPULoadWidget.cpp b/src/gui/widgets/CPULoadWidget.cpp index 799e037ef..db1f5cacc 100644 --- a/src/gui/widgets/CPULoadWidget.cpp +++ b/src/gui/widgets/CPULoadWidget.cpp @@ -24,6 +24,7 @@ */ +#include #include #include "AudioEngine.h" @@ -72,10 +73,9 @@ void CPULoadWidget::paintEvent( QPaintEvent * ) QPainter p( &m_temp ); p.drawPixmap( 0, 0, m_background ); - // as load-indicator consists of small 2-pixel wide leds with - // 1 pixel spacing, we have to make sure, only whole leds are - // shown which we achieve by the following formula - int w = ( m_leds.width() * m_currentLoad / 300 ) * 3; + // Normally the CPU load indicator moves smoothly, with 1 pixel resolution. However, some themes may want to + // draw discrete elements (like LEDs), so the stepSize property can be used to specify a larger step size. + int w = (m_leds.width() * std::min(m_currentLoad, 100) / (stepSize() * 100)) * stepSize(); if( w > 0 ) { p.drawPixmap( 23, 3, m_leds, 0, 0, w, @@ -91,10 +91,21 @@ void CPULoadWidget::paintEvent( QPaintEvent * ) void CPULoadWidget::updateCpuLoad() { - // smooth load-values a bit - int new_load = ( m_currentLoad + Engine::audioEngine()->cpuLoad() ) / 2; - if( new_load != m_currentLoad ) + // Additional display smoothing for the main load-value. Stronger averaging + // cannot be used directly in the profiler: cpuLoad() must react fast enough + // to be useful as overload indicator in AudioEngine::criticalXRuns(). + const int new_load = (m_currentLoad + Engine::audioEngine()->cpuLoad()) / 2; + + if (new_load != m_currentLoad) { + auto engine = Engine::audioEngine(); + setToolTip( + tr("DSP total: %1%").arg(new_load) + "\n" + + tr(" - Notes and setup: %1%").arg(engine->detailLoad(AudioEngineProfiler::DetailType::NoteSetup)) + "\n" + + tr(" - Instruments: %1%").arg(engine->detailLoad(AudioEngineProfiler::DetailType::Instruments)) + "\n" + + tr(" - Effects: %1%").arg(engine->detailLoad(AudioEngineProfiler::DetailType::Effects)) + "\n" + + tr(" - Mixing: %1%").arg(engine->detailLoad(AudioEngineProfiler::DetailType::Mixing)) + ); m_currentLoad = new_load; m_changed = true; update(); @@ -102,4 +113,4 @@ void CPULoadWidget::updateCpuLoad() } -} // namespace lmms::gui \ No newline at end of file +} // namespace lmms::gui diff --git a/src/gui/widgets/CustomTextKnob.cpp b/src/gui/widgets/CustomTextKnob.cpp index ce880608c..a4edde47c 100644 --- a/src/gui/widgets/CustomTextKnob.cpp +++ b/src/gui/widgets/CustomTextKnob.cpp @@ -28,7 +28,7 @@ namespace lmms::gui { -CustomTextKnob::CustomTextKnob( knobTypes _knob_num, QWidget * _parent, const QString & _name, const QString & _value_text ) : +CustomTextKnob::CustomTextKnob( KnobType _knob_num, QWidget * _parent, const QString & _name, const QString & _value_text ) : Knob( _knob_num, _parent, _name ), m_value_text( _value_text ) {} diff --git a/src/gui/widgets/Graph.cpp b/src/gui/widgets/Graph.cpp index 53a0a130d..9972209a8 100644 --- a/src/gui/widgets/Graph.cpp +++ b/src/gui/widgets/Graph.cpp @@ -36,7 +36,7 @@ namespace lmms namespace gui { -Graph::Graph( QWidget * _parent, graphStyle _style, int _width, +Graph::Graph( QWidget * _parent, Style _style, int _width, int _height ) : QWidget( _parent ), /* TODO: size, background? */ @@ -305,7 +305,7 @@ void Graph::paintEvent( QPaintEvent * ) switch( m_graphStyle ) { - case Graph::LinearStyle: + case Style::Linear: p.setRenderHints( QPainter::Antialiasing, true ); for( int i=0; i < length; i++ ) @@ -329,7 +329,7 @@ void Graph::paintEvent( QPaintEvent * ) break; - case Graph::NearestStyle: + case Style::Nearest: for( int i=0; i < length; i++ ) { p.drawLine(2+static_cast(i*xscale), @@ -350,7 +350,7 @@ void Graph::paintEvent( QPaintEvent * ) 2+static_cast( ( (*samps)[length] - maxVal ) * yscale ) ); break; - case Graph::LinearNonCyclicStyle: + case Style::LinearNonCyclic: p.setRenderHints( QPainter::Antialiasing, true ); for( int i=0; i < length; i++ ) @@ -369,7 +369,7 @@ void Graph::paintEvent( QPaintEvent * ) p.setRenderHints( QPainter::Antialiasing, false ); break; - case Graph::BarStyle: + case Style::Bar: for( int i=0; i <= length; i++ ) { p.fillRect( 2+static_cast( i*xscale ), diff --git a/src/gui/widgets/Knob.cpp b/src/gui/widgets/Knob.cpp index 8640bb81d..56cf29345 100644 --- a/src/gui/widgets/Knob.cpp +++ b/src/gui/widgets/Knob.cpp @@ -22,6 +22,8 @@ * */ +#include "Knob.h" + #include #include #include @@ -34,7 +36,6 @@ #endif #include "lmms_math.h" -#include "Knob.h" #include "CaptionMenu.h" #include "ConfigManager.h" #include "ControllerConnection.h" @@ -48,7 +49,6 @@ #include "SimpleTextFloat.h" #include "StringPairDrag.h" - namespace lmms::gui { @@ -57,7 +57,7 @@ SimpleTextFloat * Knob::s_textFloat = nullptr; -Knob::Knob( knobTypes _knob_num, QWidget * _parent, const QString & _name ) : +Knob::Knob( KnobType _knob_num, QWidget * _parent, const QString & _name ) : QWidget( _parent ), FloatModelView( new FloatModel( 0, 0, 0, 1, nullptr, _name, true ), this ), m_label( "" ), @@ -75,7 +75,7 @@ Knob::Knob( knobTypes _knob_num, QWidget * _parent, const QString & _name ) : } Knob::Knob( QWidget * _parent, const QString & _name ) : - Knob( knobBright_26, _parent, _name ) + Knob( KnobType::Bright26, _parent, _name ) { } @@ -106,15 +106,15 @@ void Knob::initUi( const QString & _name ) // overrides that color. switch (knobNum()) { - case knobSmall_17: - case knobBright_26: - case knobDark_28: + case KnobType::Small17: + case KnobType::Bright26: + case KnobType::Dark28: m_lineActiveColor = QApplication::palette().color(QPalette::Active, QPalette::WindowText); m_arcActiveColor = QColor(QApplication::palette().color( QPalette::Active, QPalette::WindowText)); m_arcActiveColor.setAlpha(70); break; - case knobVintage_32: + case KnobType::Vintage32: m_lineActiveColor = QApplication::palette().color(QPalette::Active, QPalette::Shadow); m_arcActiveColor = QColor(QApplication::palette().color( QPalette::Active, QPalette::Shadow)); @@ -132,24 +132,24 @@ void Knob::initUi( const QString & _name ) void Knob::onKnobNumUpdated() { - if( m_knobNum != knobStyled ) + if( m_knobNum != KnobType::Styled ) { QString knobFilename; switch (m_knobNum) { - case knobDark_28: + case KnobType::Dark28: knobFilename = "knob01"; break; - case knobBright_26: + case KnobType::Bright26: knobFilename = "knob02"; break; - case knobSmall_17: + case KnobType::Small17: knobFilename = "knob03"; break; - case knobVintage_32: + case KnobType::Vintage32: knobFilename = "knob05"; break; - case knobStyled: // only here to stop the compiler from complaining + case KnobType::Styled: // only here to stop the compiler from complaining break; } @@ -251,7 +251,7 @@ void Knob::setOuterRadius( float r ) -knobTypes Knob::knobNum() const +KnobType Knob::knobNum() const { return m_knobNum; } @@ -259,7 +259,7 @@ knobTypes Knob::knobNum() const -void Knob::setknobNum( knobTypes k ) +void Knob::setknobNum( KnobType k ) { if( m_knobNum != k ) { @@ -397,7 +397,7 @@ void Knob::drawKnob( QPainter * _p ) QPoint mid; - if( m_knobNum == knobStyled ) + if( m_knobNum == KnobType::Styled ) { p.setRenderHint( QPainter::Antialiasing ); @@ -448,17 +448,17 @@ void Knob::drawKnob( QPainter * _p ) p.setPen(QPen(currentLineColor, 2)); switch( m_knobNum ) { - case knobSmall_17: + case KnobType::Small17: { p.drawLine( calculateLine( mid, radius-2 ) ); break; } - case knobBright_26: + case KnobType::Bright26: { p.drawLine( calculateLine( mid, radius-5 ) ); break; } - case knobDark_28: + case KnobType::Dark28: { const float rb = qMax( ( radius - 10 ) / 3.0, 0.0 ); @@ -468,12 +468,12 @@ void Knob::drawKnob( QPainter * _p ) p.drawLine( ln ); break; } - case knobVintage_32: + case KnobType::Vintage32: { p.drawLine( calculateLine( mid, radius-2, 2 ) ); break; } - case knobStyled: + case KnobType::Styled: break; } @@ -484,6 +484,13 @@ void Knob::drawKnob( QPainter * _p ) _p->drawImage( 0, 0, m_cache ); } +void Knob::showTextFloat(int msecBeforeDisplay, int msecDisplayTime) +{ + s_textFloat->setText(displayValue()); + s_textFloat->moveGlobal(this, QPoint(width() + 2, 0)); + s_textFloat->showWithDelay(msecBeforeDisplay, msecDisplayTime); +} + float Knob::getValue( const QPoint & _p ) { float value; @@ -580,10 +587,8 @@ void Knob::mousePressEvent( QMouseEvent * _me ) emit sliderPressed(); - s_textFloat->setText( displayValue() ); - s_textFloat->moveGlobal( this, - QPoint( width() + 2, 0 ) ); - s_textFloat->show(); + showTextFloat(0, 0); + m_buttonPressed = true; } else if( _me->button() == Qt::LeftButton && @@ -613,6 +618,7 @@ void Knob::mouseMoveEvent( QMouseEvent * _me ) m_lastMousePos = _me->pos(); } s_textFloat->setText( displayValue() ); + s_textFloat->show(); } @@ -638,7 +644,15 @@ void Knob::mouseReleaseEvent( QMouseEvent* event ) s_textFloat->hide(); } +void Knob::enterEvent(QEvent *event) +{ + showTextFloat(700, 2000); +} +void Knob::leaveEvent(QEvent *event) +{ + s_textFloat->hide(); +} void Knob::focusOutEvent( QFocusEvent * _fe ) @@ -689,10 +703,52 @@ void Knob::paintEvent( QPaintEvent * _me ) void Knob::wheelEvent(QWheelEvent * we) { we->accept(); - const float stepMult = model()->range() / 2000 / model()->step(); - const int inc = ((we->angleDelta().y() > 0 ) ? 1 : -1) * ((stepMult < 1 ) ? 1 : stepMult); - model()->incValue( inc ); + const int deltaY = we->angleDelta().y(); + float direction = deltaY > 0 ? 1 : -1; + auto * m = model(); + float const step = m->step(); + float const range = m->range(); + + // This is the default number of steps or mouse wheel events that it takes to sweep + // from the lowest value to the highest value. + // It might be modified if the user presses modifier keys. See below. + float numberOfStepsForFullSweep = 100.; + + auto const modKeys = we->modifiers(); + if (modKeys == Qt::ShiftModifier) + { + // The shift is intended to go through the values in very coarse steps as in: + // "Shift into overdrive" + numberOfStepsForFullSweep = 10; + } + else if (modKeys == Qt::ControlModifier) + { + // The control key gives more control, i.e. it enables more fine-grained adjustments + numberOfStepsForFullSweep = 1000; + } + else if (modKeys == Qt::AltModifier) + { + // The alt key enables even finer adjustments + numberOfStepsForFullSweep = 2000; + + // It seems that on some systems pressing Alt with mess with the directions, + // i.e. scrolling the mouse wheel is interpreted as pressing the mouse wheel + // left and right. Account for this quirk. + if (deltaY == 0) + { + int const deltaX = we->angleDelta().x(); + if (deltaX != 0) + { + direction = deltaX > 0 ? 1 : -1; + } + } + } + + // Compute the number of steps but make sure that we always do at least one step + const float stepMult = std::max(range / numberOfStepsForFullSweep / step, 1.f); + const int inc = direction * stepMult; + model()->incValue(inc); s_textFloat->setText( displayValue() ); s_textFloat->moveGlobal( this, QPoint( width() + 2, 0 ) ); diff --git a/src/gui/widgets/LedCheckBox.cpp b/src/gui/widgets/LedCheckBox.cpp index 1d4f6468b..75e73328f 100644 --- a/src/gui/widgets/LedCheckBox.cpp +++ b/src/gui/widgets/LedCheckBox.cpp @@ -44,7 +44,7 @@ static const auto names = std::array LedCheckBox::LedCheckBox( const QString & _text, QWidget * _parent, - const QString & _name, LedColors _color, bool legacyMode ) : + const QString & _name, LedColor _color, bool legacyMode ) : AutomatableButton( _parent, _name ), m_text( _text ), m_legacyMode(legacyMode) @@ -56,7 +56,7 @@ LedCheckBox::LedCheckBox( const QString & _text, QWidget * _parent, LedCheckBox::LedCheckBox( QWidget * _parent, - const QString & _name, LedColors _color, bool legacyMode ) : + const QString & _name, LedColor _color, bool legacyMode ) : LedCheckBox( QString(), _parent, _name, _color, legacyMode ) { } @@ -96,16 +96,12 @@ void LedCheckBox::paintEvent( QPaintEvent * pe ) -void LedCheckBox::initUi( LedColors _color ) +void LedCheckBox::initUi( LedColor _color ) { setCheckable( true ); - if( _color >= NumColors || _color < Yellow ) - { - _color = Yellow; - } m_ledOnPixmap = new QPixmap( embed::getIconPixmap( - names[_color].toUtf8().constData() ) ); + names[static_cast(_color)].toUtf8().constData() ) ); m_ledOffPixmap = new QPixmap( embed::getIconPixmap( "led_off" ) ); if (m_legacyMode) diff --git a/src/gui/widgets/SimpleTextFloat.cpp b/src/gui/widgets/SimpleTextFloat.cpp index d1f490b5e..e37753229 100644 --- a/src/gui/widgets/SimpleTextFloat.cpp +++ b/src/gui/widgets/SimpleTextFloat.cpp @@ -45,6 +45,14 @@ SimpleTextFloat::SimpleTextFloat() : m_textLabel = new QLabel(this); layout->addWidget(m_textLabel); + + m_showTimer = new QTimer(this); + m_showTimer->setSingleShot(true); + QObject::connect(m_showTimer, &QTimer::timeout, this, &SimpleTextFloat::show); + + m_hideTimer = new QTimer(this); + m_hideTimer->setSingleShot(true); + QObject::connect(m_hideTimer, &QTimer::timeout, this, &SimpleTextFloat::hide); } void SimpleTextFloat::setText(const QString & text) @@ -52,6 +60,29 @@ void SimpleTextFloat::setText(const QString & text) m_textLabel->setText(text); } +void SimpleTextFloat::showWithDelay(int msecBeforeDisplay, int msecDisplayTime) +{ + if (msecBeforeDisplay != 0) + { + m_showTimer->start(msecBeforeDisplay); + } + else + { + show(); + } + + if (msecDisplayTime != 0) + { + m_hideTimer->start(msecBeforeDisplay + msecDisplayTime); + } +} + +void SimpleTextFloat::hide() +{ + m_showTimer->stop(); + m_hideTimer->stop(); + QWidget::hide(); +} void SimpleTextFloat::setVisibilityTimeOut(int msecs) { diff --git a/src/gui/widgets/TempoSyncKnob.cpp b/src/gui/widgets/TempoSyncKnob.cpp index 86ee6df3c..473cee28c 100644 --- a/src/gui/widgets/TempoSyncKnob.cpp +++ b/src/gui/widgets/TempoSyncKnob.cpp @@ -42,7 +42,7 @@ namespace lmms::gui -TempoSyncKnob::TempoSyncKnob( knobTypes _knob_num, QWidget * _parent, +TempoSyncKnob::TempoSyncKnob( KnobType _knob_num, QWidget * _parent, const QString & _name ) : Knob( _knob_num, _parent, _name ), m_tempoSyncIcon( embed::getIconPixmap( "tempo_sync" ) ), @@ -75,8 +75,7 @@ void TempoSyncKnob::modelChanged() { m_custom->setModel( &model()->m_custom ); } - connect( model(), SIGNAL(syncModeChanged(lmms::TempoSyncKnobModel::TempoSyncMode)), - this, SLOT(updateDescAndIcon())); + connect(model(), &TempoSyncKnobModel::syncModeChanged, this, &TempoSyncKnob::updateDescAndIcon); connect( this, SIGNAL(sliderMoved(float)), model(), SLOT(disableSync())); updateDescAndIcon(); @@ -104,51 +103,51 @@ void TempoSyncKnob::contextMenuEvent( QContextMenuEvent * ) connect( syncMenu, SIGNAL(triggered(QAction*)), model(), SLOT(setTempoSync(QAction*))); syncMenu->addAction( embed::getIconPixmap( "note_none" ), - tr( "No Sync" ) )->setData( (int) TempoSyncKnobModel::SyncNone ); + tr( "No Sync" ) )->setData( (int) TempoSyncKnobModel::SyncMode::None ); if( limit / 0.125f <= model()->maxValue() ) { syncMenu->addAction( embed::getIconPixmap( "note_double_whole" ), tr( "Eight beats" ) )->setData( - (int) TempoSyncKnobModel::SyncDoubleWholeNote ); + (int) TempoSyncKnobModel::SyncMode::DoubleWholeNote ); } if( limit / 0.25f <= model()->maxValue() ) { syncMenu->addAction( embed::getIconPixmap( "note_whole" ), tr( "Whole note" ) )->setData( - (int) TempoSyncKnobModel::SyncWholeNote ); + (int) TempoSyncKnobModel::SyncMode::WholeNote ); } if( limit / 0.5f <= model()->maxValue() ) { syncMenu->addAction( embed::getIconPixmap( "note_half" ), tr( "Half note" ) )->setData( - (int) TempoSyncKnobModel::SyncHalfNote ); + (int) TempoSyncKnobModel::SyncMode::HalfNote ); } if( limit <= model()->maxValue() ) { syncMenu->addAction( embed::getIconPixmap( "note_quarter" ), tr( "Quarter note" ) )->setData( - (int) TempoSyncKnobModel::SyncQuarterNote ); + (int) TempoSyncKnobModel::SyncMode::QuarterNote ); } if( limit / 2.0f <= model()->maxValue() ) { syncMenu->addAction( embed::getIconPixmap( "note_eighth" ), tr( "8th note" ) )->setData( - (int) TempoSyncKnobModel::SyncEighthNote ); + (int) TempoSyncKnobModel::SyncMode::EighthNote ); } if( limit / 4.0f <= model()->maxValue() ) { syncMenu->addAction( embed::getIconPixmap( "note_sixteenth" ), tr( "16th note" ) )->setData( - (int) TempoSyncKnobModel::SyncSixteenthNote ); + (int) TempoSyncKnobModel::SyncMode::SixteenthNote ); } syncMenu->addAction( embed::getIconPixmap( "note_thirtysecond" ), tr( "32nd note" ) )->setData( - (int) TempoSyncKnobModel::SyncThirtysecondNote ); + (int) TempoSyncKnobModel::SyncMode::ThirtysecondNote ); syncMenu->addAction( embed::getIconPixmap( "dont_know" ), tr( "Custom..." ), this, SLOT(showCustom()) )->setData( - (int) TempoSyncKnobModel::SyncCustom ); + (int) TempoSyncKnobModel::SyncMode::Custom ); contextMenu.addSeparator(); } @@ -162,11 +161,11 @@ void TempoSyncKnob::contextMenuEvent( QContextMenuEvent * ) void TempoSyncKnob::updateDescAndIcon() { - if( model()->m_tempoSyncMode ) + if( model()->m_tempoSyncMode != TempoSyncKnobModel::SyncMode::None ) { switch( model()->m_tempoSyncMode ) { - case TempoSyncKnobModel::SyncCustom: + case TempoSyncKnobModel::SyncMode::Custom: m_tempoSyncDescription = tr( "Custom " ) + "(" + QString::number( model()->m_custom.numeratorModel().value() ) + @@ -174,31 +173,31 @@ void TempoSyncKnob::updateDescAndIcon() QString::number( model()->m_custom.denominatorModel().value() ) + ")"; break; - case TempoSyncKnobModel::SyncDoubleWholeNote: + case TempoSyncKnobModel::SyncMode::DoubleWholeNote: m_tempoSyncDescription = tr( "Synced to Eight Beats" ); break; - case TempoSyncKnobModel::SyncWholeNote: + case TempoSyncKnobModel::SyncMode::WholeNote: m_tempoSyncDescription = tr( "Synced to Whole Note" ); break; - case TempoSyncKnobModel::SyncHalfNote: + case TempoSyncKnobModel::SyncMode::HalfNote: m_tempoSyncDescription = tr( "Synced to Half Note" ); break; - case TempoSyncKnobModel::SyncQuarterNote: + case TempoSyncKnobModel::SyncMode::QuarterNote: m_tempoSyncDescription = tr( "Synced to Quarter Note" ); break; - case TempoSyncKnobModel::SyncEighthNote: + case TempoSyncKnobModel::SyncMode::EighthNote: m_tempoSyncDescription = tr( "Synced to 8th Note" ); break; - case TempoSyncKnobModel::SyncSixteenthNote: + case TempoSyncKnobModel::SyncMode::SixteenthNote: m_tempoSyncDescription = tr( "Synced to 16th Note" ); break; - case TempoSyncKnobModel::SyncThirtysecondNote: + case TempoSyncKnobModel::SyncMode::ThirtysecondNote: m_tempoSyncDescription = tr( "Synced to 32nd Note" ); break; @@ -210,38 +209,38 @@ void TempoSyncKnob::updateDescAndIcon() m_tempoSyncDescription = tr( "Tempo Sync" ); } if( m_custom != nullptr && - model()->m_tempoSyncMode != TempoSyncKnobModel::SyncCustom ) + model()->m_tempoSyncMode != TempoSyncKnobModel::SyncMode::Custom ) { m_custom->parentWidget()->hide(); } switch( model()->m_tempoSyncMode ) { - case TempoSyncKnobModel::SyncNone: + case TempoSyncKnobModel::SyncMode::None: m_tempoSyncIcon = embed::getIconPixmap( "tempo_sync" ); break; - case TempoSyncKnobModel::SyncCustom: + case TempoSyncKnobModel::SyncMode::Custom: m_tempoSyncIcon = embed::getIconPixmap( "dont_know" ); break; - case TempoSyncKnobModel::SyncDoubleWholeNote: + case TempoSyncKnobModel::SyncMode::DoubleWholeNote: m_tempoSyncIcon = embed::getIconPixmap( "note_double_whole" ); break; - case TempoSyncKnobModel::SyncWholeNote: + case TempoSyncKnobModel::SyncMode::WholeNote: m_tempoSyncIcon = embed::getIconPixmap( "note_whole" ); break; - case TempoSyncKnobModel::SyncHalfNote: + case TempoSyncKnobModel::SyncMode::HalfNote: m_tempoSyncIcon = embed::getIconPixmap( "note_half" ); break; - case TempoSyncKnobModel::SyncQuarterNote: + case TempoSyncKnobModel::SyncMode::QuarterNote: m_tempoSyncIcon = embed::getIconPixmap( "note_quarter" ); break; - case TempoSyncKnobModel::SyncEighthNote: + case TempoSyncKnobModel::SyncMode::EighthNote: m_tempoSyncIcon = embed::getIconPixmap( "note_eighth" ); break; - case TempoSyncKnobModel::SyncSixteenthNote: + case TempoSyncKnobModel::SyncMode::SixteenthNote: m_tempoSyncIcon = embed::getIconPixmap( "note_sixteenth" ); break; - case TempoSyncKnobModel::SyncThirtysecondNote: + case TempoSyncKnobModel::SyncMode::ThirtysecondNote: m_tempoSyncIcon = embed::getIconPixmap( "note_thirtysecond" ); break; default: @@ -305,7 +304,7 @@ void TempoSyncKnob::showCustom() m_custom->setModel( &model()->m_custom ); } m_custom->parentWidget()->show(); - model()->setTempoSync( TempoSyncKnobModel::SyncCustom ); + model()->setTempoSync( TempoSyncKnobModel::SyncMode::Custom ); } diff --git a/src/gui/widgets/TimeDisplayWidget.cpp b/src/gui/widgets/TimeDisplayWidget.cpp index cf139d4a8..3dad6b1b0 100644 --- a/src/gui/widgets/TimeDisplayWidget.cpp +++ b/src/gui/widgets/TimeDisplayWidget.cpp @@ -36,7 +36,7 @@ namespace lmms::gui TimeDisplayWidget::TimeDisplayWidget() : QWidget(), - m_displayMode( MinutesSeconds ), + m_displayMode( DisplayMode::MinutesSeconds ), m_spinBoxesLayout( this ), m_majorLCD( 4, this ), m_minorLCD( 2, this ), @@ -65,13 +65,13 @@ void TimeDisplayWidget::setDisplayMode( DisplayMode displayMode ) switch( m_displayMode ) { - case MinutesSeconds: + case DisplayMode::MinutesSeconds: m_majorLCD.setLabel( tr( "MIN" ) ); m_minorLCD.setLabel( tr( "SEC" ) ); m_milliSecondsLCD.setLabel( tr( "MSEC" ) ); break; - case BarsTicks: + case DisplayMode::BarsTicks: m_majorLCD.setLabel( tr( "BAR" ) ); m_minorLCD.setLabel( tr( "BEAT" ) ); m_milliSecondsLCD.setLabel( tr( "TICK" ) ); @@ -90,7 +90,7 @@ void TimeDisplayWidget::updateTime() switch( m_displayMode ) { - case MinutesSeconds: + case DisplayMode::MinutesSeconds: int msec; msec = s->getMilliseconds(); m_majorLCD.setValue(msec / 60000); @@ -98,7 +98,7 @@ void TimeDisplayWidget::updateTime() m_milliSecondsLCD.setValue(msec % 1000); break; - case BarsTicks: + case DisplayMode::BarsTicks: int tick; tick = s->getPlayPos().getTicks(); m_majorLCD.setValue((int)(tick / s->ticksPerBar()) + 1); @@ -119,13 +119,13 @@ void TimeDisplayWidget::mousePressEvent( QMouseEvent* mouseEvent ) { if( mouseEvent->button() == Qt::LeftButton ) { - if( m_displayMode == MinutesSeconds ) + if( m_displayMode == DisplayMode::MinutesSeconds ) { - setDisplayMode( BarsTicks ); + setDisplayMode( DisplayMode::BarsTicks ); } else { - setDisplayMode( MinutesSeconds ); + setDisplayMode( DisplayMode::MinutesSeconds ); } } } diff --git a/src/tracks/AutomationTrack.cpp b/src/tracks/AutomationTrack.cpp index deb6f763c..e353197f8 100644 --- a/src/tracks/AutomationTrack.cpp +++ b/src/tracks/AutomationTrack.cpp @@ -34,7 +34,7 @@ namespace lmms AutomationTrack::AutomationTrack( TrackContainer* tc, bool _hidden ) : - Track( _hidden ? HiddenAutomationTrack : Track::AutomationTrack, tc ) + Track( _hidden ? Type::HiddenAutomation : Type::Automation, tc ) { setName( tr( "Automation track" ) ); } @@ -77,7 +77,7 @@ void AutomationTrack::saveTrackSpecificSettings( QDomDocument & _doc, void AutomationTrack::loadTrackSpecificSettings( const QDomElement & _this ) { // just in case something somehow wrent wrong... - if( type() == HiddenAutomationTrack ) + if( type() == Type::HiddenAutomation ) { setMuted( false ); } diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 7eb6bba11..a4de188a5 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -28,6 +28,7 @@ #include "ConfigManager.h" #include "ControllerConnection.h" #include "DataFile.h" +#include "GuiApplication.h" #include "Mixer.h" #include "InstrumentTrackView.h" #include "Instrument.h" @@ -37,6 +38,7 @@ #include "MixHelpers.h" #include "PatternStore.h" #include "PatternTrack.h" +#include "PianoRoll.h" #include "Pitch.h" #include "Song.h" @@ -45,7 +47,7 @@ namespace lmms InstrumentTrack::InstrumentTrack( TrackContainer* tc ) : - Track( Track::InstrumentTrack, tc ), + Track( Track::Type::Instrument, tc ), MidiEventProcessor(), m_midiPort( tr( "unnamed_track" ), Engine::audioEngine()->midiClient(), this, this ), @@ -72,6 +74,7 @@ InstrumentTrack::InstrumentTrack( TrackContainer* tc ) : m_microtuner() { m_pitchModel.setCenterValue( 0 ); + m_pitchModel.setStrictStepSize(true); m_panningModel.setCenterValue( DefaultPanning ); m_baseNoteModel.setInitValue( DefaultKey ); m_firstKeyModel.setInitValue(0); @@ -220,7 +223,7 @@ InstrumentTrack::~InstrumentTrack() void InstrumentTrack::processAudioBuffer( sampleFrame* buf, const fpp_t frames, NotePlayHandle* n ) { // we must not play the sound if this InstrumentTrack is muted... - if( isMuted() || ( Engine::getSong()->playMode() != Song::Mode_PlayMidiClip && + if( isMuted() || ( Engine::getSong()->playMode() != Song::PlayMode::MidiClip && n && n->isPatternTrackMuted() ) || ! m_instrument ) { return; @@ -230,7 +233,7 @@ void InstrumentTrack::processAudioBuffer( sampleFrame* buf, const fpp_t frames, // We could do that in all other cases as well but the overhead for silence test is bigger than // what we potentially save. While playing a note, a NotePlayHandle-driven instrument will produce sound in // 99 of 100 cases so that test would be a waste of time. - if( m_instrument->flags().testFlag( Instrument::IsSingleStreamed ) && + if( m_instrument->flags().testFlag( Instrument::Flag::IsSingleStreamed ) && MixHelpers::isSilent( buf, frames ) ) { // at least pass one silent buffer to allow @@ -260,12 +263,12 @@ void InstrumentTrack::processAudioBuffer( sampleFrame* buf, const fpp_t frames, // instruments using instrument-play-handles will call this method // without any knowledge about notes, so they pass NULL for n, which // is no problem for us since we just bypass the envelopes+LFOs - if( m_instrument->flags().testFlag( Instrument::IsSingleStreamed ) == false && n != nullptr ) + if( m_instrument->flags().testFlag( Instrument::Flag::IsSingleStreamed ) == false && n != nullptr ) { const f_cnt_t offset = n->noteOffset(); m_soundShaping.processAudioBuffer( buf + offset, frames - offset, n ); const float vol = ( (float) n->getVolume() * DefaultVolumeRatio ); - const panning_t pan = qBound( PanningLeft, n->getPanning(), PanningRight ); + const panning_t pan = std::clamp(n->getPanning(), PanningLeft, PanningRight); StereoVolumeVector vv = panningToVolumeVector( pan, vol ); for( f_cnt_t f = offset; f < frames; ++f ) { @@ -341,9 +344,10 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const TimePos& tim NotePlayHandleManager::acquire( this, offset, typeInfo::max() / 2, - Note( TimePos(), TimePos(), event.key(), event.volume( midiPort()->baseVelocity() ) ), + Note(TimePos(), Engine::getSong()->getPlayPos(Engine::getSong()->playMode()), + event.key(), event.volume(midiPort()->baseVelocity())), nullptr, event.channel(), - NotePlayHandle::OriginMidiInput ); + NotePlayHandle::Origin::MidiInput); m_notes[event.key()] = nph; if( ! Engine::audioEngine()->addPlayHandle( nph ) ) { @@ -363,7 +367,7 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const TimePos& tim m_notes[event.key()]->noteOff( offset ); if (isSustainPedalPressed() && m_notes[event.key()]->origin() == - m_notes[event.key()]->OriginMidiInput) + NotePlayHandle::Origin::MidiInput) { m_sustainedNotes << m_notes[event.key()]; } @@ -403,7 +407,7 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const TimePos& tim if (nph && nph->isReleased()) { if( nph->origin() == - nph->OriginMidiInput) + NotePlayHandle::Origin::MidiInput) { nph->setLength( TimePos( static_cast( @@ -536,10 +540,10 @@ void InstrumentTrack::silenceAllNotes( bool removeIPH ) // invalidate all NotePlayHandles and PresetPreviewHandles linked to this track m_processHandles.clear(); - quint8 flags = PlayHandle::TypeNotePlayHandle | PlayHandle::TypePresetPreviewHandle; + auto flags = PlayHandle::Type::NotePlayHandle | PlayHandle::Type::PresetPreviewHandle; if( removeIPH ) { - flags |= PlayHandle::TypeInstrumentPlayHandle; + flags |= PlayHandle::Type::InstrumentPlayHandle; } Engine::audioEngine()->removePlayHandlesOfTypes( this, flags ); Engine::audioEngine()->doneChangeInModel(); @@ -666,7 +670,7 @@ int InstrumentTrack::masterKey( int _midi_key ) const { int key = baseNote(); - return qBound( 0, _midi_key - ( key - DefaultKey ), NumKeys ); + return std::clamp(_midi_key - (key - DefaultKey), 0, NumKeys); } @@ -710,7 +714,7 @@ bool InstrumentTrack::play( const TimePos & _start, const fpp_t _frames, // Handle automation: detuning for (const auto& processHandle : m_processHandles) { - processHandle->processTimePos(_start); + processHandle->processTimePos(_start, m_pitchModel.value(), gui::GuiApplication::instance()->pianoRoll()->isRecording()); } if ( clips.size() == 0 ) @@ -726,7 +730,7 @@ bool InstrumentTrack::play( const TimePos & _start, const fpp_t _frames, auto c = dynamic_cast(clip); // everything which is not a MIDI clip won't be played // A MIDI clip playing in the Piano Roll window will always play - if (c == nullptr || (Engine::getSong()->playMode() != Song::Mode_PlayMidiClip && clip->isMuted())) + if (c == nullptr || (Engine::getSong()->playMode() != Song::PlayMode::MidiClip && clip->isMuted())) { continue; } @@ -739,7 +743,7 @@ bool InstrumentTrack::play( const TimePos & _start, const fpp_t _frames, // get all notes from the given clip... const NoteVector & notes = c->notes(); // ...and set our index to zero - NoteVector::ConstIterator nit = notes.begin(); + auto nit = notes.begin(); // very effective algorithm for playing notes that are // posated within the current sample-frame diff --git a/src/tracks/MidiClip.cpp b/src/tracks/MidiClip.cpp index 08e76ae59..490f6e6d0 100644 --- a/src/tracks/MidiClip.cpp +++ b/src/tracks/MidiClip.cpp @@ -48,7 +48,7 @@ QPixmap * gui::MidiClipView::s_stepBtnOffLight = nullptr; MidiClip::MidiClip( InstrumentTrack * _instrument_track ) : Clip( _instrument_track ), m_instrumentTrack( _instrument_track ), - m_clipType( BeatClip ), + m_clipType( Type::BeatClip ), m_steps( TimePos::stepsPerBar() ) { if (_instrument_track->trackContainer() == Engine::patternStore()) @@ -76,11 +76,11 @@ MidiClip::MidiClip( const MidiClip& other ) : init(); switch( getTrack()->trackContainer()->type() ) { - case TrackContainer::PatternContainer: + case TrackContainer::Type::Pattern: setAutoResize( true ); break; - case TrackContainer::SongContainer: + case TrackContainer::Type::Song: // move down default: setAutoResize( false ); @@ -111,15 +111,15 @@ void MidiClip::resizeToFirstTrack() m_instrumentTrack->trackContainer()->tracks(); for (const auto& track : tracks) { - if (track->type() == Track::InstrumentTrack) + if (track->type() == Track::Type::Instrument) { if (track != m_instrumentTrack) { - unsigned int currentClip = m_instrumentTrack-> - getClips().indexOf(this); - m_steps = static_cast - (track->getClip(currentClip)) - ->m_steps; + const auto& instrumentTrackClips = m_instrumentTrack->getClips(); + const auto currentClipIt = std::find(instrumentTrackClips.begin(), instrumentTrackClips.end(), this); + unsigned int currentClip = currentClipIt != instrumentTrackClips.end() ? + std::distance(instrumentTrackClips.begin(), currentClipIt) : -1; + m_steps = static_cast(track->getClip(currentClip))->m_steps; } break; } @@ -144,7 +144,7 @@ void MidiClip::init() void MidiClip::updateLength() { - if( m_clipType == BeatClip ) + if( m_clipType == Type::BeatClip ) { changeLength( beatClipLength() ); updatePatternTrack(); @@ -157,7 +157,7 @@ void MidiClip::updateLength() { if (note->length() > 0) { - max_length = qMax(max_length, note->endPos()); + max_length = std::max(max_length, note->endPos()); } } changeLength( TimePos( max_length ).nextFullBar() * @@ -176,7 +176,7 @@ TimePos MidiClip::beatClipLength() const { if (note->length() < 0) { - max_length = qMax(max_length, note->pos() + 1); + max_length = std::max(max_length, note->pos() + 1); } } @@ -218,17 +218,14 @@ Note * MidiClip::addNote( const Note & _new_note, const bool _quant_pos ) void MidiClip::removeNote( Note * _note_to_del ) { instrumentTrack()->lock(); - NoteVector::Iterator it = m_notes.begin(); - while( it != m_notes.end() ) + + m_notes.erase(std::remove_if(m_notes.begin(), m_notes.end(), [&](Note* note) { - if( *it == _note_to_del ) - { - delete *it; - m_notes.erase( it ); - break; - } - ++it; - } + auto shouldRemove = note == _note_to_del; + if (shouldRemove) { delete note; } + return shouldRemove; + }), m_notes.end()); + instrumentTrack()->unlock(); checkType(); @@ -308,7 +305,7 @@ void MidiClip::setStep( int step, bool enabled ) -void MidiClip::splitNotes(NoteVector notes, TimePos pos) +void MidiClip::splitNotes(const NoteVector& notes, TimePos pos) { if (notes.empty()) { return; } @@ -340,10 +337,10 @@ void MidiClip::splitNotes(NoteVector notes, TimePos pos) -void MidiClip::setType( MidiClipTypes _new_clip_type ) +void MidiClip::setType( Type _new_clip_type ) { - if( _new_clip_type == BeatClip || - _new_clip_type == MelodyClip ) + if( _new_clip_type == Type::BeatClip || + _new_clip_type == Type::MelodyClip ) { m_clipType = _new_clip_type; } @@ -354,17 +351,15 @@ void MidiClip::setType( MidiClipTypes _new_clip_type ) void MidiClip::checkType() { - NoteVector::Iterator it = m_notes.begin(); - while( it != m_notes.end() ) + for (auto& note : m_notes) { - if( ( *it )->length() > 0 ) + if (note->length() > 0) { - setType( MelodyClip ); + setType(Type::MelodyClip); return; } - ++it; } - setType( BeatClip ); + setType( Type::BeatClip ); } @@ -372,7 +367,7 @@ void MidiClip::checkType() void MidiClip::saveSettings( QDomDocument & _doc, QDomElement & _this ) { - _this.setAttribute( "type", m_clipType ); + _this.setAttribute( "type", static_cast(m_clipType) ); _this.setAttribute( "name", name() ); if( usesCustomClipColor() ) @@ -395,9 +390,9 @@ void MidiClip::saveSettings( QDomDocument & _doc, QDomElement & _this ) _this.setAttribute( "steps", m_steps ); // now save settings of all notes - for (const auto& note : m_notes) + for (auto& note : m_notes) { - note->saveState( _doc, _this ); + note->saveState(_doc, _this); } } @@ -406,7 +401,7 @@ void MidiClip::saveSettings( QDomDocument & _doc, QDomElement & _this ) void MidiClip::loadSettings( const QDomElement & _this ) { - m_clipType = static_cast( _this.attribute( "type" + m_clipType = static_cast( _this.attribute( "type" ).toInt() ); setName( _this.attribute( "name" ) ); @@ -477,9 +472,10 @@ MidiClip * MidiClip::nextMidiClip() const MidiClip * MidiClip::adjacentMidiClipByOffset(int offset) const { - QVector clips = m_instrumentTrack->getClips(); + auto& clips = m_instrumentTrack->getClips(); int clipNum = m_instrumentTrack->getClipNum(this); - return dynamic_cast(clips.value(clipNum + offset, nullptr)); + if (clipNum < 0 || clipNum > clips.size() - 1) { return nullptr; } + return dynamic_cast(clips[clipNum + offset]); } @@ -595,8 +591,8 @@ void MidiClip::changeTimeSignature() } } last_pos = last_pos.nextFullBar() * TimePos::ticksPerBar(); - m_steps = qMax( TimePos::stepsPerBar(), - last_pos.getBar() * TimePos::stepsPerBar() ); + m_steps = std::max(TimePos::stepsPerBar(), + last_pos.getBar() * TimePos::stepsPerBar()); updateLength(); } diff --git a/src/tracks/PatternTrack.cpp b/src/tracks/PatternTrack.cpp index cdcd108ff..bdde4780c 100644 --- a/src/tracks/PatternTrack.cpp +++ b/src/tracks/PatternTrack.cpp @@ -41,7 +41,7 @@ PatternTrack::infoMap PatternTrack::s_infoMap; PatternTrack::PatternTrack(TrackContainer* tc) : - Track(Track::PatternTrack, tc) + Track(Track::Type::Pattern, tc) { int patternNum = s_infoMap.size(); s_infoMap[this] = patternNum; @@ -61,9 +61,9 @@ PatternTrack::PatternTrack(TrackContainer* tc) : PatternTrack::~PatternTrack() { Engine::audioEngine()->removePlayHandlesOfTypes( this, - PlayHandle::TypeNotePlayHandle - | PlayHandle::TypeInstrumentPlayHandle - | PlayHandle::TypeSamplePlayHandle ); + PlayHandle::Type::NotePlayHandle + | PlayHandle::Type::InstrumentPlayHandle + | PlayHandle::Type::SamplePlayHandle ); const int pattern = s_infoMap[this]; Engine::patternStore()->removePattern(pattern); diff --git a/src/tracks/SampleTrack.cpp b/src/tracks/SampleTrack.cpp index af5cbef6d..876cb307f 100644 --- a/src/tracks/SampleTrack.cpp +++ b/src/tracks/SampleTrack.cpp @@ -45,7 +45,7 @@ namespace lmms SampleTrack::SampleTrack(TrackContainer* tc) : - Track(Track::SampleTrack, tc), + Track(Track::Type::Sample, tc), m_volumeModel(DefaultVolume, MinVolume, MaxVolume, 0.1f, this, tr("Volume")), m_panningModel(DefaultPanning, PanningLeft, PanningRight, 0.1f, this, tr("Panning")), m_mixerChannelModel(0, 0, 0, this, tr("Mixer channel")), @@ -64,7 +64,7 @@ SampleTrack::SampleTrack(TrackContainer* tc) : SampleTrack::~SampleTrack() { - Engine::audioEngine()->removePlayHandlesOfTypes( this, PlayHandle::TypeSamplePlayHandle ); + Engine::audioEngine()->removePlayHandlesOfTypes( this, PlayHandle::Type::SamplePlayHandle ); } @@ -229,7 +229,7 @@ void SampleTrack::loadTrackSpecificSettings( const QDomElement & _this ) void SampleTrack::updateClips() { - Engine::audioEngine()->removePlayHandlesOfTypes( this, PlayHandle::TypeSamplePlayHandle ); + Engine::audioEngine()->removePlayHandlesOfTypes( this, PlayHandle::Type::SamplePlayHandle ); setPlayingClips( false ); } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6ff9c41e9..514bf7815 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -19,6 +19,7 @@ ADD_EXECUTABLE(tests QTestSuite.cpp $ + src/core/ArrayVectorTest.cpp src/core/AutomatableModelTest.cpp src/core/ProjectVersionTest.cpp src/core/RelativePathsTest.cpp diff --git a/tests/main.cpp b/tests/main.cpp index 6d375e6c6..c1a5b5a10 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -16,7 +16,7 @@ int main(int argc, char* argv[]) int failed = 0; for (QTestSuite*& suite : QTestSuite::suites()) { - failed += QTest::qExec(suite, argc, argv); + if (QTest::qExec(suite, argc, argv) != 0) { ++failed; } } qDebug() << "<<" << failed << "out of"< +#include + +#include "QTestSuite.h" + +using lmms::ArrayVector; + +struct ShouldNotConstruct +{ + ShouldNotConstruct() { QFAIL("should not construct"); } +}; + +struct ShouldNotDestruct +{ + ~ShouldNotDestruct() { QFAIL("should not destruct"); } +}; + +enum class Construction { Default, Copy, Move, CopyAssign, MoveAssign }; + +struct Constructible +{ + Constructible() : construction{Construction::Default} {} + Constructible(const Constructible&) : construction{Construction::Copy} {} + Constructible(Constructible&&) : construction{Construction::Move} {} + Constructible& operator=(const Constructible&) { construction = Construction::CopyAssign; return *this; } + Constructible& operator=(Constructible&&) { construction = Construction::MoveAssign; return *this; } + Construction construction; +}; + +struct DestructorCheck +{ + ~DestructorCheck() { *destructed = true; } + bool* destructed; +}; + +class ArrayVectorTest : QTestSuite +{ + Q_OBJECT + +private slots: + void defaultConstructorTest() + { + // Ensure no elements are constructed + const auto v = ArrayVector(); + // Ensure the container is empty + QVERIFY(v.empty()); + } + + void copyConstructorTest() + { + { + // Ensure all elements are copy constructed + const auto v = ArrayVector{{}}; + const auto copy = v; + for (const auto& element : copy) { + QCOMPARE(element.construction, Construction::Copy); + } + } + { + // Ensure corresponding elements are used + const auto v = ArrayVector{1, 2, 3}; + const auto copy = v; + const auto expected = std::array{1, 2, 3}; + QVERIFY(std::equal(copy.begin(), copy.end(), expected.begin(), expected.end())); + } + } + + void moveConstructorTest() + { + { + // Ensure all elements are move constructed + auto v = ArrayVector{{}}; + const auto moved = std::move(v); + for (const auto& element : moved) { + QCOMPARE(element.construction, Construction::Move); + } + } + { + // Ensure corresponding elements are used + auto v = ArrayVector{1, 2, 3}; + const auto moved = std::move(v); + const auto expected = std::array{1, 2, 3}; + QVERIFY(std::equal(moved.begin(), moved.end(), expected.begin(), expected.end())); + // Move construction should leave the source empty + QVERIFY(v.empty()); + } + } + + void fillValueConstructorTest() + { + // Ensure all elements are copy constructed + const auto v = ArrayVector(1, {}); + for (const auto& element : v) { + QCOMPARE(element.construction, Construction::Copy); + } + // Ensure the container has the correct size + QCOMPARE(v.size(), std::size_t{1}); + } + + void fillDefaultConstructorTest() + { + // Ensure all elements are copy constructed + const auto v = ArrayVector(1); + for (const auto& element : v) { + QCOMPARE(element.construction, Construction::Default); + } + // Ensure the container has the correct size + QCOMPARE(v.size(), std::size_t{1}); + } + + void rangeConstructorTest() + { + { + // Ensure the elements are copy constructed from normal iterators + const auto data = std::array{Constructible{}}; + const auto v = ArrayVector(data.begin(), data.end()); + for (const auto& element : v) { + QCOMPARE(element.construction, Construction::Copy); + } + } + { + // Ensure the elements are move constructed from move iterators + auto data = std::array{Constructible{}}; + const auto v = ArrayVector( + std::move_iterator{data.begin()}, std::move_iterator{data.end()}); + for (const auto& element : v) { + QCOMPARE(element.construction, Construction::Move); + } + } + { + // Ensure corresponding elements are used + const auto data = std::array{1, 2, 3}; + const auto v = ArrayVector(data.begin(), data.end()); + QVERIFY(std::equal(v.begin(), v.end(), data.begin(), data.end())); + } + } + + void initializerListConstructorTest() + { + // Ensure the container is constructed with the correct data + const auto v = ArrayVector{1, 2, 3}; + const auto expected = std::array{1, 2, 3}; + QVERIFY(std::equal(v.begin(), v.end(), expected.begin(), expected.end())); + } + + void destructorTest() + { + { + // Should not call destructors for space without elements + const auto v = ArrayVector{}; + } + { + // Should call destructors for all elements + auto destructed = false; + { + const auto v = ArrayVector{{&destructed}}; + } + QVERIFY(destructed); + } + } + + void copyAssignmentTest() + { + { + // Self-assignment should not change the contents + auto v = ArrayVector{1, 2, 3}; + const auto oldValue = v; + v = v; + QCOMPARE(v, oldValue); + } + { + // Assignment to a larger container should copy assign + const auto src = ArrayVector(3); + auto dst = ArrayVector(5); + dst = src; + QCOMPARE(dst.size(), std::size_t{3}); + for (const auto& element : dst) { + QCOMPARE(element.construction, Construction::CopyAssign); + } + } + { + // Assignment to a smaller container should copy construct + const auto src = ArrayVector(3); + auto dst = ArrayVector{}; + dst = src; + QCOMPARE(dst.size(), std::size_t{3}); + for (const auto& element : dst) { + QCOMPARE(element.construction, Construction::Copy); + } + } + { + // Ensure corresponding elements are used + const auto src = ArrayVector{1, 2, 3}; + auto dst = ArrayVector{}; + dst = src; + QCOMPARE(dst, (ArrayVector{1, 2, 3})); + } + } + + void moveAssignmentTest() + { + { + // Self-assignment should not change the contents + auto v = ArrayVector{1, 2, 3}; + const auto oldValue = v; + v = std::move(v); + QCOMPARE(v, oldValue); + } + { + // Assignment to a larger container should move assign + auto src = ArrayVector(3); + auto dst = ArrayVector(5); + dst = std::move(src); + QCOMPARE(dst.size(), std::size_t{3}); + for (const auto& element : dst) { + QCOMPARE(element.construction, Construction::MoveAssign); + } + } + { + // Assignment to a smaller container should move construct + auto src = ArrayVector(3); + auto dst = ArrayVector{}; + dst = std::move(src); + QCOMPARE(dst.size(), std::size_t{3}); + for (const auto& element : dst) { + QCOMPARE(element.construction, Construction::Move); + } + } + { + // Ensure corresponding elements are used + auto src = ArrayVector{1, 2, 3}; + auto dst = ArrayVector{}; + dst = std::move(src); + QCOMPARE(dst, (ArrayVector{1, 2, 3})); + } + } + + void initializerListAssignmentTest() + { + { + // Assignment to a larger container should copy assign + auto v = ArrayVector(2); + v = {Constructible{}}; + QCOMPARE(v.size(), std::size_t{1}); + for (const auto& element : v) { + QCOMPARE(element.construction, Construction::CopyAssign); + } + } + { + // Assignment to a smaller container should copy construct + auto v = ArrayVector{}; + v = {Constructible{}}; + QCOMPARE(v.size(), std::size_t{1}); + for (const auto& element : v) { + QCOMPARE(element.construction, Construction::Copy); + } + } + { + // Ensure corresponding elements are used + auto v = ArrayVector{}; + v = {1, 2, 3}; + QCOMPARE(v, (ArrayVector{1, 2, 3})); + } + } + + void fillValueAssignTest() + { + { + // Assignment to a larger container should copy assign + auto v = ArrayVector(5); + v.assign(3, {}); + QCOMPARE(v.size(), std::size_t{3}); + for (const auto& element : v) { + QCOMPARE(element.construction, Construction::CopyAssign); + } + } + { + // Assignment to a smaller container should copy construct + auto v = ArrayVector{}; + v.assign(3, {}); + QCOMPARE(v.size(), std::size_t{3}); + for (const auto& element : v) { + QCOMPARE(element.construction, Construction::Copy); + } + } + { + // Ensure correct value is filled + auto v = ArrayVector{}; + v.assign(3, 1); + QCOMPARE(v, (ArrayVector{1, 1, 1})); + } + } + + void rangeAssignTest() + { + { + // Assignment to a larger container should copy assign + const auto data = std::array{Constructible{}}; + auto v = ArrayVector(2); + v.assign(data.begin(), data.end()); + QCOMPARE(v.size(), std::size_t{1}); + for (const auto& element : v) { + QCOMPARE(element.construction, Construction::CopyAssign); + } + } + { + // Assignment to a smaller container should copy construct + const auto data = std::array{Constructible{}}; + auto v = ArrayVector{}; + v.assign(data.begin(), data.end()); + QCOMPARE(v.size(), std::size_t{1}); + for (const auto& element : v) { + QCOMPARE(element.construction, Construction::Copy); + } + } + { + // Ensure correct value is filled + const auto data = std::array{1, 2, 3}; + auto v = ArrayVector{}; + v.assign(data.begin(), data.end()); + QCOMPARE(v, (ArrayVector{1, 2, 3})); + } + } + + void atTest() + { + { + // Non-const version + auto v = ArrayVector{1, 2, 3}; + QCOMPARE(v.at(1), 2); + QVERIFY_EXCEPTION_THROWN(v.at(3), std::out_of_range); + } + { + // Const version + const auto v = ArrayVector{1, 2, 3}; + QCOMPARE(v.at(1), 2); + QVERIFY_EXCEPTION_THROWN(v.at(3), std::out_of_range); + } + } + + void subscriptTest() + { + { + // Non-const version + auto v = ArrayVector{1, 2, 3}; + QCOMPARE(v[1], 2); + } + { + // Const version + const auto v = ArrayVector{1, 2, 3}; + QCOMPARE(v[1], 2); + } + } + + void frontTest() + { + { + // Non-const version + auto v = ArrayVector{1, 2, 3}; + QCOMPARE(v.front(), 1); + } + { + // Const version + const auto v = ArrayVector{1, 2, 3}; + QCOMPARE(v.front(), 1); + } + } + + void backTest() + { + { + // Non-const version + auto v = ArrayVector{1, 2, 3}; + QCOMPARE(v.back(), 3); + } + { + // Const version + const auto v = ArrayVector{1, 2, 3}; + QCOMPARE(v.back(), 3); + } + } + + void dataTest() + { + { + // Non-const version + auto v = ArrayVector{1, 2, 3}; + QCOMPARE(v.data(), &v.front()); + } + { + // Const version + const auto v = ArrayVector{1, 2, 3}; + QCOMPARE(v.data(), &v.front()); + } + } + + void beginEndTest() + { + const auto expected = std::array{1, 2, 3}; + { + // Non-const version + auto v = ArrayVector{1, 2, 3}; + QVERIFY(std::equal(v.begin(), v.end(), expected.begin(), expected.end())); + QVERIFY(std::equal(v.cbegin(), v.cend(), expected.begin(), expected.end())); + } + { + // Const version + const auto v = ArrayVector{1, 2, 3}; + QVERIFY(std::equal(v.begin(), v.end(), expected.begin(), expected.end())); + } + } + + void rbeginRendTest() + { + const auto expected = std::array{3, 2, 1}; + { + // Non-const version + auto v = ArrayVector{1, 2, 3}; + QVERIFY(std::equal(v.rbegin(), v.rend(), expected.begin(), expected.end())); + QVERIFY(std::equal(v.crbegin(), v.crend(), expected.begin(), expected.end())); + } + { + // Const version + const auto v = ArrayVector{1, 2, 3}; + QVERIFY(std::equal(v.rbegin(), v.rend(), expected.begin(), expected.end())); + } + } + + void emptyFullSizeMaxCapacityTest() + { + auto v = ArrayVector{}; + QVERIFY(v.empty()); + QVERIFY(!v.full()); + QCOMPARE(v.size(), std::size_t{0}); + QCOMPARE(v.max_size(), std::size_t{2}); + QCOMPARE(v.capacity(), std::size_t{2}); + + v.push_back(1); + QVERIFY(!v.empty()); + QVERIFY(!v.full()); + QCOMPARE(v.size(), std::size_t{1}); + QCOMPARE(v.max_size(), std::size_t{2}); + QCOMPARE(v.capacity(), std::size_t{2}); + + v.push_back(2); + QVERIFY(!v.empty()); + QVERIFY(v.full()); + QCOMPARE(v.size(), std::size_t{2}); + QCOMPARE(v.max_size(), std::size_t{2}); + QCOMPARE(v.capacity(), std::size_t{2}); + + auto empty = ArrayVector{}; + QVERIFY(empty.empty()); + QVERIFY(empty.full()); + QCOMPARE(empty.size(), std::size_t{0}); + QCOMPARE(empty.max_size(), std::size_t{0}); + QCOMPARE(empty.capacity(), std::size_t{0}); + } + + void insertValueTest() + { + { + // Copy + const auto data = Constructible{}; + auto v = ArrayVector{}; + v.insert(v.cbegin(), data); + QCOMPARE(v.size(), std::size_t{1}); + QCOMPARE(v[0].construction, Construction::Copy); + } + { + // Move + auto v = ArrayVector{}; + v.insert(v.cbegin(), Constructible{}); + QCOMPARE(v.size(), std::size_t{1}); + QCOMPARE(v[0].construction, Construction::Move); + } + { + // Ensure the correct value is used (copy) + const auto data = 1; + auto v = ArrayVector{2, 3}; + v.insert(v.cbegin(), data); + QCOMPARE(v, (ArrayVector{1, 2, 3})); + } + { + // Ensure the correct value is used (move) + auto v = ArrayVector{2, 3}; + v.insert(v.cbegin(), 1); + QCOMPARE(v, (ArrayVector{1, 2, 3})); + } + } + + void insertFillValueTest() + { + { + // Insertion should copy construct + auto v = ArrayVector{}; + v.insert(v.cbegin(), 3, {}); + QCOMPARE(v.size(), std::size_t{3}); + for (const auto& element : v) { + QCOMPARE(element.construction, Construction::Copy); + } + } + { + // Ensure correct value is filled + auto v = ArrayVector{1, 3}; + v.insert(v.cbegin() + 1, 3, 2); + QCOMPARE(v, (ArrayVector{1, 2, 2, 2, 3})); + } + } + + void insertRangeTest() + { + { + // Insertion should copy construct + const auto data = std::array{Constructible{}}; + auto v = ArrayVector{}; + v.insert(v.cbegin(), data.begin(), data.end()); + QCOMPARE(v.size(), std::size_t{1}); + for (const auto& element : v) { + QCOMPARE(element.construction, Construction::Copy); + } + } + { + // Ensure correct value is filled + const auto data = std::array{2, 3}; + auto v = ArrayVector{1, 4}; + v.insert(v.cbegin() + 1, data.begin(), data.end()); + QCOMPARE(v, (ArrayVector{1, 2, 3, 4})); + } + } + + void insertInitializerListTest() + { + { + // Insertion should copy construct + auto v = ArrayVector{}; + v.insert(v.cbegin(), {Constructible{}}); + QCOMPARE(v.size(), std::size_t{1}); + for (const auto& element : v) { + QCOMPARE(element.construction, Construction::Copy); + } + } + { + // Ensure corresponding elements are used + auto v = ArrayVector{1, 4}; + v.insert(v.cbegin() + 1, {2, 3}); + QCOMPARE(v, (ArrayVector{1, 2, 3, 4})); + } + } + + void emplaceTest() + { + { + // Ensure the value is constructed in-place + auto v = ArrayVector{}; + v.emplace(v.cbegin()); + QCOMPARE(v.size(), std::size_t{1}); + QCOMPARE(v[0].construction, Construction::Default); + } + { + // Ensure the correct value is used (move) + auto v = ArrayVector{2, 3}; + v.emplace(v.cbegin(), 1); + QCOMPARE(v, (ArrayVector{1, 2, 3})); + } + } + + void eraseTest() + { + { + // Ensure destructors are run + auto destructed = false; + auto v = ArrayVector{{&destructed}}; + v.erase(v.cbegin()); + QVERIFY(destructed); + } + { + // Ensure the result is correct + auto v = ArrayVector{10, 1, 2, 3}; + v.erase(v.cbegin()); + QCOMPARE(v, (ArrayVector{1, 2, 3})); + } + } + + void eraseRangeTest() + { + { + // Ensure destructors are run + auto destructed = false; + auto v = ArrayVector{{&destructed}}; + v.erase(v.cbegin(), v.cend()); + QVERIFY(destructed); + } + { + // Ensure the result is correct + auto v = ArrayVector{1, 20, 21, 2, 3}; + v.erase(v.cbegin() + 1, v.cbegin() + 3); + QCOMPARE(v, (ArrayVector{1, 2, 3})); + } + } + + void pushBackTest() + { + { + // Copy + const auto data = Constructible{}; + auto v = ArrayVector{}; + v.push_back(data); + QCOMPARE(v.size(), std::size_t{1}); + QCOMPARE(v[0].construction, Construction::Copy); + } + { + // Move + auto v = ArrayVector{}; + v.push_back({}); + QCOMPARE(v.size(), std::size_t{1}); + QCOMPARE(v[0].construction, Construction::Move); + } + { + // Ensure the correct value is used (copy) + const auto data = 3; + auto v = ArrayVector{1, 2}; + v.push_back(data); + QCOMPARE(v, (ArrayVector{1, 2, 3})); + } + { + // Ensure the correct value is used (move) + auto v = ArrayVector{1, 2}; + v.push_back(3); + QCOMPARE(v, (ArrayVector{1, 2, 3})); + } + } + + void emplaceBackTest() + { + { + // Ensure the value is constructed in-place + auto v = ArrayVector{}; + v.emplace_back(); + QCOMPARE(v.size(), std::size_t{1}); + QCOMPARE(v[0].construction, Construction::Default); + } + { + // Ensure the correct value is used (move) + auto v = ArrayVector{1, 2}; + v.emplace_back(3); + QCOMPARE(v, (ArrayVector{1, 2, 3})); + } + } + + void popBackTest() + { + { + // Ensure destructors are run + auto destructed = false; + auto v = ArrayVector{{&destructed}}; + v.pop_back(); + QVERIFY(destructed); + } + { + // Ensure the result is correct + auto v = ArrayVector{1, 2, 3}; + v.pop_back(); + QCOMPARE(v, (ArrayVector{1, 2})); + } + } + + void resizeDefaultTest() + { + { + // Smaller + auto destructed = false; + auto v = ArrayVector{{&destructed}}; + QCOMPARE(v.size(), std::size_t{1}); + v.resize(0); + QCOMPARE(v.size(), std::size_t{0}); + QVERIFY(destructed); + } + { + // Bigger + auto v = ArrayVector{}; + QCOMPARE(v.size(), std::size_t{0}); + v.resize(1); + QCOMPARE(v.size(), std::size_t{1}); + QCOMPARE(v[0].construction, Construction::Default); + } + { + // Too big + auto v = ArrayVector{}; + QVERIFY_EXCEPTION_THROWN(v.resize(2), std::length_error); + } + } + + void resizeValueTest() + { + { + // Smaller + auto dummy = false; + auto destructed = false; + auto v = ArrayVector{{&destructed}}; + QCOMPARE(v.size(), std::size_t{1}); + v.resize(0, {&dummy}); + QCOMPARE(v.size(), std::size_t{0}); + QVERIFY(destructed); + } + { + // Bigger + auto v = ArrayVector{}; + QCOMPARE(v.size(), std::size_t{0}); + v.resize(1, {}); + QCOMPARE(v.size(), std::size_t{1}); + QCOMPARE(v[0].construction, Construction::Copy); + } + { + // Too big + auto v = ArrayVector{}; + QVERIFY_EXCEPTION_THROWN(v.resize(2), std::length_error); + } + { + // Ensure the correct value is used + auto v = ArrayVector{}; + v.resize(1, 1); + QCOMPARE(v, (ArrayVector{1})); + } + } + + void clearTest() + { + { + // Ensure destructors are run + auto destructed = false; + auto v = ArrayVector{{&destructed}}; + v.clear(); + QVERIFY(destructed); + } + { + // Ensure the result is correct + auto v = ArrayVector{1, 2, 3}; + v.clear(); + QCOMPARE(v, (ArrayVector{})); + } + } + + void memberSwapTest() + { + auto a = ArrayVector{1, 2, 3, 4}; + auto b = ArrayVector{2, 4, 6}; + + const auto aOriginal = a; + const auto bOriginal = b; + + a.swap(b); + + QCOMPARE(a, bOriginal); + QCOMPARE(b, aOriginal); + } + + void freeSwapTest() + { + auto a = ArrayVector{1, 2, 3, 4}; + auto b = ArrayVector{2, 4, 6}; + + const auto aOriginal = a; + const auto bOriginal = b; + + swap(a, b); + + QCOMPARE(a, bOriginal); + QCOMPARE(b, aOriginal); + } + + void comparisonTest() + { + const auto v = ArrayVector{1, 2, 3}; + const auto l = ArrayVector{1, 2, 2}; + const auto e = ArrayVector{1, 2, 3}; + const auto g = ArrayVector{1, 3, 3}; + + QVERIFY(l < v); + QVERIFY(!(e < v)); + QVERIFY(!(g < v)); + + QVERIFY(l <= v); + QVERIFY(e <= v); + QVERIFY(!(g <= v)); + + QVERIFY(!(l > v)); + QVERIFY(!(e > v)); + QVERIFY(g > v); + + QVERIFY(!(l >= v)); + QVERIFY(e >= v); + QVERIFY(g >= v); + + QVERIFY(!(l == v)); + QVERIFY(e == v); + QVERIFY(!(g == v)); + + QVERIFY(l != v); + QVERIFY(!(e != v)); + QVERIFY(g != v); + } +} ArrayVectorTests; + +#include "ArrayVectorTest.moc" diff --git a/tests/src/core/ProjectVersionTest.cpp b/tests/src/core/ProjectVersionTest.cpp index 2d066dca5..387d90056 100644 --- a/tests/src/core/ProjectVersionTest.cpp +++ b/tests/src/core/ProjectVersionTest.cpp @@ -34,13 +34,13 @@ private slots: { using namespace lmms; - QVERIFY(ProjectVersion("1.1.0", ProjectVersion::Minor) > "1.0.3"); - QVERIFY(ProjectVersion("1.1.0", ProjectVersion::Major) < "2.1.0"); - QVERIFY(ProjectVersion("1.1.0", ProjectVersion::Release) > "0.2.1"); - QVERIFY(ProjectVersion("1.1.4", ProjectVersion::Release) < "1.1.10"); - QVERIFY(ProjectVersion("1.1.0", ProjectVersion::Minor) == "1.1.5"); - QVERIFY( ! ( ProjectVersion("3.1.0", ProjectVersion::Minor) < "2.2.5" ) ); - QVERIFY( ! ( ProjectVersion("2.5.0", ProjectVersion::Release) < "2.2.5" ) ); + QVERIFY(ProjectVersion("1.1.0", ProjectVersion::CompareType::Minor) > "1.0.3"); + QVERIFY(ProjectVersion("1.1.0", ProjectVersion::CompareType::Major) < "2.1.0"); + QVERIFY(ProjectVersion("1.1.0", ProjectVersion::CompareType::Release) > "0.2.1"); + QVERIFY(ProjectVersion("1.1.4", ProjectVersion::CompareType::Release) < "1.1.10"); + QVERIFY(ProjectVersion("1.1.0", ProjectVersion::CompareType::Minor) == "1.1.5"); + QVERIFY( ! ( ProjectVersion("3.1.0", ProjectVersion::CompareType::Minor) < "2.2.5" ) ); + QVERIFY( ! ( ProjectVersion("2.5.0", ProjectVersion::CompareType::Release) < "2.2.5" ) ); //A pre-release version has lower precedence than a normal version QVERIFY(ProjectVersion("1.1.0") > "1.1.0-alpha"); //But higher precedence than the previous version @@ -62,7 +62,7 @@ private slots: QVERIFY(ProjectVersion("1.2.3.42") == "1.2.3"); //CompareVersion "All" should compare every identifier QVERIFY( - ProjectVersion("1.0.0-a.b.c.d.e.f.g.h.i.j.k.l", ProjectVersion::All) + ProjectVersion("1.0.0-a.b.c.d.e.f.g.h.i.j.k.l", ProjectVersion::CompareType::All) < "1.0.0-a.b.c.d.e.f.g.h.i.j.k.m" ); //Prerelease identifiers may contain hyphens diff --git a/tests/src/tracks/AutomationTrackTest.cpp b/tests/src/tracks/AutomationTrackTest.cpp index 2bf875992..05f345f8b 100644 --- a/tests/src/tracks/AutomationTrackTest.cpp +++ b/tests/src/tracks/AutomationTrackTest.cpp @@ -52,7 +52,7 @@ private slots: using namespace lmms; AutomationClip c(nullptr); - c.setProgressionType(AutomationClip::LinearProgression); + c.setProgressionType(AutomationClip::ProgressionType::Linear); c.putValue(0, 0.0, false); c.putValue(100, 1.0, false); @@ -69,7 +69,7 @@ private slots: using namespace lmms; AutomationClip c(nullptr); - c.setProgressionType(AutomationClip::DiscreteProgression); + c.setProgressionType(AutomationClip::ProgressionType::Discrete); c.putValue(0, 0.0, false); c.putValue(100, 1.0, false); @@ -89,14 +89,14 @@ private slots: AutomationTrack track(song); AutomationClip c1(&track); - c1.setProgressionType(AutomationClip::LinearProgression); + c1.setProgressionType(AutomationClip::ProgressionType::Linear); c1.putValue(0, 0.0, false); c1.putValue(10, 1.0, false); c1.movePosition(0); c1.addObject(&model); AutomationClip c2(&track); - c2.setProgressionType(AutomationClip::LinearProgression); + c2.setProgressionType(AutomationClip::ProgressionType::Linear); c2.putValue(0, 0.0, false); c2.putValue(100, 1.0, false); c2.movePosition(100); @@ -125,7 +125,7 @@ private slots: AutomationTrack track(song); AutomationClip c(&track); - c.setProgressionType(AutomationClip::LinearProgression); + c.setProgressionType(AutomationClip::ProgressionType::Linear); c.addObject(&model); c.putValue(0, 0.0, false); @@ -149,7 +149,7 @@ private slots: auto song = Engine::getSong(); InstrumentTrack* instrumentTrack = - dynamic_cast(Track::create(Track::InstrumentTrack, song)); + dynamic_cast(Track::create(Track::Type::Instrument, song)); MidiClip* midiClip = dynamic_cast(instrumentTrack->createClip(0)); midiClip->changeLength(TimePos(4, 0)); @@ -158,7 +158,7 @@ private slots: DetuningHelper* dh = note->detuning(); auto clip = dh->automationClip(); - clip->setProgressionType( AutomationClip::LinearProgression ); + clip->setProgressionType( AutomationClip::ProgressionType::Linear ); clip->putValue(TimePos(0, 0), 0.0); clip->putValue(TimePos(4, 0), 1.0); @@ -175,7 +175,7 @@ private slots: auto song = Engine::getSong(); auto patternStore = Engine::patternStore(); PatternTrack patternTrack(song); - Track* automationTrack = Track::create(Track::AutomationTrack, patternStore); + Track* automationTrack = Track::create(Track::Type::Automation, patternStore); QVERIFY(automationTrack->numOfClips()); AutomationClip* c1 = dynamic_cast(automationTrack->getClip(0)); @@ -183,7 +183,7 @@ private slots: FloatModel model; - c1->setProgressionType(AutomationClip::LinearProgression); + c1->setProgressionType(AutomationClip::ProgressionType::Linear); c1->putValue(0, 0.0, false); c1->putValue(10, 1.0, false); c1->addObject(&model); @@ -222,8 +222,8 @@ private slots: AutomationClip localClip(&localTrack); FloatModel model; - globalClip.setProgressionType(AutomationClip::DiscreteProgression); - localClip.setProgressionType(AutomationClip::DiscreteProgression); + globalClip.setProgressionType(AutomationClip::ProgressionType::Discrete); + localClip.setProgressionType(AutomationClip::ProgressionType::Discrete); globalClip.addObject(&model); localClip.addObject(&model); globalClip.putValue(0, 100.0f, false);