From fe6df8dbafdbb09a5a02c4e163f4979508dbec91 Mon Sep 17 00:00:00 2001 From: Dalton Messmer Date: Mon, 2 Jan 2023 19:51:32 -0500 Subject: [PATCH 001/308] Add namespace prefix to include guards --- include/AboutDialog.h | 6 ++---- include/ActionGroup.h | 5 ++--- include/AudioAlsa.h | 4 ++-- include/AudioAlsaSetupWidget.h | 4 ++-- include/AudioDevice.h | 4 ++-- include/AudioDeviceSetupWidget.h | 4 ++-- include/AudioDummy.h | 4 ++-- include/AudioEngine.h | 4 ++-- include/AudioEngineProfiler.h | 4 ++-- include/AudioEngineWorkerThread.h | 4 ++-- include/AudioFileDevice.h | 4 ++-- include/AudioFileFlac.h | 8 ++++---- include/AudioFileMP3.h | 4 ++-- include/AudioFileOgg.h | 4 ++-- include/AudioFileWave.h | 4 ++-- include/AudioJack.h | 4 ++-- include/AudioOss.h | 4 ++-- include/AudioPort.h | 4 ++-- include/AudioPortAudio.h | 4 ++-- include/AudioPulseAudio.h | 4 ++-- include/AudioSampleRecorder.h | 4 ++-- include/AudioSdl.h | 4 ++-- include/AudioSndio.h | 8 ++++---- include/AudioSoundIo.h | 4 ++-- include/AutomatableButton.h | 5 ++--- include/AutomatableModel.h | 4 ++-- include/AutomatableModelView.h | 4 ++-- include/AutomatableSlider.h | 5 ++--- include/AutomationClip.h | 4 ++-- include/AutomationClipView.h | 4 ++-- include/AutomationEditor.h | 4 ++-- include/AutomationNode.h | 4 ++-- include/AutomationTrack.h | 4 ++-- include/AutomationTrackView.h | 4 ++-- include/BandLimitedWave.h | 4 ++-- include/BasicFilters.h | 5 ++--- include/BufferManager.h | 4 ++-- include/CPULoadWidget.h | 5 ++--- include/CaptionMenu.h | 5 ++--- include/Clip.h | 4 ++-- include/ClipView.h | 4 ++-- include/Clipboard.h | 4 ++-- include/ColorChooser.h | 7 +++---- include/ComboBox.h | 5 ++--- include/ComboBoxModel.h | 4 ++-- include/ConfigManager.h | 5 ++--- include/ControlLayout.h | 6 +++--- include/Controller.h | 6 ++---- include/ControllerConnection.h | 6 ++---- include/ControllerConnectionDialog.h | 5 ++--- include/ControllerDialog.h | 4 ++-- include/ControllerRackView.h | 4 ++-- include/ControllerView.h | 4 ++-- include/Controls.h | 8 +++----- include/CustomTextKnob.h | 4 ++-- include/DataFile.h | 5 ++--- include/Delay.h | 7 +++---- include/DeprecationHelper.h | 6 +++--- include/DetuningHelper.h | 4 ++-- include/DrumSynth.h | 7 +++---- include/DspEffectLibrary.h | 5 ++--- include/DummyEffect.h | 4 ++-- include/DummyInstrument.h | 4 ++-- include/DummyPlugin.h | 4 ++-- include/Editor.h | 4 ++-- include/Effect.h | 4 ++-- include/EffectChain.h | 5 ++--- include/EffectControlDialog.h | 4 ++-- include/EffectControls.h | 4 ++-- include/EffectRackView.h | 4 ++-- include/EffectSelectDialog.h | 4 ++-- include/EffectView.h | 4 ++-- include/Engine.h | 7 ++----- include/EnvelopeAndLfoParameters.h | 4 ++-- include/EnvelopeAndLfoView.h | 4 ++-- include/ExportFilter.h | 4 ++-- include/ExportProjectDialog.h | 5 ++--- include/FadeButton.h | 5 ++--- include/Fader.h | 5 ++--- include/FifoBuffer.h | 4 ++-- include/FileBrowser.h | 5 ++--- include/FileDialog.h | 7 +++---- include/Graph.h | 5 ++--- include/GroupBox.h | 5 ++--- include/GuiApplication.h | 6 +++--- include/ImportFilter.h | 4 ++-- include/InlineAutomation.h | 4 ++-- include/Instrument.h | 4 ++-- include/InstrumentFunctionViews.h | 4 ++-- include/InstrumentFunctions.h | 4 ++-- include/InstrumentMidiIOView.h | 4 ++-- include/InstrumentMiscView.h | 4 ++-- include/InstrumentPlayHandle.h | 4 ++-- include/InstrumentSoundShaping.h | 4 ++-- include/InstrumentSoundShapingView.h | 4 ++-- include/InstrumentTrack.h | 4 ++-- include/InstrumentTrackView.h | 4 ++-- include/InstrumentTrackWindow.h | 4 ++-- include/InstrumentView.h | 5 ++--- include/IoHelper.h | 4 ++-- include/JournallingObject.h | 5 ++--- include/Keymap.h | 4 ++-- include/Knob.h | 5 ++--- include/Ladspa2LMMS.h | 6 ++---- include/LadspaBase.h | 4 ++-- include/LadspaControl.h | 4 ++-- include/LadspaControlView.h | 4 ++-- include/LadspaManager.h | 5 ++--- include/LcdFloatSpinBox.h | 5 ++--- include/LcdSpinBox.h | 5 ++--- include/LcdWidget.h | 5 ++--- include/LedCheckBox.h | 5 ++--- include/LeftRightNav.h | 6 +++--- include/LfoController.h | 6 +++--- include/LinkedModelGroupViews.h | 8 +++----- include/LinkedModelGroups.h | 8 +++----- include/LmmsPalette.h | 6 ++---- include/LmmsStyle.h | 5 ++--- include/LocaleHelper.h | 6 +++--- include/LocklessAllocator.h | 4 ++-- include/LocklessList.h | 4 ++-- include/LocklessRingBuffer.h | 6 +++--- include/Lv2Basics.h | 9 ++++----- include/Lv2ControlBase.h | 7 ++++--- include/Lv2Evbuf.h | 8 ++++---- include/Lv2Features.h | 6 +++--- include/Lv2Manager.h | 6 +++--- include/Lv2Options.h | 6 +++--- include/Lv2Ports.h | 7 ++++--- include/Lv2Proc.h | 7 ++++--- include/Lv2SubPluginFeatures.h | 4 ++-- include/Lv2UridCache.h | 7 ++++--- include/Lv2UridMap.h | 7 ++++--- include/Lv2ViewBase.h | 8 ++++---- include/MainApplication.h | 6 +++--- include/MainWindow.h | 4 ++-- include/MemoryHelper.h | 6 ++---- include/MemoryManager.h | 4 ++-- include/MeterDialog.h | 4 ++-- include/MeterModel.h | 4 ++-- include/MicroTimer.h | 6 +++--- include/Microtuner.h | 4 ++-- include/MicrotunerConfig.h | 5 ++--- include/Midi.h | 4 ++-- include/MidiAlsaRaw.h | 4 ++-- include/MidiAlsaSeq.h | 5 ++--- include/MidiApple.h | 5 ++--- include/MidiCCRackView.h | 4 ++-- include/MidiClient.h | 5 ++--- include/MidiClip.h | 5 ++--- include/MidiClipView.h | 14 +++++++------- include/MidiController.h | 4 ++-- include/MidiDummy.h | 4 ++-- include/MidiEvent.h | 4 ++-- include/MidiEventProcessor.h | 4 ++-- include/MidiEventToByteSeq.h | 6 +++--- include/MidiJack.h | 6 +++--- include/MidiOss.h | 5 ++--- include/MidiPort.h | 4 ++-- include/MidiPortMenu.h | 4 ++-- include/MidiSetupWidget.h | 5 ++--- include/MidiSndio.h | 6 +++--- include/MidiWinMM.h | 5 ++--- include/MixHelpers.h | 5 ++--- include/Mixer.h | 24 ++++++++++++------------ include/MixerLine.h | 6 +++--- include/MixerLineLcdSpinBox.h | 4 ++-- include/MixerView.h | 6 +++--- include/Model.h | 5 ++--- include/ModelView.h | 5 ++--- include/ModelVisitor.h | 6 +++--- include/NStateButton.h | 5 ++--- include/Note.h | 4 ++-- include/NotePlayHandle.h | 4 ++-- include/Oscillator.h | 4 ++-- include/OscillatorConstants.h | 8 ++++---- include/Oscilloscope.h | 7 +++---- include/OutputSettings.h | 5 ++--- include/PathUtil.h | 4 ++-- include/PatternClip.h | 5 ++--- include/PatternClipView.h | 6 ++---- include/PatternEditor.h | 6 ++---- include/PatternStore.h | 5 ++--- include/PatternTrack.h | 6 ++---- include/PatternTrackView.h | 6 ++---- include/PeakController.h | 4 ++-- include/PerfLog.h | 4 ++-- include/Piano.h | 5 ++--- include/PianoRoll.h | 4 ++-- include/PianoView.h | 4 ++-- include/Pitch.h | 4 ++-- include/PixmapButton.h | 5 ++--- include/PlayHandle.h | 4 ++-- include/Plugin.h | 4 ++-- include/PluginBrowser.h | 6 ++---- include/PluginFactory.h | 6 +++--- include/PluginIssue.h | 7 +++---- include/PluginView.h | 4 ++-- include/PositionLine.h | 4 ++-- include/PresetPreviewPlayHandle.h | 4 ++-- include/ProjectJournal.h | 5 ++--- include/ProjectNotes.h | 5 ++--- include/ProjectRenderer.h | 4 ++-- include/ProjectVersion.h | 5 ++--- include/QuadratureLfo.h | 6 +++--- include/RaiiHelpers.h | 7 ++++--- include/RecentProjectsMenu.h | 6 +++--- include/RemotePlugin.h | 6 +++--- include/RemotePluginBase.h | 6 +++--- include/RemotePluginClient.h | 6 +++--- include/RenameDialog.h | 6 ++---- include/RenderManager.h | 4 ++-- include/RingBuffer.h | 5 ++--- include/RmsHelper.h | 4 ++-- include/RowTableView.h | 4 ++-- include/Rubberband.h | 6 ++---- include/SampleBuffer.h | 5 ++--- include/SampleClip.h | 6 +++--- include/SampleClipView.h | 6 ++---- include/SamplePlayHandle.h | 4 ++-- include/SampleRecordHandle.h | 5 ++--- include/SampleTrack.h | 7 +++---- include/SampleTrackView.h | 6 +++--- include/SampleTrackWindow.h | 9 +++------ include/Scale.h | 4 ++-- include/SendButtonIndicator.h | 7 ++++--- include/SerializingObject.h | 5 ++--- include/SetupDialog.h | 5 ++--- include/SharedMemory.h | 7 ++++--- include/SideBar.h | 4 ++-- include/SideBarWidget.h | 4 ++-- include/Song.h | 4 ++-- include/SongEditor.h | 6 ++---- include/StepRecorder.h | 6 +++--- include/StepRecorderWidget.h | 6 +++--- include/StringPairDrag.h | 4 ++-- include/SubWindow.h | 5 +++-- include/SweepOscillator.h | 4 ++-- include/TabBar.h | 5 ++--- include/TabButton.h | 5 ++--- include/TabWidget.h | 5 ++--- include/TemplatesMenu.h | 7 ++++--- include/TempoSyncKnob.h | 4 ++-- include/TempoSyncKnobModel.h | 4 ++-- include/TextFloat.h | 5 ++--- include/ThreadableJob.h | 4 ++-- include/TimeDisplayWidget.h | 6 +++--- include/TimeLineWidget.h | 5 ++--- include/TimePos.h | 6 ++---- include/ToolButton.h | 6 ++---- include/ToolPlugin.h | 4 ++-- include/ToolPluginView.h | 4 ++-- include/Track.h | 4 ++-- include/TrackContainer.h | 4 ++-- include/TrackContainerView.h | 5 ++--- include/TrackContentWidget.h | 4 ++-- include/TrackLabelButton.h | 5 ++--- include/TrackOperationsWidget.h | 4 ++-- include/TrackRenameLineEdit.h | 5 ++--- include/TrackView.h | 7 ++----- include/ValueBuffer.h | 4 ++-- include/VersionedSaveDialog.h | 7 +++---- include/VstSyncController.h | 4 ++-- include/VstSyncData.h | 4 ++-- include/aeffectx.h | 1 - include/base64.h | 4 ++-- include/debug.h | 5 ++--- include/denormals.h | 9 ++++----- include/embed.h | 4 ++-- include/endian_handling.h | 4 ++-- include/fft_helpers.h | 5 ++--- include/gui_templates.h | 5 ++--- include/interpolation.h | 5 ++--- include/lmms_basics.h | 5 ++--- include/lmms_math.h | 1 - include/panning.h | 4 ++-- include/panning_constants.h | 4 ++-- include/shared_object.h | 4 ++-- include/versioninfo.h | 4 ++-- include/volume.h | 4 ++-- 280 files changed, 645 insertions(+), 761 deletions(-) diff --git a/include/AboutDialog.h b/include/AboutDialog.h index c7d65023f..bb0c509a9 100644 --- a/include/AboutDialog.h +++ b/include/AboutDialog.h @@ -22,9 +22,8 @@ * */ - -#ifndef ABOUT_DIALOG_H -#define ABOUT_DIALOG_H +#ifndef LMMS_GUI_ABOUT_DIALOG_H +#define LMMS_GUI_ABOUT_DIALOG_H #include @@ -43,4 +42,3 @@ public: } // namespace lmms::gui #endif - diff --git a/include/ActionGroup.h b/include/ActionGroup.h index 0fe9d78ed..80a6d523e 100644 --- a/include/ActionGroup.h +++ b/include/ActionGroup.h @@ -22,9 +22,8 @@ * */ - -#ifndef ACTION_GROUP_H -#define ACTION_GROUP_H +#ifndef LMMS_GUI_ACTION_GROUP_H +#define LMMS_GUI_ACTION_GROUP_H #include diff --git a/include/AudioAlsa.h b/include/AudioAlsa.h index f96dd01c9..263925286 100644 --- a/include/AudioAlsa.h +++ b/include/AudioAlsa.h @@ -22,8 +22,8 @@ * */ -#ifndef AUDIO_ALSA_H -#define AUDIO_ALSA_H +#ifndef LMMS_AUDIO_ALSA_H +#define LMMS_AUDIO_ALSA_H #include "lmmsconfig.h" diff --git a/include/AudioAlsaSetupWidget.h b/include/AudioAlsaSetupWidget.h index f68d71e8a..068754b69 100644 --- a/include/AudioAlsaSetupWidget.h +++ b/include/AudioAlsaSetupWidget.h @@ -22,8 +22,8 @@ * */ -#ifndef AUDIO_ALSA_SETUP_WIDGET_H -#define AUDIO_ALSA_SETUP_WIDGET_H +#ifndef LMMS_GUI_AUDIO_ALSA_SETUP_WIDGET_H +#define LMMS_GUI_AUDIO_ALSA_SETUP_WIDGET_H #include "lmmsconfig.h" diff --git a/include/AudioDevice.h b/include/AudioDevice.h index 6b4e9939a..26cbbaccc 100644 --- a/include/AudioDevice.h +++ b/include/AudioDevice.h @@ -22,8 +22,8 @@ * */ -#ifndef AUDIO_DEVICE_H -#define AUDIO_DEVICE_H +#ifndef LMMS_AUDIO_DEVICE_H +#define LMMS_AUDIO_DEVICE_H #include #include diff --git a/include/AudioDeviceSetupWidget.h b/include/AudioDeviceSetupWidget.h index e984651e4..9c70859d2 100644 --- a/include/AudioDeviceSetupWidget.h +++ b/include/AudioDeviceSetupWidget.h @@ -22,8 +22,8 @@ * */ -#ifndef AUDIO_DEVICE_SETUP_WIDGET_H -#define AUDIO_DEVICE_SETUP_WIDGET_H +#ifndef LMMS_GUI_AUDIO_DEVICE_SETUP_WIDGET_H +#define LMMS_GUI_AUDIO_DEVICE_SETUP_WIDGET_H #include "TabWidget.h" diff --git a/include/AudioDummy.h b/include/AudioDummy.h index 30b125b3a..37363d501 100644 --- a/include/AudioDummy.h +++ b/include/AudioDummy.h @@ -22,8 +22,8 @@ * */ -#ifndef AUDIO_DUMMY_H -#define AUDIO_DUMMY_H +#ifndef LMMS_AUDIO_DUMMY_H +#define LMMS_AUDIO_DUMMY_H #include "AudioDevice.h" #include "AudioDeviceSetupWidget.h" diff --git a/include/AudioEngine.h b/include/AudioEngine.h index 71751acb8..534182d69 100644 --- a/include/AudioEngine.h +++ b/include/AudioEngine.h @@ -22,8 +22,8 @@ * */ -#ifndef AUDIO_ENGINE_H -#define AUDIO_ENGINE_H +#ifndef LMMS_AUDIO_ENGINE_H +#define LMMS_AUDIO_ENGINE_H #include diff --git a/include/AudioEngineProfiler.h b/include/AudioEngineProfiler.h index 38631c6a9..1f72939be 100644 --- a/include/AudioEngineProfiler.h +++ b/include/AudioEngineProfiler.h @@ -22,8 +22,8 @@ * */ -#ifndef AUDIO_ENGINE_PROFILER_H -#define AUDIO_ENGINE_PROFILER_H +#ifndef LMMS_AUDIO_ENGINE_PROFILER_H +#define LMMS_AUDIO_ENGINE_PROFILER_H #include diff --git a/include/AudioEngineWorkerThread.h b/include/AudioEngineWorkerThread.h index 87e2791b1..0f41982a1 100644 --- a/include/AudioEngineWorkerThread.h +++ b/include/AudioEngineWorkerThread.h @@ -22,8 +22,8 @@ * */ -#ifndef AUDIO_ENGINE_WORKER_THREAD_H -#define AUDIO_ENGINE_WORKER_THREAD_H +#ifndef LMMS_AUDIO_ENGINE_WORKER_THREAD_H +#define LMMS_AUDIO_ENGINE_WORKER_THREAD_H #include diff --git a/include/AudioFileDevice.h b/include/AudioFileDevice.h index beee087e7..fb98315db 100644 --- a/include/AudioFileDevice.h +++ b/include/AudioFileDevice.h @@ -23,8 +23,8 @@ * */ -#ifndef AUDIO_FILE_DEVICE_H -#define AUDIO_FILE_DEVICE_H +#ifndef LMMS_AUDIO_FILE_DEVICE_H +#define LMMS_AUDIO_FILE_DEVICE_H #include diff --git a/include/AudioFileFlac.h b/include/AudioFileFlac.h index 542a2e717..6750d264a 100644 --- a/include/AudioFileFlac.h +++ b/include/AudioFileFlac.h @@ -22,8 +22,8 @@ * */ -#ifndef AUDIO_FILE_FLAC_H -#define AUDIO_FILE_FLAC_H +#ifndef LMMS_AUDIO_FILE_FLAC_H +#define LMMS_AUDIO_FILE_FLAC_H #include "lmmsconfig.h" @@ -33,7 +33,7 @@ namespace lmms { -class AudioFileFlac: public AudioFileDevice +class AudioFileFlac : public AudioFileDevice { public: AudioFileFlac(OutputSettings const& outputSettings, @@ -77,4 +77,4 @@ private: } // namespace lmms -#endif //AUDIO_FILE_FLAC_H +#endif diff --git a/include/AudioFileMP3.h b/include/AudioFileMP3.h index 290c9ccbf..61406cced 100644 --- a/include/AudioFileMP3.h +++ b/include/AudioFileMP3.h @@ -23,8 +23,8 @@ * */ -#ifndef AUDIO_FILE_MP3_H -#define AUDIO_FILE_MP3_H +#ifndef LMMS_AUDIO_FILE_MP3_H +#define LMMS_AUDIO_FILE_MP3_H #include "lmmsconfig.h" diff --git a/include/AudioFileOgg.h b/include/AudioFileOgg.h index 18617fa5f..981b61733 100644 --- a/include/AudioFileOgg.h +++ b/include/AudioFileOgg.h @@ -23,8 +23,8 @@ * */ -#ifndef AUDIO_FILE_OGG_H -#define AUDIO_FILE_OGG_H +#ifndef LMMS_AUDIO_FILE_OGG_H +#define LMMS_AUDIO_FILE_OGG_H #include "lmmsconfig.h" diff --git a/include/AudioFileWave.h b/include/AudioFileWave.h index 8dd3566f4..06b797cc6 100644 --- a/include/AudioFileWave.h +++ b/include/AudioFileWave.h @@ -23,8 +23,8 @@ * */ -#ifndef AUDIO_FILE_WAVE_H -#define AUDIO_FILE_WAVE_H +#ifndef LMMS_AUDIO_FILE_WAVE_H +#define LMMS_AUDIO_FILE_WAVE_H #include "lmmsconfig.h" #include "AudioFileDevice.h" diff --git a/include/AudioJack.h b/include/AudioJack.h index 263399487..5e63074bd 100644 --- a/include/AudioJack.h +++ b/include/AudioJack.h @@ -22,8 +22,8 @@ * */ -#ifndef AUDIO_JACK_H -#define AUDIO_JACK_H +#ifndef LMMS_AUDIO_JACK_H +#define LMMS_AUDIO_JACK_H #include "lmmsconfig.h" diff --git a/include/AudioOss.h b/include/AudioOss.h index 71103586a..045cc6c56 100644 --- a/include/AudioOss.h +++ b/include/AudioOss.h @@ -22,8 +22,8 @@ * */ -#ifndef AUDIO_OSS_H -#define AUDIO_OSS_H +#ifndef LMMS_AUDIO_OSS_H +#define LMMS_AUDIO_OSS_H #include "lmmsconfig.h" diff --git a/include/AudioPort.h b/include/AudioPort.h index 5a2645784..38e495436 100644 --- a/include/AudioPort.h +++ b/include/AudioPort.h @@ -22,8 +22,8 @@ * */ -#ifndef AUDIO_PORT_H -#define AUDIO_PORT_H +#ifndef LMMS_AUDIO_PORT_H +#define LMMS_AUDIO_PORT_H #include #include diff --git a/include/AudioPortAudio.h b/include/AudioPortAudio.h index 3fd32a7ac..8ab18ce6e 100644 --- a/include/AudioPortAudio.h +++ b/include/AudioPortAudio.h @@ -22,8 +22,8 @@ * */ -#ifndef AUDIO_PORTAUDIO_H -#define AUDIO_PORTAUDIO_H +#ifndef LMMS_AUDIO_PORTAUDIO_H +#define LMMS_AUDIO_PORTAUDIO_H #include diff --git a/include/AudioPulseAudio.h b/include/AudioPulseAudio.h index 789296e27..bb5541a30 100644 --- a/include/AudioPulseAudio.h +++ b/include/AudioPulseAudio.h @@ -22,8 +22,8 @@ * */ -#ifndef AUDIO_PULSEAUDIO_H -#define AUDIO_PULSEAUDIO_H +#ifndef LMMS_AUDIO_PULSEAUDIO_H +#define LMMS_AUDIO_PULSEAUDIO_H #include "lmmsconfig.h" diff --git a/include/AudioSampleRecorder.h b/include/AudioSampleRecorder.h index 7ad551916..23c4643d8 100644 --- a/include/AudioSampleRecorder.h +++ b/include/AudioSampleRecorder.h @@ -23,8 +23,8 @@ * */ -#ifndef AUDIO_SAMPLE_RECORDER_H -#define AUDIO_SAMPLE_RECORDER_H +#ifndef LMMS_AUDIO_SAMPLE_RECORDER_H +#define LMMS_AUDIO_SAMPLE_RECORDER_H #include #include diff --git a/include/AudioSdl.h b/include/AudioSdl.h index 7e7710a2f..bd7f4b960 100644 --- a/include/AudioSdl.h +++ b/include/AudioSdl.h @@ -22,8 +22,8 @@ * */ -#ifndef AUDIO_SDL_H -#define AUDIO_SDL_H +#ifndef LMMS_AUDIO_SDL_H +#define LMMS_AUDIO_SDL_H #include "lmmsconfig.h" diff --git a/include/AudioSndio.h b/include/AudioSndio.h index 606850105..b7f42aca2 100644 --- a/include/AudioSndio.h +++ b/include/AudioSndio.h @@ -23,8 +23,8 @@ * */ -#ifndef _AUDIO_SNDIO_H -#define _AUDIO_SNDIO_H +#ifndef LMMS_AUDIO_SNDIO_H +#define LMMS_AUDIO_SNDIO_H #include "lmmsconfig.h" @@ -87,6 +87,6 @@ private: } // namespace lmms -#endif // LMMS_HAVE_SNDIO +#endif // LMMS_HAVE_SNDIO -#endif // _AUDIO_SNDIO_H +#endif diff --git a/include/AudioSoundIo.h b/include/AudioSoundIo.h index dc9afe7e4..b29ff3779 100644 --- a/include/AudioSoundIo.h +++ b/include/AudioSoundIo.h @@ -22,8 +22,8 @@ * */ -#ifndef AUDIO_SOUNDIO_H -#define AUDIO_SOUNDIO_H +#ifndef LMMS_AUDIO_SOUNDIO_H +#define LMMS_AUDIO_SOUNDIO_H #include diff --git a/include/AutomatableButton.h b/include/AutomatableButton.h index d8c58523c..4a695a677 100644 --- a/include/AutomatableButton.h +++ b/include/AutomatableButton.h @@ -22,9 +22,8 @@ * */ - -#ifndef AUTOMATABLE_BUTTON_H -#define AUTOMATABLE_BUTTON_H +#ifndef LMMS_GUI_AUTOMATABLE_BUTTON_H +#define LMMS_GUI_AUTOMATABLE_BUTTON_H #include diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index c8f2ab548..2fccf31f4 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -22,8 +22,8 @@ * */ -#ifndef AUTOMATABLE_MODEL_H -#define AUTOMATABLE_MODEL_H +#ifndef LMMS_AUTOMATABLE_MODEL_H +#define LMMS_AUTOMATABLE_MODEL_H #include #include diff --git a/include/AutomatableModelView.h b/include/AutomatableModelView.h index 1e8ef7398..e2475be48 100644 --- a/include/AutomatableModelView.h +++ b/include/AutomatableModelView.h @@ -23,8 +23,8 @@ * */ -#ifndef AUTOMATABLE_MODEL_VIEW_H -#define AUTOMATABLE_MODEL_VIEW_H +#ifndef LMMS_GUI_AUTOMATABLE_MODEL_VIEW_H +#define LMMS_GUI_AUTOMATABLE_MODEL_VIEW_H #include "ModelView.h" #include "AutomatableModel.h" diff --git a/include/AutomatableSlider.h b/include/AutomatableSlider.h index ba11741b5..9ec55c2df 100644 --- a/include/AutomatableSlider.h +++ b/include/AutomatableSlider.h @@ -22,9 +22,8 @@ * */ - -#ifndef AUTOMATABLE_SLIDER_H -#define AUTOMATABLE_SLIDER_H +#ifndef LMMS_GUI_AUTOMATABLE_SLIDER_H +#define LMMS_GUI_AUTOMATABLE_SLIDER_H #include diff --git a/include/AutomationClip.h b/include/AutomationClip.h index 3e253d85f..7281af133 100644 --- a/include/AutomationClip.h +++ b/include/AutomationClip.h @@ -24,8 +24,8 @@ * */ -#ifndef AUTOMATION_CLIP_H -#define AUTOMATION_CLIP_H +#ifndef LMMS_AUTOMATION_CLIP_H +#define LMMS_AUTOMATION_CLIP_H #include #include diff --git a/include/AutomationClipView.h b/include/AutomationClipView.h index b4de7839c..69d4943bc 100644 --- a/include/AutomationClipView.h +++ b/include/AutomationClipView.h @@ -22,8 +22,8 @@ * */ -#ifndef AUTOMATION_CLIP_VIEW_H -#define AUTOMATION_CLIP_VIEW_H +#ifndef LMMS_GUI_AUTOMATION_CLIP_VIEW_H +#define LMMS_GUI_AUTOMATION_CLIP_VIEW_H #include diff --git a/include/AutomationEditor.h b/include/AutomationEditor.h index 52609416f..8ead191a9 100644 --- a/include/AutomationEditor.h +++ b/include/AutomationEditor.h @@ -23,8 +23,8 @@ * */ -#ifndef AUTOMATION_EDITOR_H -#define AUTOMATION_EDITOR_H +#ifndef LMMS_GUI_AUTOMATION_EDITOR_H +#define LMMS_GUI_AUTOMATION_EDITOR_H #include diff --git a/include/AutomationNode.h b/include/AutomationNode.h index 11bd6d57d..9f4a4f219 100644 --- a/include/AutomationNode.h +++ b/include/AutomationNode.h @@ -23,8 +23,8 @@ * */ -#ifndef AUTOMATION_NODE_H -#define AUTOMATION_NODE_H +#ifndef LMMS_AUTOMATION_NODE_H +#define LMMS_AUTOMATION_NODE_H namespace lmms { diff --git a/include/AutomationTrack.h b/include/AutomationTrack.h index 1779bf102..653174caa 100644 --- a/include/AutomationTrack.h +++ b/include/AutomationTrack.h @@ -24,8 +24,8 @@ * */ -#ifndef AUTOMATION_TRACK_H -#define AUTOMATION_TRACK_H +#ifndef LMMS_AUTOMATION_TRACK_H +#define LMMS_AUTOMATION_TRACK_H #include "Track.h" diff --git a/include/AutomationTrackView.h b/include/AutomationTrackView.h index 18454bec2..d948d762a 100644 --- a/include/AutomationTrackView.h +++ b/include/AutomationTrackView.h @@ -23,8 +23,8 @@ * */ -#ifndef AUTOMATION_TRACK_VIEW_H -#define AUTOMATION_TRACK_VIEW_H +#ifndef LMMS_GUI_AUTOMATION_TRACK_VIEW_H +#define LMMS_GUI_AUTOMATION_TRACK_VIEW_H #include "TrackView.h" diff --git a/include/BandLimitedWave.h b/include/BandLimitedWave.h index 588fc4eea..51e55c337 100644 --- a/include/BandLimitedWave.h +++ b/include/BandLimitedWave.h @@ -23,8 +23,8 @@ * */ -#ifndef BANDLIMITEDWAVE_H -#define BANDLIMITEDWAVE_H +#ifndef LMMS_BANDLIMITEDWAVE_H +#define LMMS_BANDLIMITEDWAVE_H class QDataStream; class QString; diff --git a/include/BasicFilters.h b/include/BasicFilters.h index 836d758b6..6912f3d36 100644 --- a/include/BasicFilters.h +++ b/include/BasicFilters.h @@ -28,9 +28,8 @@ * */ - -#ifndef BASIC_FILTERS_H -#define BASIC_FILTERS_H +#ifndef LMMS_BASIC_FILTERS_H +#define LMMS_BASIC_FILTERS_H #ifndef __USE_XOPEN #define __USE_XOPEN diff --git a/include/BufferManager.h b/include/BufferManager.h index 57729918e..8e93afc92 100644 --- a/include/BufferManager.h +++ b/include/BufferManager.h @@ -23,8 +23,8 @@ * */ -#ifndef BUFFER_MANAGER_H -#define BUFFER_MANAGER_H +#ifndef LMMS_BUFFER_MANAGER_H +#define LMMS_BUFFER_MANAGER_H #include "lmms_export.h" #include "lmms_basics.h" diff --git a/include/CPULoadWidget.h b/include/CPULoadWidget.h index dd2747ef2..a249cdc5e 100644 --- a/include/CPULoadWidget.h +++ b/include/CPULoadWidget.h @@ -23,9 +23,8 @@ * */ - -#ifndef CPULOAD_WIDGET_H -#define CPULOAD_WIDGET_H +#ifndef LMMS_GUI_CPU_LOAD_WIDGET_H +#define LMMS_GUI_CPU_LOAD_WIDGET_H #include #include diff --git a/include/CaptionMenu.h b/include/CaptionMenu.h index f6a2fff25..87aedf133 100644 --- a/include/CaptionMenu.h +++ b/include/CaptionMenu.h @@ -22,9 +22,8 @@ * */ - -#ifndef CAPTION_MENU_H -#define CAPTION_MENU_H +#ifndef LMMS_GUI_CAPTION_MENU_H +#define LMMS_GUI_CAPTION_MENU_H #include diff --git a/include/Clip.h b/include/Clip.h index 204a071a7..75416ef94 100644 --- a/include/Clip.h +++ b/include/Clip.h @@ -22,8 +22,8 @@ * */ -#ifndef TRACK_CONTENT_OBJECT_H -#define TRACK_CONTENT_OBJECT_H +#ifndef LMMS_CLIP_H +#define LMMS_CLIP_H #include diff --git a/include/ClipView.h b/include/ClipView.h index 8cfb9e7a4..a342590e1 100644 --- a/include/ClipView.h +++ b/include/ClipView.h @@ -22,8 +22,8 @@ * */ -#ifndef TRACK_CONTENT_OBJECT_VIEW_H -#define TRACK_CONTENT_OBJECT_VIEW_H +#ifndef LMMS_GUI_CLIP_VIEW_H +#define LMMS_GUI_CLIP_VIEW_H #include diff --git a/include/Clipboard.h b/include/Clipboard.h index 1c2dcb647..3c38c90fe 100644 --- a/include/Clipboard.h +++ b/include/Clipboard.h @@ -22,8 +22,8 @@ * */ -#ifndef CLIPBOARD_H -#define CLIPBOARD_H +#ifndef LMMS_CLIPBOARD_H +#define LMMS_CLIPBOARD_H #include #include diff --git a/include/ColorChooser.h b/include/ColorChooser.h index 5482a9a03..da4069f5d 100644 --- a/include/ColorChooser.h +++ b/include/ColorChooser.h @@ -21,8 +21,8 @@ * */ -#ifndef COLOR_CHOOSER_H -#define COLOR_CHOOSER_H +#ifndef LMMS_GUI_COLOR_CHOOSER_H +#define LMMS_GUI_COLOR_CHOOSER_H #include #include @@ -34,7 +34,7 @@ namespace lmms::gui { -class ColorChooser: public QColorDialog +class ColorChooser : public QColorDialog { public: ColorChooser(const QColor &initial, QWidget *parent): QColorDialog(initial, parent) {}; @@ -69,4 +69,3 @@ private: } // namespace lmms::gui #endif - diff --git a/include/ComboBox.h b/include/ComboBox.h index 9a0e5a517..ba2410491 100644 --- a/include/ComboBox.h +++ b/include/ComboBox.h @@ -22,9 +22,8 @@ * */ - -#ifndef COMBOBOX_H -#define COMBOBOX_H +#ifndef LMMS_GUI_COMBOBOX_H +#define LMMS_GUI_COMBOBOX_H #include #include diff --git a/include/ComboBoxModel.h b/include/ComboBoxModel.h index 0c76620d8..a895b838f 100644 --- a/include/ComboBoxModel.h +++ b/include/ComboBoxModel.h @@ -22,8 +22,8 @@ * */ -#ifndef COMBOBOX_MODEL_H -#define COMBOBOX_MODEL_H +#ifndef LMMS_COMBOBOX_MODEL_H +#define LMMS_COMBOBOX_MODEL_H #include #include diff --git a/include/ConfigManager.h b/include/ConfigManager.h index fd2967b6a..abeb5246f 100644 --- a/include/ConfigManager.h +++ b/include/ConfigManager.h @@ -22,9 +22,8 @@ * */ - -#ifndef CONFIG_MGR_H -#define CONFIG_MGR_H +#ifndef LMMS_CONFIG_MANAGER_H +#define LMMS_CONFIG_MANAGER_H #include "lmmsconfig.h" diff --git a/include/ControlLayout.h b/include/ControlLayout.h index 8c629f8e1..e78609a37 100644 --- a/include/ControlLayout.h +++ b/include/ControlLayout.h @@ -70,8 +70,8 @@ ** ****************************************************************************/ -#ifndef CONTROLLAYOUT_H -#define CONTROLLAYOUT_H +#ifndef LMMS_GUI_CONTROL_LAYOUT_H +#define LMMS_GUI_CONTROL_LAYOUT_H #include #include @@ -141,4 +141,4 @@ private: } // namespace lmms::gui -#endif // CONTROLLAYOUT_H +#endif diff --git a/include/Controller.h b/include/Controller.h index d949cf90c..0bb229d38 100644 --- a/include/Controller.h +++ b/include/Controller.h @@ -23,9 +23,8 @@ * */ - -#ifndef CONTROLLER_H -#define CONTROLLER_H +#ifndef LMMS_CONTROLLER_H +#define LMMS_CONTROLLER_H #include "lmms_export.h" #include "Engine.h" @@ -185,4 +184,3 @@ signals: } // namespace lmms #endif - diff --git a/include/ControllerConnection.h b/include/ControllerConnection.h index 8230971cc..d75d529f6 100644 --- a/include/ControllerConnection.h +++ b/include/ControllerConnection.h @@ -26,9 +26,8 @@ * */ - -#ifndef CONTROLLER_CONNECTION_H -#define CONTROLLER_CONNECTION_H +#ifndef LMMS_CONTROLLER_CONNECTION_H +#define LMMS_CONTROLLER_CONNECTION_H #include #include @@ -129,4 +128,3 @@ signals: } // namespace lmms #endif - diff --git a/include/ControllerConnectionDialog.h b/include/ControllerConnectionDialog.h index 5565c8a67..2e3446072 100644 --- a/include/ControllerConnectionDialog.h +++ b/include/ControllerConnectionDialog.h @@ -23,9 +23,8 @@ * */ - -#ifndef CONTROLLER_CONNECTION_DIALOG_H -#define CONTROLLER_CONNECTION_DIALOG_H +#ifndef LMMS_GUI_CONTROLLER_CONNECTION_DIALOG_H +#define LMMS_GUI_CONTROLLER_CONNECTION_DIALOG_H #include #include diff --git a/include/ControllerDialog.h b/include/ControllerDialog.h index 4f496ad77..81a9a0eb6 100644 --- a/include/ControllerDialog.h +++ b/include/ControllerDialog.h @@ -23,8 +23,8 @@ * */ -#ifndef CONTROLLER_DIALOG_H -#define CONTROLLER_DIALOG_H +#ifndef LMMS_GUI_CONTROLLER_DIALOG_H +#define LMMS_GUI_CONTROLLER_DIALOG_H #include diff --git a/include/ControllerRackView.h b/include/ControllerRackView.h index 904e523dd..1133e8ec8 100644 --- a/include/ControllerRackView.h +++ b/include/ControllerRackView.h @@ -22,8 +22,8 @@ * */ -#ifndef CONTROLLER_RACK_VIEW_H -#define CONTROLLER_RACK_VIEW_H +#ifndef LMMS_GUI_CONTROLLER_RACK_VIEW_H +#define LMMS_GUI_CONTROLLER_RACK_VIEW_H #include #include diff --git a/include/ControllerView.h b/include/ControllerView.h index 8b8db0674..44f362b70 100644 --- a/include/ControllerView.h +++ b/include/ControllerView.h @@ -22,8 +22,8 @@ * */ -#ifndef CONTROLLER_VIEW_H -#define CONTROLLER_VIEW_H +#ifndef LMMS_GUI_CONTROLLER_VIEW_H +#define LMMS_GUI_CONTROLLER_VIEW_H #include diff --git a/include/Controls.h b/include/Controls.h index 9ffed465e..53c93a36f 100644 --- a/include/Controls.h +++ b/include/Controls.h @@ -22,10 +22,8 @@ * */ -#ifndef CONTROLS_H -#define CONTROLS_H - - +#ifndef LMMS_GUI_CONTROLS_H +#define LMMS_GUI_CONTROLS_H // headers only required for covariance #include "AutomatableModel.h" @@ -146,4 +144,4 @@ public: } // namespace lmms -#endif // CONTROLS_H +#endif diff --git a/include/CustomTextKnob.h b/include/CustomTextKnob.h index cde718810..23b7e8b1f 100644 --- a/include/CustomTextKnob.h +++ b/include/CustomTextKnob.h @@ -1,6 +1,6 @@ /* Text customizable knob */ -#ifndef CUSTOM_TEXT_KNOB_H -#define CUSTOM_TEXT_KNOB_H +#ifndef LMMS_GUI_CUSTOM_TEXT_KNOB_H +#define LMMS_GUI_CUSTOM_TEXT_KNOB_H #include "Knob.h" diff --git a/include/DataFile.h b/include/DataFile.h index fb8b2ae3e..18f9697b0 100644 --- a/include/DataFile.h +++ b/include/DataFile.h @@ -23,9 +23,8 @@ * */ - -#ifndef DATA_FILE_H -#define DATA_FILE_H +#ifndef LMMS_DATA_FILE_H +#define LMMS_DATA_FILE_H #include #include diff --git a/include/Delay.h b/include/Delay.h index 529577d58..ef23d7be1 100644 --- a/include/Delay.h +++ b/include/Delay.h @@ -22,10 +22,9 @@ * Boston, MA 02110-1301 USA. * */ - - -#ifndef DELAY_H -#define DELAY_H + +#ifndef LMMS_DELAY_H +#define LMMS_DELAY_H #include "lmms_basics.h" #include "lmms_math.h" diff --git a/include/DeprecationHelper.h b/include/DeprecationHelper.h index 7786665a3..f1c68902b 100644 --- a/include/DeprecationHelper.h +++ b/include/DeprecationHelper.h @@ -24,8 +24,8 @@ * */ -#ifndef DEPRECATIONHELPER_H -#define DEPRECATIONHELPER_H +#ifndef LMMS_DEPRECATIONHELPER_H +#define LMMS_DEPRECATIONHELPER_H #include #include @@ -66,4 +66,4 @@ inline QPoint position(QWheelEvent *wheelEvent) } // namespace lmms -#endif // DEPRECATIONHELPER_H +#endif diff --git a/include/DetuningHelper.h b/include/DetuningHelper.h index f90af3697..41723bee8 100644 --- a/include/DetuningHelper.h +++ b/include/DetuningHelper.h @@ -23,8 +23,8 @@ * */ -#ifndef DETUNING_HELPER_H -#define DETUNING_HELPER_H +#ifndef LMMS_DETUNING_HELPER_H +#define LMMS_DETUNING_HELPER_H #include "InlineAutomation.h" #include "MemoryManager.h" diff --git a/include/DrumSynth.h b/include/DrumSynth.h index 98574f2d2..9b759ac1a 100644 --- a/include/DrumSynth.h +++ b/include/DrumSynth.h @@ -23,9 +23,8 @@ * */ - -#ifndef DRUMSYNTH_H -#define DRUMSYNTH_H +#ifndef LMMS_DRUM_SYNTH_H +#define LMMS_DRUM_SYNTH_H #include #include "lmms_basics.h" @@ -57,4 +56,4 @@ class DrumSynth { } // namespace lmms -#endif // DRUMSYNTH_H +#endif diff --git a/include/DspEffectLibrary.h b/include/DspEffectLibrary.h index eb03e1cf0..0a19783f6 100644 --- a/include/DspEffectLibrary.h +++ b/include/DspEffectLibrary.h @@ -22,9 +22,8 @@ * */ - -#ifndef DSP_EFFECT_LIBRARY_H -#define DSP_EFFECT_LIBRARY_H +#ifndef LMMS_DSPEFFECTLIBRARY_H +#define LMMS_DSPEFFECTLIBRARY_H #include "lmms_math.h" #include "lmms_constants.h" diff --git a/include/DummyEffect.h b/include/DummyEffect.h index 9db45a3e1..945738e1b 100644 --- a/include/DummyEffect.h +++ b/include/DummyEffect.h @@ -22,8 +22,8 @@ * */ -#ifndef DUMMY_EFFECT_H -#define DUMMY_EFFECT_H +#ifndef LMMS_DUMMY_EFFECT_H +#define LMMS_DUMMY_EFFECT_H #include diff --git a/include/DummyInstrument.h b/include/DummyInstrument.h index a40d8338f..19b6b6fbd 100644 --- a/include/DummyInstrument.h +++ b/include/DummyInstrument.h @@ -23,8 +23,8 @@ * */ -#ifndef DUMMY_INSTRUMENT_H -#define DUMMY_INSTRUMENT_H +#ifndef LMMS_DUMMY_INSTRUMENT_H +#define LMMS_DUMMY_INSTRUMENT_H #include "Instrument.h" #include "InstrumentView.h" diff --git a/include/DummyPlugin.h b/include/DummyPlugin.h index 1c763ec3e..ad517c1a9 100644 --- a/include/DummyPlugin.h +++ b/include/DummyPlugin.h @@ -23,8 +23,8 @@ * */ -#ifndef DUMMY_PLUGIN_H -#define DUMMY_PLUGIN_H +#ifndef LMMS_DUMMY_PLUGIN_H +#define LMMS_DUMMY_PLUGIN_H #include "Plugin.h" #include "PluginView.h" diff --git a/include/Editor.h b/include/Editor.h index 1a39ea72f..ad330ac06 100644 --- a/include/Editor.h +++ b/include/Editor.h @@ -22,8 +22,8 @@ * */ -#ifndef EDITOR_COMMON_H -#define EDITOR_COMMON_H +#ifndef LMMS_EDITOR_H +#define LMMS_EDITOR_H #include #include diff --git a/include/Effect.h b/include/Effect.h index add1f7158..a9952d339 100644 --- a/include/Effect.h +++ b/include/Effect.h @@ -23,8 +23,8 @@ * */ -#ifndef EFFECT_H -#define EFFECT_H +#ifndef LMMS_EFFECT_H +#define LMMS_EFFECT_H #include "Plugin.h" #include "Engine.h" diff --git a/include/EffectChain.h b/include/EffectChain.h index a9da8e530..dad4de5e1 100644 --- a/include/EffectChain.h +++ b/include/EffectChain.h @@ -23,8 +23,8 @@ * */ -#ifndef EFFECT_CHAIN_H -#define EFFECT_CHAIN_H +#ifndef LMMS_EFFECT_CHAIN_H +#define LMMS_EFFECT_CHAIN_H #include "Model.h" #include "SerializingObject.h" @@ -86,4 +86,3 @@ signals: } // namespace lmms #endif - diff --git a/include/EffectControlDialog.h b/include/EffectControlDialog.h index 6389db4a3..bda845dc5 100644 --- a/include/EffectControlDialog.h +++ b/include/EffectControlDialog.h @@ -23,8 +23,8 @@ * */ -#ifndef EFFECT_CONTROL_DIALOG_H -#define EFFECT_CONTROL_DIALOG_H +#ifndef LMMS_GUI_EFFECT_CONTROL_DIALOG_H +#define LMMS_GUI_EFFECT_CONTROL_DIALOG_H #include diff --git a/include/EffectControls.h b/include/EffectControls.h index 994145a40..dfecc0792 100644 --- a/include/EffectControls.h +++ b/include/EffectControls.h @@ -22,8 +22,8 @@ * */ -#ifndef EFFECT_CONTROLS_H -#define EFFECT_CONTROLS_H +#ifndef LMMS_EFFECT_CONTROLS_H +#define LMMS_EFFECT_CONTROLS_H #include "Model.h" #include "JournallingObject.h" diff --git a/include/EffectRackView.h b/include/EffectRackView.h index fb68fda68..96f70548a 100644 --- a/include/EffectRackView.h +++ b/include/EffectRackView.h @@ -23,8 +23,8 @@ * */ -#ifndef EFFECT_RACK_VIEW_H -#define EFFECT_RACK_VIEW_H +#ifndef LMMS_GUI_EFFECT_RACK_VIEW_H +#define LMMS_GUI_EFFECT_RACK_VIEW_H #include diff --git a/include/EffectSelectDialog.h b/include/EffectSelectDialog.h index b0acfb734..c31f96e14 100644 --- a/include/EffectSelectDialog.h +++ b/include/EffectSelectDialog.h @@ -22,8 +22,8 @@ * */ -#ifndef EFFECT_SELECT_DIALOG_H -#define EFFECT_SELECT_DIALOG_H +#ifndef LMMS_GUI_EFFECT_SELECT_DIALOG_H +#define LMMS_GUI_EFFECT_SELECT_DIALOG_H #include #include diff --git a/include/EffectView.h b/include/EffectView.h index 90bb54896..fb19d52dd 100644 --- a/include/EffectView.h +++ b/include/EffectView.h @@ -23,8 +23,8 @@ * */ -#ifndef EFFECT_VIEW_H -#define EFFECT_VIEW_H +#ifndef LMMS_GUI_EFFECT_VIEW_H +#define LMMS_GUI_EFFECT_VIEW_H #include "AutomatableModel.h" #include "PluginView.h" diff --git a/include/Engine.h b/include/Engine.h index b63308cde..0cb77315f 100644 --- a/include/Engine.h +++ b/include/Engine.h @@ -22,14 +22,12 @@ * */ - -#ifndef ENGINE_H -#define ENGINE_H +#ifndef LMMS_ENGINE_H +#define LMMS_ENGINE_H #include #include - #include "lmmsconfig.h" #include "lmms_export.h" #include "lmms_basics.h" @@ -158,4 +156,3 @@ private: } // namespace lmms #endif - diff --git a/include/EnvelopeAndLfoParameters.h b/include/EnvelopeAndLfoParameters.h index 534adcbe5..0a90ec68b 100644 --- a/include/EnvelopeAndLfoParameters.h +++ b/include/EnvelopeAndLfoParameters.h @@ -22,8 +22,8 @@ * */ -#ifndef ENVELOPE_AND_LFO_PARAMETERS_H -#define ENVELOPE_AND_LFO_PARAMETERS_H +#ifndef LMMS_ENVELOPE_AND_LFO_PARAMETERS_H +#define LMMS_ENVELOPE_AND_LFO_PARAMETERS_H #include diff --git a/include/EnvelopeAndLfoView.h b/include/EnvelopeAndLfoView.h index a82ccf606..e927e9fcc 100644 --- a/include/EnvelopeAndLfoView.h +++ b/include/EnvelopeAndLfoView.h @@ -23,8 +23,8 @@ * */ -#ifndef ENVELOPE_AND_LFO_VIEW_H -#define ENVELOPE_AND_LFO_VIEW_H +#ifndef LMMS_GUI_ENVELOPE_AND_LFO_VIEW_H +#define LMMS_GUI_ENVELOPE_AND_LFO_VIEW_H #include diff --git a/include/ExportFilter.h b/include/ExportFilter.h index 29efef539..13a3c179d 100644 --- a/include/ExportFilter.h +++ b/include/ExportFilter.h @@ -23,8 +23,8 @@ * */ -#ifndef EXPORT_FILTER_H -#define EXPORT_FILTER_H +#ifndef LMMS_EXPORT_FILTER_H +#define LMMS_EXPORT_FILTER_H #include diff --git a/include/ExportProjectDialog.h b/include/ExportProjectDialog.h index 56d039afe..af33d6766 100644 --- a/include/ExportProjectDialog.h +++ b/include/ExportProjectDialog.h @@ -23,9 +23,8 @@ * */ - -#ifndef EXPORT_PROJECT_DIALOG_H -#define EXPORT_PROJECT_DIALOG_H +#ifndef LMMS_GUI_EXPORT_PROJECT_DIALOG_H +#define LMMS_GUI_EXPORT_PROJECT_DIALOG_H #include #include diff --git a/include/FadeButton.h b/include/FadeButton.h index d33900913..df0e2abf2 100644 --- a/include/FadeButton.h +++ b/include/FadeButton.h @@ -22,9 +22,8 @@ * */ - -#ifndef FADE_BUTTON_H -#define FADE_BUTTON_H +#ifndef LMMS_GUI_FADE_BUTTON_H +#define LMMS_GUI_FADE_BUTTON_H #include #include diff --git a/include/Fader.h b/include/Fader.h index 54acfc57d..cfffba843 100644 --- a/include/Fader.h +++ b/include/Fader.h @@ -44,9 +44,8 @@ * */ - -#ifndef FADER_H -#define FADER_H +#ifndef LMMS_GUI_FADER_H +#define LMMS_GUI_FADER_H #include #include diff --git a/include/FifoBuffer.h b/include/FifoBuffer.h index d49e367c0..4b5682a51 100644 --- a/include/FifoBuffer.h +++ b/include/FifoBuffer.h @@ -22,8 +22,8 @@ * */ -#ifndef FIFO_BUFFER_H -#define FIFO_BUFFER_H +#ifndef LMMS_FIFO_BUFFER_H +#define LMMS_FIFO_BUFFER_H #include diff --git a/include/FileBrowser.h b/include/FileBrowser.h index 43a0b3331..387be38d1 100644 --- a/include/FileBrowser.h +++ b/include/FileBrowser.h @@ -22,9 +22,8 @@ * */ - -#ifndef FILE_BROWSER_H -#define FILE_BROWSER_H +#ifndef LMMS_GUI_FILE_BROWSER_H +#define LMMS_GUI_FILE_BROWSER_H #include #include diff --git a/include/FileDialog.h b/include/FileDialog.h index ed5d2f231..a999fff16 100644 --- a/include/FileDialog.h +++ b/include/FileDialog.h @@ -22,9 +22,8 @@ * */ - -#ifndef FILEDIALOG_H -#define FILEDIALOG_H +#ifndef LMMS_GUI_FILE_DIALOG_H +#define LMMS_GUI_FILE_DIALOG_H #include @@ -57,4 +56,4 @@ public: } // namespace lmms::gui -#endif // FILEDIALOG_H +#endif diff --git a/include/Graph.h b/include/Graph.h index 178d1b567..d04fd926c 100644 --- a/include/Graph.h +++ b/include/Graph.h @@ -23,9 +23,8 @@ * */ - -#ifndef GRAPH_H -#define GRAPH_H +#ifndef LMMS_GUI_GRAPH_H +#define LMMS_GUI_GRAPH_H #include #include diff --git a/include/GroupBox.h b/include/GroupBox.h index e20db80a6..bf2773e23 100644 --- a/include/GroupBox.h +++ b/include/GroupBox.h @@ -22,9 +22,8 @@ * */ - -#ifndef GROUP_BOX_H -#define GROUP_BOX_H +#ifndef LMMS_GUI_GROUP_BOX_H +#define LMMS_GUI_GROUP_BOX_H #include diff --git a/include/GuiApplication.h b/include/GuiApplication.h index e39983138..dd87a5607 100644 --- a/include/GuiApplication.h +++ b/include/GuiApplication.h @@ -22,8 +22,8 @@ * */ -#ifndef GUIAPPLICATION_H -#define GUIAPPLICATION_H +#ifndef LMMS_GUI_GUI_APPLICATION_H +#define LMMS_GUI_GUI_APPLICATION_H #include @@ -93,4 +93,4 @@ LMMS_EXPORT GuiApplication* getGUI(); } // namespace lmms::gui -#endif // GUIAPPLICATION_H +#endif diff --git a/include/ImportFilter.h b/include/ImportFilter.h index b7a910e5d..587a62a78 100644 --- a/include/ImportFilter.h +++ b/include/ImportFilter.h @@ -23,8 +23,8 @@ * */ -#ifndef IMPORT_FILTER_H -#define IMPORT_FILTER_H +#ifndef LMMS_IMPORT_FILTER_H +#define LMMS_IMPORT_FILTER_H #include diff --git a/include/InlineAutomation.h b/include/InlineAutomation.h index 435604506..fbecd2769 100644 --- a/include/InlineAutomation.h +++ b/include/InlineAutomation.h @@ -22,8 +22,8 @@ * */ -#ifndef INLINE_AUTOMATION_H -#define INLINE_AUTOMATION_H +#ifndef LMMS_INLINE_AUTOMATION_H +#define LMMS_INLINE_AUTOMATION_H #include "AutomationNode.h" #include "AutomationClip.h" diff --git a/include/Instrument.h b/include/Instrument.h index 4e48e2fd6..3ea8bdf2f 100644 --- a/include/Instrument.h +++ b/include/Instrument.h @@ -23,8 +23,8 @@ * */ -#ifndef INSTRUMENT_H -#define INSTRUMENT_H +#ifndef LMMS_INSTRUMENT_H +#define LMMS_INSTRUMENT_H #include #include "lmms_export.h" diff --git a/include/InstrumentFunctionViews.h b/include/InstrumentFunctionViews.h index 99ba92031..3abd8eae7 100644 --- a/include/InstrumentFunctionViews.h +++ b/include/InstrumentFunctionViews.h @@ -22,8 +22,8 @@ * */ -#ifndef INSTRUMENT_FUNCTION_VIEWS_H -#define INSTRUMENT_FUNCTION_VIEWS_H +#ifndef LMMS_INSTRUMENT_FUNCTION_VIEWS_H +#define LMMS_INSTRUMENT_FUNCTION_VIEWS_H #include "ModelView.h" diff --git a/include/InstrumentFunctions.h b/include/InstrumentFunctions.h index 5dcb1114b..5b6c1af6d 100644 --- a/include/InstrumentFunctions.h +++ b/include/InstrumentFunctions.h @@ -22,8 +22,8 @@ * */ -#ifndef INSTRUMENT_FUNCTIONS_H -#define INSTRUMENT_FUNCTIONS_H +#ifndef LMMS_INSTRUMENT_FUNCTIONS_H +#define LMMS_INSTRUMENT_FUNCTIONS_H #include "JournallingObject.h" #include "lmms_basics.h" diff --git a/include/InstrumentMidiIOView.h b/include/InstrumentMidiIOView.h index 81feee082..dd6e43151 100644 --- a/include/InstrumentMidiIOView.h +++ b/include/InstrumentMidiIOView.h @@ -23,8 +23,8 @@ * */ -#ifndef INSTRUMENT_MIDI_IO_VIEW_H -#define INSTRUMENT_MIDI_IO_VIEW_H +#ifndef LMMS_GUI_INSTRUMENT_MIDI_IO_VIEW_H +#define LMMS_GUI_INSTRUMENT_MIDI_IO_VIEW_H #include diff --git a/include/InstrumentMiscView.h b/include/InstrumentMiscView.h index 25e16395d..9aee23676 100644 --- a/include/InstrumentMiscView.h +++ b/include/InstrumentMiscView.h @@ -24,8 +24,8 @@ * */ -#ifndef INSTRUMENT_MISC_VIEW_H -#define INSTRUMENT_MISC_VIEW_H +#ifndef LMMS_GUI_INSTRUMENT_MISC_VIEW_H +#define LMMS_GUI_INSTRUMENT_MISC_VIEW_H #include diff --git a/include/InstrumentPlayHandle.h b/include/InstrumentPlayHandle.h index e9516ab19..b65f906ae 100644 --- a/include/InstrumentPlayHandle.h +++ b/include/InstrumentPlayHandle.h @@ -22,8 +22,8 @@ * */ -#ifndef INSTRUMENT_PLAY_HANDLE_H -#define INSTRUMENT_PLAY_HANDLE_H +#ifndef LMMS_INSTRUMENT_PLAY_HANDLE_H +#define LMMS_INSTRUMENT_PLAY_HANDLE_H #include "PlayHandle.h" #include "Instrument.h" diff --git a/include/InstrumentSoundShaping.h b/include/InstrumentSoundShaping.h index 11ed4f1c4..607871c85 100644 --- a/include/InstrumentSoundShaping.h +++ b/include/InstrumentSoundShaping.h @@ -22,8 +22,8 @@ * */ -#ifndef INSTRUMENT_SOUND_SHAPING_H -#define INSTRUMENT_SOUND_SHAPING_H +#ifndef LMMS_INSTRUMENT_SOUND_SHAPING_H +#define LMMS_INSTRUMENT_SOUND_SHAPING_H #include "ComboBoxModel.h" diff --git a/include/InstrumentSoundShapingView.h b/include/InstrumentSoundShapingView.h index aa8aff19d..f37cfaa55 100644 --- a/include/InstrumentSoundShapingView.h +++ b/include/InstrumentSoundShapingView.h @@ -22,8 +22,8 @@ * */ -#ifndef INSTRUMENT_SOUND_SHAPING_VIEW_H -#define INSTRUMENT_SOUND_SHAPING_VIEW_H +#ifndef LMMS_GUI_INSTRUMENT_SOUND_SHAPING_VIEW_H +#define LMMS_GUI_INSTRUMENT_SOUND_SHAPING_VIEW_H #include diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index 129969292..6fa41b4a1 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -23,8 +23,8 @@ * */ -#ifndef INSTRUMENT_TRACK_H -#define INSTRUMENT_TRACK_H +#ifndef LMMS_INSTRUMENT_TRACK_H +#define LMMS_INSTRUMENT_TRACK_H #include "AudioPort.h" #include "InstrumentFunctions.h" diff --git a/include/InstrumentTrackView.h b/include/InstrumentTrackView.h index 3201f81d6..66fb7804b 100644 --- a/include/InstrumentTrackView.h +++ b/include/InstrumentTrackView.h @@ -22,8 +22,8 @@ * */ -#ifndef INSTRUMENT_TRACK_VIEW_H -#define INSTRUMENT_TRACK_VIEW_H +#ifndef LMMS_GUI_INSTRUMENT_TRACK_VIEW_H +#define LMMS_GUI_INSTRUMENT_TRACK_VIEW_H #include "TrackView.h" diff --git a/include/InstrumentTrackWindow.h b/include/InstrumentTrackWindow.h index 68750c0b8..f50b138df 100644 --- a/include/InstrumentTrackWindow.h +++ b/include/InstrumentTrackWindow.h @@ -22,8 +22,8 @@ * */ -#ifndef INSTRUMENT_TRACK_WINDOW_H -#define INSTRUMENT_TRACK_WINDOW_H +#ifndef LMMS_GUI_INSTRUMENT_TRACK_WINDOW_H +#define LMMS_GUI_INSTRUMENT_TRACK_WINDOW_H #include diff --git a/include/InstrumentView.h b/include/InstrumentView.h index ab18465eb..ff4b9cd66 100644 --- a/include/InstrumentView.h +++ b/include/InstrumentView.h @@ -22,9 +22,8 @@ * */ - -#ifndef INSTRUMENT_VIEW_H -#define INSTRUMENT_VIEW_H +#ifndef LMMS_GUI_INSTRUMENT_VIEW_H +#define LMMS_GUI_INSTRUMENT_VIEW_H #include "Instrument.h" #include "PluginView.h" diff --git a/include/IoHelper.h b/include/IoHelper.h index c7d65c917..423cbaab3 100644 --- a/include/IoHelper.h +++ b/include/IoHelper.h @@ -22,8 +22,8 @@ * */ -#ifndef IO_HELPER_H -#define IO_HELPER_H +#ifndef LMMS_IO_HELPER_H +#define LMMS_IO_HELPER_H #include "lmmsconfig.h" diff --git a/include/JournallingObject.h b/include/JournallingObject.h index 41ae65295..15e071577 100644 --- a/include/JournallingObject.h +++ b/include/JournallingObject.h @@ -22,8 +22,8 @@ * */ -#ifndef JOURNALLING_OBJECT_H -#define JOURNALLING_OBJECT_H +#ifndef LMMS_JOURNALLING_OBJECT_H +#define LMMS_JOURNALLING_OBJECT_H #include @@ -104,4 +104,3 @@ private: } // namespace lmms #endif - diff --git a/include/Keymap.h b/include/Keymap.h index 6286f8362..88f0df428 100644 --- a/include/Keymap.h +++ b/include/Keymap.h @@ -22,8 +22,8 @@ * */ -#ifndef KEYMAP_H -#define KEYMAP_H +#ifndef LMMS_KEYMAP_H +#define LMMS_KEYMAP_H #include #include diff --git a/include/Knob.h b/include/Knob.h index 16ac7ed01..94fb8b640 100644 --- a/include/Knob.h +++ b/include/Knob.h @@ -22,9 +22,8 @@ * */ - -#ifndef KNOB_H -#define KNOB_H +#ifndef LMMS_GUI_KNOB_H +#define LMMS_GUI_KNOB_H #include #include diff --git a/include/Ladspa2LMMS.h b/include/Ladspa2LMMS.h index 4b7eb2482..d4fd12b2d 100644 --- a/include/Ladspa2LMMS.h +++ b/include/Ladspa2LMMS.h @@ -23,13 +23,11 @@ * */ -#ifndef LADSPA_2_LMMS_H -#define LADSPA_2_LMMS_H - +#ifndef LMMS_LADSPA_2_LMMS_H +#define LMMS_LADSPA_2_LMMS_H #include "LadspaManager.h" - namespace lmms { diff --git a/include/LadspaBase.h b/include/LadspaBase.h index 3feb7d204..442d12293 100644 --- a/include/LadspaBase.h +++ b/include/LadspaBase.h @@ -23,8 +23,8 @@ * */ -#ifndef LADSPA_BASE_H -#define LADSPA_BASE_H +#ifndef LMMS_LADSPA_BASE_H +#define LMMS_LADSPA_BASE_H #include "LadspaManager.h" #include "Plugin.h" diff --git a/include/LadspaControl.h b/include/LadspaControl.h index 258a5d8fc..9bc83e352 100644 --- a/include/LadspaControl.h +++ b/include/LadspaControl.h @@ -23,8 +23,8 @@ * */ -#ifndef LADSPA_CONTROL_H -#define LADSPA_CONTROL_H +#ifndef LMMS_LADSPA_CONTROL_H +#define LMMS_LADSPA_CONTROL_H #include diff --git a/include/LadspaControlView.h b/include/LadspaControlView.h index 5dafa4e5c..4638d5b5c 100644 --- a/include/LadspaControlView.h +++ b/include/LadspaControlView.h @@ -23,8 +23,8 @@ * */ -#ifndef LADSPA_CONTROL_VIEW_H -#define LADSPA_CONTROL_VIEW_H +#ifndef LMMS_GUI_LADSPA_CONTROL_VIEW_H +#define LMMS_GUI_LADSPA_CONTROL_VIEW_H #include diff --git a/include/LadspaManager.h b/include/LadspaManager.h index 176526193..7b8639779 100644 --- a/include/LadspaManager.h +++ b/include/LadspaManager.h @@ -24,9 +24,8 @@ * */ - -#ifndef LADSPA_MANAGER_H -#define LADSPA_MANAGER_H +#ifndef LMMS_LADSPA_MANAGER_H +#define LMMS_LADSPA_MANAGER_H #include diff --git a/include/LcdFloatSpinBox.h b/include/LcdFloatSpinBox.h index ab0de304e..3dcf500b9 100644 --- a/include/LcdFloatSpinBox.h +++ b/include/LcdFloatSpinBox.h @@ -23,9 +23,8 @@ * */ - -#ifndef LCD_FLOATSPINBOX_H -#define LCD_FLOATSPINBOX_H +#ifndef LMMS_GUI_LCD_FLOATSPINBOX_H +#define LMMS_GUI_LCD_FLOATSPINBOX_H #include diff --git a/include/LcdSpinBox.h b/include/LcdSpinBox.h index 9c8923763..6dcb68c1b 100644 --- a/include/LcdSpinBox.h +++ b/include/LcdSpinBox.h @@ -22,9 +22,8 @@ * */ - -#ifndef LCD_SPINBOX_H -#define LCD_SPINBOX_H +#ifndef LMMS_GUI_LCD_SPINBOX_H +#define LMMS_GUI_LCD_SPINBOX_H #include "LcdWidget.h" #include "AutomatableModelView.h" diff --git a/include/LcdWidget.h b/include/LcdWidget.h index d55cfc017..665668b3f 100644 --- a/include/LcdWidget.h +++ b/include/LcdWidget.h @@ -22,9 +22,8 @@ * */ - -#ifndef LCD_WIDGET_H -#define LCD_WIDGET_H +#ifndef LMMS_GUI_LCD_WIDGET_H +#define LMMS_GUI_LCD_WIDGET_H #include #include diff --git a/include/LedCheckBox.h b/include/LedCheckBox.h index a215592e6..12642ef3b 100644 --- a/include/LedCheckBox.h +++ b/include/LedCheckBox.h @@ -22,9 +22,8 @@ * */ - -#ifndef LED_CHECKBOX_H -#define LED_CHECKBOX_H +#ifndef LMMS_GUI_LED_CHECKBOX_H +#define LMMS_GUI_LED_CHECKBOX_H #include "AutomatableButton.h" diff --git a/include/LeftRightNav.h b/include/LeftRightNav.h index df72193dc..e752d44c0 100644 --- a/include/LeftRightNav.h +++ b/include/LeftRightNav.h @@ -22,8 +22,8 @@ * */ -#ifndef LEFT_RIGHT_NAV_H -#define LEFT_RIGHT_NAV_H +#ifndef LMMS_GUI_LEFT_RIGHT_NAV_H +#define LMMS_GUI_LEFT_RIGHT_NAV_H #include "PixmapButton.h" @@ -51,4 +51,4 @@ private: } // namespace lmms::gui -#endif \ No newline at end of file +#endif diff --git a/include/LfoController.h b/include/LfoController.h index 48aee3d30..ccd5804c7 100644 --- a/include/LfoController.h +++ b/include/LfoController.h @@ -22,8 +22,8 @@ * */ -#ifndef LFO_CONTROLLER_H -#define LFO_CONTROLLER_H +#ifndef LMMS_LFO_CONTROLLER_H +#define LMMS_LFO_CONTROLLER_H #include @@ -51,7 +51,7 @@ class LfoControllerDialog; } -class LfoController : public Controller +class LfoController : public Controller { Q_OBJECT public: diff --git a/include/LinkedModelGroupViews.h b/include/LinkedModelGroupViews.h index 72598281b..08c25a8bb 100644 --- a/include/LinkedModelGroupViews.h +++ b/include/LinkedModelGroupViews.h @@ -22,15 +22,13 @@ * */ -#ifndef LINKEDMODELGROUPVIEWS_H -#define LINKEDMODELGROUPVIEWS_H - +#ifndef LMMS_GUI_LINKEDMODELGROUPVIEWS_H +#define LMMS_GUI_LINKEDMODELGROUPVIEWS_H #include #include #include - namespace lmms { @@ -120,4 +118,4 @@ private: } // namespace lmms -#endif // LINKEDMODELGROUPVIEWS_H +#endif diff --git a/include/LinkedModelGroups.h b/include/LinkedModelGroups.h index 84a216f30..11950d85e 100644 --- a/include/LinkedModelGroups.h +++ b/include/LinkedModelGroups.h @@ -22,15 +22,13 @@ * */ -#ifndef LINKEDMODELGROUPS_H -#define LINKEDMODELGROUPS_H - +#ifndef LMMS_LINKEDMODELGROUPS_H +#define LMMS_LINKEDMODELGROUPS_H #include #include "Model.h" - class QDomDocument; class QDomElement; @@ -178,4 +176,4 @@ public: } // namespace lmms -#endif // LINKEDMODELGROUPS_H +#endif diff --git a/include/LmmsPalette.h b/include/LmmsPalette.h index 023872254..68cd2d2ab 100644 --- a/include/LmmsPalette.h +++ b/include/LmmsPalette.h @@ -23,13 +23,12 @@ * */ -#ifndef LMMSPALETTE_H -#define LMMSPALETTE_H +#ifndef LMMS_GUI_LMMS_PALETTE_H +#define LMMS_GUI_LMMS_PALETTE_H #include #include "lmms_export.h" - namespace lmms::gui { @@ -86,7 +85,6 @@ private: }; - } // namespace lmms::gui #endif diff --git a/include/LmmsStyle.h b/include/LmmsStyle.h index ae5b65f99..c560b5be8 100644 --- a/include/LmmsStyle.h +++ b/include/LmmsStyle.h @@ -23,9 +23,8 @@ * */ - -#ifndef LMMS_STYLE_H -#define LMMS_STYLE_H +#ifndef LMMS_GUI_LMMS_STYLE_H +#define LMMS_GUI_LMMS_STYLE_H #include diff --git a/include/LocaleHelper.h b/include/LocaleHelper.h index b071a1596..61298f42b 100644 --- a/include/LocaleHelper.h +++ b/include/LocaleHelper.h @@ -25,8 +25,8 @@ * */ -#ifndef LOCALEHELPER_H -#define LOCALEHELPER_H +#ifndef LMMS_LOCALEHELPER_H +#define LMMS_LOCALEHELPER_H #include @@ -67,4 +67,4 @@ inline float toFloat(QString str, bool* ok = nullptr) } // namespace lmms::LocaleHelper -#endif // LOCALEHELPER_H +#endif diff --git a/include/LocklessAllocator.h b/include/LocklessAllocator.h index adde5fe6f..f1b3dea40 100644 --- a/include/LocklessAllocator.h +++ b/include/LocklessAllocator.h @@ -22,8 +22,8 @@ * */ -#ifndef LOCKLESS_ALLOCATOR_H -#define LOCKLESS_ALLOCATOR_H +#ifndef LMMS_LOCKLESS_ALLOCATOR_H +#define LMMS_LOCKLESS_ALLOCATOR_H #include #include diff --git a/include/LocklessList.h b/include/LocklessList.h index 44b718059..e5c5cce71 100644 --- a/include/LocklessList.h +++ b/include/LocklessList.h @@ -22,8 +22,8 @@ * */ -#ifndef LOCKLESS_LIST_H -#define LOCKLESS_LIST_H +#ifndef LMMS_LOCKLESS_LIST_H +#define LMMS_LOCKLESS_LIST_H #include "LocklessAllocator.h" diff --git a/include/LocklessRingBuffer.h b/include/LocklessRingBuffer.h index e77c62ccb..904e54f9c 100644 --- a/include/LocklessRingBuffer.h +++ b/include/LocklessRingBuffer.h @@ -22,8 +22,8 @@ * */ -#ifndef LOCKLESSRINGBUFFER_H -#define LOCKLESSRINGBUFFER_H +#ifndef LMMS_LOCKLESS_RING_BUFFER_H +#define LMMS_LOCKLESS_RING_BUFFER_H #include #include @@ -89,4 +89,4 @@ private: } // namespace lmms -#endif //LOCKLESSRINGBUFFER_H +#endif diff --git a/include/Lv2Basics.h b/include/Lv2Basics.h index b935e6a02..73f006b46 100644 --- a/include/Lv2Basics.h +++ b/include/Lv2Basics.h @@ -22,10 +22,8 @@ * */ - -#ifndef LV2BASICS_H -#define LV2BASICS_H - +#ifndef LMMS_LV2BASICS_H +#define LMMS_LV2BASICS_H #include "lmmsconfig.h" @@ -69,4 +67,5 @@ std::string stdStringFromPortName(const LilvPlugin* plug, const LilvPort* port); } // namespace lmms #endif // LMMS_HAVE_LV2 -#endif // LV2BASICS_H + +#endif diff --git a/include/Lv2ControlBase.h b/include/Lv2ControlBase.h index c6b08db8c..dcb90f27a 100644 --- a/include/Lv2ControlBase.h +++ b/include/Lv2ControlBase.h @@ -22,8 +22,8 @@ * */ -#ifndef LV2_CONTROL_BASE_H -#define LV2_CONTROL_BASE_H +#ifndef LMMS_LV2_CONTROL_BASE_H +#define LMMS_LV2_CONTROL_BASE_H #include "lmmsconfig.h" @@ -163,4 +163,5 @@ private: } // namespace lmms #endif // LMMS_HAVE_LV2 -#endif // LV2_CONTROL_BASE_H + +#endif diff --git a/include/Lv2Evbuf.h b/include/Lv2Evbuf.h index 9732fc5e1..ecf61ec99 100644 --- a/include/Lv2Evbuf.h +++ b/include/Lv2Evbuf.h @@ -1,5 +1,5 @@ /* - * lv2_evbuf.h - Lv2 event buffer definitions + * Lv2Evbuf.h - Lv2 event buffer definitions * * Copyright (c) 2019-2020 Johannes Lorenz * @@ -30,8 +30,8 @@ * match the LMMS coding conventions. */ -#ifndef LV2_EVBUF_H -#define LV2_EVBUF_H +#ifndef LMMS_LV2_EVBUF_H +#define LMMS_LV2_EVBUF_H #include "lmmsconfig.h" @@ -155,4 +155,4 @@ lv2_evbuf_write( LV2_Evbuf_Iterator* iter, #endif // LMMS_HAVE_LV2 -#endif // LV2_EVBUF_H +#endif diff --git a/include/Lv2Features.h b/include/Lv2Features.h index 033273f31..99a5762b0 100644 --- a/include/Lv2Features.h +++ b/include/Lv2Features.h @@ -22,8 +22,8 @@ * */ -#ifndef LV2FEATURES_H -#define LV2FEATURES_H +#ifndef LMMS_LV2_FEATURES_H +#define LMMS_LV2_FEATURES_H #include "lmmsconfig.h" @@ -84,4 +84,4 @@ private: #endif // LMMS_HAVE_LV2 -#endif // LV2FEATURES_H +#endif diff --git a/include/Lv2Manager.h b/include/Lv2Manager.h index 7c4a4bcb7..45ca868dd 100644 --- a/include/Lv2Manager.h +++ b/include/Lv2Manager.h @@ -22,8 +22,8 @@ * */ -#ifndef LV2MANAGER_H -#define LV2MANAGER_H +#ifndef LMMS_LV2_MANAGER_H +#define LMMS_LV2_MANAGER_H #include "lmmsconfig.h" @@ -166,4 +166,4 @@ private: #endif // LMMS_HAVE_LV2 -#endif // LV2MANAGER_H +#endif diff --git a/include/Lv2Options.h b/include/Lv2Options.h index 32225ea89..c81e4b953 100644 --- a/include/Lv2Options.h +++ b/include/Lv2Options.h @@ -22,8 +22,8 @@ * */ -#ifndef LV2OPTIONS_H -#define LV2OPTIONS_H +#ifndef LMMS_LV2_OPTIONS_H +#define LMMS_LV2_OPTIONS_H #include "lmmsconfig.h" @@ -107,4 +107,4 @@ private: #endif // LMMS_HAVE_LV2 -#endif // LV2OPTIONS_H +#endif diff --git a/include/Lv2Ports.h b/include/Lv2Ports.h index 07676fdd4..7283ebbd3 100644 --- a/include/Lv2Ports.h +++ b/include/Lv2Ports.h @@ -22,8 +22,8 @@ * */ -#ifndef LV2PORTS_H -#define LV2PORTS_H +#ifndef LMMS_LV2PORTS_H +#define LMMS_LV2PORTS_H #include "lmmsconfig.h" @@ -270,4 +270,5 @@ const Target* dcast(const PortBase* base) } // namespace lmms #endif // LMMS_HAVE_LV2 -#endif // LV2PORTS_H + +#endif diff --git a/include/Lv2Proc.h b/include/Lv2Proc.h index 31a694044..eea4e7c0e 100644 --- a/include/Lv2Proc.h +++ b/include/Lv2Proc.h @@ -22,8 +22,8 @@ * */ -#ifndef LV2PROC_H -#define LV2PROC_H +#ifndef LMMS_LV2_PROC_H +#define LMMS_LV2_PROC_H #include "lmmsconfig.h" @@ -220,4 +220,5 @@ private: } // namespace lmms #endif // LMMS_HAVE_LV2 -#endif // LV2PROC_H + +#endif diff --git a/include/Lv2SubPluginFeatures.h b/include/Lv2SubPluginFeatures.h index 9ba2c76cb..f8fbf55df 100644 --- a/include/Lv2SubPluginFeatures.h +++ b/include/Lv2SubPluginFeatures.h @@ -24,8 +24,8 @@ * */ -#ifndef LV2_SUBPLUGIN_FEATURES_H -#define LV2_SUBPLUGIN_FEATURES_H +#ifndef LMMS_LV2_SUBPLUGIN_FEATURES_H +#define LMMS_LV2_SUBPLUGIN_FEATURES_H #include "lmmsconfig.h" diff --git a/include/Lv2UridCache.h b/include/Lv2UridCache.h index bae42d318..ab80760b0 100644 --- a/include/Lv2UridCache.h +++ b/include/Lv2UridCache.h @@ -22,8 +22,8 @@ * */ -#ifndef LV2URIDCACHE_H -#define LV2URIDCACHE_H +#ifndef LMMS_LV2_URID_CACHE_H +#define LMMS_LV2_URID_CACHE_H #include "lmmsconfig.h" @@ -74,4 +74,5 @@ template<> struct Lv2UridCache::IdForType { static constexpr auto } // namespace lmms #endif // LMMS_HAVE_LV2 -#endif // LV2URIDCACHE_H + +#endif diff --git a/include/Lv2UridMap.h b/include/Lv2UridMap.h index 9db9cb0c2..ec23f4c6d 100644 --- a/include/Lv2UridMap.h +++ b/include/Lv2UridMap.h @@ -22,8 +22,8 @@ * */ -#ifndef LV2URIDMAP_H -#define LV2URIDMAP_H +#ifndef LMMS_LV2_URID_MAP_H +#define LMMS_LV2_URID_MAP_H #include "lmmsconfig.h" @@ -75,4 +75,5 @@ public: } // namespace lmms #endif // LMMS_HAVE_LV2 -#endif // LV2URIDMAP_H + +#endif diff --git a/include/Lv2ViewBase.h b/include/Lv2ViewBase.h index 605440814..e84c6c5dc 100644 --- a/include/Lv2ViewBase.h +++ b/include/Lv2ViewBase.h @@ -22,15 +22,14 @@ * */ -#ifndef LV2VIEWBASE_H -#define LV2VIEWBASE_H +#ifndef LMMS_LV2_VIEW_BASE_H +#define LMMS_LV2_VIEW_BASE_H #include "lmmsconfig.h" #ifdef LMMS_HAVE_LV2 - #include "LinkedModelGroupViews.h" #include "lmms_export.h" #include "Lv2Basics.h" @@ -109,4 +108,5 @@ private: } // namespace lmms #endif // LMMS_HAVE_LV2 -#endif // LV2VIEWBASE_H + +#endif diff --git a/include/MainApplication.h b/include/MainApplication.h index 04bc82226..0ab2877e7 100644 --- a/include/MainApplication.h +++ b/include/MainApplication.h @@ -22,8 +22,8 @@ * */ -#ifndef MAINAPPLICATION_H -#define MAINAPPLICATION_H +#ifndef LMMS_GUI_MAIN_APPLICATION_H +#define LMMS_GUI_MAIN_APPLICATION_H #include "lmmsconfig.h" @@ -64,4 +64,4 @@ private: } // namespace lmms::gui -#endif // MAINAPPLICATION_H +#endif diff --git a/include/MainWindow.h b/include/MainWindow.h index e093d1082..78d7f48d8 100644 --- a/include/MainWindow.h +++ b/include/MainWindow.h @@ -22,8 +22,8 @@ * */ -#ifndef MAIN_WINDOW_H -#define MAIN_WINDOW_H +#ifndef LMMS_GUI_MAIN_WINDOW_H +#define LMMS_GUI_MAIN_WINDOW_H #include #include diff --git a/include/MemoryHelper.h b/include/MemoryHelper.h index 1def9d9c4..22ab10a6c 100644 --- a/include/MemoryHelper.h +++ b/include/MemoryHelper.h @@ -21,9 +21,8 @@ * */ - -#ifndef MEMORY_HELPER_H -#define MEMORY_HELPER_H +#ifndef LMMS_MEMORY_HELPER_H +#define LMMS_MEMORY_HELPER_H #include @@ -48,4 +47,3 @@ private: } // namespace lmms #endif - diff --git a/include/MemoryManager.h b/include/MemoryManager.h index d50ad173d..6e172468b 100644 --- a/include/MemoryManager.h +++ b/include/MemoryManager.h @@ -24,8 +24,8 @@ * */ -#ifndef MEMORY_MANAGER_H -#define MEMORY_MANAGER_H +#ifndef LMMS_MEMORY_MANAGER_H +#define LMMS_MEMORY_MANAGER_H #include #include diff --git a/include/MeterDialog.h b/include/MeterDialog.h index 67dca2568..425590807 100644 --- a/include/MeterDialog.h +++ b/include/MeterDialog.h @@ -23,8 +23,8 @@ * */ -#ifndef METER_DIALOG_H -#define METER_DIALOG_H +#ifndef LMMS_GUI_METER_DIALOG_H +#define LMMS_GUI_METER_DIALOG_H #include diff --git a/include/MeterModel.h b/include/MeterModel.h index c2e715b79..9a6ec8015 100644 --- a/include/MeterModel.h +++ b/include/MeterModel.h @@ -22,8 +22,8 @@ * */ -#ifndef METER_MODEL_H -#define METER_MODEL_H +#ifndef LMMS_METER_MODEL_H +#define LMMS_METER_MODEL_H #include "AutomatableModel.h" diff --git a/include/MicroTimer.h b/include/MicroTimer.h index ea74e964d..e5c8e2f61 100644 --- a/include/MicroTimer.h +++ b/include/MicroTimer.h @@ -22,8 +22,8 @@ * */ -#ifndef MICRO_TIMER_H -#define MICRO_TIMER_H +#ifndef LMMS_MICRO_TIMER_H +#define LMMS_MICRO_TIMER_H #include @@ -48,4 +48,4 @@ private: } // namespace lmms -#endif // MICRO_TIMER_H +#endif diff --git a/include/Microtuner.h b/include/Microtuner.h index dff8f5773..795748b39 100644 --- a/include/Microtuner.h +++ b/include/Microtuner.h @@ -22,8 +22,8 @@ * */ -#ifndef MICROTUNER_H -#define MICROTUNER_H +#ifndef LMMS_MICROTUNER_H +#define LMMS_MICROTUNER_H #include "AutomatableModel.h" #include "ComboBoxModel.h" diff --git a/include/MicrotunerConfig.h b/include/MicrotunerConfig.h index 690587dd5..3a5130b60 100644 --- a/include/MicrotunerConfig.h +++ b/include/MicrotunerConfig.h @@ -22,9 +22,8 @@ * */ -#ifndef MICROTUNER_CONFIG_H -#define MICROTUNER_CONFIG_H - +#ifndef LMMS_GUI_MICROTUNER_CONFIG_H +#define LMMS_GUI_MICROTUNER_CONFIG_H #include diff --git a/include/Midi.h b/include/Midi.h index f75254d84..839d0b684 100644 --- a/include/Midi.h +++ b/include/Midi.h @@ -22,8 +22,8 @@ * */ -#ifndef MIDI_H -#define MIDI_H +#ifndef LMMS_MIDI_H +#define LMMS_MIDI_H #include "lmms_basics.h" diff --git a/include/MidiAlsaRaw.h b/include/MidiAlsaRaw.h index 57a477264..a2b8c4e69 100644 --- a/include/MidiAlsaRaw.h +++ b/include/MidiAlsaRaw.h @@ -22,8 +22,8 @@ * */ -#ifndef MIDI_ALSA_RAW_H -#define MIDI_ALSA_RAW_H +#ifndef LMMS_MIDI_ALSA_RAW_H +#define LMMS_MIDI_ALSA_RAW_H #include "lmmsconfig.h" diff --git a/include/MidiAlsaSeq.h b/include/MidiAlsaSeq.h index fa287a409..d6f488c82 100644 --- a/include/MidiAlsaSeq.h +++ b/include/MidiAlsaSeq.h @@ -22,8 +22,8 @@ * */ -#ifndef MIDI_ALSA_SEQ_H -#define MIDI_ALSA_SEQ_H +#ifndef LMMS_MIDI_ALSA_SEQ_H +#define LMMS_MIDI_ALSA_SEQ_H #include "lmmsconfig.h" @@ -159,4 +159,3 @@ signals: #endif // LMMS_HAVE_ALSA #endif - diff --git a/include/MidiApple.h b/include/MidiApple.h index 794641e64..1b0d59218 100644 --- a/include/MidiApple.h +++ b/include/MidiApple.h @@ -23,8 +23,8 @@ * */ -#ifndef MIDI_APPLE_H -#define MIDI_APPLE_H +#ifndef LMMS_MIDI_APPLE_H +#define LMMS_MIDI_APPLE_H #include "lmmsconfig.h" @@ -155,5 +155,4 @@ signals: #endif // LMMS_BUILD_APPLE - #endif diff --git a/include/MidiCCRackView.h b/include/MidiCCRackView.h index 59f1de020..98f5ce183 100644 --- a/include/MidiCCRackView.h +++ b/include/MidiCCRackView.h @@ -1,5 +1,5 @@ -#ifndef MIDI_CC_RACK_VIEW_H -#define MIDI_CC_RACK_VIEW_H +#ifndef LMMS_GUI_MIDI_CC_RACK_VIEW_H +#define LMMS_GUI_MIDI_CC_RACK_VIEW_H #include diff --git a/include/MidiClient.h b/include/MidiClient.h index 954cd5ef5..45ba54ee5 100644 --- a/include/MidiClient.h +++ b/include/MidiClient.h @@ -22,8 +22,8 @@ * */ -#ifndef MIDI_CLIENT_H -#define MIDI_CLIENT_H +#ifndef LMMS_MIDI_CLIENT_H +#define LMMS_MIDI_CLIENT_H #include #include @@ -174,4 +174,3 @@ private: } // namespace lmms #endif - diff --git a/include/MidiClip.h b/include/MidiClip.h index 6433ba507..2dbedc0dd 100644 --- a/include/MidiClip.h +++ b/include/MidiClip.h @@ -23,9 +23,8 @@ * */ -#ifndef MIDI_CLIP_H -#define MIDI_CLIP_H - +#ifndef LMMS_MIDI_CLIP_H +#define LMMS_MIDI_CLIP_H #include "Clip.h" #include "Note.h" diff --git a/include/MidiClipView.h b/include/MidiClipView.h index 1a9809733..dd83f98b8 100644 --- a/include/MidiClipView.h +++ b/include/MidiClipView.h @@ -21,10 +21,10 @@ * Boston, MA 02110-1301 USA. * */ - -#ifndef MIDI_CLIP_VIEW_H -#define MIDI_CLIP_VIEW_H - + +#ifndef LMMS_GUI_MIDI_CLIP_VIEW_H +#define LMMS_GUI_MIDI_CLIP_VIEW_H + #include #include "ClipView.h" @@ -43,7 +43,7 @@ class MidiClipView : public ClipView public: MidiClipView( MidiClip* clip, TrackView* parent ); - ~MidiClipView() override = default; + ~MidiClipView() override = default; Q_PROPERTY(QColor noteFillColor READ getNoteFillColor WRITE setNoteFillColor) Q_PROPERTY(QColor noteBorderColor READ getNoteBorderColor WRITE setNoteBorderColor) @@ -107,5 +107,5 @@ private: } // namespace gui } // namespace lmms - - #endif + +#endif diff --git a/include/MidiController.h b/include/MidiController.h index 500acc5f8..19577281f 100644 --- a/include/MidiController.h +++ b/include/MidiController.h @@ -22,8 +22,8 @@ * */ -#ifndef MIDI_CONTROLLER_H -#define MIDI_CONTROLLER_H +#ifndef LMMS_MIDI_CONTROLLER_H +#define LMMS_MIDI_CONTROLLER_H #include diff --git a/include/MidiDummy.h b/include/MidiDummy.h index 67a91e326..03deaf7bc 100644 --- a/include/MidiDummy.h +++ b/include/MidiDummy.h @@ -22,8 +22,8 @@ * */ -#ifndef MIDI_DUMMY_H -#define MIDI_DUMMY_H +#ifndef LMMS_MIDI_DUMMY_H +#define LMMS_MIDI_DUMMY_H #include "MidiClient.h" diff --git a/include/MidiEvent.h b/include/MidiEvent.h index 6c2bfdd55..03d3be604 100644 --- a/include/MidiEvent.h +++ b/include/MidiEvent.h @@ -22,8 +22,8 @@ * */ -#ifndef MIDI_EVENT_H -#define MIDI_EVENT_H +#ifndef LMMS_MIDI_EVENT_H +#define LMMS_MIDI_EVENT_H #include #include "Midi.h" diff --git a/include/MidiEventProcessor.h b/include/MidiEventProcessor.h index 132a5fc42..3e51d1177 100644 --- a/include/MidiEventProcessor.h +++ b/include/MidiEventProcessor.h @@ -22,8 +22,8 @@ * */ -#ifndef MIDI_EVENT_PROCESSOR_H -#define MIDI_EVENT_PROCESSOR_H +#ifndef LMMS_MIDI_EVENT_PROCESSOR_H +#define LMMS_MIDI_EVENT_PROCESSOR_H #include "MidiEvent.h" #include "MemoryManager.h" diff --git a/include/MidiEventToByteSeq.h b/include/MidiEventToByteSeq.h index f2e36f50a..03308d7b8 100644 --- a/include/MidiEventToByteSeq.h +++ b/include/MidiEventToByteSeq.h @@ -22,8 +22,8 @@ * */ -#ifndef MIDIEVENTTOBYTESEQ_H -#define MIDIEVENTTOBYTESEQ_H +#ifndef LMMS_MIDIEVENTTOBYTESEQ_H +#define LMMS_MIDIEVENTTOBYTESEQ_H #include #include @@ -51,4 +51,4 @@ std::size_t LMMS_EXPORT writeToByteSeq( const class MidiEvent& ev, } // namespace lmms -#endif // MIDIEVENTTOBYTESEQ_H +#endif diff --git a/include/MidiJack.h b/include/MidiJack.h index a4a944b81..265abedfc 100644 --- a/include/MidiJack.h +++ b/include/MidiJack.h @@ -22,8 +22,8 @@ * */ -#ifndef MIDIJACK_H -#define MIDIJACK_H +#ifndef LMMS_MIDI_JACK_H +#define LMMS_MIDI_JACK_H #include "lmmsconfig.h" @@ -102,4 +102,4 @@ private: #endif // LMMS_HAVE_JACK -#endif // MIDIJACK_H +#endif diff --git a/include/MidiOss.h b/include/MidiOss.h index 944359055..dba0a9a71 100644 --- a/include/MidiOss.h +++ b/include/MidiOss.h @@ -22,8 +22,8 @@ * */ -#ifndef MIDI_OSS_H -#define MIDI_OSS_H +#ifndef LMMS_MIDI_OSS_H +#define LMMS_MIDI_OSS_H #include "lmmsconfig.h" @@ -78,5 +78,4 @@ private: #endif // LMMS_HAVE_OSS - #endif diff --git a/include/MidiPort.h b/include/MidiPort.h index 7ef9adf90..a03b8477c 100644 --- a/include/MidiPort.h +++ b/include/MidiPort.h @@ -23,8 +23,8 @@ * */ -#ifndef MIDI_PORT_H -#define MIDI_PORT_H +#ifndef LMMS_MIDI_PORT_H +#define LMMS_MIDI_PORT_H #include #include diff --git a/include/MidiPortMenu.h b/include/MidiPortMenu.h index 215a73d06..88328e734 100644 --- a/include/MidiPortMenu.h +++ b/include/MidiPortMenu.h @@ -23,8 +23,8 @@ * */ -#ifndef MIDI_PORT_MENU_H -#define MIDI_PORT_MENU_H +#ifndef LMMS_GUI_MIDI_PORT_MENU_H +#define LMMS_GUI_MIDI_PORT_MENU_H #include diff --git a/include/MidiSetupWidget.h b/include/MidiSetupWidget.h index 4021db142..492a5bb85 100644 --- a/include/MidiSetupWidget.h +++ b/include/MidiSetupWidget.h @@ -22,9 +22,8 @@ * */ -#ifndef MIDISETUPWIDGET_H -#define MIDISETUPWIDGET_H - +#ifndef LMMS_GUI_MIDI_SETUP_WIDGET_H +#define LMMS_GUI_MIDI_SETUP_WIDGET_H #include "TabWidget.h" diff --git a/include/MidiSndio.h b/include/MidiSndio.h index 3ebd14d05..3d7226431 100644 --- a/include/MidiSndio.h +++ b/include/MidiSndio.h @@ -23,8 +23,8 @@ * */ -#ifndef _MIDI_SNDIO_H -#define _MIDI_SNDIO_H +#ifndef LMMS_MIDI_SNDIO_H +#define LMMS_MIDI_SNDIO_H #include "lmmsconfig.h" @@ -75,4 +75,4 @@ private: #endif // LMMS_HAVE_SNDIO -#endif // _MIDI_SNDIO_H +#endif diff --git a/include/MidiWinMM.h b/include/MidiWinMM.h index 0f2bd0d5f..ca1850347 100644 --- a/include/MidiWinMM.h +++ b/include/MidiWinMM.h @@ -22,8 +22,8 @@ * */ -#ifndef MIDI_WINMM_H -#define MIDI_WINMM_H +#ifndef LMMS_MIDI_WINMM_H +#define LMMS_MIDI_WINMM_H #include "lmmsconfig.h" @@ -151,4 +151,3 @@ signals: #endif // LMMS_BUILD_WIN32 #endif - diff --git a/include/MixHelpers.h b/include/MixHelpers.h index 6599b40ec..76242dd7a 100644 --- a/include/MixHelpers.h +++ b/include/MixHelpers.h @@ -22,8 +22,8 @@ * */ -#ifndef MIX_HELPERS_H -#define MIX_HELPERS_H +#ifndef LMMS_MIX_HELPERS_H +#define LMMS_MIX_HELPERS_H #include "lmms_basics.h" @@ -82,4 +82,3 @@ void multiplyAndAddMultipliedJoined( sampleFrame* dst, const sample_t* srcLeft, } // namespace lmms #endif - diff --git a/include/Mixer.h b/include/Mixer.h index ecd864ae7..d49d950ea 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -22,8 +22,8 @@ * */ -#ifndef MIXER_H -#define MIXER_H +#ifndef LMMS_MIXER_H +#define LMMS_MIXER_H #include "Model.h" #include "EffectChain.h" @@ -100,37 +100,37 @@ class MixerChannel : public ThreadableJob class MixerRoute : public QObject { Q_OBJECT - public: - MixerRoute( MixerChannel * from, MixerChannel * to, float amount ); - ~MixerRoute() override = default; - +public: + MixerRoute( MixerChannel * from, MixerChannel * to, float amount ); + ~MixerRoute() override = default; + mix_ch_t senderIndex() const { return m_from->m_channelIndex; } - + mix_ch_t receiverIndex() const { return m_to->m_channelIndex; } - + FloatModel * amount() { return &m_amount; } - + MixerChannel * sender() const { return m_from; } - + MixerChannel * receiver() const { return m_to; } - + void updateName(); - + private: MixerChannel * m_from; MixerChannel * m_to; diff --git a/include/MixerLine.h b/include/MixerLine.h index decd5f3aa..0121717cf 100644 --- a/include/MixerLine.h +++ b/include/MixerLine.h @@ -23,8 +23,8 @@ * */ -#ifndef MIXERLINE_H -#define MIXERLINE_H +#ifndef LMMS_GUI_MIXER_LINE_H +#define LMMS_GUI_MIXER_LINE_H #include @@ -117,4 +117,4 @@ private slots: } // namespace lmms::gui -#endif // MIXERLINE_H +#endif diff --git a/include/MixerLineLcdSpinBox.h b/include/MixerLineLcdSpinBox.h index bfd6cd5c9..0d3b182b0 100644 --- a/include/MixerLineLcdSpinBox.h +++ b/include/MixerLineLcdSpinBox.h @@ -22,8 +22,8 @@ * */ -#ifndef MIXER_LINE_LCD_SPIN_BOX_H -#define MIXER_LINE_LCD_SPIN_BOX_H +#ifndef LMMS_GUI_MIXER_LINE_LCD_SPIN_BOX_H +#define LMMS_GUI_MIXER_LINE_LCD_SPIN_BOX_H #include "LcdSpinBox.h" diff --git a/include/MixerView.h b/include/MixerView.h index a7b1b5191..e73e2e391 100644 --- a/include/MixerView.h +++ b/include/MixerView.h @@ -22,8 +22,8 @@ * */ -#ifndef MIXER_VIEW_H -#define MIXER_VIEW_H +#ifndef LMMS_GUI_MIXER_VIEW_H +#define LMMS_GUI_MIXER_VIEW_H #include #include @@ -132,7 +132,7 @@ private: QWidget * m_racksWidget; void updateMaxChannelSelector(); - + friend class MixerChannelView; } ; diff --git a/include/Model.h b/include/Model.h index 567d4ffd7..0b8142659 100644 --- a/include/Model.h +++ b/include/Model.h @@ -22,8 +22,8 @@ * */ -#ifndef MODEL_H -#define MODEL_H +#ifndef LMMS_MODEL_H +#define LMMS_MODEL_H #include #include @@ -91,4 +91,3 @@ signals: } // namespace lmms #endif - diff --git a/include/ModelView.h b/include/ModelView.h index a858dc7ec..89e60c3a6 100644 --- a/include/ModelView.h +++ b/include/ModelView.h @@ -22,8 +22,8 @@ * */ -#ifndef MODEL_VIEW_H -#define MODEL_VIEW_H +#ifndef LMMS_GUI_MODEL_VIEW_H +#define LMMS_GUI_MODEL_VIEW_H #include #include "Model.h" @@ -86,4 +86,3 @@ private: } // namespace lmms::gui #endif - diff --git a/include/ModelVisitor.h b/include/ModelVisitor.h index 8805e30e2..59928d04b 100644 --- a/include/ModelVisitor.h +++ b/include/ModelVisitor.h @@ -22,8 +22,8 @@ * */ -#ifndef MODELVISITOR_H -#define MODELVISITOR_H +#ifndef LMMS_MODEL_VISITOR_H +#define LMMS_MODEL_VISITOR_H namespace lmms { @@ -68,4 +68,4 @@ public: } // namespace lmms -#endif // MODELVISITOR_H +#endif diff --git a/include/NStateButton.h b/include/NStateButton.h index 4dac1a436..dd1c06a66 100644 --- a/include/NStateButton.h +++ b/include/NStateButton.h @@ -22,9 +22,8 @@ * */ - -#ifndef NSTATE_BUTTON_H -#define NSTATE_BUTTON_H +#ifndef LMMS_GUI_NSTATE_BUTTON_H +#define LMMS_GUI_NSTATE_BUTTON_H #include #include diff --git a/include/Note.h b/include/Note.h index 464f3906f..9eecd585f 100644 --- a/include/Note.h +++ b/include/Note.h @@ -23,8 +23,8 @@ * */ -#ifndef NOTE_H -#define NOTE_H +#ifndef LMMS_NOTE_H +#define LMMS_NOTE_H #include #include diff --git a/include/NotePlayHandle.h b/include/NotePlayHandle.h index 4969fd84a..89fc7e570 100644 --- a/include/NotePlayHandle.h +++ b/include/NotePlayHandle.h @@ -23,8 +23,8 @@ * */ -#ifndef NOTE_PLAY_HANDLE_H -#define NOTE_PLAY_HANDLE_H +#ifndef LMMS_NOTE_PLAY_HANDLE_H +#define LMMS_NOTE_PLAY_HANDLE_H #include diff --git a/include/Oscillator.h b/include/Oscillator.h index 8727ee39c..025404c41 100644 --- a/include/Oscillator.h +++ b/include/Oscillator.h @@ -23,8 +23,8 @@ * */ -#ifndef OSCILLATOR_H -#define OSCILLATOR_H +#ifndef LMMS_OSCILLATOR_H +#define LMMS_OSCILLATOR_H #include #include diff --git a/include/OscillatorConstants.h b/include/OscillatorConstants.h index 0450c2f17..ef12636d4 100644 --- a/include/OscillatorConstants.h +++ b/include/OscillatorConstants.h @@ -1,5 +1,5 @@ /* - * OscillatorConstants.h - declaration of constants used in Oscillator and SampleBuffer + * OscillatorConstants.h - declaration of constants used in Oscillator and SampleBuffer * for band limited wave tables * * Copyright (c) 2018 Dave French @@ -23,8 +23,8 @@ * */ -#ifndef OSCILLATORCONSTANTS_H -#define OSCILLATORCONSTANTS_H +#ifndef LMMS_OSCILLATORCONSTANTS_H +#define LMMS_OSCILLATORCONSTANTS_H #include @@ -55,4 +55,4 @@ namespace lmms::OscillatorConstants } // namespace lmms::OscillatorConstants -#endif // OSCILLATORCONSTANTS_H +#endif diff --git a/include/Oscilloscope.h b/include/Oscilloscope.h index db4cf2b4a..c7a52cef9 100644 --- a/include/Oscilloscope.h +++ b/include/Oscilloscope.h @@ -22,9 +22,8 @@ * */ - -#ifndef OSCILLOSCOPE_H -#define OSCILLOSCOPE_H +#ifndef LMMS_GUI_OSCILLOSCOPE_H +#define LMMS_GUI_OSCILLOSCOPE_H #include #include @@ -79,4 +78,4 @@ private: } // namespace lmms::gui -#endif // OSCILLOSCOPE_H +#endif diff --git a/include/OutputSettings.h b/include/OutputSettings.h index 03e3333ac..0b10d2b01 100644 --- a/include/OutputSettings.h +++ b/include/OutputSettings.h @@ -23,12 +23,11 @@ * */ -#ifndef OUTPUT_SETTINGS_H -#define OUTPUT_SETTINGS_H +#ifndef LMMS_OUTPUT_SETTINGS_H +#define LMMS_OUTPUT_SETTINGS_H #include "lmms_basics.h" - namespace lmms { diff --git a/include/PathUtil.h b/include/PathUtil.h index 8b1ef1097..9efd73096 100644 --- a/include/PathUtil.h +++ b/include/PathUtil.h @@ -22,8 +22,8 @@ * */ -#ifndef PATHUTIL_H -#define PATHUTIL_H +#ifndef LMMS_PATHUTIL_H +#define LMMS_PATHUTIL_H #include "lmms_export.h" diff --git a/include/PatternClip.h b/include/PatternClip.h index f1d0e2557..3f9d07cb6 100644 --- a/include/PatternClip.h +++ b/include/PatternClip.h @@ -21,10 +21,9 @@ * Boston, MA 02110-1301 USA. * */ - -#ifndef PATTERN_CLIP_H -#define PATTERN_CLIP_H +#ifndef LMMS_PATTERN_CLIP_H +#define LMMS_PATTERN_CLIP_H #include "Clip.h" diff --git a/include/PatternClipView.h b/include/PatternClipView.h index d170e4bef..f2e2208bd 100644 --- a/include/PatternClipView.h +++ b/include/PatternClipView.h @@ -21,11 +21,9 @@ * Boston, MA 02110-1301 USA. * */ - - -#ifndef PATTERN_CLIP_VIEW_H -#define PATTERN_CLIP_VIEW_H +#ifndef LMMS_GUI_PATTERN_CLIP_VIEW_H +#define LMMS_GUI_PATTERN_CLIP_VIEW_H #include diff --git a/include/PatternEditor.h b/include/PatternEditor.h index ffe08e335..fd9a1b254 100644 --- a/include/PatternEditor.h +++ b/include/PatternEditor.h @@ -22,10 +22,8 @@ * */ - -#ifndef PATTERN_EDITOR_H -#define PATTERN_EDITOR_H - +#ifndef LMMS_GUI_PATTERN_EDITOR_H +#define LMMS_GUI_PATTERN_EDITOR_H #include "Editor.h" #include "TrackContainerView.h" diff --git a/include/PatternStore.h b/include/PatternStore.h index 7bd377941..024505b83 100644 --- a/include/PatternStore.h +++ b/include/PatternStore.h @@ -22,9 +22,8 @@ * */ - -#ifndef PATTERN_STORE_H -#define PATTERN_STORE_H +#ifndef LMMS_PATTERN_STORE_H +#define LMMS_PATTERN_STORE_H #include "TrackContainer.h" #include "ComboBoxModel.h" diff --git a/include/PatternTrack.h b/include/PatternTrack.h index 73ddd4766..8e319216a 100644 --- a/include/PatternTrack.h +++ b/include/PatternTrack.h @@ -22,10 +22,8 @@ * */ - -#ifndef PATTERN_TRACK_H -#define PATTERN_TRACK_H - +#ifndef LMMS_PATTERN_TRACK_H +#define LMMS_PATTERN_TRACK_H #include diff --git a/include/PatternTrackView.h b/include/PatternTrackView.h index b6d33e444..b4d373b5d 100644 --- a/include/PatternTrackView.h +++ b/include/PatternTrackView.h @@ -22,10 +22,8 @@ * */ - -#ifndef PATTERN_TRACK_VIEW_H -#define PATTERN_TRACK_VIEW_H - +#ifndef LMMS_GUI_PATTERN_TRACK_VIEW_H +#define LMMS_GUI_PATTERN_TRACK_VIEW_H #include "TrackView.h" diff --git a/include/PeakController.h b/include/PeakController.h index 58d666dd0..ebdf49cb0 100644 --- a/include/PeakController.h +++ b/include/PeakController.h @@ -22,8 +22,8 @@ * */ -#ifndef PEAK_CONTROLLER_H -#define PEAK_CONTROLLER_H +#ifndef LMMS_PEAK_CONTROLLER_H +#define LMMS_PEAK_CONTROLLER_H #include "Controller.h" #include "ControllerDialog.h" diff --git a/include/PerfLog.h b/include/PerfLog.h index b8cc35f45..f786de1cc 100644 --- a/include/PerfLog.h +++ b/include/PerfLog.h @@ -22,8 +22,8 @@ * */ -#ifndef PERFLOG_H -#define PERFLOG_H +#ifndef LMMS_PERFLOG_H +#define LMMS_PERFLOG_H #include #include diff --git a/include/Piano.h b/include/Piano.h index 531bb65a6..e22710bba 100644 --- a/include/Piano.h +++ b/include/Piano.h @@ -22,8 +22,8 @@ * */ -#ifndef PIANO_H -#define PIANO_H +#ifndef LMMS_PIANO_H +#define LMMS_PIANO_H #include "Note.h" #include "Model.h" @@ -90,4 +90,3 @@ private: } // namespace lmms #endif - diff --git a/include/PianoRoll.h b/include/PianoRoll.h index c1973f407..5013e3e1b 100644 --- a/include/PianoRoll.h +++ b/include/PianoRoll.h @@ -24,8 +24,8 @@ * */ -#ifndef PIANO_ROLL_H -#define PIANO_ROLL_H +#ifndef LMMS_GUI_PIANO_ROLL_H +#define LMMS_GUI_PIANO_ROLL_H #include #include diff --git a/include/PianoView.h b/include/PianoView.h index 7f586809d..1d5cd4be4 100644 --- a/include/PianoView.h +++ b/include/PianoView.h @@ -22,8 +22,8 @@ * */ -#ifndef PIANO_VIEW_H -#define PIANO_VIEW_H +#ifndef LMMS_GUI_PIANO_VIEW_H +#define LMMS_GUI_PIANO_VIEW_H #include #include diff --git a/include/Pitch.h b/include/Pitch.h index 6213ef374..537941700 100644 --- a/include/Pitch.h +++ b/include/Pitch.h @@ -22,8 +22,8 @@ * */ -#ifndef PITCH_H -#define PITCH_H +#ifndef LMMS_PITCH_H +#define LMMS_PITCH_H #include diff --git a/include/PixmapButton.h b/include/PixmapButton.h index 6c37f9112..b9568e5ad 100644 --- a/include/PixmapButton.h +++ b/include/PixmapButton.h @@ -22,9 +22,8 @@ * */ - -#ifndef PIXMAP_BUTTON_H -#define PIXMAP_BUTTON_H +#ifndef LMMS_GUI_PIXMAP_BUTTON_H +#define LMMS_GUI_PIXMAP_BUTTON_H #include diff --git a/include/PlayHandle.h b/include/PlayHandle.h index 542d45871..005ef17a0 100644 --- a/include/PlayHandle.h +++ b/include/PlayHandle.h @@ -22,8 +22,8 @@ * */ -#ifndef PLAY_HANDLE_H -#define PLAY_HANDLE_H +#ifndef LMMS_PLAY_HANDLE_H +#define LMMS_PLAY_HANDLE_H #include #include diff --git a/include/Plugin.h b/include/Plugin.h index 6a4d95bb4..0a7b68a55 100644 --- a/include/Plugin.h +++ b/include/Plugin.h @@ -22,8 +22,8 @@ * */ -#ifndef PLUGIN_H -#define PLUGIN_H +#ifndef LMMS_PLUGIN_H +#define LMMS_PLUGIN_H #include #include diff --git a/include/PluginBrowser.h b/include/PluginBrowser.h index 1f2041cf4..262732398 100644 --- a/include/PluginBrowser.h +++ b/include/PluginBrowser.h @@ -22,8 +22,8 @@ * */ -#ifndef PLUGIN_BROWSER_H -#define PLUGIN_BROWSER_H +#ifndef LMMS_GUI_PLUGIN_BROWSER_H +#define LMMS_GUI_PLUGIN_BROWSER_H #include @@ -56,8 +56,6 @@ private: }; - - class PluginDescWidget : public QWidget { Q_OBJECT diff --git a/include/PluginFactory.h b/include/PluginFactory.h index 8b8b88b6e..8ea020073 100644 --- a/include/PluginFactory.h +++ b/include/PluginFactory.h @@ -22,8 +22,8 @@ * */ -#ifndef PLUGINFACTORY_H -#define PLUGINFACTORY_H +#ifndef LMMS_PLUGIN_FACTORY_H +#define LMMS_PLUGIN_FACTORY_H #include #include @@ -111,4 +111,4 @@ LMMS_EXPORT PluginFactory* getPluginFactory(); } // namespace lmms -#endif // PLUGINFACTORY_H +#endif diff --git a/include/PluginIssue.h b/include/PluginIssue.h index f0fa275f3..c3f3e5dbe 100644 --- a/include/PluginIssue.h +++ b/include/PluginIssue.h @@ -22,13 +22,12 @@ * */ -#ifndef PLUGINISSUE_H -#define PLUGINISSUE_H +#ifndef LMMS_PLUGIN_ISSUE_H +#define LMMS_PLUGIN_ISSUE_H #include #include - namespace lmms { @@ -86,4 +85,4 @@ QDebug operator<<(QDebug stream, const PluginIssue& iss); } // namespace lmms -#endif // PLUGINISSUE_H +#endif diff --git a/include/PluginView.h b/include/PluginView.h index 2c06b9ba2..75576a8c8 100644 --- a/include/PluginView.h +++ b/include/PluginView.h @@ -22,8 +22,8 @@ * */ -#ifndef PLUGIN_VIEW_H -#define PLUGIN_VIEW_H +#ifndef LMMS_GUI_PLUGIN_VIEW_H +#define LMMS_GUI_PLUGIN_VIEW_H #include diff --git a/include/PositionLine.h b/include/PositionLine.h index cc1313e57..8c1d7d60a 100644 --- a/include/PositionLine.h +++ b/include/PositionLine.h @@ -23,8 +23,8 @@ * */ -#ifndef POSITION_LINE_H -#define POSITION_LINE_H +#ifndef LMMS_GUI_POSITION_LINE_H +#define LMMS_GUI_POSITION_LINE_H #include diff --git a/include/PresetPreviewPlayHandle.h b/include/PresetPreviewPlayHandle.h index dfff0fc21..e37e976e0 100644 --- a/include/PresetPreviewPlayHandle.h +++ b/include/PresetPreviewPlayHandle.h @@ -23,8 +23,8 @@ * */ -#ifndef PRESET_PREVIEW_PLAY_HANDLE_H -#define PRESET_PREVIEW_PLAY_HANDLE_H +#ifndef LMMS_PRESET_PREVIEW_PLAY_HANDLE_H +#define LMMS_PRESET_PREVIEW_PLAY_HANDLE_H #include "NotePlayHandle.h" diff --git a/include/ProjectJournal.h b/include/ProjectJournal.h index 31a61755d..655d64a17 100644 --- a/include/ProjectJournal.h +++ b/include/ProjectJournal.h @@ -22,8 +22,8 @@ * */ -#ifndef PROJECT_JOURNAL_H -#define PROJECT_JOURNAL_H +#ifndef LMMS_PROJECT_JOURNAL_H +#define LMMS_PROJECT_JOURNAL_H #include #include @@ -127,4 +127,3 @@ private: } // namespace lmms #endif - diff --git a/include/ProjectNotes.h b/include/ProjectNotes.h index 4b9476616..51577f0b2 100644 --- a/include/ProjectNotes.h +++ b/include/ProjectNotes.h @@ -22,9 +22,8 @@ * */ - -#ifndef PROJECT_NOTES_H -#define PROJECT_NOTES_H +#ifndef LMMS_GUI_PROJECT_NOTES_H +#define LMMS_GUI_PROJECT_NOTES_H #include diff --git a/include/ProjectRenderer.h b/include/ProjectRenderer.h index 2ca20569b..d9309d3db 100644 --- a/include/ProjectRenderer.h +++ b/include/ProjectRenderer.h @@ -22,8 +22,8 @@ * */ -#ifndef PROJECT_RENDERER_H -#define PROJECT_RENDERER_H +#ifndef LMMS_PROJECT_RENDERER_H +#define LMMS_PROJECT_RENDERER_H #include "AudioFileDevice.h" #include "lmmsconfig.h" diff --git a/include/ProjectVersion.h b/include/ProjectVersion.h index 5be259c97..5401e7126 100644 --- a/include/ProjectVersion.h +++ b/include/ProjectVersion.h @@ -23,9 +23,8 @@ * */ - -#ifndef PROJECT_VERSION_H -#define PROJECT_VERSION_H +#ifndef LMMS_PROJECT_VERSION_H +#define LMMS_PROJECT_VERSION_H #include #include diff --git a/include/QuadratureLfo.h b/include/QuadratureLfo.h index 42d4d32c0..59ff81ba7 100644 --- a/include/QuadratureLfo.h +++ b/include/QuadratureLfo.h @@ -22,8 +22,8 @@ * */ -#ifndef QUADRATURELFO_H -#define QUADRATURELFO_H +#ifndef LMMS_QUADRATURE_LFO_H +#define LMMS_QUADRATURE_LFO_H #include "lmms_math.h" @@ -100,4 +100,4 @@ private: } // namespace lmms -#endif // QUADRATURELFO_H +#endif diff --git a/include/RaiiHelpers.h b/include/RaiiHelpers.h index 0cfa2c4ac..827cc955d 100644 --- a/include/RaiiHelpers.h +++ b/include/RaiiHelpers.h @@ -19,10 +19,11 @@ * 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 RAII_HELPERS_H -#define RAII_HELPERS_H +#ifndef LMMS_RAII_HELPERS_H +#define LMMS_RAII_HELPERS_H #include #include @@ -63,4 +64,4 @@ using UniqueNullableResource = std::unique_ptr @@ -45,4 +45,4 @@ private slots: } // namespace lmms::gui -#endif // RECENTPROJECTSMENU_H +#endif diff --git a/include/RemotePlugin.h b/include/RemotePlugin.h index 96c910d5d..af15d7d14 100644 --- a/include/RemotePlugin.h +++ b/include/RemotePlugin.h @@ -22,8 +22,8 @@ * */ -#ifndef REMOTE_PLUGIN_H -#define REMOTE_PLUGIN_H +#ifndef LMMS_REMOTE_PLUGIN_H +#define LMMS_REMOTE_PLUGIN_H #include "RemotePluginBase.h" #include "SharedMemory.h" @@ -197,4 +197,4 @@ LMMS_EXPORT inline std::string QSTR_TO_STDSTR(QString const& qstr) } // namespace lmms -#endif // REMOTE_PLUGIN_H +#endif diff --git a/include/RemotePluginBase.h b/include/RemotePluginBase.h index e309496bc..2c5e5054e 100644 --- a/include/RemotePluginBase.h +++ b/include/RemotePluginBase.h @@ -22,8 +22,8 @@ * */ -#ifndef REMOTE_PLUGIN_BASE_H -#define REMOTE_PLUGIN_BASE_H +#ifndef LMMS_REMOTE_PLUGIN_BASE_H +#define LMMS_REMOTE_PLUGIN_BASE_H #include "MidiEvent.h" @@ -673,4 +673,4 @@ private: } // namespace lmms -#endif // REMOTE_PLUGIN_BASE_H +#endif diff --git a/include/RemotePluginClient.h b/include/RemotePluginClient.h index 4c5fcc060..38c311129 100644 --- a/include/RemotePluginClient.h +++ b/include/RemotePluginClient.h @@ -22,8 +22,8 @@ * */ -#ifndef REMOTE_PLUGIN_CLIENT_H -#define REMOTE_PLUGIN_CLIENT_H +#ifndef LMMS_REMOTE_PLUGIN_CLIENT_H +#define LMMS_REMOTE_PLUGIN_CLIENT_H #include "RemotePluginBase.h" @@ -355,4 +355,4 @@ void RemotePluginClient::doProcessing() } // namespace lmms -#endif // REMOTE_PLUGIN_CLIENT_H +#endif diff --git a/include/RenameDialog.h b/include/RenameDialog.h index b543963d7..e7e5b662f 100644 --- a/include/RenameDialog.h +++ b/include/RenameDialog.h @@ -23,13 +23,11 @@ * */ - -#ifndef RENAME_DIALOG_H -#define RENAME_DIALOG_H +#ifndef LMMS_GUI_RENAME_DIALOG_H +#define LMMS_GUI_RENAME_DIALOG_H #include - class QLineEdit; namespace lmms::gui diff --git a/include/RenderManager.h b/include/RenderManager.h index 9ec4c511e..0787db6d7 100644 --- a/include/RenderManager.h +++ b/include/RenderManager.h @@ -23,8 +23,8 @@ * */ -#ifndef RENDER_MANAGER_H -#define RENDER_MANAGER_H +#ifndef LMMS_RENDER_MANAGER_H +#define LMMS_RENDER_MANAGER_H #include diff --git a/include/RingBuffer.h b/include/RingBuffer.h index c7db6b4e5..17f06fc00 100644 --- a/include/RingBuffer.h +++ b/include/RingBuffer.h @@ -23,9 +23,8 @@ * */ - -#ifndef RINGBUFFER_H -#define RINGBUFFER_H +#ifndef LMMS_RING_BUFFER_H +#define LMMS_RING_BUFFER_H #include #include diff --git a/include/RmsHelper.h b/include/RmsHelper.h index 19b7da89c..1d739ee0b 100644 --- a/include/RmsHelper.h +++ b/include/RmsHelper.h @@ -23,8 +23,8 @@ * */ -#ifndef RMS_HELPER_H -#define RMS_HELPER_H +#ifndef LMMS_RMS_HELPER_H +#define LMMS_RMS_HELPER_H #include "lmms_math.h" diff --git a/include/RowTableView.h b/include/RowTableView.h index 9934dbade..04272026e 100644 --- a/include/RowTableView.h +++ b/include/RowTableView.h @@ -22,8 +22,8 @@ * */ -#ifndef ROW_TABLE_VIEW_H -#define ROW_TABLE_VIEW_H +#ifndef LMMS_GUI_ROW_TABLE_VIEW_H +#define LMMS_GUI_ROW_TABLE_VIEW_H #include diff --git a/include/Rubberband.h b/include/Rubberband.h index d35233b4f..4805d1d31 100644 --- a/include/Rubberband.h +++ b/include/Rubberband.h @@ -23,9 +23,8 @@ * */ - -#ifndef RUBBERBAND_H -#define RUBBERBAND_H +#ifndef LMMS_GUI_RUBBERBAND_H +#define LMMS_GUI_RUBBERBAND_H #include #include @@ -95,4 +94,3 @@ private: } // namespace lmms::gui #endif - diff --git a/include/SampleBuffer.h b/include/SampleBuffer.h index f4d67859e..3fac28168 100644 --- a/include/SampleBuffer.h +++ b/include/SampleBuffer.h @@ -22,9 +22,8 @@ * */ - -#ifndef SAMPLE_BUFFER_H -#define SAMPLE_BUFFER_H +#ifndef LMMS_SAMPLE_BUFFER_H +#define LMMS_SAMPLE_BUFFER_H #include #include diff --git a/include/SampleClip.h b/include/SampleClip.h index 51225ded8..427a2bf8b 100644 --- a/include/SampleClip.h +++ b/include/SampleClip.h @@ -21,9 +21,9 @@ * Boston, MA 02110-1301 USA. * */ - -#ifndef SAMPLE_CLIP_H -#define SAMPLE_CLIP_H + +#ifndef LMMS_SAMPLE_CLIP_H +#define LMMS_SAMPLE_CLIP_H #include "Clip.h" diff --git a/include/SampleClipView.h b/include/SampleClipView.h index 74873dca7..7f09ec022 100644 --- a/include/SampleClipView.h +++ b/include/SampleClipView.h @@ -22,13 +22,11 @@ * */ -#ifndef SAMPLE_CLIP_VIEW_H -#define SAMPLE_CLIP_VIEW_H +#ifndef LMMS_GUI_SAMPLE_CLIP_VIEW_H +#define LMMS_GUI_SAMPLE_CLIP_VIEW_H #include "ClipView.h" - - namespace lmms { diff --git a/include/SamplePlayHandle.h b/include/SamplePlayHandle.h index 69ee3b38d..c0ff656db 100644 --- a/include/SamplePlayHandle.h +++ b/include/SamplePlayHandle.h @@ -23,8 +23,8 @@ * */ -#ifndef SAMPLE_PLAY_HANDLE_H -#define SAMPLE_PLAY_HANDLE_H +#ifndef LMMS_SAMPLE_PLAY_HANDLE_H +#define LMMS_SAMPLE_PLAY_HANDLE_H #include "SampleBuffer.h" #include "AutomatableModel.h" diff --git a/include/SampleRecordHandle.h b/include/SampleRecordHandle.h index 5b23f5345..deb415537 100644 --- a/include/SampleRecordHandle.h +++ b/include/SampleRecordHandle.h @@ -22,9 +22,8 @@ * */ - -#ifndef SAMPLE_RECORD_HANDLE_H -#define SAMPLE_RECORD_HANDLE_H +#ifndef LMMS_SAMPLE_RECORD_HANDLE_H +#define LMMS_SAMPLE_RECORD_HANDLE_H #include #include diff --git a/include/SampleTrack.h b/include/SampleTrack.h index 8f424178a..94d1413b7 100644 --- a/include/SampleTrack.h +++ b/include/SampleTrack.h @@ -22,9 +22,8 @@ * */ -#ifndef SAMPLE_TRACK_H -#define SAMPLE_TRACK_H - +#ifndef LMMS_SAMPLE_TRACK_H +#define LMMS_SAMPLE_TRACK_H #include "AudioPort.h" #include "Track.h" @@ -110,4 +109,4 @@ private: } // namespace lmms -#endif \ No newline at end of file +#endif diff --git a/include/SampleTrackView.h b/include/SampleTrackView.h index 9921aa735..12f95bd19 100644 --- a/include/SampleTrackView.h +++ b/include/SampleTrackView.h @@ -22,8 +22,8 @@ * */ -#ifndef SAMPLE_TRACK_VIEW_H -#define SAMPLE_TRACK_VIEW_H +#ifndef LMMS_GUI_SAMPLE_TRACK_VIEW_H +#define LMMS_GUI_SAMPLE_TRACK_VIEW_H #include "TrackView.h" @@ -109,4 +109,4 @@ private: } // namespace lmms -#endif \ No newline at end of file +#endif diff --git a/include/SampleTrackWindow.h b/include/SampleTrackWindow.h index d302b2c44..02d5cacb0 100644 --- a/include/SampleTrackWindow.h +++ b/include/SampleTrackWindow.h @@ -21,12 +21,9 @@ * Boston, MA 02110-1301 USA. * */ - - -#ifndef SAMPLE_TRACK_WINDOW_H -#define SAMPLE_TRACK_WINDOW_H - +#ifndef LMMS_GUI_SAMPLE_TRACK_WINDOW_H +#define LMMS_GUI_SAMPLE_TRACK_WINDOW_H #include @@ -43,7 +40,7 @@ class EffectRackView; class Knob; class MixerLineLcdSpinBox; class SampleTrackView; - + class SampleTrackWindow : public QWidget, public ModelView, public SerializingObjectHook { diff --git a/include/Scale.h b/include/Scale.h index 96159a53c..e36a5e08d 100644 --- a/include/Scale.h +++ b/include/Scale.h @@ -22,8 +22,8 @@ * */ -#ifndef SCALE_H -#define SCALE_H +#ifndef LMMS_SCALE_H +#define LMMS_SCALE_H #include #include diff --git a/include/SendButtonIndicator.h b/include/SendButtonIndicator.h index ec4a90db3..78fe23852 100644 --- a/include/SendButtonIndicator.h +++ b/include/SendButtonIndicator.h @@ -21,8 +21,9 @@ * Boston, MA 02110-1301 USA. * */ -#ifndef SENDBUTTONINDICATOR_H -#define SENDBUTTONINDICATOR_H + +#ifndef LMMS_GUI_SEND_BUTTON_INDICATOR_H +#define LMMS_GUI_SEND_BUTTON_INDICATOR_H #include @@ -63,4 +64,4 @@ private: } // namespace lmms -#endif // SENDBUTTONINDICATOR_H +#endif diff --git a/include/SerializingObject.h b/include/SerializingObject.h index e32d5d046..bbbbaafcc 100644 --- a/include/SerializingObject.h +++ b/include/SerializingObject.h @@ -22,8 +22,8 @@ * */ -#ifndef SERIALIZING_OBJECT_H -#define SERIALIZING_OBJECT_H +#ifndef LMMS_SERIALIZING_OBJECT_H +#define LMMS_SERIALIZING_OBJECT_H #include @@ -102,4 +102,3 @@ private: } // namespace lmms #endif - diff --git a/include/SetupDialog.h b/include/SetupDialog.h index 8973938bf..962804a9c 100644 --- a/include/SetupDialog.h +++ b/include/SetupDialog.h @@ -22,9 +22,8 @@ * */ - -#ifndef SETUP_DIALOG_H -#define SETUP_DIALOG_H +#ifndef LMMS_GUI_SETUP_DIALOG_H +#define LMMS_GUI_SETUP_DIALOG_H #include #include diff --git a/include/SharedMemory.h b/include/SharedMemory.h index 32a40ff25..0a6d3bf89 100644 --- a/include/SharedMemory.h +++ b/include/SharedMemory.h @@ -19,10 +19,11 @@ * 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 SHARED_MEMORY_H -#define SHARED_MEMORY_H +#ifndef LMMS_SHARED_MEMORY_H +#define LMMS_SHARED_MEMORY_H #include #include @@ -148,4 +149,4 @@ private: } // namespace lmms -#endif // SHARED_MEMORY_H +#endif diff --git a/include/SideBar.h b/include/SideBar.h index 8755c660a..0ca597b5a 100644 --- a/include/SideBar.h +++ b/include/SideBar.h @@ -22,8 +22,8 @@ * */ -#ifndef SIDE_BAR_H -#define SIDE_BAR_H +#ifndef LMMS_GUI_SIDE_BAR_H +#define LMMS_GUI_SIDE_BAR_H #include #include diff --git a/include/SideBarWidget.h b/include/SideBarWidget.h index 5df3ccb7a..2d7cce15a 100644 --- a/include/SideBarWidget.h +++ b/include/SideBarWidget.h @@ -22,8 +22,8 @@ * */ -#ifndef SIDE_BAR_WIDGET_H -#define SIDE_BAR_WIDGET_H +#ifndef LMMS_GUI_SIDE_BAR_WIDGET_H +#define LMMS_GUI_SIDE_BAR_WIDGET_H #include #include diff --git a/include/Song.h b/include/Song.h index 569b3ad14..2e4736ea5 100644 --- a/include/Song.h +++ b/include/Song.h @@ -22,8 +22,8 @@ * */ -#ifndef SONG_H -#define SONG_H +#ifndef LMMS_SONG_H +#define LMMS_SONG_H #include diff --git a/include/SongEditor.h b/include/SongEditor.h index ea57cc125..ab71b7fa7 100644 --- a/include/SongEditor.h +++ b/include/SongEditor.h @@ -23,10 +23,8 @@ * */ - -#ifndef SONG_EDITOR_H -#define SONG_EDITOR_H - +#ifndef LMMS_GUI_SONG_EDITOR_H +#define LMMS_GUI_SONG_EDITOR_H #include "Editor.h" #include "TrackContainerView.h" diff --git a/include/StepRecorder.h b/include/StepRecorder.h index b89fadb15..7cd568a79 100644 --- a/include/StepRecorder.h +++ b/include/StepRecorder.h @@ -18,8 +18,8 @@ * */ -#ifndef STEP_RECORDER_H -#define STEP_RECORDER_H +#ifndef LMMS_STEP_RECORDER_H +#define LMMS_STEP_RECORDER_H #include #include @@ -152,4 +152,4 @@ class StepRecorder : public QObject } // namespace lmms -#endif //STEP_RECORDER_H +#endif diff --git a/include/StepRecorderWidget.h b/include/StepRecorderWidget.h index 4067b0001..ec6a37330 100644 --- a/include/StepRecorderWidget.h +++ b/include/StepRecorderWidget.h @@ -19,9 +19,9 @@ * Boston, MA 02110-1301 USA. * */ -#ifndef STEP_RECOREDER_WIDGET_H -#define STEP_RECOREDER_WIDGET_H +#ifndef LMMS_GUI_STEP_RECOREDER_WIDGET_H +#define LMMS_GUI_STEP_RECOREDER_WIDGET_H #include #include @@ -95,4 +95,4 @@ signals: } // namespace lmms::gui -#endif //STEP_RECOREDER_WIDGET_H +#endif diff --git a/include/StringPairDrag.h b/include/StringPairDrag.h index e58b88f90..4763122be 100644 --- a/include/StringPairDrag.h +++ b/include/StringPairDrag.h @@ -23,8 +23,8 @@ * */ -#ifndef STRING_PAIR_DRAG_H -#define STRING_PAIR_DRAG_H +#ifndef LMMS_GUI_STRING_PAIR_DRAG_H +#define LMMS_GUI_STRING_PAIR_DRAG_H #include #include diff --git a/include/SubWindow.h b/include/SubWindow.h index 3c73a9dde..95bd6c59e 100644 --- a/include/SubWindow.h +++ b/include/SubWindow.h @@ -23,8 +23,9 @@ * Boston, MA 02110-1301 USA. * */ -#ifndef SUBWINDOW_H -#define SUBWINDOW_H + +#ifndef LMMS_GUI_SUBWINDOW_H +#define LMMS_GUI_SUBWINDOW_H #include #include diff --git a/include/SweepOscillator.h b/include/SweepOscillator.h index f113ea0fa..3463851c4 100644 --- a/include/SweepOscillator.h +++ b/include/SweepOscillator.h @@ -22,8 +22,8 @@ * */ -#ifndef SWEEP_OSCILLATOR_H -#define SWEEP_OSCILLATOR_H +#ifndef LMMS_SWEEP_OSCILLATOR_H +#define LMMS_SWEEP_OSCILLATOR_H #include "Oscillator.h" #include "DspEffectLibrary.h" diff --git a/include/TabBar.h b/include/TabBar.h index 2395e15f5..b8334c1f5 100644 --- a/include/TabBar.h +++ b/include/TabBar.h @@ -22,9 +22,8 @@ * */ - -#ifndef TAB_BAR_H -#define TAB_BAR_H +#ifndef LMMS_GUI_TAB_BAR_H +#define LMMS_GUI_TAB_BAR_H #include #include diff --git a/include/TabButton.h b/include/TabButton.h index 938230a91..c09d1ed8a 100644 --- a/include/TabButton.h +++ b/include/TabButton.h @@ -22,9 +22,8 @@ * */ - -#ifndef TAB_BUTTON_H -#define TAB_BUTTON_H +#ifndef LMMS_GUI_TAB_BUTTON_H +#define LMMS_GUI_TAB_BUTTON_H #include diff --git a/include/TabWidget.h b/include/TabWidget.h index 27a35d2a8..942b08738 100644 --- a/include/TabWidget.h +++ b/include/TabWidget.h @@ -22,9 +22,8 @@ * */ - -#ifndef TAB_WIDGET_H -#define TAB_WIDGET_H +#ifndef LMMS_GUI_TAB_WIDGET_H +#define LMMS_GUI_TAB_WIDGET_H #include #include diff --git a/include/TemplatesMenu.h b/include/TemplatesMenu.h index 7f425bd2f..660d3c760 100644 --- a/include/TemplatesMenu.h +++ b/include/TemplatesMenu.h @@ -21,8 +21,9 @@ * Boston, MA 02110-1301 USA. * */ -#ifndef TEMPLATESMENU_H -#define TEMPLATESMENU_H + +#ifndef LMMS_GUI_TEMPLATES_MENU_H +#define LMMS_GUI_TEMPLATES_MENU_H #include #include @@ -49,4 +50,4 @@ private slots: } // namespace lmms::gui -#endif // TEMPLATESMENU_H +#endif diff --git a/include/TempoSyncKnob.h b/include/TempoSyncKnob.h index 25a3b7e3b..0987e1903 100644 --- a/include/TempoSyncKnob.h +++ b/include/TempoSyncKnob.h @@ -23,8 +23,8 @@ * */ -#ifndef TEMPO_SYNC_KNOB_H -#define TEMPO_SYNC_KNOB_H +#ifndef LMMS_GUI_TEMPO_SYNC_KNOB_H +#define LMMS_GUI_TEMPO_SYNC_KNOB_H #include #include diff --git a/include/TempoSyncKnobModel.h b/include/TempoSyncKnobModel.h index 1a18486ff..7b1a10b5e 100644 --- a/include/TempoSyncKnobModel.h +++ b/include/TempoSyncKnobModel.h @@ -23,8 +23,8 @@ * */ -#ifndef TEMPO_SYNC_KNOB_MODEL_H -#define TEMPO_SYNC_KNOB_MODEL_H +#ifndef LMMS_TEMPO_SYNC_KNOB_MODEL_H +#define LMMS_TEMPO_SYNC_KNOB_MODEL_H #include "MeterModel.h" diff --git a/include/TextFloat.h b/include/TextFloat.h index 9fdabc06b..7ba38d141 100644 --- a/include/TextFloat.h +++ b/include/TextFloat.h @@ -22,9 +22,8 @@ * */ - -#ifndef TEXT_FLOAT_H -#define TEXT_FLOAT_H +#ifndef LMMS_GUI_TEXT_FLOAT_H +#define LMMS_GUI_TEXT_FLOAT_H #include #include diff --git a/include/ThreadableJob.h b/include/ThreadableJob.h index 8e714ae19..efb4b3dc7 100644 --- a/include/ThreadableJob.h +++ b/include/ThreadableJob.h @@ -22,8 +22,8 @@ * */ -#ifndef THREADABLE_JOB_H -#define THREADABLE_JOB_H +#ifndef LMMS_THREADABLE_JOB_H +#define LMMS_THREADABLE_JOB_H #include "lmms_basics.h" diff --git a/include/TimeDisplayWidget.h b/include/TimeDisplayWidget.h index 894666970..269c24978 100644 --- a/include/TimeDisplayWidget.h +++ b/include/TimeDisplayWidget.h @@ -23,8 +23,8 @@ * */ -#ifndef TIME_DISPLAY_WIDGET_H -#define TIME_DISPLAY_WIDGET_H +#ifndef LMMS_GUI_TIME_DISPLAY_WIDGET_H +#define LMMS_GUI_TIME_DISPLAY_WIDGET_H #include #include @@ -71,4 +71,4 @@ private: } // namespace lmms::gui -#endif // TIME_DISPLAY_WIDGET_H +#endif diff --git a/include/TimeLineWidget.h b/include/TimeLineWidget.h index bada25640..882e9453c 100644 --- a/include/TimeLineWidget.h +++ b/include/TimeLineWidget.h @@ -22,9 +22,8 @@ * */ - -#ifndef TIMELINE_H -#define TIMELINE_H +#ifndef LMMS_GUI_TIMELINE_WIDGET_H +#define LMMS_GUI_TIMELINE_WIDGET_H #include diff --git a/include/TimePos.h b/include/TimePos.h index 808eede25..61769de35 100644 --- a/include/TimePos.h +++ b/include/TimePos.h @@ -23,10 +23,8 @@ * */ - -#ifndef TIME_POS_H -#define TIME_POS_H - +#ifndef LMMS_TIME_POS_H +#define LMMS_TIME_POS_H #include "lmms_export.h" #include "lmms_basics.h" diff --git a/include/ToolButton.h b/include/ToolButton.h index c173a9052..aeb88a7e5 100644 --- a/include/ToolButton.h +++ b/include/ToolButton.h @@ -22,9 +22,8 @@ * */ - -#ifndef TOOL_BUTTON_H -#define TOOL_BUTTON_H +#ifndef LMMS_GUI_TOOL_BUTTON_H +#define LMMS_GUI_TOOL_BUTTON_H #include @@ -50,4 +49,3 @@ public: } // namespace lmms::gui #endif - diff --git a/include/ToolPlugin.h b/include/ToolPlugin.h index 38f4d87b1..4d7107582 100644 --- a/include/ToolPlugin.h +++ b/include/ToolPlugin.h @@ -24,8 +24,8 @@ * */ -#ifndef TOOL_PLUGIN_H -#define TOOL_PLUGIN_H +#ifndef LMMS_TOOL_PLUGIN_H +#define LMMS_TOOL_PLUGIN_H #include "Plugin.h" diff --git a/include/ToolPluginView.h b/include/ToolPluginView.h index 0b702fd1b..201a4b165 100644 --- a/include/ToolPluginView.h +++ b/include/ToolPluginView.h @@ -23,8 +23,8 @@ * */ -#ifndef TOOL_PLUGIN_VIEW_H -#define TOOL_PLUGIN_VIEW_H +#ifndef LMMS_GUI_TOOL_PLUGIN_VIEW_H +#define LMMS_GUI_TOOL_PLUGIN_VIEW_H #include "PluginView.h" diff --git a/include/Track.h b/include/Track.h index 8d756c914..555850f88 100644 --- a/include/Track.h +++ b/include/Track.h @@ -22,8 +22,8 @@ * */ -#ifndef TRACK_H -#define TRACK_H +#ifndef LMMS_TRACK_H +#define LMMS_TRACK_H #include diff --git a/include/TrackContainer.h b/include/TrackContainer.h index d947094f7..d0c116f3a 100644 --- a/include/TrackContainer.h +++ b/include/TrackContainer.h @@ -23,8 +23,8 @@ * */ -#ifndef TRACK_CONTAINER_H -#define TRACK_CONTAINER_H +#ifndef LMMS_TRACK_CONTAINER_H +#define LMMS_TRACK_CONTAINER_H #include diff --git a/include/TrackContainerView.h b/include/TrackContainerView.h index 444420d98..df61666b8 100644 --- a/include/TrackContainerView.h +++ b/include/TrackContainerView.h @@ -22,9 +22,8 @@ * */ - -#ifndef TRACK_CONTAINER_VIEW_H -#define TRACK_CONTAINER_VIEW_H +#ifndef LMMS_GUI_TRACK_CONTAINER_VIEW_H +#define LMMS_GUI_TRACK_CONTAINER_VIEW_H #include #include diff --git a/include/TrackContentWidget.h b/include/TrackContentWidget.h index f4a44d2a6..09239b392 100644 --- a/include/TrackContentWidget.h +++ b/include/TrackContentWidget.h @@ -22,8 +22,8 @@ * */ -#ifndef TRACK_CONTENT_WIDGET_H -#define TRACK_CONTENT_WIDGET_H +#ifndef LMMS_GUI_TRACK_CONTENT_WIDGET_H +#define LMMS_GUI_TRACK_CONTENT_WIDGET_H #include diff --git a/include/TrackLabelButton.h b/include/TrackLabelButton.h index 1a8d05e71..e7f159798 100644 --- a/include/TrackLabelButton.h +++ b/include/TrackLabelButton.h @@ -22,9 +22,8 @@ * */ - -#ifndef TRACK_LABEL_BUTTON_H -#define TRACK_LABEL_BUTTON_H +#ifndef LMMS_GUI_TRACK_LABEL_BUTTON_H +#define LMMS_GUI_TRACK_LABEL_BUTTON_H #include diff --git a/include/TrackOperationsWidget.h b/include/TrackOperationsWidget.h index edd9796ac..39e59ac98 100644 --- a/include/TrackOperationsWidget.h +++ b/include/TrackOperationsWidget.h @@ -22,8 +22,8 @@ * */ -#ifndef TRACK_OPERATIONS_WIDGET_H -#define TRACK_OPERATIONS_WIDGET_H +#ifndef LMMS_GUI_TRACK_OPERATIONS_WIDGET_H +#define LMMS_GUI_TRACK_OPERATIONS_WIDGET_H #include diff --git a/include/TrackRenameLineEdit.h b/include/TrackRenameLineEdit.h index 4b13ff9b7..48fb96092 100644 --- a/include/TrackRenameLineEdit.h +++ b/include/TrackRenameLineEdit.h @@ -23,9 +23,8 @@ * */ - -#ifndef TRACK_RENAME_LINE_EDIT_H -#define TRACK_RENAME_LINE_EDIT_H +#ifndef LMMS_GUI_TRACK_RENAME_LINE_EDIT_H +#define LMMS_GUI_TRACK_RENAME_LINE_EDIT_H #include diff --git a/include/TrackView.h b/include/TrackView.h index 4b02c8015..a46c15d75 100644 --- a/include/TrackView.h +++ b/include/TrackView.h @@ -22,10 +22,8 @@ * */ - - -#ifndef TRACK_VIEW_H -#define TRACK_VIEW_H +#ifndef LMMS_GUI_TRACK_VIEW_H +#define LMMS_GUI_TRACK_VIEW_H #include @@ -34,7 +32,6 @@ #include "TrackContentWidget.h" #include "TrackOperationsWidget.h" - class QMenu; namespace lmms diff --git a/include/ValueBuffer.h b/include/ValueBuffer.h index 950ad06f0..9e80b7ead 100644 --- a/include/ValueBuffer.h +++ b/include/ValueBuffer.h @@ -23,8 +23,8 @@ * */ -#ifndef VALUE_BUFFER_H -#define VALUE_BUFFER_H +#ifndef LMMS_VALUE_BUFFER_H +#define LMMS_VALUE_BUFFER_H #include diff --git a/include/VersionedSaveDialog.h b/include/VersionedSaveDialog.h index 79ab516b0..326b11fde 100644 --- a/include/VersionedSaveDialog.h +++ b/include/VersionedSaveDialog.h @@ -24,9 +24,8 @@ * */ - -#ifndef VERSIONEDSAVEDIALOG_H -#define VERSIONEDSAVEDIALOG_H +#ifndef LMMS_GUI_VERSIONED_SAVE_DIALOG_H +#define LMMS_GUI_VERSIONED_SAVE_DIALOG_H #include "FileDialog.h" #include "Song.h" @@ -69,4 +68,4 @@ public slots: } // namespace lmms::gui -#endif // VERSIONEDSAVEDIALOG_H +#endif diff --git a/include/VstSyncController.h b/include/VstSyncController.h index c70bc85c8..f63bafc41 100644 --- a/include/VstSyncController.h +++ b/include/VstSyncController.h @@ -23,8 +23,8 @@ * */ -#ifndef VST_SYNC_CONTROLLER_H -#define VST_SYNC_CONTROLLER_H +#ifndef LMMS_VST_SYNC_CONTROLLER_H +#define LMMS_VST_SYNC_CONTROLLER_H #include diff --git a/include/VstSyncData.h b/include/VstSyncData.h index baf3fa7a8..11da91d8d 100644 --- a/include/VstSyncData.h +++ b/include/VstSyncData.h @@ -23,8 +23,8 @@ * */ -#ifndef VST_SYNC_DATA_H -#define VST_SYNC_DATA_H +#ifndef LMMS_VST_SYNC_DATA_H +#define LMMS_VST_SYNC_DATA_H namespace lmms { diff --git a/include/aeffectx.h b/include/aeffectx.h index a06567ba7..188feae9f 100644 --- a/include/aeffectx.h +++ b/include/aeffectx.h @@ -22,7 +22,6 @@ * */ - #ifndef AEFFECTX_H #define AEFFECTX_H diff --git a/include/base64.h b/include/base64.h index f52d90d13..01116e4cd 100644 --- a/include/base64.h +++ b/include/base64.h @@ -23,8 +23,8 @@ * */ -#ifndef _BASE64_H -#define _BASE64_H +#ifndef LMMS_BASE64_H +#define LMMS_BASE64_H #include #include diff --git a/include/debug.h b/include/debug.h index f2ea29cc1..efabd4522 100644 --- a/include/debug.h +++ b/include/debug.h @@ -22,9 +22,8 @@ * */ - -#ifndef DEBUG_H -#define DEBUG_H +#ifndef LMMS_DEBUG_H +#define LMMS_DEBUG_H #include "lmmsconfig.h" diff --git a/include/denormals.h b/include/denormals.h index e99e767a3..cfb0d5c92 100644 --- a/include/denormals.h +++ b/include/denormals.h @@ -1,8 +1,8 @@ -// Denormals stripping. +// Denormals stripping. // These snippets should be common enough to be considered public domain. -#ifndef DENORMALS_H -#define DENORMALS_H +#ifndef LMMS_DENORMALS_H +#define LMMS_DENORMALS_H #ifdef __SSE__ #include @@ -50,5 +50,4 @@ void inline disable_denormals() } // namespace lmms -#endif // DENORMALS_H - +#endif diff --git a/include/embed.h b/include/embed.h index 03d767b43..b3d1cbc21 100644 --- a/include/embed.h +++ b/include/embed.h @@ -22,8 +22,8 @@ * */ -#ifndef EMBED_H -#define EMBED_H +#ifndef LMMS_EMBED_H +#define LMMS_EMBED_H #include #include diff --git a/include/endian_handling.h b/include/endian_handling.h index b3d122fa3..96bf11704 100644 --- a/include/endian_handling.h +++ b/include/endian_handling.h @@ -22,8 +22,8 @@ * */ -#ifndef ENDIAN_HANDLING_H -#define ENDIAN_HANDLING_H +#ifndef LMMS_ENDIAN_HANDLING_H +#define LMMS_ENDIAN_HANDLING_H #include diff --git a/include/fft_helpers.h b/include/fft_helpers.h index 8ba0fc7a0..ab4238409 100644 --- a/include/fft_helpers.h +++ b/include/fft_helpers.h @@ -23,9 +23,8 @@ * */ - -#ifndef FFT_HELPERS_H -#define FFT_HELPERS_H +#ifndef LMMS_FFT_HELPERS_H +#define LMMS_FFT_HELPERS_H #include "lmms_export.h" diff --git a/include/gui_templates.h b/include/gui_templates.h index ee0ccdbf6..7a61ccfed 100644 --- a/include/gui_templates.h +++ b/include/gui_templates.h @@ -22,9 +22,8 @@ * */ - -#ifndef GUI_TEMPLATES_H -#define GUI_TEMPLATES_H +#ifndef LMMS_GUI_TEMPLATES_H +#define LMMS_GUI_TEMPLATES_H #include "lmmsconfig.h" diff --git a/include/interpolation.h b/include/interpolation.h index 3a74334e4..9f3b3913d 100644 --- a/include/interpolation.h +++ b/include/interpolation.h @@ -22,9 +22,8 @@ * */ - -#ifndef INTERPOLATION_H -#define INTERPOLATION_H +#ifndef LMMS_INTERPOLATION_H +#define LMMS_INTERPOLATION_H #ifndef __USE_XOPEN #define __USE_XOPEN diff --git a/include/lmms_basics.h b/include/lmms_basics.h index 59a6aa359..71cc4ce53 100644 --- a/include/lmms_basics.h +++ b/include/lmms_basics.h @@ -22,9 +22,8 @@ * */ - -#ifndef TYPES_H -#define TYPES_H +#ifndef LMMS_TYPES_H +#define LMMS_TYPES_H #include #include diff --git a/include/lmms_math.h b/include/lmms_math.h index db4502f1c..a010a9d3e 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -22,7 +22,6 @@ * */ - #ifndef LMMS_MATH_H #define LMMS_MATH_H diff --git a/include/panning.h b/include/panning.h index 1521ec984..52698677c 100644 --- a/include/panning.h +++ b/include/panning.h @@ -23,8 +23,8 @@ * */ -#ifndef PANNING_H -#define PANNING_H +#ifndef LMMS_PANNING_H +#define LMMS_PANNING_H #include "lmms_basics.h" #include "panning_constants.h" diff --git a/include/panning_constants.h b/include/panning_constants.h index 00a5c3291..6e894e9d8 100644 --- a/include/panning_constants.h +++ b/include/panning_constants.h @@ -23,8 +23,8 @@ * */ -#ifndef PANNING_CONSTANTS_H -#define PANNING_CONSTANTS_H +#ifndef LMMS_PANNING_CONSTANTS_H +#define LMMS_PANNING_CONSTANTS_H namespace lmms { diff --git a/include/shared_object.h b/include/shared_object.h index ac45d6cd7..dfc94b96a 100644 --- a/include/shared_object.h +++ b/include/shared_object.h @@ -23,8 +23,8 @@ * */ -#ifndef SHARED_OBJECT_H -#define SHARED_OBJECT_H +#ifndef LMMS_SHARED_OBJECT_H +#define LMMS_SHARED_OBJECT_H #include diff --git a/include/versioninfo.h b/include/versioninfo.h index 29bf3bea9..de852b59c 100644 --- a/include/versioninfo.h +++ b/include/versioninfo.h @@ -1,5 +1,5 @@ -#ifndef VERSION_INFO_H -#define VERSION_INFO_H +#ifndef LMMS_VERSION_INFO_H +#define LMMS_VERSION_INFO_H #include "lmms_basics.h" diff --git a/include/volume.h b/include/volume.h index 5223bfa09..4d26cc815 100644 --- a/include/volume.h +++ b/include/volume.h @@ -23,8 +23,8 @@ * */ -#ifndef VOLUME_H -#define VOLUME_H +#ifndef LMMS_VOLUME_H +#define LMMS_VOLUME_H #include "lmms_basics.h" From bbf31a2e7384a7ff8eb20c6d7db5169b149a42d7 Mon Sep 17 00:00:00 2001 From: Dalton Messmer Date: Mon, 2 Jan 2023 22:02:12 -0500 Subject: [PATCH 002/308] Add missing copyright statement to MidiCCRackView.h --- include/MidiCCRackView.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/include/MidiCCRackView.h b/include/MidiCCRackView.h index 98f5ce183..ca99a7ce5 100644 --- a/include/MidiCCRackView.h +++ b/include/MidiCCRackView.h @@ -1,3 +1,27 @@ +/* + * MidiCCRackView.h - declaration of the MIDI CC rack widget + * + * Copyright (c) 2020 Ian Caio + * + * 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_MIDI_CC_RACK_VIEW_H #define LMMS_GUI_MIDI_CC_RACK_VIEW_H From 92522cf3ab82506e31cdbcb961abd82da2e86c9c Mon Sep 17 00:00:00 2001 From: Dalton Messmer Date: Thu, 5 Jan 2023 14:03:07 -0500 Subject: [PATCH 003/308] Add missing copyright statement to CustomTextKnob.h/cpp --- include/CustomTextKnob.h | 25 ++++++++++++++++++++++++- src/gui/widgets/CustomTextKnob.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/include/CustomTextKnob.h b/include/CustomTextKnob.h index 23b7e8b1f..25bba1315 100644 --- a/include/CustomTextKnob.h +++ b/include/CustomTextKnob.h @@ -1,4 +1,27 @@ -/* Text customizable knob */ +/* + * CustomTextKnob.h + * + * Copyright (c) 2020 Ibuki Sugiyama
+ * + * 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_CUSTOM_TEXT_KNOB_H #define LMMS_GUI_CUSTOM_TEXT_KNOB_H diff --git a/src/gui/widgets/CustomTextKnob.cpp b/src/gui/widgets/CustomTextKnob.cpp index 9f6e19b90..ce880608c 100644 --- a/src/gui/widgets/CustomTextKnob.cpp +++ b/src/gui/widgets/CustomTextKnob.cpp @@ -1,3 +1,27 @@ +/* + * CustomTextKnob.cpp + * + * Copyright (c) 2020 Ibuki Sugiyama
+ * + * 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 "CustomTextKnob.h" namespace lmms::gui From 2c6d88f799203bc2a21173d597af566ac783f174 Mon Sep 17 00:00:00 2001 From: Dalton Messmer Date: Thu, 5 Jan 2023 17:58:49 -0500 Subject: [PATCH 004/308] Add GUARD_H closing comments --- include/AboutDialog.h | 2 +- include/ActionGroup.h | 2 +- include/AudioAlsa.h | 2 +- include/AudioAlsaSetupWidget.h | 2 +- include/AudioDevice.h | 2 +- include/AudioDeviceSetupWidget.h | 2 +- include/AudioDummy.h | 2 +- include/AudioEngine.h | 2 +- include/AudioEngineProfiler.h | 2 +- include/AudioEngineWorkerThread.h | 2 +- include/AudioFileDevice.h | 2 +- include/AudioFileFlac.h | 2 +- include/AudioFileMP3.h | 2 +- include/AudioFileOgg.h | 2 +- include/AudioFileWave.h | 2 +- include/AudioJack.h | 2 +- include/AudioOss.h | 2 +- include/AudioPort.h | 2 +- include/AudioPortAudio.h | 2 +- include/AudioPulseAudio.h | 2 +- include/AudioSampleRecorder.h | 2 +- include/AudioSdl.h | 2 +- include/AudioSndio.h | 2 +- include/AudioSoundIo.h | 2 +- include/AutomatableButton.h | 2 +- include/AutomatableModel.h | 3 +-- include/AutomatableModelView.h | 3 +-- include/AutomatableSlider.h | 2 +- include/AutomationClip.h | 2 +- include/AutomationClipView.h | 2 +- include/AutomationEditor.h | 2 +- include/AutomationNode.h | 2 +- include/AutomationTrack.h | 2 +- include/AutomationTrackView.h | 2 +- include/BandLimitedWave.h | 7 ++++--- include/BasicFilters.h | 2 +- include/BufferManager.h | 2 +- include/CPULoadWidget.h | 2 +- include/CaptionMenu.h | 2 +- include/Clip.h | 2 +- include/ClipView.h | 2 +- include/Clipboard.h | 2 +- include/ColorChooser.h | 2 +- include/ComboBox.h | 2 +- include/ComboBoxModel.h | 2 +- include/ConfigManager.h | 2 +- include/ControlLayout.h | 2 +- include/Controller.h | 2 +- include/ControllerConnection.h | 2 +- include/ControllerConnectionDialog.h | 2 +- include/ControllerDialog.h | 2 +- include/ControllerRackView.h | 2 +- include/ControllerView.h | 2 +- include/Controls.h | 2 +- include/CustomTextKnob.h | 2 +- include/DataFile.h | 2 +- include/Delay.h | 2 +- include/DeprecationHelper.h | 2 +- include/DetuningHelper.h | 2 +- include/DrumSynth.h | 2 +- include/DspEffectLibrary.h | 3 +-- include/DummyEffect.h | 2 +- include/DummyInstrument.h | 2 +- include/DummyPlugin.h | 2 +- include/Editor.h | 2 +- include/Effect.h | 2 +- include/EffectChain.h | 2 +- include/EffectControlDialog.h | 2 +- include/EffectControls.h | 2 +- include/EffectRackView.h | 2 +- include/EffectSelectDialog.h | 3 +-- include/EffectView.h | 2 +- include/Engine.h | 2 +- include/EnvelopeAndLfoParameters.h | 2 +- include/EnvelopeAndLfoView.h | 2 +- include/ExportFilter.h | 2 +- include/ExportProjectDialog.h | 3 +-- include/FadeButton.h | 2 +- include/Fader.h | 3 +-- include/FifoBuffer.h | 2 +- include/FileBrowser.h | 2 +- include/FileDialog.h | 2 +- include/Graph.h | 2 +- include/GroupBox.h | 3 +-- include/GuiApplication.h | 2 +- include/ImportFilter.h | 2 +- include/InlineAutomation.h | 2 +- include/Instrument.h | 2 +- include/InstrumentFunctionViews.h | 2 +- include/InstrumentFunctions.h | 2 +- include/InstrumentMidiIOView.h | 2 +- include/InstrumentMiscView.h | 2 +- include/InstrumentPlayHandle.h | 2 +- include/InstrumentSoundShaping.h | 2 +- include/InstrumentSoundShapingView.h | 2 +- include/InstrumentTrack.h | 2 +- include/InstrumentTrackView.h | 2 +- include/InstrumentTrackWindow.h | 2 +- include/InstrumentView.h | 2 +- include/IoHelper.h | 2 +- include/JournallingObject.h | 2 +- include/Keymap.h | 2 +- include/Knob.h | 2 +- include/Ladspa2LMMS.h | 2 +- include/LadspaBase.h | 2 +- include/LadspaControl.h | 2 +- include/LadspaControlView.h | 2 +- include/LadspaManager.h | 2 +- include/LcdFloatSpinBox.h | 2 +- include/LcdSpinBox.h | 2 +- include/LcdWidget.h | 2 +- include/LedCheckBox.h | 2 +- include/LeftRightNav.h | 2 +- include/LfoController.h | 2 +- include/LinkedModelGroupViews.h | 6 +++--- include/LinkedModelGroups.h | 6 +++--- include/LmmsPalette.h | 2 +- include/LmmsStyle.h | 2 +- include/LocaleHelper.h | 2 +- include/LocklessAllocator.h | 2 +- include/LocklessList.h | 2 +- include/LocklessRingBuffer.h | 2 +- include/Lv2Basics.h | 2 +- include/Lv2ControlBase.h | 2 +- include/Lv2Evbuf.h | 2 +- include/Lv2Features.h | 2 +- include/Lv2Manager.h | 2 +- include/Lv2Options.h | 2 +- include/Lv2Ports.h | 2 +- include/Lv2Proc.h | 2 +- include/Lv2SubPluginFeatures.h | 2 +- include/Lv2UridCache.h | 2 +- include/Lv2UridMap.h | 2 +- include/Lv2ViewBase.h | 2 +- include/MainApplication.h | 2 +- include/MainWindow.h | 2 +- include/MemoryHelper.h | 2 +- include/MemoryManager.h | 2 +- include/MeterDialog.h | 2 +- include/MeterModel.h | 2 +- include/MicroTimer.h | 2 +- include/Microtuner.h | 2 +- include/MicrotunerConfig.h | 2 +- include/Midi.h | 2 +- include/MidiAlsaRaw.h | 2 +- include/MidiAlsaSeq.h | 2 +- include/MidiApple.h | 2 +- include/MidiCCRackView.h | 2 +- include/MidiClient.h | 2 +- include/MidiClip.h | 2 +- include/MidiClipView.h | 2 +- include/MidiController.h | 2 +- include/MidiDummy.h | 2 +- include/MidiEvent.h | 2 +- include/MidiEventProcessor.h | 2 +- include/MidiEventToByteSeq.h | 2 +- include/MidiJack.h | 2 +- include/MidiOss.h | 2 +- include/MidiPort.h | 2 +- include/MidiPortMenu.h | 2 +- include/MidiSetupWidget.h | 2 +- include/MidiSndio.h | 2 +- include/MidiWinMM.h | 2 +- include/MixHelpers.h | 2 +- include/Mixer.h | 2 +- include/MixerLine.h | 2 +- include/MixerLineLcdSpinBox.h | 2 +- include/MixerView.h | 2 +- include/Model.h | 2 +- include/ModelView.h | 2 +- include/ModelVisitor.h | 2 +- include/NStateButton.h | 2 +- include/Note.h | 2 +- include/NotePlayHandle.h | 2 +- include/Oscillator.h | 2 +- include/OscillatorConstants.h | 2 +- include/Oscilloscope.h | 2 +- include/OutputSettings.h | 2 +- include/PathUtil.h | 2 +- include/PatternClip.h | 2 +- include/PatternClipView.h | 2 +- include/PatternEditor.h | 2 +- include/PatternStore.h | 2 +- include/PatternTrack.h | 2 +- include/PatternTrackView.h | 2 +- include/PeakController.h | 2 +- include/PerfLog.h | 2 +- include/Piano.h | 2 +- include/PianoRoll.h | 2 +- include/PianoView.h | 2 +- include/Pitch.h | 2 +- include/PixmapButton.h | 2 +- include/PlayHandle.h | 2 +- include/Plugin.h | 2 +- include/PluginBrowser.h | 2 +- include/PluginFactory.h | 2 +- include/PluginIssue.h | 3 +-- include/PluginView.h | 2 +- include/PositionLine.h | 2 +- include/PresetPreviewPlayHandle.h | 2 +- include/ProjectJournal.h | 2 +- include/ProjectNotes.h | 2 +- include/ProjectRenderer.h | 2 +- include/ProjectVersion.h | 2 +- include/QuadratureLfo.h | 2 +- include/RaiiHelpers.h | 2 +- include/RecentProjectsMenu.h | 2 +- include/RemotePlugin.h | 2 +- include/RemotePluginBase.h | 2 +- include/RemotePluginClient.h | 2 +- include/RenameDialog.h | 2 +- include/RenderManager.h | 2 +- include/RingBuffer.h | 2 +- include/RmsHelper.h | 2 +- include/RowTableView.h | 2 +- include/Rubberband.h | 2 +- include/SampleBuffer.h | 2 +- include/SampleClip.h | 2 +- include/SampleClipView.h | 2 +- include/SamplePlayHandle.h | 2 +- include/SampleRecordHandle.h | 2 +- include/SampleTrack.h | 2 +- include/SampleTrackView.h | 2 +- include/SampleTrackWindow.h | 3 +-- include/Scale.h | 2 +- include/SendButtonIndicator.h | 2 +- include/SerializingObject.h | 2 +- include/SetupDialog.h | 2 +- include/SharedMemory.h | 2 +- include/SideBar.h | 2 +- include/SideBarWidget.h | 2 +- include/Song.h | 2 +- include/SongEditor.h | 2 +- include/StepRecorder.h | 2 +- include/StepRecorderWidget.h | 2 +- include/StringPairDrag.h | 2 +- include/SubWindow.h | 2 +- include/SweepOscillator.h | 2 +- include/TabBar.h | 2 +- include/TabButton.h | 2 +- include/TabWidget.h | 2 +- include/TemplatesMenu.h | 2 +- include/TempoSyncKnob.h | 2 +- include/TempoSyncKnobModel.h | 2 +- include/TextFloat.h | 2 +- include/ThreadableJob.h | 2 +- include/TimeDisplayWidget.h | 2 +- include/TimeLineWidget.h | 2 +- include/TimePos.h | 2 +- include/ToolButton.h | 2 +- include/ToolPlugin.h | 2 +- include/ToolPluginView.h | 2 +- include/Track.h | 3 +-- include/TrackContainer.h | 2 +- include/TrackContainerView.h | 2 +- include/TrackContentWidget.h | 2 +- include/TrackLabelButton.h | 2 +- include/TrackOperationsWidget.h | 2 +- include/TrackRenameLineEdit.h | 2 +- include/TrackView.h | 2 +- include/ValueBuffer.h | 2 +- include/VersionedSaveDialog.h | 2 +- include/VstSyncController.h | 2 +- include/VstSyncData.h | 2 +- include/aeffectx.h | 6 +++--- include/base64.h | 2 +- include/debug.h | 2 +- include/denormals.h | 4 ++-- include/embed.h | 2 +- include/endian_handling.h | 2 +- include/fenv.h | 2 +- include/fft_helpers.h | 2 +- include/gui_templates.h | 2 +- include/interpolation.h | 2 +- include/lmms_basics.h | 2 +- include/lmms_constants.h | 2 +- include/lmms_math.h | 2 +- include/panning.h | 2 +- include/panning_constants.h | 2 +- include/shared_object.h | 2 +- include/versioninfo.h | 2 +- include/volume.h | 2 +- 282 files changed, 292 insertions(+), 301 deletions(-) diff --git a/include/AboutDialog.h b/include/AboutDialog.h index bb0c509a9..2fd01faf5 100644 --- a/include/AboutDialog.h +++ b/include/AboutDialog.h @@ -41,4 +41,4 @@ public: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_ABOUT_DIALOG_H diff --git a/include/ActionGroup.h b/include/ActionGroup.h index 80a6d523e..e18f6fb23 100644 --- a/include/ActionGroup.h +++ b/include/ActionGroup.h @@ -58,4 +58,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_ACTION_GROUP_H diff --git a/include/AudioAlsa.h b/include/AudioAlsa.h index 263925286..975532071 100644 --- a/include/AudioAlsa.h +++ b/include/AudioAlsa.h @@ -108,4 +108,4 @@ private: #endif // LMMS_HAVE_ALSA -#endif +#endif // LMMS_AUDIO_ALSA_H diff --git a/include/AudioAlsaSetupWidget.h b/include/AudioAlsaSetupWidget.h index 068754b69..cbe99ba01 100644 --- a/include/AudioAlsaSetupWidget.h +++ b/include/AudioAlsaSetupWidget.h @@ -66,4 +66,4 @@ private: #endif // LMMS_HAVE_ALSA -#endif +#endif // LMMS_GUI_AUDIO_ALSA_SETUP_WIDGET_H diff --git a/include/AudioDevice.h b/include/AudioDevice.h index 26cbbaccc..d1a9617cd 100644 --- a/include/AudioDevice.h +++ b/include/AudioDevice.h @@ -160,4 +160,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_AUDIO_DEVICE_H diff --git a/include/AudioDeviceSetupWidget.h b/include/AudioDeviceSetupWidget.h index 9c70859d2..f56fa07a6 100644 --- a/include/AudioDeviceSetupWidget.h +++ b/include/AudioDeviceSetupWidget.h @@ -45,4 +45,4 @@ public: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_AUDIO_DEVICE_SETUP_WIDGET_H diff --git a/include/AudioDummy.h b/include/AudioDummy.h index 37363d501..e34260171 100644 --- a/include/AudioDummy.h +++ b/include/AudioDummy.h @@ -116,4 +116,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_AUDIO_DUMMY_H diff --git a/include/AudioEngine.h b/include/AudioEngine.h index 534182d69..d0f269d87 100644 --- a/include/AudioEngine.h +++ b/include/AudioEngine.h @@ -487,4 +487,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_AUDIO_ENGINE_H diff --git a/include/AudioEngineProfiler.h b/include/AudioEngineProfiler.h index 1f72939be..7b5191e76 100644 --- a/include/AudioEngineProfiler.h +++ b/include/AudioEngineProfiler.h @@ -62,4 +62,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_AUDIO_ENGINE_PROFILER_H diff --git a/include/AudioEngineWorkerThread.h b/include/AudioEngineWorkerThread.h index 0f41982a1..112930808 100644 --- a/include/AudioEngineWorkerThread.h +++ b/include/AudioEngineWorkerThread.h @@ -121,4 +121,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_AUDIO_ENGINE_WORKER_THREAD_H diff --git a/include/AudioFileDevice.h b/include/AudioFileDevice.h index fb98315db..dc9a786a4 100644 --- a/include/AudioFileDevice.h +++ b/include/AudioFileDevice.h @@ -73,4 +73,4 @@ using AudioFileDeviceInstantiaton } // namespace lmms -#endif +#endif // LMMS_AUDIO_FILE_DEVICE_H diff --git a/include/AudioFileFlac.h b/include/AudioFileFlac.h index 6750d264a..944e30478 100644 --- a/include/AudioFileFlac.h +++ b/include/AudioFileFlac.h @@ -77,4 +77,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_AUDIO_FILE_FLAC_H diff --git a/include/AudioFileMP3.h b/include/AudioFileMP3.h index 61406cced..4289ad211 100644 --- a/include/AudioFileMP3.h +++ b/include/AudioFileMP3.h @@ -75,4 +75,4 @@ private: #endif // LMMS_HAVE_MP3LAME -#endif +#endif // LMMS_AUDIO_FILE_MP3_H diff --git a/include/AudioFileOgg.h b/include/AudioFileOgg.h index 981b61733..77be8ca1c 100644 --- a/include/AudioFileOgg.h +++ b/include/AudioFileOgg.h @@ -113,4 +113,4 @@ private: #endif // LMMS_HAVE_OGGVORBIS -#endif +#endif // LMMS_AUDIO_FILE_OGG_H diff --git a/include/AudioFileWave.h b/include/AudioFileWave.h index 06b797cc6..c186aaaa7 100644 --- a/include/AudioFileWave.h +++ b/include/AudioFileWave.h @@ -71,4 +71,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_AUDIO_FILE_WAVE_H diff --git a/include/AudioJack.h b/include/AudioJack.h index 5e63074bd..2ef0f665c 100644 --- a/include/AudioJack.h +++ b/include/AudioJack.h @@ -144,4 +144,4 @@ signals: #endif // LMMS_HAVE_JACK -#endif +#endif // LMMS_AUDIO_JACK_H diff --git a/include/AudioOss.h b/include/AudioOss.h index 045cc6c56..55f64de85 100644 --- a/include/AudioOss.h +++ b/include/AudioOss.h @@ -92,4 +92,4 @@ private: #endif // LMMS_HAVE_OSS -#endif +#endif // LMMS_AUDIO_OSS_H diff --git a/include/AudioPort.h b/include/AudioPort.h index 38e495436..d9803d205 100644 --- a/include/AudioPort.h +++ b/include/AudioPort.h @@ -138,4 +138,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_AUDIO_PORT_H diff --git a/include/AudioPortAudio.h b/include/AudioPortAudio.h index 8ab18ce6e..01b8f3fd7 100644 --- a/include/AudioPortAudio.h +++ b/include/AudioPortAudio.h @@ -163,4 +163,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_AUDIO_PORTAUDIO_H diff --git a/include/AudioPulseAudio.h b/include/AudioPulseAudio.h index bb5541a30..b6a998274 100644 --- a/include/AudioPulseAudio.h +++ b/include/AudioPulseAudio.h @@ -104,4 +104,4 @@ private: #endif // LMMS_HAVE_PULSEAUDIO -#endif +#endif // LMMS_AUDIO_PULSEAUDIO_H diff --git a/include/AudioSampleRecorder.h b/include/AudioSampleRecorder.h index 23c4643d8..8937ceb5e 100644 --- a/include/AudioSampleRecorder.h +++ b/include/AudioSampleRecorder.h @@ -59,4 +59,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_AUDIO_SAMPLE_RECORDER_H diff --git a/include/AudioSdl.h b/include/AudioSdl.h index bd7f4b960..62db8b68a 100644 --- a/include/AudioSdl.h +++ b/include/AudioSdl.h @@ -115,4 +115,4 @@ private: #endif // LMMS_HAVE_SDL -#endif +#endif // LMMS_AUDIO_SDL_H diff --git a/include/AudioSndio.h b/include/AudioSndio.h index b7f42aca2..594ca94e7 100644 --- a/include/AudioSndio.h +++ b/include/AudioSndio.h @@ -89,4 +89,4 @@ private: #endif // LMMS_HAVE_SNDIO -#endif +#endif // LMMS_AUDIO_SNDIO_H diff --git a/include/AudioSoundIo.h b/include/AudioSoundIo.h index b29ff3779..b327f7d84 100644 --- a/include/AudioSoundIo.h +++ b/include/AudioSoundIo.h @@ -145,4 +145,4 @@ private: #endif // LMMS_HAVE_SOUNDIO -#endif +#endif // LMMS_AUDIO_SOUNDIO_H diff --git a/include/AutomatableButton.h b/include/AutomatableButton.h index 4a695a677..3d78b8e9c 100644 --- a/include/AutomatableButton.h +++ b/include/AutomatableButton.h @@ -108,4 +108,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_AUTOMATABLE_BUTTON_H diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index 2fccf31f4..1e6d5eda3 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -507,5 +507,4 @@ using AutomatedValueMap = QMap; } // namespace lmms -#endif - +#endif // LMMS_AUTOMATABLE_MODEL_H diff --git a/include/AutomatableModelView.h b/include/AutomatableModelView.h index e2475be48..12b2e4d49 100644 --- a/include/AutomatableModelView.h +++ b/include/AutomatableModelView.h @@ -137,5 +137,4 @@ using BoolModelView = TypedModelView; } // namespace lmms::gui -#endif - +#endif // LMMS_GUI_AUTOMATABLE_MODEL_VIEW_H diff --git a/include/AutomatableSlider.h b/include/AutomatableSlider.h index 9ec55c2df..cb1a6965f 100644 --- a/include/AutomatableSlider.h +++ b/include/AutomatableSlider.h @@ -76,4 +76,4 @@ using sliderModel = IntModel; } // namespace lmms::gui -#endif +#endif // LMMS_GUI_AUTOMATABLE_SLIDER_H diff --git a/include/AutomationClip.h b/include/AutomationClip.h index 7281af133..077c282f8 100644 --- a/include/AutomationClip.h +++ b/include/AutomationClip.h @@ -260,4 +260,4 @@ inline int POS(AutomationClip::TimemapIterator it) } // namespace lmms -#endif +#endif // LMMS_AUTOMATION_CLIP_H diff --git a/include/AutomationClipView.h b/include/AutomationClipView.h index 69d4943bc..a20e2ce28 100644 --- a/include/AutomationClipView.h +++ b/include/AutomationClipView.h @@ -85,4 +85,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_GUI_AUTOMATION_CLIP_VIEW_H diff --git a/include/AutomationEditor.h b/include/AutomationEditor.h index 8ead191a9..c2ab98092 100644 --- a/include/AutomationEditor.h +++ b/include/AutomationEditor.h @@ -304,4 +304,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_GUI_AUTOMATION_EDITOR_H diff --git a/include/AutomationNode.h b/include/AutomationNode.h index 9f4a4f219..a922109e6 100644 --- a/include/AutomationNode.h +++ b/include/AutomationNode.h @@ -156,4 +156,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_AUTOMATION_NODE_H diff --git a/include/AutomationTrack.h b/include/AutomationTrack.h index 653174caa..64c2cc43a 100644 --- a/include/AutomationTrack.h +++ b/include/AutomationTrack.h @@ -62,4 +62,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_AUTOMATION_TRACK_H diff --git a/include/AutomationTrackView.h b/include/AutomationTrackView.h index d948d762a..449e9bef8 100644 --- a/include/AutomationTrackView.h +++ b/include/AutomationTrackView.h @@ -52,4 +52,4 @@ public: } // namespace lmms -#endif +#endif // LMMS_GUI_AUTOMATION_TRACK_VIEW_H diff --git a/include/BandLimitedWave.h b/include/BandLimitedWave.h index 51e55c337..2a12c62e3 100644 --- a/include/BandLimitedWave.h +++ b/include/BandLimitedWave.h @@ -149,7 +149,8 @@ public: return sr; -/* lookup = lookup << 1; + /* + lookup = lookup << 1; tlen = tlen << 1; t += 1; const sample_t s3 = s_waveforms[ _wave ].sampleAt( t, lookup ); @@ -159,7 +160,7 @@ public: const float ip2 = ( ( tlen - _wavelen ) / tlen - 0.5 ) * 2.0; return linearInterpolate( s12, s34, ip2 ); - */ + */ }; @@ -174,4 +175,4 @@ public: } // namespace lmms -#endif +#endif // LMMS_BANDLIMITEDWAVE_H diff --git a/include/BasicFilters.h b/include/BasicFilters.h index 6912f3d36..c10c47489 100644 --- a/include/BasicFilters.h +++ b/include/BasicFilters.h @@ -917,4 +917,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_BASIC_FILTERS_H diff --git a/include/BufferManager.h b/include/BufferManager.h index 8e93afc92..712e420ff 100644 --- a/include/BufferManager.h +++ b/include/BufferManager.h @@ -54,4 +54,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_BUFFER_MANAGER_H diff --git a/include/CPULoadWidget.h b/include/CPULoadWidget.h index a249cdc5e..904445c67 100644 --- a/include/CPULoadWidget.h +++ b/include/CPULoadWidget.h @@ -69,4 +69,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_CPU_LOAD_WIDGET_H diff --git a/include/CaptionMenu.h b/include/CaptionMenu.h index 87aedf133..4a8889a83 100644 --- a/include/CaptionMenu.h +++ b/include/CaptionMenu.h @@ -46,4 +46,4 @@ public: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_CAPTION_MENU_H diff --git a/include/Clip.h b/include/Clip.h index 75416ef94..8f4162d96 100644 --- a/include/Clip.h +++ b/include/Clip.h @@ -194,4 +194,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_CLIP_H diff --git a/include/ClipView.h b/include/ClipView.h index a342590e1..32c5130b9 100644 --- a/include/ClipView.h +++ b/include/ClipView.h @@ -252,4 +252,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_GUI_CLIP_VIEW_H diff --git a/include/Clipboard.h b/include/Clipboard.h index 3c38c90fe..c6ae66ee8 100644 --- a/include/Clipboard.h +++ b/include/Clipboard.h @@ -68,4 +68,4 @@ namespace lmms::Clipboard } // namespace lmms::Clipboard -#endif +#endif // LMMS_CLIPBOARD_H diff --git a/include/ColorChooser.h b/include/ColorChooser.h index da4069f5d..0e85ea9bb 100644 --- a/include/ColorChooser.h +++ b/include/ColorChooser.h @@ -68,4 +68,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_COLOR_CHOOSER_H diff --git a/include/ComboBox.h b/include/ComboBox.h index ba2410491..8153451e8 100644 --- a/include/ComboBox.h +++ b/include/ComboBox.h @@ -82,4 +82,4 @@ private slots: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_COMBOBOX_H diff --git a/include/ComboBoxModel.h b/include/ComboBoxModel.h index a895b838f..8fd1f49f4 100644 --- a/include/ComboBoxModel.h +++ b/include/ComboBoxModel.h @@ -95,4 +95,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_COMBOBOX_MODEL_H diff --git a/include/ConfigManager.h b/include/ConfigManager.h index abeb5246f..eee069681 100644 --- a/include/ConfigManager.h +++ b/include/ConfigManager.h @@ -313,4 +313,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_CONFIG_MANAGER_H diff --git a/include/ControlLayout.h b/include/ControlLayout.h index e78609a37..568ce1a85 100644 --- a/include/ControlLayout.h +++ b/include/ControlLayout.h @@ -141,4 +141,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_CONTROL_LAYOUT_H diff --git a/include/Controller.h b/include/Controller.h index 0bb229d38..0a5eb0f36 100644 --- a/include/Controller.h +++ b/include/Controller.h @@ -183,4 +183,4 @@ signals: } // namespace lmms -#endif +#endif // LMMS_CONTROLLER_H diff --git a/include/ControllerConnection.h b/include/ControllerConnection.h index d75d529f6..4473b68e0 100644 --- a/include/ControllerConnection.h +++ b/include/ControllerConnection.h @@ -127,4 +127,4 @@ signals: } // namespace lmms -#endif +#endif // LMMS_CONTROLLER_CONNECTION_H diff --git a/include/ControllerConnectionDialog.h b/include/ControllerConnectionDialog.h index 2e3446072..6fb9d45d0 100644 --- a/include/ControllerConnectionDialog.h +++ b/include/ControllerConnectionDialog.h @@ -110,4 +110,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_GUI_CONTROLLER_CONNECTION_DIALOG_H diff --git a/include/ControllerDialog.h b/include/ControllerDialog.h index 81a9a0eb6..0c53a8c84 100644 --- a/include/ControllerDialog.h +++ b/include/ControllerDialog.h @@ -61,4 +61,4 @@ protected: } // namespace lmms -#endif +#endif // LMMS_GUI_CONTROLLER_DIALOG_H diff --git a/include/ControllerRackView.h b/include/ControllerRackView.h index 1133e8ec8..303cc2b40 100644 --- a/include/ControllerRackView.h +++ b/include/ControllerRackView.h @@ -92,4 +92,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_GUI_CONTROLLER_RACK_VIEW_H diff --git a/include/ControllerView.h b/include/ControllerView.h index 44f362b70..d1ba533a1 100644 --- a/include/ControllerView.h +++ b/include/ControllerView.h @@ -88,4 +88,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_CONTROLLER_VIEW_H diff --git a/include/Controls.h b/include/Controls.h index 53c93a36f..5ed19027e 100644 --- a/include/Controls.h +++ b/include/Controls.h @@ -144,4 +144,4 @@ public: } // namespace lmms -#endif +#endif // LMMS_GUI_CONTROLS_H diff --git a/include/CustomTextKnob.h b/include/CustomTextKnob.h index 25bba1315..19768ec87 100644 --- a/include/CustomTextKnob.h +++ b/include/CustomTextKnob.h @@ -57,4 +57,4 @@ protected: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_CUSTOM_TEXT_KNOB_H diff --git a/include/DataFile.h b/include/DataFile.h index 18f9697b0..a91b37f9b 100644 --- a/include/DataFile.h +++ b/include/DataFile.h @@ -153,4 +153,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_DATA_FILE_H diff --git a/include/Delay.h b/include/Delay.h index ef23d7be1..daa871baf 100644 --- a/include/Delay.h +++ b/include/Delay.h @@ -364,4 +364,4 @@ using StereoAllpassDelay = AllpassDelay<2>; } // namespace lmms -#endif +#endif // LMMS_DELAY_H diff --git a/include/DeprecationHelper.h b/include/DeprecationHelper.h index f1c68902b..b9be6d42f 100644 --- a/include/DeprecationHelper.h +++ b/include/DeprecationHelper.h @@ -66,4 +66,4 @@ inline QPoint position(QWheelEvent *wheelEvent) } // namespace lmms -#endif +#endif // LMMS_DEPRECATIONHELPER_H diff --git a/include/DetuningHelper.h b/include/DetuningHelper.h index 41723bee8..e5d5f5712 100644 --- a/include/DetuningHelper.h +++ b/include/DetuningHelper.h @@ -64,4 +64,4 @@ public: } // namespace lmms -#endif +#endif // LMMS_DETUNING_HELPER_H diff --git a/include/DrumSynth.h b/include/DrumSynth.h index 9b759ac1a..750055ddb 100644 --- a/include/DrumSynth.h +++ b/include/DrumSynth.h @@ -56,4 +56,4 @@ class DrumSynth { } // namespace lmms -#endif +#endif // LMMS_DRUM_SYNTH_H diff --git a/include/DspEffectLibrary.h b/include/DspEffectLibrary.h index 0a19783f6..d8268fd8d 100644 --- a/include/DspEffectLibrary.h +++ b/include/DspEffectLibrary.h @@ -330,5 +330,4 @@ namespace lmms::DspEffectLibrary } // namespace lmms::DspEffectLibrary - -#endif +#endif // LMMS_DSPEFFECTLIBRARY_H diff --git a/include/DummyEffect.h b/include/DummyEffect.h index 945738e1b..0a80b90a9 100644 --- a/include/DummyEffect.h +++ b/include/DummyEffect.h @@ -149,4 +149,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_DUMMY_EFFECT_H diff --git a/include/DummyInstrument.h b/include/DummyInstrument.h index 19b6b6fbd..aefa035db 100644 --- a/include/DummyInstrument.h +++ b/include/DummyInstrument.h @@ -77,4 +77,4 @@ public: } // namespace lmms -#endif +#endif // LMMS_DUMMY_INSTRUMENT_H diff --git a/include/DummyPlugin.h b/include/DummyPlugin.h index ad517c1a9..3f6746b74 100644 --- a/include/DummyPlugin.h +++ b/include/DummyPlugin.h @@ -68,4 +68,4 @@ protected: } // namespace lmms -#endif +#endif // LMMS_DUMMY_PLUGIN_H diff --git a/include/Editor.h b/include/Editor.h index ad330ac06..c5e9a2d05 100644 --- a/include/Editor.h +++ b/include/Editor.h @@ -113,4 +113,4 @@ protected: } // namespace lmms::gui -#endif +#endif // LMMS_EDITOR_H diff --git a/include/Effect.h b/include/Effect.h index a9952d339..1f566e0e9 100644 --- a/include/Effect.h +++ b/include/Effect.h @@ -241,4 +241,4 @@ using EffectKeyList = Effect::Descriptor::SubPluginFeatures::KeyList; } // namespace lmms -#endif +#endif // LMMS_EFFECT_H diff --git a/include/EffectChain.h b/include/EffectChain.h index dad4de5e1..57cf8d547 100644 --- a/include/EffectChain.h +++ b/include/EffectChain.h @@ -85,4 +85,4 @@ signals: } // namespace lmms -#endif +#endif // LMMS_EFFECT_CHAIN_H diff --git a/include/EffectControlDialog.h b/include/EffectControlDialog.h index bda845dc5..4bef5ee79 100644 --- a/include/EffectControlDialog.h +++ b/include/EffectControlDialog.h @@ -64,4 +64,4 @@ protected: } // namespace lmms -#endif +#endif // LMMS_GUI_EFFECT_CONTROL_DIALOG_H diff --git a/include/EffectControls.h b/include/EffectControls.h index dfecc0792..294f61027 100644 --- a/include/EffectControls.h +++ b/include/EffectControls.h @@ -82,4 +82,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_EFFECT_CONTROLS_H diff --git a/include/EffectRackView.h b/include/EffectRackView.h index 96f70548a..a1e21be09 100644 --- a/include/EffectRackView.h +++ b/include/EffectRackView.h @@ -88,4 +88,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_EFFECT_RACK_VIEW_H diff --git a/include/EffectSelectDialog.h b/include/EffectSelectDialog.h index c31f96e14..493b07774 100644 --- a/include/EffectSelectDialog.h +++ b/include/EffectSelectDialog.h @@ -70,5 +70,4 @@ private: } // namespace lmms::gui - -#endif +#endif // LMMS_GUI_EFFECT_SELECT_DIALOG_H diff --git a/include/EffectView.h b/include/EffectView.h index fb19d52dd..5b669114d 100644 --- a/include/EffectView.h +++ b/include/EffectView.h @@ -96,4 +96,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_EFFECT_VIEW_H diff --git a/include/Engine.h b/include/Engine.h index 0cb77315f..ed4cbd93c 100644 --- a/include/Engine.h +++ b/include/Engine.h @@ -155,4 +155,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_ENGINE_H diff --git a/include/EnvelopeAndLfoParameters.h b/include/EnvelopeAndLfoParameters.h index 0a90ec68b..a713a90f3 100644 --- a/include/EnvelopeAndLfoParameters.h +++ b/include/EnvelopeAndLfoParameters.h @@ -190,4 +190,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_ENVELOPE_AND_LFO_PARAMETERS_H diff --git a/include/EnvelopeAndLfoView.h b/include/EnvelopeAndLfoView.h index e927e9fcc..b5c7a67d4 100644 --- a/include/EnvelopeAndLfoView.h +++ b/include/EnvelopeAndLfoView.h @@ -104,4 +104,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_GUI_ENVELOPE_AND_LFO_VIEW_H diff --git a/include/ExportFilter.h b/include/ExportFilter.h index 13a3c179d..acbdbb65e 100644 --- a/include/ExportFilter.h +++ b/include/ExportFilter.h @@ -69,4 +69,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_EXPORT_FILTER_H diff --git a/include/ExportProjectDialog.h b/include/ExportProjectDialog.h index af33d6766..56a9fc1f5 100644 --- a/include/ExportProjectDialog.h +++ b/include/ExportProjectDialog.h @@ -69,5 +69,4 @@ private: } // namespace lmms::gui - -#endif +#endif // LMMS_GUI_EXPORT_PROJECT_DIALOG_H diff --git a/include/FadeButton.h b/include/FadeButton.h index df0e2abf2..166ef5f21 100644 --- a/include/FadeButton.h +++ b/include/FadeButton.h @@ -76,4 +76,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_FADE_BUTTON_H diff --git a/include/Fader.h b/include/Fader.h index cfffba843..2847819a4 100644 --- a/include/Fader.h +++ b/include/Fader.h @@ -173,5 +173,4 @@ private: } // namespace lmms::gui - -#endif +#endif // LMMS_GUI_FADER_H diff --git a/include/FifoBuffer.h b/include/FifoBuffer.h index 4b5682a51..cdb1df41f 100644 --- a/include/FifoBuffer.h +++ b/include/FifoBuffer.h @@ -94,4 +94,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_FIFO_BUFFER_H diff --git a/include/FileBrowser.h b/include/FileBrowser.h index 387be38d1..51103b19f 100644 --- a/include/FileBrowser.h +++ b/include/FileBrowser.h @@ -297,4 +297,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_GUI_FILE_BROWSER_H diff --git a/include/FileDialog.h b/include/FileDialog.h index a999fff16..67ef1d8eb 100644 --- a/include/FileDialog.h +++ b/include/FileDialog.h @@ -56,4 +56,4 @@ public: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_FILE_DIALOG_H diff --git a/include/Graph.h b/include/Graph.h index d04fd926c..f62215ac2 100644 --- a/include/Graph.h +++ b/include/Graph.h @@ -227,4 +227,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_GUI_GRAPH_H diff --git a/include/GroupBox.h b/include/GroupBox.h index bf2773e23..6a8f424f9 100644 --- a/include/GroupBox.h +++ b/include/GroupBox.h @@ -73,5 +73,4 @@ private: } // namespace lmms::gui - -#endif +#endif // LMMS_GUI_GROUP_BOX_H diff --git a/include/GuiApplication.h b/include/GuiApplication.h index dd87a5607..3a0851499 100644 --- a/include/GuiApplication.h +++ b/include/GuiApplication.h @@ -93,4 +93,4 @@ LMMS_EXPORT GuiApplication* getGUI(); } // namespace lmms::gui -#endif +#endif // LMMS_GUI_GUI_APPLICATION_H diff --git a/include/ImportFilter.h b/include/ImportFilter.h index 587a62a78..9c73b3861 100644 --- a/include/ImportFilter.h +++ b/include/ImportFilter.h @@ -114,4 +114,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_IMPORT_FILTER_H diff --git a/include/InlineAutomation.h b/include/InlineAutomation.h index fbecd2769..3e27e137b 100644 --- a/include/InlineAutomation.h +++ b/include/InlineAutomation.h @@ -99,4 +99,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_INLINE_AUTOMATION_H diff --git a/include/Instrument.h b/include/Instrument.h index 3ea8bdf2f..1c42c970e 100644 --- a/include/Instrument.h +++ b/include/Instrument.h @@ -154,4 +154,4 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(Instrument::Flags) } // namespace lmms -#endif +#endif // LMMS_INSTRUMENT_H diff --git a/include/InstrumentFunctionViews.h b/include/InstrumentFunctionViews.h index 3abd8eae7..71a6e8aaa 100644 --- a/include/InstrumentFunctionViews.h +++ b/include/InstrumentFunctionViews.h @@ -99,4 +99,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_INSTRUMENT_FUNCTION_VIEWS_H diff --git a/include/InstrumentFunctions.h b/include/InstrumentFunctions.h index 5b6c1af6d..f62b74e9a 100644 --- a/include/InstrumentFunctions.h +++ b/include/InstrumentFunctions.h @@ -224,4 +224,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_INSTRUMENT_FUNCTIONS_H diff --git a/include/InstrumentMidiIOView.h b/include/InstrumentMidiIOView.h index dd6e43151..7877229a2 100644 --- a/include/InstrumentMidiIOView.h +++ b/include/InstrumentMidiIOView.h @@ -77,4 +77,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_GUI_INSTRUMENT_MIDI_IO_VIEW_H diff --git a/include/InstrumentMiscView.h b/include/InstrumentMiscView.h index 9aee23676..28f3c6a8e 100644 --- a/include/InstrumentMiscView.h +++ b/include/InstrumentMiscView.h @@ -71,4 +71,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_GUI_INSTRUMENT_MISC_VIEW_H diff --git a/include/InstrumentPlayHandle.h b/include/InstrumentPlayHandle.h index b65f906ae..bbf53d16c 100644 --- a/include/InstrumentPlayHandle.h +++ b/include/InstrumentPlayHandle.h @@ -85,4 +85,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_INSTRUMENT_PLAY_HANDLE_H diff --git a/include/InstrumentSoundShaping.h b/include/InstrumentSoundShaping.h index 607871c85..6db3078ec 100644 --- a/include/InstrumentSoundShaping.h +++ b/include/InstrumentSoundShaping.h @@ -92,4 +92,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_INSTRUMENT_SOUND_SHAPING_H diff --git a/include/InstrumentSoundShapingView.h b/include/InstrumentSoundShapingView.h index f37cfaa55..8f671514a 100644 --- a/include/InstrumentSoundShapingView.h +++ b/include/InstrumentSoundShapingView.h @@ -73,4 +73,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_INSTRUMENT_SOUND_SHAPING_VIEW_H diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index 6fa41b4a1..7c6d1d795 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -325,4 +325,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_INSTRUMENT_TRACK_H diff --git a/include/InstrumentTrackView.h b/include/InstrumentTrackView.h index 66fb7804b..363f5b3ab 100644 --- a/include/InstrumentTrackView.h +++ b/include/InstrumentTrackView.h @@ -121,4 +121,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_INSTRUMENT_TRACK_VIEW_H diff --git a/include/InstrumentTrackWindow.h b/include/InstrumentTrackWindow.h index f50b138df..d41bbdac8 100644 --- a/include/InstrumentTrackWindow.h +++ b/include/InstrumentTrackWindow.h @@ -169,4 +169,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_GUI_INSTRUMENT_TRACK_WINDOW_H diff --git a/include/InstrumentView.h b/include/InstrumentView.h index ff4b9cd66..40014a11f 100644 --- a/include/InstrumentView.h +++ b/include/InstrumentView.h @@ -75,4 +75,4 @@ public: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_INSTRUMENT_VIEW_H diff --git a/include/IoHelper.h b/include/IoHelper.h index 423cbaab3..8043df9af 100644 --- a/include/IoHelper.h +++ b/include/IoHelper.h @@ -91,4 +91,4 @@ int fileToDescriptor(FILE* f, bool closeFile = true) } // namespace lmms -#endif +#endif // LMMS_IO_HELPER_H diff --git a/include/JournallingObject.h b/include/JournallingObject.h index 15e071577..f3e134f34 100644 --- a/include/JournallingObject.h +++ b/include/JournallingObject.h @@ -103,4 +103,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_JOURNALLING_OBJECT_H diff --git a/include/Keymap.h b/include/Keymap.h index 88f0df428..967d80789 100644 --- a/include/Keymap.h +++ b/include/Keymap.h @@ -80,4 +80,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_KEYMAP_H diff --git a/include/Knob.h b/include/Knob.h index 94fb8b640..18b26f7e6 100644 --- a/include/Knob.h +++ b/include/Knob.h @@ -213,4 +213,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_KNOB_H diff --git a/include/Ladspa2LMMS.h b/include/Ladspa2LMMS.h index d4fd12b2d..abb969124 100644 --- a/include/Ladspa2LMMS.h +++ b/include/Ladspa2LMMS.h @@ -81,4 +81,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_LADSPA_2_LMMS_H diff --git a/include/LadspaBase.h b/include/LadspaBase.h index 442d12293..51c0ca202 100644 --- a/include/LadspaBase.h +++ b/include/LadspaBase.h @@ -83,4 +83,4 @@ inline Plugin::Descriptor::SubPluginFeatures::Key ladspaKeyToSubPluginKey( } // namespace lmms -#endif +#endif // LMMS_LADSPA_BASE_H diff --git a/include/LadspaControl.h b/include/LadspaControl.h index 9bc83e352..e4f0cd745 100644 --- a/include/LadspaControl.h +++ b/include/LadspaControl.h @@ -131,4 +131,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_LADSPA_CONTROL_H diff --git a/include/LadspaControlView.h b/include/LadspaControlView.h index 4638d5b5c..4f12c29e2 100644 --- a/include/LadspaControlView.h +++ b/include/LadspaControlView.h @@ -55,4 +55,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_GUI_LADSPA_CONTROL_VIEW_H diff --git a/include/LadspaManager.h b/include/LadspaManager.h index 7b8639779..8c00d2604 100644 --- a/include/LadspaManager.h +++ b/include/LadspaManager.h @@ -349,4 +349,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_LADSPA_MANAGER_H diff --git a/include/LcdFloatSpinBox.h b/include/LcdFloatSpinBox.h index 3dcf500b9..74a870114 100644 --- a/include/LcdFloatSpinBox.h +++ b/include/LcdFloatSpinBox.h @@ -84,4 +84,4 @@ using LcdFloatSpinBoxModel = FloatModel; } // namespace lmms::gui -#endif +#endif // LMMS_GUI_LCD_FLOATSPINBOX_H diff --git a/include/LcdSpinBox.h b/include/LcdSpinBox.h index 6dcb68c1b..aeccd2635 100644 --- a/include/LcdSpinBox.h +++ b/include/LcdSpinBox.h @@ -89,4 +89,4 @@ using LcdSpinBoxModel = IntModel; } // namespace lmms::gui -#endif +#endif // LMMS_GUI_LCD_SPINBOX_H diff --git a/include/LcdWidget.h b/include/LcdWidget.h index 665668b3f..f19c2c583 100644 --- a/include/LcdWidget.h +++ b/include/LcdWidget.h @@ -116,4 +116,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_LCD_WIDGET_H diff --git a/include/LedCheckBox.h b/include/LedCheckBox.h index 12642ef3b..95016b87f 100644 --- a/include/LedCheckBox.h +++ b/include/LedCheckBox.h @@ -83,4 +83,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_LED_CHECKBOX_H diff --git a/include/LeftRightNav.h b/include/LeftRightNav.h index e752d44c0..49ad25ecf 100644 --- a/include/LeftRightNav.h +++ b/include/LeftRightNav.h @@ -51,4 +51,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_LEFT_RIGHT_NAV_H diff --git a/include/LfoController.h b/include/LfoController.h index ccd5804c7..1c63ba698 100644 --- a/include/LfoController.h +++ b/include/LfoController.h @@ -136,4 +136,4 @@ private slots: } // namespace lmms -#endif +#endif // LMMS_LFO_CONTROLLER_H diff --git a/include/LinkedModelGroupViews.h b/include/LinkedModelGroupViews.h index 08c25a8bb..cf5aabd0d 100644 --- a/include/LinkedModelGroupViews.h +++ b/include/LinkedModelGroupViews.h @@ -22,8 +22,8 @@ * */ -#ifndef LMMS_GUI_LINKEDMODELGROUPVIEWS_H -#define LMMS_GUI_LINKEDMODELGROUPVIEWS_H +#ifndef LMMS_GUI_LINKED_MODEL_GROUP_VIEWS_H +#define LMMS_GUI_LINKED_MODEL_GROUP_VIEWS_H #include #include @@ -118,4 +118,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_GUI_LINKED_MODEL_GROUP_VIEWS_H diff --git a/include/LinkedModelGroups.h b/include/LinkedModelGroups.h index 11950d85e..3f274d10c 100644 --- a/include/LinkedModelGroups.h +++ b/include/LinkedModelGroups.h @@ -22,8 +22,8 @@ * */ -#ifndef LMMS_LINKEDMODELGROUPS_H -#define LMMS_LINKEDMODELGROUPS_H +#ifndef LMMS_LINKED_MODEL_GROUPS_H +#define LMMS_LINKED_MODEL_GROUPS_H #include @@ -176,4 +176,4 @@ public: } // namespace lmms -#endif +#endif // LMMS_LINKED_MODEL_GROUPS_H diff --git a/include/LmmsPalette.h b/include/LmmsPalette.h index 68cd2d2ab..91a469de0 100644 --- a/include/LmmsPalette.h +++ b/include/LmmsPalette.h @@ -87,4 +87,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_LMMS_PALETTE_H diff --git a/include/LmmsStyle.h b/include/LmmsStyle.h index c560b5be8..b3be03952 100644 --- a/include/LmmsStyle.h +++ b/include/LmmsStyle.h @@ -95,4 +95,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_LMMS_STYLE_H diff --git a/include/LocaleHelper.h b/include/LocaleHelper.h index 61298f42b..9c829fcaa 100644 --- a/include/LocaleHelper.h +++ b/include/LocaleHelper.h @@ -67,4 +67,4 @@ inline float toFloat(QString str, bool* ok = nullptr) } // namespace lmms::LocaleHelper -#endif +#endif // LMMS_LOCALEHELPER_H diff --git a/include/LocklessAllocator.h b/include/LocklessAllocator.h index f1b3dea40..d44b99543 100644 --- a/include/LocklessAllocator.h +++ b/include/LocklessAllocator.h @@ -84,4 +84,4 @@ public: } // namespace lmms -#endif +#endif // LMMS_LOCKLESS_ALLOCATOR_H diff --git a/include/LocklessList.h b/include/LocklessList.h index e5c5cce71..4a0c27de0 100644 --- a/include/LocklessList.h +++ b/include/LocklessList.h @@ -97,4 +97,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_LOCKLESS_LIST_H diff --git a/include/LocklessRingBuffer.h b/include/LocklessRingBuffer.h index 904e54f9c..99c48cc90 100644 --- a/include/LocklessRingBuffer.h +++ b/include/LocklessRingBuffer.h @@ -89,4 +89,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_LOCKLESS_RING_BUFFER_H diff --git a/include/Lv2Basics.h b/include/Lv2Basics.h index 73f006b46..3dae4c9f2 100644 --- a/include/Lv2Basics.h +++ b/include/Lv2Basics.h @@ -68,4 +68,4 @@ std::string stdStringFromPortName(const LilvPlugin* plug, const LilvPort* port); #endif // LMMS_HAVE_LV2 -#endif +#endif // LMMS_LV2BASICS_H diff --git a/include/Lv2ControlBase.h b/include/Lv2ControlBase.h index dcb90f27a..93b3b21ef 100644 --- a/include/Lv2ControlBase.h +++ b/include/Lv2ControlBase.h @@ -164,4 +164,4 @@ private: #endif // LMMS_HAVE_LV2 -#endif +#endif // LMMS_LV2_CONTROL_BASE_H diff --git a/include/Lv2Evbuf.h b/include/Lv2Evbuf.h index ecf61ec99..319bdf9ce 100644 --- a/include/Lv2Evbuf.h +++ b/include/Lv2Evbuf.h @@ -155,4 +155,4 @@ lv2_evbuf_write( LV2_Evbuf_Iterator* iter, #endif // LMMS_HAVE_LV2 -#endif +#endif // LMMS_LV2_EVBUF_H diff --git a/include/Lv2Features.h b/include/Lv2Features.h index 99a5762b0..b4fd6c06d 100644 --- a/include/Lv2Features.h +++ b/include/Lv2Features.h @@ -84,4 +84,4 @@ private: #endif // LMMS_HAVE_LV2 -#endif +#endif // LMMS_LV2_FEATURES_H diff --git a/include/Lv2Manager.h b/include/Lv2Manager.h index 45ca868dd..b62e989cf 100644 --- a/include/Lv2Manager.h +++ b/include/Lv2Manager.h @@ -166,4 +166,4 @@ private: #endif // LMMS_HAVE_LV2 -#endif +#endif // LMMS_LV2_MANAGER_H diff --git a/include/Lv2Options.h b/include/Lv2Options.h index c81e4b953..ca4fe2b7f 100644 --- a/include/Lv2Options.h +++ b/include/Lv2Options.h @@ -107,4 +107,4 @@ private: #endif // LMMS_HAVE_LV2 -#endif +#endif // LMMS_LV2_OPTIONS_H diff --git a/include/Lv2Ports.h b/include/Lv2Ports.h index 7283ebbd3..0f0b02913 100644 --- a/include/Lv2Ports.h +++ b/include/Lv2Ports.h @@ -271,4 +271,4 @@ const Target* dcast(const PortBase* base) #endif // LMMS_HAVE_LV2 -#endif +#endif // LMMS_LV2PORTS_H diff --git a/include/Lv2Proc.h b/include/Lv2Proc.h index eea4e7c0e..7e6342ec4 100644 --- a/include/Lv2Proc.h +++ b/include/Lv2Proc.h @@ -221,4 +221,4 @@ private: #endif // LMMS_HAVE_LV2 -#endif +#endif // LMMS_LV2_PROC_H diff --git a/include/Lv2SubPluginFeatures.h b/include/Lv2SubPluginFeatures.h index f8fbf55df..497c72830 100644 --- a/include/Lv2SubPluginFeatures.h +++ b/include/Lv2SubPluginFeatures.h @@ -66,4 +66,4 @@ public: #endif // LMMS_HAVE_LV2 -#endif +#endif // LMMS_LV2_SUBPLUGIN_FEATURES_H diff --git a/include/Lv2UridCache.h b/include/Lv2UridCache.h index ab80760b0..b64003a2e 100644 --- a/include/Lv2UridCache.h +++ b/include/Lv2UridCache.h @@ -75,4 +75,4 @@ template<> struct Lv2UridCache::IdForType { static constexpr auto #endif // LMMS_HAVE_LV2 -#endif +#endif // LMMS_LV2_URID_CACHE_H diff --git a/include/Lv2UridMap.h b/include/Lv2UridMap.h index ec23f4c6d..b8733023e 100644 --- a/include/Lv2UridMap.h +++ b/include/Lv2UridMap.h @@ -76,4 +76,4 @@ public: #endif // LMMS_HAVE_LV2 -#endif +#endif // LMMS_LV2_URID_MAP_H diff --git a/include/Lv2ViewBase.h b/include/Lv2ViewBase.h index e84c6c5dc..f6d97d6aa 100644 --- a/include/Lv2ViewBase.h +++ b/include/Lv2ViewBase.h @@ -109,4 +109,4 @@ private: #endif // LMMS_HAVE_LV2 -#endif +#endif // LMMS_LV2_VIEW_BASE_H diff --git a/include/MainApplication.h b/include/MainApplication.h index 0ab2877e7..98fcdef20 100644 --- a/include/MainApplication.h +++ b/include/MainApplication.h @@ -64,4 +64,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_MAIN_APPLICATION_H diff --git a/include/MainWindow.h b/include/MainWindow.h index 78d7f48d8..c4bbb6767 100644 --- a/include/MainWindow.h +++ b/include/MainWindow.h @@ -263,4 +263,4 @@ signals: } // namespace lmms -#endif +#endif // LMMS_GUI_MAIN_WINDOW_H diff --git a/include/MemoryHelper.h b/include/MemoryHelper.h index 22ab10a6c..e709ffc8a 100644 --- a/include/MemoryHelper.h +++ b/include/MemoryHelper.h @@ -46,4 +46,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_MEMORY_HELPER_H diff --git a/include/MemoryManager.h b/include/MemoryManager.h index 6e172468b..fa2fe8110 100644 --- a/include/MemoryManager.h +++ b/include/MemoryManager.h @@ -108,4 +108,4 @@ void MM_FREE(T* ptr) } // namespace lmms -#endif +#endif // LMMS_MEMORY_MANAGER_H diff --git a/include/MeterDialog.h b/include/MeterDialog.h index 425590807..dca7e5de6 100644 --- a/include/MeterDialog.h +++ b/include/MeterDialog.h @@ -54,4 +54,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_METER_DIALOG_H diff --git a/include/MeterModel.h b/include/MeterModel.h index 9a6ec8015..6c0304e37 100644 --- a/include/MeterModel.h +++ b/include/MeterModel.h @@ -68,4 +68,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_METER_MODEL_H diff --git a/include/MicroTimer.h b/include/MicroTimer.h index e5c8e2f61..cd03403dc 100644 --- a/include/MicroTimer.h +++ b/include/MicroTimer.h @@ -48,4 +48,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_MICRO_TIMER_H diff --git a/include/Microtuner.h b/include/Microtuner.h index 795748b39..c92549581 100644 --- a/include/Microtuner.h +++ b/include/Microtuner.h @@ -74,4 +74,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_MICROTUNER_H diff --git a/include/MicrotunerConfig.h b/include/MicrotunerConfig.h index 3a5130b60..0706a530f 100644 --- a/include/MicrotunerConfig.h +++ b/include/MicrotunerConfig.h @@ -95,4 +95,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_MICROTUNER_CONFIG_H diff --git a/include/Midi.h b/include/Midi.h index 839d0b684..21db021b3 100644 --- a/include/Midi.h +++ b/include/Midi.h @@ -143,4 +143,4 @@ const int MidiMaxPitchBend = 16383; } // namespace lmms -#endif +#endif // LMMS_MIDI_H diff --git a/include/MidiAlsaRaw.h b/include/MidiAlsaRaw.h index a2b8c4e69..345cdbd54 100644 --- a/include/MidiAlsaRaw.h +++ b/include/MidiAlsaRaw.h @@ -85,4 +85,4 @@ private: #endif // LMMS_HAVE_ALSA -#endif +#endif // LMMS_MIDI_ALSA_RAW_H diff --git a/include/MidiAlsaSeq.h b/include/MidiAlsaSeq.h index d6f488c82..006cdefc8 100644 --- a/include/MidiAlsaSeq.h +++ b/include/MidiAlsaSeq.h @@ -158,4 +158,4 @@ signals: #endif // LMMS_HAVE_ALSA -#endif +#endif // LMMS_MIDI_ALSA_SEQ_H diff --git a/include/MidiApple.h b/include/MidiApple.h index 1b0d59218..37d408d4d 100644 --- a/include/MidiApple.h +++ b/include/MidiApple.h @@ -155,4 +155,4 @@ signals: #endif // LMMS_BUILD_APPLE -#endif +#endif // LMMS_MIDI_APPLE_H diff --git a/include/MidiCCRackView.h b/include/MidiCCRackView.h index ca99a7ce5..4cb82b3d8 100644 --- a/include/MidiCCRackView.h +++ b/include/MidiCCRackView.h @@ -73,4 +73,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_GUI_MIDI_CC_RACK_VIEW_H diff --git a/include/MidiClient.h b/include/MidiClient.h index 45ba54ee5..3a64f709c 100644 --- a/include/MidiClient.h +++ b/include/MidiClient.h @@ -173,4 +173,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_MIDI_CLIENT_H diff --git a/include/MidiClip.h b/include/MidiClip.h index 2dbedc0dd..bbb7d325d 100644 --- a/include/MidiClip.h +++ b/include/MidiClip.h @@ -154,4 +154,4 @@ signals: } // namespace lmms -#endif +#endif // LMMS_MIDI_CLIP_H diff --git a/include/MidiClipView.h b/include/MidiClipView.h index dd83f98b8..6558688b4 100644 --- a/include/MidiClipView.h +++ b/include/MidiClipView.h @@ -108,4 +108,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_GUI_MIDI_CLIP_VIEW_H diff --git a/include/MidiController.h b/include/MidiController.h index 19577281f..c4ef49590 100644 --- a/include/MidiController.h +++ b/include/MidiController.h @@ -92,4 +92,4 @@ protected: } // namespace lmms -#endif +#endif // LMMS_MIDI_CONTROLLER_H diff --git a/include/MidiDummy.h b/include/MidiDummy.h index 03deaf7bc..b117bd136 100644 --- a/include/MidiDummy.h +++ b/include/MidiDummy.h @@ -65,4 +65,4 @@ protected: } // namespace lmms -#endif +#endif // LMMS_MIDI_DUMMY_H diff --git a/include/MidiEvent.h b/include/MidiEvent.h index 03d3be604..956c33fb3 100644 --- a/include/MidiEvent.h +++ b/include/MidiEvent.h @@ -221,4 +221,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_MIDI_EVENT_H diff --git a/include/MidiEventProcessor.h b/include/MidiEventProcessor.h index 3e51d1177..1c45b3e3f 100644 --- a/include/MidiEventProcessor.h +++ b/include/MidiEventProcessor.h @@ -49,4 +49,4 @@ public: } // namespace lmms -#endif +#endif // LMMS_MIDI_EVENT_PROCESSOR_H diff --git a/include/MidiEventToByteSeq.h b/include/MidiEventToByteSeq.h index 03308d7b8..6490ae385 100644 --- a/include/MidiEventToByteSeq.h +++ b/include/MidiEventToByteSeq.h @@ -51,4 +51,4 @@ std::size_t LMMS_EXPORT writeToByteSeq( const class MidiEvent& ev, } // namespace lmms -#endif +#endif // LMMS_MIDIEVENTTOBYTESEQ_H diff --git a/include/MidiJack.h b/include/MidiJack.h index 265abedfc..e2b38e290 100644 --- a/include/MidiJack.h +++ b/include/MidiJack.h @@ -102,4 +102,4 @@ private: #endif // LMMS_HAVE_JACK -#endif +#endif // LMMS_MIDI_JACK_H diff --git a/include/MidiOss.h b/include/MidiOss.h index dba0a9a71..9acc0e8e6 100644 --- a/include/MidiOss.h +++ b/include/MidiOss.h @@ -78,4 +78,4 @@ private: #endif // LMMS_HAVE_OSS -#endif +#endif // LMMS_MIDI_OSS_H diff --git a/include/MidiPort.h b/include/MidiPort.h index a03b8477c..6f759708e 100644 --- a/include/MidiPort.h +++ b/include/MidiPort.h @@ -190,4 +190,4 @@ using MidiPortList = QList; } // namespace lmms -#endif +#endif // LMMS_MIDI_PORT_H diff --git a/include/MidiPortMenu.h b/include/MidiPortMenu.h index 88328e734..0b3fc1b2f 100644 --- a/include/MidiPortMenu.h +++ b/include/MidiPortMenu.h @@ -61,4 +61,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_MIDI_PORT_MENU_H diff --git a/include/MidiSetupWidget.h b/include/MidiSetupWidget.h index 492a5bb85..a61b606ac 100644 --- a/include/MidiSetupWidget.h +++ b/include/MidiSetupWidget.h @@ -59,4 +59,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_MIDI_SETUP_WIDGET_H diff --git a/include/MidiSndio.h b/include/MidiSndio.h index 3d7226431..5734745b9 100644 --- a/include/MidiSndio.h +++ b/include/MidiSndio.h @@ -75,4 +75,4 @@ private: #endif // LMMS_HAVE_SNDIO -#endif +#endif // LMMS_MIDI_SNDIO_H diff --git a/include/MidiWinMM.h b/include/MidiWinMM.h index ca1850347..3a8edfbcd 100644 --- a/include/MidiWinMM.h +++ b/include/MidiWinMM.h @@ -150,4 +150,4 @@ signals: #endif // LMMS_BUILD_WIN32 -#endif +#endif // LMMS_MIDI_WINMM_H diff --git a/include/MixHelpers.h b/include/MixHelpers.h index 76242dd7a..6458c65fc 100644 --- a/include/MixHelpers.h +++ b/include/MixHelpers.h @@ -81,4 +81,4 @@ void multiplyAndAddMultipliedJoined( sampleFrame* dst, const sample_t* srcLeft, } // namespace lmms -#endif +#endif // LMMS_MIX_HELPERS_H diff --git a/include/Mixer.h b/include/Mixer.h index d49d950ea..d84a11063 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -226,4 +226,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_MIXER_H diff --git a/include/MixerLine.h b/include/MixerLine.h index 0121717cf..68a61728c 100644 --- a/include/MixerLine.h +++ b/include/MixerLine.h @@ -117,4 +117,4 @@ private slots: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_MIXER_LINE_H diff --git a/include/MixerLineLcdSpinBox.h b/include/MixerLineLcdSpinBox.h index 0d3b182b0..1ae2813f2 100644 --- a/include/MixerLineLcdSpinBox.h +++ b/include/MixerLineLcdSpinBox.h @@ -56,4 +56,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_MIXER_LINE_LCD_SPIN_BOX_H diff --git a/include/MixerView.h b/include/MixerView.h index e73e2e391..9dc5abeee 100644 --- a/include/MixerView.h +++ b/include/MixerView.h @@ -139,4 +139,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_MIXER_VIEW_H diff --git a/include/Model.h b/include/Model.h index 0b8142659..3e304297f 100644 --- a/include/Model.h +++ b/include/Model.h @@ -90,4 +90,4 @@ signals: } // namespace lmms -#endif +#endif // LMMS_MODEL_H diff --git a/include/ModelView.h b/include/ModelView.h index 89e60c3a6..786a6812c 100644 --- a/include/ModelView.h +++ b/include/ModelView.h @@ -85,4 +85,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_MODEL_VIEW_H diff --git a/include/ModelVisitor.h b/include/ModelVisitor.h index 59928d04b..a4654e529 100644 --- a/include/ModelVisitor.h +++ b/include/ModelVisitor.h @@ -68,4 +68,4 @@ public: } // namespace lmms -#endif +#endif // LMMS_MODEL_VISITOR_H diff --git a/include/NStateButton.h b/include/NStateButton.h index dd1c06a66..a6b4c4d9a 100644 --- a/include/NStateButton.h +++ b/include/NStateButton.h @@ -77,4 +77,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_NSTATE_BUTTON_H diff --git a/include/Note.h b/include/Note.h index 9eecd585f..15aeaa2ce 100644 --- a/include/Note.h +++ b/include/Note.h @@ -265,4 +265,4 @@ std::optional boundsForNotes(const NoteVector& notes); } // namespace lmms -#endif +#endif // LMMS_NOTE_H diff --git a/include/NotePlayHandle.h b/include/NotePlayHandle.h index 89fc7e570..29477705b 100644 --- a/include/NotePlayHandle.h +++ b/include/NotePlayHandle.h @@ -364,4 +364,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_NOTE_PLAY_HANDLE_H diff --git a/include/Oscillator.h b/include/Oscillator.h index 025404c41..46d858032 100644 --- a/include/Oscillator.h +++ b/include/Oscillator.h @@ -313,4 +313,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_OSCILLATOR_H diff --git a/include/OscillatorConstants.h b/include/OscillatorConstants.h index ef12636d4..85ae38fe8 100644 --- a/include/OscillatorConstants.h +++ b/include/OscillatorConstants.h @@ -55,4 +55,4 @@ namespace lmms::OscillatorConstants } // namespace lmms::OscillatorConstants -#endif +#endif // LMMS_OSCILLATORCONSTANTS_H diff --git a/include/Oscilloscope.h b/include/Oscilloscope.h index c7a52cef9..209370ce0 100644 --- a/include/Oscilloscope.h +++ b/include/Oscilloscope.h @@ -78,4 +78,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_OSCILLOSCOPE_H diff --git a/include/OutputSettings.h b/include/OutputSettings.h index 0b10d2b01..12242e1bb 100644 --- a/include/OutputSettings.h +++ b/include/OutputSettings.h @@ -119,4 +119,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_OUTPUT_SETTINGS_H diff --git a/include/PathUtil.h b/include/PathUtil.h index 9efd73096..9b410d014 100644 --- a/include/PathUtil.h +++ b/include/PathUtil.h @@ -70,4 +70,4 @@ namespace lmms::PathUtil } // namespace lmms::PathUtil -#endif +#endif // LMMS_PATHUTIL_H diff --git a/include/PatternClip.h b/include/PatternClip.h index 3f9d07cb6..968a0b198 100644 --- a/include/PatternClip.h +++ b/include/PatternClip.h @@ -58,4 +58,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_PATTERN_CLIP_H diff --git a/include/PatternClipView.h b/include/PatternClipView.h index f2e2208bd..ee313f32a 100644 --- a/include/PatternClipView.h +++ b/include/PatternClipView.h @@ -72,4 +72,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_GUI_PATTERN_CLIP_VIEW_H diff --git a/include/PatternEditor.h b/include/PatternEditor.h index fd9a1b254..5787f27ec 100644 --- a/include/PatternEditor.h +++ b/include/PatternEditor.h @@ -97,4 +97,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_GUI_PATTERN_EDITOR_H diff --git a/include/PatternStore.h b/include/PatternStore.h index 024505b83..fcb55e411 100644 --- a/include/PatternStore.h +++ b/include/PatternStore.h @@ -113,4 +113,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_PATTERN_STORE_H diff --git a/include/PatternTrack.h b/include/PatternTrack.h index 8e319216a..1c0c610d2 100644 --- a/include/PatternTrack.h +++ b/include/PatternTrack.h @@ -102,4 +102,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_PATTERN_TRACK_H diff --git a/include/PatternTrackView.h b/include/PatternTrackView.h index b4d373b5d..09a1ba37b 100644 --- a/include/PatternTrackView.h +++ b/include/PatternTrackView.h @@ -68,4 +68,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_GUI_PATTERN_TRACK_VIEW_H diff --git a/include/PeakController.h b/include/PeakController.h index ebdf49cb0..357e2a95d 100644 --- a/include/PeakController.h +++ b/include/PeakController.h @@ -107,4 +107,4 @@ protected: } // namespace lmms -#endif +#endif // LMMS_PEAK_CONTROLLER_H diff --git a/include/PerfLog.h b/include/PerfLog.h index f786de1cc..7b0b587f6 100644 --- a/include/PerfLog.h +++ b/include/PerfLog.h @@ -77,4 +77,4 @@ class PerfLogTimer } // namespace lmms -#endif +#endif // LMMS_PERFLOG_H diff --git a/include/Piano.h b/include/Piano.h index e22710bba..96f374840 100644 --- a/include/Piano.h +++ b/include/Piano.h @@ -89,4 +89,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_PIANO_H diff --git a/include/PianoRoll.h b/include/PianoRoll.h index 5013e3e1b..23fe7ddc6 100644 --- a/include/PianoRoll.h +++ b/include/PianoRoll.h @@ -573,4 +573,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_GUI_PIANO_ROLL_H diff --git a/include/PianoView.h b/include/PianoView.h index 1d5cd4be4..6421ff438 100644 --- a/include/PianoView.h +++ b/include/PianoView.h @@ -103,4 +103,4 @@ signals: } // namespace lmms -#endif +#endif // LMMS_GUI_PIANO_VIEW_H diff --git a/include/Pitch.h b/include/Pitch.h index 537941700..1f721b5f1 100644 --- a/include/Pitch.h +++ b/include/Pitch.h @@ -40,4 +40,4 @@ constexpr pitch_t DefaultPitch = 0; } // namespace lmms -#endif +#endif // LMMS_PITCH_H diff --git a/include/PixmapButton.h b/include/PixmapButton.h index b9568e5ad..e8f546dc0 100644 --- a/include/PixmapButton.h +++ b/include/PixmapButton.h @@ -67,4 +67,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_PIXMAP_BUTTON_H diff --git a/include/PlayHandle.h b/include/PlayHandle.h index 005ef17a0..c64931ac0 100644 --- a/include/PlayHandle.h +++ b/include/PlayHandle.h @@ -166,4 +166,4 @@ using ConstPlayHandleList = QList; } // namespace lmms -#endif +#endif // LMMS_PLAY_HANDLE_H diff --git a/include/Plugin.h b/include/Plugin.h index 0a7b68a55..b1982f98c 100644 --- a/include/Plugin.h +++ b/include/Plugin.h @@ -312,4 +312,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_PLUGIN_H diff --git a/include/PluginBrowser.h b/include/PluginBrowser.h index 262732398..dd2e0a5cb 100644 --- a/include/PluginBrowser.h +++ b/include/PluginBrowser.h @@ -83,4 +83,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_PLUGIN_BROWSER_H diff --git a/include/PluginFactory.h b/include/PluginFactory.h index 8ea020073..ad09b74ed 100644 --- a/include/PluginFactory.h +++ b/include/PluginFactory.h @@ -111,4 +111,4 @@ LMMS_EXPORT PluginFactory* getPluginFactory(); } // namespace lmms -#endif +#endif // LMMS_PLUGIN_FACTORY_H diff --git a/include/PluginIssue.h b/include/PluginIssue.h index c3f3e5dbe..87e895113 100644 --- a/include/PluginIssue.h +++ b/include/PluginIssue.h @@ -84,5 +84,4 @@ QDebug operator<<(QDebug stream, const PluginIssue& iss); } // namespace lmms - -#endif +#endif // LMMS_PLUGIN_ISSUE_H diff --git a/include/PluginView.h b/include/PluginView.h index 75576a8c8..3c78cb00a 100644 --- a/include/PluginView.h +++ b/include/PluginView.h @@ -47,4 +47,4 @@ public: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_PLUGIN_VIEW_H diff --git a/include/PositionLine.h b/include/PositionLine.h index 8c1d7d60a..3e798948f 100644 --- a/include/PositionLine.h +++ b/include/PositionLine.h @@ -51,4 +51,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_POSITION_LINE_H diff --git a/include/PresetPreviewPlayHandle.h b/include/PresetPreviewPlayHandle.h index e37e976e0..b8199a71b 100644 --- a/include/PresetPreviewPlayHandle.h +++ b/include/PresetPreviewPlayHandle.h @@ -69,4 +69,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_PRESET_PREVIEW_PLAY_HANDLE_H diff --git a/include/ProjectJournal.h b/include/ProjectJournal.h index 655d64a17..a4a263078 100644 --- a/include/ProjectJournal.h +++ b/include/ProjectJournal.h @@ -126,4 +126,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_PROJECT_JOURNAL_H diff --git a/include/ProjectNotes.h b/include/ProjectNotes.h index 51577f0b2..861dcb4a8 100644 --- a/include/ProjectNotes.h +++ b/include/ProjectNotes.h @@ -93,4 +93,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_PROJECT_NOTES_H diff --git a/include/ProjectRenderer.h b/include/ProjectRenderer.h index d9309d3db..95a1f53ed 100644 --- a/include/ProjectRenderer.h +++ b/include/ProjectRenderer.h @@ -103,4 +103,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_PROJECT_RENDERER_H diff --git a/include/ProjectVersion.h b/include/ProjectVersion.h index 5401e7126..d9a459a43 100644 --- a/include/ProjectVersion.h +++ b/include/ProjectVersion.h @@ -81,4 +81,4 @@ inline bool operator!=(const ProjectVersion & v1, const ProjectVersion & v2) { r } // namespace lmms -#endif +#endif // LMMS_PROJECT_VERSION_H diff --git a/include/QuadratureLfo.h b/include/QuadratureLfo.h index 59ff81ba7..6f007e072 100644 --- a/include/QuadratureLfo.h +++ b/include/QuadratureLfo.h @@ -100,4 +100,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_QUADRATURE_LFO_H diff --git a/include/RaiiHelpers.h b/include/RaiiHelpers.h index 827cc955d..3108dc080 100644 --- a/include/RaiiHelpers.h +++ b/include/RaiiHelpers.h @@ -64,4 +64,4 @@ using UniqueNullableResource = std::unique_ptr #include @@ -257,4 +256,4 @@ signals: } // namespace lmms -#endif +#endif // LMMS_TRACK_H diff --git a/include/TrackContainer.h b/include/TrackContainer.h index d0c116f3a..5ca831dbe 100644 --- a/include/TrackContainer.h +++ b/include/TrackContainer.h @@ -124,4 +124,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_TRACK_CONTAINER_H diff --git a/include/TrackContainerView.h b/include/TrackContainerView.h index df61666b8..d53291c33 100644 --- a/include/TrackContainerView.h +++ b/include/TrackContainerView.h @@ -218,4 +218,4 @@ signals: } // namespace lmms -#endif +#endif // LMMS_GUI_TRACK_CONTAINER_VIEW_H diff --git a/include/TrackContentWidget.h b/include/TrackContentWidget.h index 09239b392..1a3e14a0e 100644 --- a/include/TrackContentWidget.h +++ b/include/TrackContentWidget.h @@ -149,4 +149,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_GUI_TRACK_CONTENT_WIDGET_H diff --git a/include/TrackLabelButton.h b/include/TrackLabelButton.h index e7f159798..0d1c6e163 100644 --- a/include/TrackLabelButton.h +++ b/include/TrackLabelButton.h @@ -71,4 +71,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_TRACK_LABEL_BUTTON_H diff --git a/include/TrackOperationsWidget.h b/include/TrackOperationsWidget.h index 39e59ac98..4dbb5353c 100644 --- a/include/TrackOperationsWidget.h +++ b/include/TrackOperationsWidget.h @@ -80,4 +80,4 @@ signals: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_TRACK_OPERATIONS_WIDGET_H diff --git a/include/TrackRenameLineEdit.h b/include/TrackRenameLineEdit.h index 48fb96092..2f6a1f4fb 100644 --- a/include/TrackRenameLineEdit.h +++ b/include/TrackRenameLineEdit.h @@ -47,4 +47,4 @@ private: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_TRACK_RENAME_LINE_EDIT_H diff --git a/include/TrackView.h b/include/TrackView.h index a46c15d75..efa4f4a0a 100644 --- a/include/TrackView.h +++ b/include/TrackView.h @@ -176,4 +176,4 @@ private slots: } // namespace lmms -#endif +#endif // LMMS_GUI_TRACK_VIEW_H diff --git a/include/ValueBuffer.h b/include/ValueBuffer.h index 9e80b7ead..683d17fb1 100644 --- a/include/ValueBuffer.h +++ b/include/ValueBuffer.h @@ -57,4 +57,4 @@ public: } // namespace lmms -#endif +#endif // LMMS_VALUE_BUFFER_H diff --git a/include/VersionedSaveDialog.h b/include/VersionedSaveDialog.h index 326b11fde..6d707cd51 100644 --- a/include/VersionedSaveDialog.h +++ b/include/VersionedSaveDialog.h @@ -68,4 +68,4 @@ public slots: } // namespace lmms::gui -#endif +#endif // LMMS_GUI_VERSIONED_SAVE_DIALOG_H diff --git a/include/VstSyncController.h b/include/VstSyncController.h index f63bafc41..d3c6af051 100644 --- a/include/VstSyncController.h +++ b/include/VstSyncController.h @@ -62,4 +62,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_VST_SYNC_CONTROLLER_H diff --git a/include/VstSyncData.h b/include/VstSyncData.h index 11da91d8d..480bc7fb4 100644 --- a/include/VstSyncData.h +++ b/include/VstSyncData.h @@ -61,4 +61,4 @@ struct VstSyncData } // namespace lmms -#endif +#endif // LMMS_VST_SYNC_DATA_H diff --git a/include/aeffectx.h b/include/aeffectx.h index 188feae9f..a7f6002b8 100644 --- a/include/aeffectx.h +++ b/include/aeffectx.h @@ -22,8 +22,8 @@ * */ -#ifndef AEFFECTX_H -#define AEFFECTX_H +#ifndef LMMS_AEFFECTX_H +#define LMMS_AEFFECTX_H #include #include @@ -297,4 +297,4 @@ public: using audioMasterCallback = intptr_t (VST_CALL_CONV*)(AEffect*, int32_t, int32_t, intptr_t, void*, float); -#endif +#endif // LMMS_AEFFECTX_H diff --git a/include/base64.h b/include/base64.h index 01116e4cd..42066d564 100644 --- a/include/base64.h +++ b/include/base64.h @@ -53,4 +53,4 @@ namespace lmms::base64 } // namespace lmms::base64 -#endif +#endif // LMMS_BASE64_H diff --git a/include/debug.h b/include/debug.h index efabd4522..7cf51acaa 100644 --- a/include/debug.h +++ b/include/debug.h @@ -38,4 +38,4 @@ #include -#endif +#endif // LMMS_DEBUG_H diff --git a/include/denormals.h b/include/denormals.h index cfb0d5c92..92b84c7dd 100644 --- a/include/denormals.h +++ b/include/denormals.h @@ -35,7 +35,7 @@ int inline can_we_daz() #endif // __SSE__ -// Set denormal protection for this thread. +// Set denormal protection for this thread. void inline disable_denormals() { #ifdef __SSE__ @@ -50,4 +50,4 @@ void inline disable_denormals() } // namespace lmms -#endif +#endif // LMMS_DENORMALS_H diff --git a/include/embed.h b/include/embed.h index b3d1cbc21..7d69f7c7d 100644 --- a/include/embed.h +++ b/include/embed.h @@ -139,4 +139,4 @@ public: } // namespace lmms -#endif +#endif // LMMS_EMBED_H diff --git a/include/endian_handling.h b/include/endian_handling.h index 96bf11704..7ddb22f22 100644 --- a/include/endian_handling.h +++ b/include/endian_handling.h @@ -57,4 +57,4 @@ inline int32_t swap32IfBE( int32_t i ) } // namespace lmms -#endif +#endif // LMMS_ENDIAN_HANDLING_H diff --git a/include/fenv.h b/include/fenv.h index c9cc508f5..665d88155 100644 --- a/include/fenv.h +++ b/include/fenv.h @@ -45,4 +45,4 @@ inline int fedisableexcept(unsigned int excepts) return fesetenv(&fenv) ? -1 : old_excepts; } -#endif +#endif // defined(__APPLE__) && defined(__MACH__) diff --git a/include/fft_helpers.h b/include/fft_helpers.h index ab4238409..2d2a8d19e 100644 --- a/include/fft_helpers.h +++ b/include/fft_helpers.h @@ -108,4 +108,4 @@ int LMMS_EXPORT compressbands(const float * _absspec_buffer, float * _compressed } // namespace lmms -#endif +#endif // LMMS_FFT_HELPERS_H diff --git a/include/gui_templates.h b/include/gui_templates.h index 7a61ccfed..c0afbdfc0 100644 --- a/include/gui_templates.h +++ b/include/gui_templates.h @@ -68,4 +68,4 @@ inline QFont pointSizeF( QFont _f, float SIZE ) } // namespace lmms -#endif +#endif // LMMS_GUI_TEMPLATES_H diff --git a/include/interpolation.h b/include/interpolation.h index 9f3b3913d..fd2c29a04 100644 --- a/include/interpolation.h +++ b/include/interpolation.h @@ -139,4 +139,4 @@ inline float lagrangeInterpolate( float v0, float v1, float v2, float v3, float } // namespace lmms -#endif +#endif // LMMS_INTERPOLATION_H diff --git a/include/lmms_basics.h b/include/lmms_basics.h index 71cc4ce53..b566fa781 100644 --- a/include/lmms_basics.h +++ b/include/lmms_basics.h @@ -145,4 +145,4 @@ constexpr const char* UI_CTRL_KEY = } // namespace lmms -#endif +#endif // LMMS_TYPES_H diff --git a/include/lmms_constants.h b/include/lmms_constants.h index 7796f6bdf..e6fce9f4d 100644 --- a/include/lmms_constants.h +++ b/include/lmms_constants.h @@ -103,4 +103,4 @@ constexpr int ARANGE_SILENT_END = -10; } // namespace lmms -#endif +#endif // LMMS_CONSTANTS_H diff --git a/include/lmms_math.h b/include/lmms_math.h index a010a9d3e..1f896a683 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -328,4 +328,4 @@ static inline T absMin( T a, T b ) } // namespace lmms -#endif +#endif // LMMS_MATH_H diff --git a/include/panning.h b/include/panning.h index 52698677c..56ca04eee 100644 --- a/include/panning.h +++ b/include/panning.h @@ -56,4 +56,4 @@ inline int panningToMidi( panning_t _p ) } // namespace lmms -#endif +#endif // LMMS_PANNING_H diff --git a/include/panning_constants.h b/include/panning_constants.h index 6e894e9d8..8f40219f8 100644 --- a/include/panning_constants.h +++ b/include/panning_constants.h @@ -38,4 +38,4 @@ constexpr panning_t DefaultPanning = PanningCenter; } // namespace lmms -#endif +#endif // LMMS_PANNING_CONSTANTS_H diff --git a/include/shared_object.h b/include/shared_object.h index dfc94b96a..e9fdb57a3 100644 --- a/include/shared_object.h +++ b/include/shared_object.h @@ -86,4 +86,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_SHARED_OBJECT_H diff --git a/include/versioninfo.h b/include/versioninfo.h index de852b59c..f224b62c5 100644 --- a/include/versioninfo.h +++ b/include/versioninfo.h @@ -51,4 +51,4 @@ constexpr const char* LMMS_BUILDCONF_PLATFORM = "win32"; constexpr const char* LMMS_BUILDCONF_PLATFORM = "Haiku"; #endif -#endif +#endif // LMMS_VERSION_INFO_H diff --git a/include/volume.h b/include/volume.h index 4d26cc815..382f76780 100644 --- a/include/volume.h +++ b/include/volume.h @@ -43,4 +43,4 @@ struct StereoVolumeVector } // namespace lmms -#endif +#endif // LMMS_VOLUME_H From 6dfdafe1f712caa50a796a2f2ae98352fc5e8fae Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sat, 7 Jan 2023 20:43:53 +0100 Subject: [PATCH 005/308] Improve readability of text floats Improve the readability of text floats by removing the hard coded pixel font size. The widget is now composed of three QLabels which are used to display the title, text and pixmap. Remove the methods paintEvent and updateSize because the widget is now updated automatically whenever the QLabels change state. Merge both versions of TextFloat::displayMessage because one of them was only called by the other. The default constructor of TextFloat now delegates to the "full" constructor. The latter is private because it is only used from within displayMessage. The methods setTitle, setText and setPixmap show/hide their corresponding labels depending on whether there is text or a pixmap to show. Adjust the class Fader so that the text float is shown to the right of the fader. Otherwise the new implementation would have covered the fader while it is being moved. --- include/TextFloat.h | 17 ++-- src/gui/widgets/Fader.cpp | 5 +- src/gui/widgets/TextFloat.cpp | 178 +++++++++++----------------------- 3 files changed, 63 insertions(+), 137 deletions(-) diff --git a/include/TextFloat.h b/include/TextFloat.h index 9fdabc06b..fccd10ae8 100644 --- a/include/TextFloat.h +++ b/include/TextFloat.h @@ -27,10 +27,11 @@ #define TEXT_FLOAT_H #include -#include #include "lmms_export.h" +class QLabel; + namespace lmms::gui { @@ -47,11 +48,6 @@ public: void setVisibilityTimeOut( int _msecs ); - - static TextFloat * displayMessage( const QString & _msg, - int _timeout = 2000, - QWidget * _parent = nullptr, - int _add_y_margin = 0 ); static TextFloat * displayMessage( const QString & _title, const QString & _msg, const QPixmap & _pixmap = @@ -66,16 +62,15 @@ public: protected: - void paintEvent( QPaintEvent * _me ) override; void mousePressEvent( QMouseEvent * _me ) override; private: - void updateSize(); + TextFloat(const QString & _title, const QString & _text, const QPixmap & _pixmap); - QString m_title; - QString m_text; - QPixmap m_pixmap; + QLabel * m_pixmapLabel; + QLabel * m_titleLabel; + QLabel * m_textLabel; }; diff --git a/src/gui/widgets/Fader.cpp b/src/gui/widgets/Fader.cpp index f853ff707..e2d6d8218 100644 --- a/src/gui/widgets/Fader.cpp +++ b/src/gui/widgets/Fader.cpp @@ -328,7 +328,8 @@ void Fader::updateTextFloat() { s_textFloat->setText( m_description + " " + QString("%1 ").arg( model()->value() * m_conversionFactor ) + " " + m_unit ); } - s_textFloat->moveGlobal( this, QPoint( width() - ( *m_knob ).width() - 5, knobPosY() - 46 ) ); + + s_textFloat->moveGlobal( this, QPoint( width() + 2, knobPosY() - s_textFloat->height() / 2 ) ); } @@ -483,4 +484,4 @@ void Fader::setPeakYellow( const QColor & c ) } -} // namespace lmms::gui \ No newline at end of file +} // namespace lmms::gui diff --git a/src/gui/widgets/TextFloat.cpp b/src/gui/widgets/TextFloat.cpp index 99eb5531f..6588902f9 100644 --- a/src/gui/widgets/TextFloat.cpp +++ b/src/gui/widgets/TextFloat.cpp @@ -22,12 +22,15 @@ * */ +#include "TextFloat.h" + #include #include #include +#include +#include +#include -#include "TextFloat.h" -#include "gui_templates.h" #include "GuiApplication.h" #include "MainWindow.h" @@ -36,170 +39,97 @@ namespace lmms::gui TextFloat::TextFloat() : - QWidget( getGUI()->mainWindow(), Qt::ToolTip ), - m_title(), - m_text(), - m_pixmap() + TextFloat("", "", QPixmap()) { - resize( 20, 20 ); - hide(); - - setAttribute( Qt::WA_TranslucentBackground, true ); - setStyle( QApplication::style() ); - setFont( pointSize<8>( font() ) ); } +TextFloat::TextFloat(const QString & _title, const QString & _text, const QPixmap & _pixmap) : + QWidget( getGUI()->mainWindow(), Qt::ToolTip ) +{ + QHBoxLayout * mainLayout = new QHBoxLayout(); + setLayout(mainLayout); + // Create the label that displays the pixmap + m_pixmapLabel = new QLabel(this); + mainLayout->addWidget(m_pixmapLabel); + // Create the widget that displays the title and the text + QWidget * titleAndTextWidget = new QWidget(this); + QVBoxLayout * titleAndTextLayout = new QVBoxLayout(); + titleAndTextWidget->setLayout(titleAndTextLayout); + + m_titleLabel = new QLabel(titleAndTextWidget); + m_titleLabel->setStyleSheet("font-weight: bold;"); + titleAndTextLayout->addWidget(m_titleLabel); + + m_textLabel = new QLabel(titleAndTextWidget); + titleAndTextLayout->addWidget(m_textLabel); + + mainLayout->addWidget(titleAndTextWidget); + + // Call the setters so that the hidden state is updated + setTitle(_title); + setText(_text); + setPixmap(_pixmap); +} void TextFloat::setTitle( const QString & _title ) { - m_title = _title; - updateSize(); + m_titleLabel->setText(_title); + m_titleLabel->setHidden(_title.isEmpty()); } - - - void TextFloat::setText( const QString & _text ) { - m_text = _text; - updateSize(); + m_textLabel->setText(_text); + m_textLabel->setHidden(_text.isEmpty()); } - - - void TextFloat::setPixmap( const QPixmap & _pixmap ) { - m_pixmap = _pixmap; - updateSize(); + m_pixmapLabel->setPixmap(_pixmap); + m_pixmapLabel->setHidden(_pixmap.isNull()); } - - - void TextFloat::setVisibilityTimeOut( int _msecs ) { QTimer::singleShot( _msecs, this, SLOT(hide())); show(); } - - - -TextFloat * TextFloat::displayMessage( const QString & _msg, int _timeout, - QWidget * _parent, int _add_y_margin ) +TextFloat * TextFloat::displayMessage( const QString & _title, + const QString & _msg, + const QPixmap & _pixmap, + int _timeout, QWidget * _parent ) { - QWidget * mw = getGUI()->mainWindow(); - auto tf = new TextFloat; + auto tf = new TextFloat(_title, _msg, _pixmap); + + // Show the widget so that the correct height is calculated in the code that follows + tf->show(); + if( _parent != nullptr ) { tf->moveGlobal( _parent, QPoint( _parent->width() + 2, 0 ) ); } else { - tf->moveGlobal( mw, QPoint( 32, mw->height() - tf->height() - 8 - _add_y_margin ) ); + // If no parent is given move the window to the lower left area of the main window + QWidget * mw = getGUI()->mainWindow(); + tf->moveGlobal( mw, QPoint( 32, mw->height() - tf->height() - 8 ) ); } - tf->setText( _msg ); - tf->show(); + if( _timeout > 0 ) { tf->setAttribute( Qt::WA_DeleteOnClose, true ); QTimer::singleShot( _timeout, tf, SLOT(close())); } - return( tf ); + + return tf; } - - - -TextFloat * TextFloat::displayMessage( const QString & _title, - const QString & _msg, - const QPixmap & _pixmap, - int _timeout, QWidget * _parent ) -{ - TextFloat * tf = displayMessage( _msg, _timeout, _parent, 16 ); - tf->setTitle( _title ); - tf->setPixmap( _pixmap ); - return( tf ); -} - - - - -void TextFloat::paintEvent( QPaintEvent * _pe ) -{ - QStyleOption opt; - opt.init( this ); - QPainter p( this ); - p.fillRect( 0, 0, width(), height(), QColor( 0, 0, 0, 0 ) ); - -/* p.setPen( p.pen().brush().color() ); - p.setBrush( p.background() );*/ - - p.setFont( pointSize<8>( p.font() ) ); - - style()->drawPrimitive( QStyle::PE_Widget, &opt, &p, this ); - -/* p.drawRect( 0, 0, rect().right(), rect().bottom() );*/ - - if( m_title.isEmpty() ) - { - p.drawText( opt.rect, Qt::AlignCenter, m_text ); - } - else - { - int text_x = opt.rect.left() + 2; - int text_y = opt.rect.top() + 12; - if( m_pixmap.isNull() == false ) - { - p.drawPixmap( opt.rect.topLeft() + QPoint( 5, 5 ), m_pixmap ); - text_x += m_pixmap.width() + 8; - } - p.drawText( text_x, text_y + 16, m_text ); - QFont f = p.font(); - f.setBold( true ); - p.setFont( f ); - p.drawText( text_x, text_y, m_title ); - } -} - - - - void TextFloat::mousePressEvent( QMouseEvent * ) { close(); } - - - -void TextFloat::updateSize() -{ - QFontMetrics metrics( pointSize<8>( font() ) ); - QRect textBound = metrics.boundingRect( m_text ); - if( !m_title.isEmpty() ) - { - QFont f = pointSize<8>( font() ); - f.setBold( true ); - int title_w = QFontMetrics( f ).boundingRect( m_title ).width(); - if( title_w > textBound.width() ) - { - textBound.setWidth( title_w ); - } - textBound.setHeight( textBound.height() * 2 + 8 ); - } - if( m_pixmap.isNull() == false ) - { - textBound.setWidth( textBound.width() + m_pixmap.width() + 10 ); - } - resize( textBound.width() + 5, textBound.height()+2 ); - //move( QPoint( parentWidget()->width() + 5, 5 ) ); - update(); -} - - - } // namespace lmms::gui From d89f53b4b0d71be4b128cc790adfa2fbffa7acde Mon Sep 17 00:00:00 2001 From: Dalton Messmer Date: Sat, 7 Jan 2023 21:12:23 -0500 Subject: [PATCH 006/308] Fix mistakes --- include/Editor.h | 6 +++--- include/Lv2ViewBase.h | 6 +++--- include/aeffectx.h | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/Editor.h b/include/Editor.h index c5e9a2d05..681bce46c 100644 --- a/include/Editor.h +++ b/include/Editor.h @@ -22,8 +22,8 @@ * */ -#ifndef LMMS_EDITOR_H -#define LMMS_EDITOR_H +#ifndef LMMS_GUI_EDITOR_H +#define LMMS_GUI_EDITOR_H #include #include @@ -113,4 +113,4 @@ protected: } // namespace lmms::gui -#endif // LMMS_EDITOR_H +#endif // LMMS_GUI_EDITOR_H diff --git a/include/Lv2ViewBase.h b/include/Lv2ViewBase.h index f6d97d6aa..d27f35cec 100644 --- a/include/Lv2ViewBase.h +++ b/include/Lv2ViewBase.h @@ -22,8 +22,8 @@ * */ -#ifndef LMMS_LV2_VIEW_BASE_H -#define LMMS_LV2_VIEW_BASE_H +#ifndef LMMS_GUI_LV2_VIEW_BASE_H +#define LMMS_GUI_LV2_VIEW_BASE_H #include "lmmsconfig.h" @@ -109,4 +109,4 @@ private: #endif // LMMS_HAVE_LV2 -#endif // LMMS_LV2_VIEW_BASE_H +#endif // LMMS_GUI_LV2_VIEW_BASE_H diff --git a/include/aeffectx.h b/include/aeffectx.h index a7f6002b8..2c69464cc 100644 --- a/include/aeffectx.h +++ b/include/aeffectx.h @@ -22,8 +22,8 @@ * */ -#ifndef LMMS_AEFFECTX_H -#define LMMS_AEFFECTX_H +#ifndef AEFFECTX_H +#define AEFFECTX_H #include #include @@ -297,4 +297,4 @@ public: using audioMasterCallback = intptr_t (VST_CALL_CONV*)(AEffect*, int32_t, int32_t, intptr_t, void*, float); -#endif // LMMS_AEFFECTX_H +#endif // AEFFECTX_H From 17295a4f864dd474eea107e5b0ccc335e29f1da5 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Tue, 10 Jan 2023 19:20:26 +0100 Subject: [PATCH 007/308] Introduce SimpleTextFloat Introduce the new class SimpleTextFloat which simply shows a text and that works like a pseudo tool tip with a narrow margin. It was extracted from TextFloat to adhere to the single responsibility principle. The new class is used by: * Fader: display the current volume when moving the fader * Knob: display the current value when the knob is moved * PianoRoll: display the current value when setting the note volume and panning Add stylings for the new widget in style.css. --- data/themes/classic/style.css | 2 +- data/themes/default/style.css | 2 +- include/Fader.h | 5 ++- include/Knob.h | 4 +- include/PianoRoll.h | 4 +- include/SimpleTextFloat.h | 61 ++++++++++++++++++++++++++++ src/gui/CMakeLists.txt | 1 + src/gui/editors/PianoRoll.cpp | 5 ++- src/gui/widgets/Fader.cpp | 8 ++-- src/gui/widgets/Knob.cpp | 6 +-- src/gui/widgets/SimpleTextFloat.cpp | 62 +++++++++++++++++++++++++++++ 11 files changed, 143 insertions(+), 17 deletions(-) create mode 100644 include/SimpleTextFloat.h create mode 100644 src/gui/widgets/SimpleTextFloat.cpp diff --git a/data/themes/classic/style.css b/data/themes/classic/style.css index 58ec5dc09..2880fe661 100644 --- a/data/themes/classic/style.css +++ b/data/themes/classic/style.css @@ -70,7 +70,7 @@ QToolTip { color: #4afd85; } -lmms--gui--TextFloat { +lmms--gui--TextFloat, lmms--gui--SimpleTextFloat { border-radius: 4px; background: qlineargradient(spread:reflect, x1:0.5, y1:0.5, x2:0.5, y2:0, stop:0 rgba(0, 0, 0, 255), stop:1 rgba(50, 50, 50, 220)); opacity: 175; diff --git a/data/themes/default/style.css b/data/themes/default/style.css index f4c651c9e..a9646cfe4 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -100,7 +100,7 @@ QToolTip { color: #d1d8e4; } -lmms--gui--TextFloat { +lmms--gui--TextFloat, lmms--gui--SimpleTextFloat { background: #040506; color: #d1d8e4; } diff --git a/include/Fader.h b/include/Fader.h index 54acfc57d..d0ee302cb 100644 --- a/include/Fader.h +++ b/include/Fader.h @@ -55,10 +55,11 @@ #include "AutomatableModelView.h" + namespace lmms::gui { -class TextFloat; +class SimpleTextFloat; class LMMS_EXPORT Fader : public QWidget, public FloatModelView @@ -164,7 +165,7 @@ private: int m_moveStartPoint; float m_startValue; - static TextFloat * s_textFloat; + static SimpleTextFloat * s_textFloat; QColor m_peakGreen; QColor m_peakRed; diff --git a/include/Knob.h b/include/Knob.h index 16ac7ed01..8976dc9ca 100644 --- a/include/Knob.h +++ b/include/Knob.h @@ -41,7 +41,7 @@ namespace lmms::gui { -class TextFloat; +class SimpleTextFloat; enum knobTypes { @@ -175,7 +175,7 @@ private: } - static TextFloat * s_textFloat; + static SimpleTextFloat * s_textFloat; QString m_label; bool m_isHtmlLabel; diff --git a/include/PianoRoll.h b/include/PianoRoll.h index c1973f407..5469e70f9 100644 --- a/include/PianoRoll.h +++ b/include/PianoRoll.h @@ -60,7 +60,7 @@ namespace gui class ComboBox; class PositionLine; -class TextFloat; +class SimpleTextFloat; class TimeLineWidget; @@ -345,7 +345,7 @@ private: static std::array prKeyOrder; - static TextFloat * s_textFloat; + static SimpleTextFloat * s_textFloat; ComboBoxModel m_zoomingModel; ComboBoxModel m_zoomingYModel; diff --git a/include/SimpleTextFloat.h b/include/SimpleTextFloat.h new file mode 100644 index 000000000..1d029c189 --- /dev/null +++ b/include/SimpleTextFloat.h @@ -0,0 +1,61 @@ +/* + * TextFloat.h - class textFloat, a floating text-label + * + * Copyright (c) 2023 LMMS team + * + * 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 SIMPLE_TEXT_FLOAT_H +#define SIMPLE_TEXT_FLOAT_H + +#include + +#include "lmms_export.h" + +class QLabel; + +namespace lmms::gui +{ + +class LMMS_EXPORT SimpleTextFloat : public QWidget +{ + Q_OBJECT +public: + SimpleTextFloat(); + ~SimpleTextFloat() override = default; + + void setText( const QString & _text ); + + void setVisibilityTimeOut( int _msecs ); + + void moveGlobal( QWidget * _w, const QPoint & _offset ) + { + move( _w->mapToGlobal( QPoint( 0, 0 ) ) + _offset ); + } + +private: + QLabel * m_textLabel; +}; + + +} // namespace lmms::gui + +#endif diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 1000ba51d..9f940c035 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -112,6 +112,7 @@ SET(LMMS_SRCS gui/widgets/NStateButton.cpp gui/widgets/Oscilloscope.cpp gui/widgets/PixmapButton.cpp + gui/widgets/SimpleTextFloat.cpp gui/widgets/TabBar.cpp gui/widgets/TabWidget.cpp gui/widgets/TempoSyncKnob.cpp diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 5f294d6e8..0cf72e5cb 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -66,6 +66,7 @@ #include "PatternStore.h" #include "PianoView.h" #include "PositionLine.h" +#include "SimpleTextFloat.h" #include "SongEditor.h" #include "StepRecorderWidget.h" #include "TextFloat.h" @@ -127,7 +128,7 @@ QPixmap * PianoRoll::s_toolMove = nullptr; QPixmap * PianoRoll::s_toolOpen = nullptr; QPixmap* PianoRoll::s_toolKnife = nullptr; -TextFloat * PianoRoll::s_textFloat = nullptr; +SimpleTextFloat * PianoRoll::s_textFloat = nullptr; static std::array s_noteStrings {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"}; @@ -290,7 +291,7 @@ PianoRoll::PianoRoll() : // init text-float if( s_textFloat == nullptr ) { - s_textFloat = new TextFloat; + s_textFloat = new SimpleTextFloat; } setAttribute( Qt::WA_OpaquePaintEvent, true ); diff --git a/src/gui/widgets/Fader.cpp b/src/gui/widgets/Fader.cpp index e2d6d8218..4cc5802a4 100644 --- a/src/gui/widgets/Fader.cpp +++ b/src/gui/widgets/Fader.cpp @@ -54,13 +54,13 @@ #include "embed.h" #include "CaptionMenu.h" #include "ConfigManager.h" -#include "TextFloat.h" +#include "SimpleTextFloat.h" namespace lmms::gui { -TextFloat * Fader::s_textFloat = nullptr; +SimpleTextFloat * Fader::s_textFloat = nullptr; QPixmap * Fader::s_back = nullptr; QPixmap * Fader::s_leds = nullptr; QPixmap * Fader::s_knob = nullptr; @@ -83,7 +83,7 @@ Fader::Fader( FloatModel * _model, const QString & _name, QWidget * _parent ) : { if( s_textFloat == nullptr ) { - s_textFloat = new TextFloat; + s_textFloat = new SimpleTextFloat; } if( ! s_back ) { @@ -125,7 +125,7 @@ Fader::Fader( FloatModel * model, const QString & name, QWidget * parent, QPixma { if( s_textFloat == nullptr ) { - s_textFloat = new TextFloat; + s_textFloat = new SimpleTextFloat; } m_back = back; diff --git a/src/gui/widgets/Knob.cpp b/src/gui/widgets/Knob.cpp index 049a86be1..8640bb81d 100644 --- a/src/gui/widgets/Knob.cpp +++ b/src/gui/widgets/Knob.cpp @@ -45,14 +45,14 @@ #include "LocaleHelper.h" #include "MainWindow.h" #include "ProjectJournal.h" +#include "SimpleTextFloat.h" #include "StringPairDrag.h" -#include "TextFloat.h" namespace lmms::gui { -TextFloat * Knob::s_textFloat = nullptr; +SimpleTextFloat * Knob::s_textFloat = nullptr; @@ -86,7 +86,7 @@ void Knob::initUi( const QString & _name ) { if( s_textFloat == nullptr ) { - s_textFloat = new TextFloat; + s_textFloat = new SimpleTextFloat; } setWindowTitle( _name ); diff --git a/src/gui/widgets/SimpleTextFloat.cpp b/src/gui/widgets/SimpleTextFloat.cpp new file mode 100644 index 000000000..e6625063b --- /dev/null +++ b/src/gui/widgets/SimpleTextFloat.cpp @@ -0,0 +1,62 @@ +/* + * TextFloat.cpp - class textFloat, a floating text-label + * + * Copyright (c) LMMS team + * + * 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 "SimpleTextFloat.h" + +#include +#include +#include +#include + +#include "GuiApplication.h" +#include "MainWindow.h" + +namespace lmms::gui +{ + + +SimpleTextFloat::SimpleTextFloat() : + QWidget(getGUI()->mainWindow(), Qt::ToolTip) +{ + QHBoxLayout * layout = new QHBoxLayout(this); + layout->setMargin(3); + setLayout(layout); + + m_textLabel = new QLabel(this); + layout->addWidget(m_textLabel); +} + +void SimpleTextFloat::setText( const QString & _text ) +{ + m_textLabel->setText(_text); +} + + +void SimpleTextFloat::setVisibilityTimeOut( int _msecs ) +{ + QTimer::singleShot( _msecs, this, SLOT(hide())); + show(); +} + +} // namespace lmms::gui From e8e54a7ba8d97357366593df19fa09b98347dc33 Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Tue, 17 Jan 2023 21:17:38 +0900 Subject: [PATCH 008/308] Remove more global automation from MidiImport (#6605) --- include/Song.h | 6 +++++- include/TrackContainer.h | 6 ------ plugins/MidiImport/MidiImport.cpp | 6 +++++- src/core/Song.cpp | 8 -------- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/include/Song.h b/include/Song.h index 569b3ad14..eacd2114f 100644 --- a/include/Song.h +++ b/include/Song.h @@ -283,7 +283,6 @@ public: bpm_t getTempo(); - AutomationClip * tempoAutomationClip() override; AutomationTrack * globalAutomationTrack() { @@ -352,6 +351,11 @@ public: return m_timeSigModel; } + IntModel& tempoModel() + { + return m_tempoModel; + } + void exportProjectMidi(QString const & exportFileName) const; inline void setLoadOnLaunch(bool value) { m_loadOnLaunch = value; } diff --git a/include/TrackContainer.h b/include/TrackContainer.h index d947094f7..ca9964e30 100644 --- a/include/TrackContainer.h +++ b/include/TrackContainer.h @@ -63,12 +63,6 @@ public: void loadSettings( const QDomElement & _this ) override; - - virtual AutomationClip * tempoAutomationClip() - { - return nullptr; - } - int countTracks( Track::TrackTypes _tt = Track::NumTrackTypes ) const; diff --git a/plugins/MidiImport/MidiImport.cpp b/plugins/MidiImport/MidiImport.cpp index 6a0314966..6836060f3 100644 --- a/plugins/MidiImport/MidiImport.cpp +++ b/plugins/MidiImport/MidiImport.cpp @@ -358,7 +358,11 @@ bool MidiImport::readSMF( TrackContainer* tc ) pd.setValue( 2 ); // Tempo stuff - AutomationClip * tap = tc->tempoAutomationClip(); + auto tt = dynamic_cast(Track::create(Track::AutomationTrack, Engine::getSong())); + tt->setName(tr("Tempo")); + auto tap = new AutomationClip(tt); + tap->setDisplayName(tr("Tempo")); + tap->addObject(&Engine::getSong()->tempoModel()); if( tap ) { tap->clear(); diff --git a/src/core/Song.cpp b/src/core/Song.cpp index ab4ac940b..82388268f 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -837,14 +837,6 @@ bpm_t Song::getTempo() } - - -AutomationClip * Song::tempoAutomationClip() -{ - return AutomationClip::globalAutomationClip( &m_tempoModel ); -} - - AutomatedValueMap Song::automatedValuesAt(TimePos time, int clipNum) const { return TrackContainer::automatedValuesFromTracks(TrackList{m_globalAutomationTrack} << tracks(), time, clipNum); From 158bb5081678931921154e20d2f9e3a0ecedfb32 Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Tue, 17 Jan 2023 21:56:31 +0900 Subject: [PATCH 009/308] Fix recent files menu on old KDE in a different way (#6612) --- src/gui/MainApplication.cpp | 13 +++++++++++++ src/gui/MainWindow.cpp | 20 -------------------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/gui/MainApplication.cpp b/src/gui/MainApplication.cpp index ab45ce304..d33ede4d2 100644 --- a/src/gui/MainApplication.cpp +++ b/src/gui/MainApplication.cpp @@ -39,6 +39,19 @@ MainApplication::MainApplication(int& argc, char** argv) : QApplication(argc, argv), m_queuedFile() { +#if !defined(LMMS_BUILD_WIN32) && !defined(LMMS_BUILD_APPLE) && !defined(LMMS_BUILD_HAIKU) + // Work around a bug of KXmlGui < 5.55 + // which breaks the recent files menu + // https://bugs.kde.org/show_bug.cgi?id=337491 + for (auto child : children()) + { + if (child->inherits("KCheckAcceleratorsInitializer")) + { + delete child; + } + } +#endif + #if defined(LMMS_BUILD_WIN32) installNativeEventFilter(this); #endif diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 706d63e27..b53ce629e 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include "AboutDialog.h" @@ -78,22 +77,6 @@ namespace lmms::gui { -#if !defined(LMMS_BUILD_WIN32) && !defined(LMMS_BUILD_APPLE) && !defined(LMMS_BUILD_HAIKU) -//Work around an issue on KDE5 as per https://bugs.kde.org/show_bug.cgi?id=337491#c21 -void disableAutoKeyAccelerators(QWidget* mainWindow) -{ - using DisablerFunc = void(*)(QWidget*); - QLibrary kf5WidgetsAddon("KF5WidgetsAddons", 5); - auto setNoAccelerators - = reinterpret_cast(kf5WidgetsAddon.resolve("_ZN19KAcceleratorManager10setNoAccelEP7QWidget")); - if(setNoAccelerators) - { - setNoAccelerators(mainWindow); - } - kf5WidgetsAddon.unload(); -} -#endif - MainWindow::MainWindow() : m_workspace( nullptr ), @@ -103,9 +86,6 @@ MainWindow::MainWindow() : m_metronomeToggle( 0 ), m_session( Normal ) { -#if !defined(LMMS_BUILD_WIN32) && !defined(LMMS_BUILD_APPLE) && !defined(LMMS_BUILD_HAIKU) - disableAutoKeyAccelerators(this); -#endif setAttribute( Qt::WA_DeleteOnClose ); auto main_widget = new QWidget(this); From f89d52fa21c1da6691735f5455ca78873843b963 Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Wed, 18 Jan 2023 10:16:28 +0900 Subject: [PATCH 010/308] Fix more Qt deprecation warnings (#6615) * Add to PluginFactory.h * Handle one more deprecated QTextStream::endl * Replace QLayout::setMargin with setContentsMargins * Replace Qt::MidButton with Qt::MiddleButton * Replace QPalette::Background with QPalette::Window * Fix deprecation warnings in LcdFloatSpinBox --- include/PluginFactory.h | 1 + plugins/LadspaBrowser/LadspaBrowser.cpp | 4 ++-- plugins/LadspaBrowser/LadspaDescription.cpp | 6 +++--- plugins/LadspaBrowser/LadspaPortDialog.cpp | 2 +- .../LadspaEffect/LadspaSubPluginFeatures.cpp | 4 ++-- plugins/VstBase/VstPlugin.cpp | 2 +- src/core/Song.cpp | 7 ++++++- src/core/lv2/Lv2SubPluginFeatures.cpp | 4 ++-- src/gui/AutomatableModelView.cpp | 2 +- src/gui/EffectRackView.cpp | 2 +- src/gui/FileBrowser.cpp | 4 ++-- src/gui/LadspaControlView.cpp | 2 +- src/gui/LmmsPalette.cpp | 2 +- src/gui/LmmsStyle.cpp | 2 +- src/gui/MainWindow.cpp | 6 +++--- src/gui/MixerView.cpp | 4 ++-- src/gui/PluginBrowser.cpp | 2 +- src/gui/SampleTrackWindow.cpp | 2 +- src/gui/SideBarWidget.cpp | 2 +- src/gui/editors/SongEditor.cpp | 2 +- src/gui/editors/TrackContainerView.cpp | 4 ++-- .../instrument/InstrumentFunctionViews.cpp | 4 ++-- src/gui/instrument/InstrumentMidiIOView.cpp | 2 +- src/gui/instrument/InstrumentMiscView.cpp | 2 +- src/gui/instrument/InstrumentTrackWindow.cpp | 4 ++-- src/gui/instrument/PianoView.cpp | 2 +- src/gui/modals/ControllerConnectionDialog.cpp | 2 +- src/gui/modals/EffectSelectDialog.cpp | 4 ++-- src/gui/modals/SetupDialog.cpp | 20 +++++++++---------- src/gui/tracks/SampleTrackView.cpp | 2 +- src/gui/tracks/TrackView.cpp | 2 +- src/gui/widgets/LcdFloatSpinBox.cpp | 7 ++++--- src/gui/widgets/MeterDialog.cpp | 6 +++--- src/gui/widgets/TabBar.cpp | 2 +- src/gui/widgets/TabWidget.cpp | 4 ++-- src/gui/widgets/TimeDisplayWidget.cpp | 2 +- 36 files changed, 69 insertions(+), 62 deletions(-) diff --git a/include/PluginFactory.h b/include/PluginFactory.h index 8b8b88b6e..15c8882ac 100644 --- a/include/PluginFactory.h +++ b/include/PluginFactory.h @@ -29,6 +29,7 @@ #include #include +#include #include #include #include diff --git a/plugins/LadspaBrowser/LadspaBrowser.cpp b/plugins/LadspaBrowser/LadspaBrowser.cpp index 714b3887c..09f83ab4e 100644 --- a/plugins/LadspaBrowser/LadspaBrowser.cpp +++ b/plugins/LadspaBrowser/LadspaBrowser.cpp @@ -98,7 +98,7 @@ LadspaBrowserView::LadspaBrowserView( ToolPlugin * _tool ) : { auto hlayout = new QHBoxLayout(this); hlayout->setSpacing( 0 ); - hlayout->setMargin( 0 ); + hlayout->setContentsMargins(0, 0, 0, 0); m_tabBar = new TabBar( this, QBoxLayout::TopToBottom ); m_tabBar->setExclusive( true ); @@ -166,7 +166,7 @@ QWidget * LadspaBrowserView::createTab( QWidget * _parent, const QString & _txt, tab->setFixedSize( 500, 400 ); auto layout = new QVBoxLayout(tab); layout->setSpacing( 0 ); - layout->setMargin( 0 ); + layout->setContentsMargins(0, 0, 0, 0); const QString type = "" + tr( "Type:" ) + " "; auto title = new QLabel(type + _txt, tab); diff --git a/plugins/LadspaBrowser/LadspaDescription.cpp b/plugins/LadspaBrowser/LadspaDescription.cpp index ff4d74867..004505d66 100644 --- a/plugins/LadspaBrowser/LadspaDescription.cpp +++ b/plugins/LadspaBrowser/LadspaDescription.cpp @@ -94,7 +94,7 @@ LadspaDescription::LadspaDescription( QWidget * _parent, auto descriptionBox = new QGroupBox(tr("Description"), this); auto descriptionLayout = new QVBoxLayout(descriptionBox); descriptionLayout->setSpacing( 0 ); - descriptionLayout->setMargin( 0 ); + descriptionLayout->setContentsMargins(0, 0, 0, 0); m_scrollArea = new QScrollArea( descriptionBox ); descriptionLayout->addWidget( m_scrollArea ); @@ -130,7 +130,7 @@ void LadspaDescription::update( const ladspa_key_t & _key ) auto maker = new QWidget(description); auto makerLayout = new QHBoxLayout(maker); - makerLayout->setMargin( 0 ); + makerLayout->setContentsMargins(0, 0, 0, 0); makerLayout->setSpacing( 0 ); layout->addWidget( maker ); @@ -145,7 +145,7 @@ void LadspaDescription::update( const ladspa_key_t & _key ) auto copyright = new QWidget(description); auto copyrightLayout = new QHBoxLayout(copyright); - copyrightLayout->setMargin( 0 ); + copyrightLayout->setContentsMargins(0, 0, 0, 0); copyrightLayout->setSpacing( 0 ); layout->addWidget( copyright ); diff --git a/plugins/LadspaBrowser/LadspaPortDialog.cpp b/plugins/LadspaBrowser/LadspaPortDialog.cpp index 3c0dbabd5..e25679511 100644 --- a/plugins/LadspaBrowser/LadspaPortDialog.cpp +++ b/plugins/LadspaBrowser/LadspaPortDialog.cpp @@ -47,7 +47,7 @@ LadspaPortDialog::LadspaPortDialog( const ladspa_key_t & _key ) auto vlayout = new QVBoxLayout(this); vlayout->setSpacing( 0 ); - vlayout->setMargin( 0 ); + vlayout->setContentsMargins(0, 0, 0, 0); int pc = manager->getPortCount( _key ); diff --git a/plugins/LadspaEffect/LadspaSubPluginFeatures.cpp b/plugins/LadspaEffect/LadspaSubPluginFeatures.cpp index 8ab50858a..1522d7187 100644 --- a/plugins/LadspaEffect/LadspaSubPluginFeatures.cpp +++ b/plugins/LadspaEffect/LadspaSubPluginFeatures.cpp @@ -71,7 +71,7 @@ void LadspaSubPluginFeatures::fillDescriptionWidget( QWidget * _parent, auto maker = new QWidget(_parent); auto l = new QHBoxLayout(maker); - l->setMargin( 0 ); + l->setContentsMargins(0, 0, 0, 0); l->setSpacing( 0 ); auto maker_label = new QLabel(maker); @@ -85,7 +85,7 @@ void LadspaSubPluginFeatures::fillDescriptionWidget( QWidget * _parent, auto copyright = new QWidget(_parent); l = new QHBoxLayout( copyright ); - l->setMargin( 0 ); + l->setContentsMargins(0, 0, 0, 0); l->setSpacing( 0 ); copyright->setMinimumWidth( _parent->minimumWidth() ); diff --git a/plugins/VstBase/VstPlugin.cpp b/plugins/VstBase/VstPlugin.cpp index 700a14ac7..c3fe17d72 100644 --- a/plugins/VstBase/VstPlugin.cpp +++ b/plugins/VstBase/VstPlugin.cpp @@ -751,7 +751,7 @@ void VstPlugin::createUI( QWidget * parent ) QHBoxLayout * l = new QHBoxLayout( helper ); QWidget * target = new QWidget( helper ); l->setSpacing( 0 ); - l->setMargin( 0 ); + l->setContentsMargins(0, 0, 0, 0); l->addWidget( target ); // we've to call that for making sure, Qt created the windows diff --git a/src/core/Song.cpp b/src/core/Song.cpp index 82388268f..06ac15633 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -1043,7 +1043,12 @@ void Song::loadProject( const QString & fileName ) else { QTextStream(stderr) << tr("Can't load project: " - "Project file contains local paths to plugins.") << endl; + "Project file contains local paths to plugins.") +#if (QT_VERSION >= QT_VERSION_CHECK(5,15,0)) + << Qt::endl; +#else + << endl; +#endif } } } diff --git a/src/core/lv2/Lv2SubPluginFeatures.cpp b/src/core/lv2/Lv2SubPluginFeatures.cpp index 4fb377b1c..8c3c98711 100644 --- a/src/core/lv2/Lv2SubPluginFeatures.cpp +++ b/src/core/lv2/Lv2SubPluginFeatures.cpp @@ -81,7 +81,7 @@ void Lv2SubPluginFeatures::fillDescriptionWidget(QWidget *parent, auto maker = new QWidget(parent); auto l = new QHBoxLayout(maker); - l->setMargin(0); + l->setContentsMargins(0, 0, 0, 0); l->setSpacing(0); auto maker_label = new QLabel(maker); @@ -98,7 +98,7 @@ void Lv2SubPluginFeatures::fillDescriptionWidget(QWidget *parent, auto copyright = new QWidget(parent); l = new QHBoxLayout(copyright); - l->setMargin(0); + l->setContentsMargins(0, 0, 0, 0); l->setSpacing(0); copyright->setMinimumWidth(parent->minimumWidth()); diff --git a/src/gui/AutomatableModelView.cpp b/src/gui/AutomatableModelView.cpp index 52ee1ed7e..0e364993f 100644 --- a/src/gui/AutomatableModelView.cpp +++ b/src/gui/AutomatableModelView.cpp @@ -176,7 +176,7 @@ void AutomatableModelView::mousePressEvent( QMouseEvent* event ) new gui::StringPairDrag( "automatable_model", QString::number( modelUntyped()->id() ), QPixmap(), widget() ); event->accept(); } - else if( event->button() == Qt::MidButton ) + else if( event->button() == Qt::MiddleButton ) { modelUntyped()->reset(); } diff --git a/src/gui/EffectRackView.cpp b/src/gui/EffectRackView.cpp index 75cac67dc..aa790d74d 100644 --- a/src/gui/EffectRackView.cpp +++ b/src/gui/EffectRackView.cpp @@ -42,7 +42,7 @@ EffectRackView::EffectRackView( EffectChain* model, QWidget* parent ) : ModelView( nullptr, this ) { auto mainLayout = new QVBoxLayout(this); - mainLayout->setMargin( 5 ); + mainLayout->setContentsMargins(5, 5, 5, 5); m_effectsGroupBox = new GroupBox( tr( "EFFECTS CHAIN" ) ); mainLayout->addWidget( m_effectsGroupBox ); diff --git a/src/gui/FileBrowser.cpp b/src/gui/FileBrowser.cpp index 4ef41217d..a104d3265 100644 --- a/src/gui/FileBrowser.cpp +++ b/src/gui/FileBrowser.cpp @@ -76,7 +76,7 @@ void FileBrowser::addContentCheckBox() auto filterWidget = new QWidget(contentParent()); filterWidget->setFixedHeight(15); auto filterWidgetLayout = new QHBoxLayout(filterWidget); - filterWidgetLayout->setMargin(0); + filterWidgetLayout->setContentsMargins(0, 0, 0, 0); filterWidgetLayout->setSpacing(0); auto configCheckBox = [this, &filterWidgetLayout](QCheckBox* box) @@ -119,7 +119,7 @@ FileBrowser::FileBrowser(const QString & directories, const QString & filter, searchWidget->setFixedHeight( 24 ); auto searchWidgetLayout = new QHBoxLayout(searchWidget); - searchWidgetLayout->setMargin( 0 ); + searchWidgetLayout->setContentsMargins(0, 0, 0, 0); searchWidgetLayout->setSpacing( 0 ); m_filterEdit = new QLineEdit( searchWidget ); diff --git a/src/gui/LadspaControlView.cpp b/src/gui/LadspaControlView.cpp index 38ad4a146..46e208d2e 100644 --- a/src/gui/LadspaControlView.cpp +++ b/src/gui/LadspaControlView.cpp @@ -43,7 +43,7 @@ LadspaControlView::LadspaControlView( QWidget * _parent, m_ctl( _ctl ) { auto layout = new QHBoxLayout(this); - layout->setMargin( 0 ); + layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing( 0 ); LedCheckBox * link = nullptr; diff --git a/src/gui/LmmsPalette.cpp b/src/gui/LmmsPalette.cpp index 48d6de0df..0d135f52c 100644 --- a/src/gui/LmmsPalette.cpp +++ b/src/gui/LmmsPalette.cpp @@ -75,7 +75,7 @@ QPalette LmmsPalette::palette() const { QPalette pal = QApplication::style()->standardPalette(); - pal.setColor( QPalette::Background, background() ); + pal.setColor( QPalette::Window, background() ); pal.setColor( QPalette::WindowText, windowText() ); pal.setColor( QPalette::Base, base() ); pal.setColor( QPalette::ButtonText, buttonText() ); diff --git a/src/gui/LmmsStyle.cpp b/src/gui/LmmsStyle.cpp index 060a97811..50a2a9de4 100644 --- a/src/gui/LmmsStyle.cpp +++ b/src/gui/LmmsStyle.cpp @@ -189,7 +189,7 @@ void LmmsStyle::drawComplexControl( ComplexControl control, /* else if( control == CC_ScrollBar ) { painter->fillRect( option->rect, QApplication::palette().color( QPalette::Active, - QPalette::Background ) ); + QPalette::Window ) ); }*/ QProxyStyle::drawComplexControl( control, option, painter, widget ); diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index b53ce629e..40c8334ba 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -91,12 +91,12 @@ MainWindow::MainWindow() : auto main_widget = new QWidget(this); auto vbox = new QVBoxLayout(main_widget); vbox->setSpacing( 0 ); - vbox->setMargin( 0 ); + vbox->setContentsMargins(0, 0, 0, 0); auto w = new QWidget(main_widget); auto hbox = new QHBoxLayout(w); hbox->setSpacing( 0 ); - hbox->setMargin( 0 ); + hbox->setContentsMargins(0, 0, 0, 0); auto sideBar = new SideBar(Qt::Vertical, w); @@ -206,7 +206,7 @@ MainWindow::MainWindow() : // add layout for organizing quite complex toolbar-layouting m_toolBarLayout = new QGridLayout( m_toolBar/*, 2, 1*/ ); - m_toolBarLayout->setMargin( 0 ); + m_toolBarLayout->setContentsMargins(0, 0, 0, 0); m_toolBarLayout->setSpacing( 0 ); vbox->addWidget( m_toolBar ); diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index 62d4cb7ce..a9b7bf992 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -59,7 +59,7 @@ MixerView::MixerView() : m->setHook( this ); //QPalette pal = palette(); - //pal.setColor( QPalette::Background, QColor( 72, 76, 88 ) ); + //pal.setColor( QPalette::Window, QColor( 72, 76, 88 ) ); //setPalette( pal ); setAutoFillBackground( true ); @@ -79,7 +79,7 @@ MixerView::MixerView() : chLayout = new QHBoxLayout( m_channelAreaWidget ); chLayout->setSizeConstraint( QLayout::SetMinimumSize ); chLayout->setSpacing( 0 ); - chLayout->setMargin( 0 ); + chLayout->setContentsMargins(0, 0, 0, 0); m_channelAreaWidget->setLayout(chLayout); // create rack layout before creating the first channel diff --git a/src/gui/PluginBrowser.cpp b/src/gui/PluginBrowser.cpp index a19c80df0..afb74dcd3 100644 --- a/src/gui/PluginBrowser.cpp +++ b/src/gui/PluginBrowser.cpp @@ -52,7 +52,7 @@ PluginBrowser::PluginBrowser( QWidget * _parent ) : addContentWidget( m_view ); auto view_layout = new QVBoxLayout(m_view); - view_layout->setMargin( 5 ); + view_layout->setContentsMargins(5, 5, 5, 5); view_layout->setSpacing( 5 ); diff --git a/src/gui/SampleTrackWindow.cpp b/src/gui/SampleTrackWindow.cpp index 78b899a09..6fe70bf41 100644 --- a/src/gui/SampleTrackWindow.cpp +++ b/src/gui/SampleTrackWindow.cpp @@ -57,7 +57,7 @@ SampleTrackWindow::SampleTrackWindow(SampleTrackView * tv) : // init own layout + widgets setFocusPolicy(Qt::StrongFocus); auto vlayout = new QVBoxLayout(this); - vlayout->setMargin(0); + vlayout->setContentsMargins(0, 0, 0, 0); vlayout->setSpacing(0); auto generalSettingsWidget = new TabWidget(tr("GENERAL SETTINGS"), this); diff --git a/src/gui/SideBarWidget.cpp b/src/gui/SideBarWidget.cpp index cf0233af1..60760ba59 100644 --- a/src/gui/SideBarWidget.cpp +++ b/src/gui/SideBarWidget.cpp @@ -44,7 +44,7 @@ SideBarWidget::SideBarWidget( const QString & _title, const QPixmap & _icon, m_contents = new QWidget( this ); m_layout = new QVBoxLayout( m_contents ); m_layout->setSpacing( 5 ); - m_layout->setMargin( 0 ); + m_layout->setContentsMargins(0, 0, 0, 0); m_closeBtn = new QPushButton(embed::getIconPixmap("close"), QString(), this); m_closeBtn->resize(m_buttonSize); m_closeBtn->setToolTip(tr("Close")); diff --git a/src/gui/editors/SongEditor.cpp b/src/gui/editors/SongEditor.cpp index 40be52319..3e62cc238 100644 --- a/src/gui/editors/SongEditor.cpp +++ b/src/gui/editors/SongEditor.cpp @@ -213,7 +213,7 @@ SongEditor::SongEditor( Song * song ) : // create widget for oscilloscope- and cpu-load-widget auto vc_w = new QWidget(tb); auto vcw_layout = new QVBoxLayout(vc_w); - vcw_layout->setMargin( 0 ); + vcw_layout->setContentsMargins(0, 0, 0, 0); vcw_layout->setSpacing( 0 ); vcw_layout->addStretch(); diff --git a/src/gui/editors/TrackContainerView.cpp b/src/gui/editors/TrackContainerView.cpp index 351fe8295..38a6a36d5 100644 --- a/src/gui/editors/TrackContainerView.cpp +++ b/src/gui/editors/TrackContainerView.cpp @@ -90,13 +90,13 @@ TrackContainerView::TrackContainerView( TrackContainer * _tc ) : //keeps the direction of the widget, undepended on the locale setLayoutDirection( Qt::LeftToRight ); auto layout = new QVBoxLayout(this); - layout->setMargin( 0 ); + layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing( 0 ); layout->addWidget( m_scrollArea ); auto scrollContent = new QWidget; m_scrollLayout = new QVBoxLayout( scrollContent ); - m_scrollLayout->setMargin( 0 ); + m_scrollLayout->setContentsMargins(0, 0, 0, 0); m_scrollLayout->setSpacing( 0 ); m_scrollLayout->setSizeConstraint( QLayout::SetMinAndMaxSize ); diff --git a/src/gui/instrument/InstrumentFunctionViews.cpp b/src/gui/instrument/InstrumentFunctionViews.cpp index 99c68a5ed..a4f0e670a 100644 --- a/src/gui/instrument/InstrumentFunctionViews.cpp +++ b/src/gui/instrument/InstrumentFunctionViews.cpp @@ -47,7 +47,7 @@ InstrumentFunctionNoteStackingView::InstrumentFunctionNoteStackingView( Instrume m_chordRangeKnob( new Knob( knobBright_26 ) ) { auto topLayout = new QHBoxLayout(this); - topLayout->setMargin( 0 ); + topLayout->setContentsMargins(0, 0, 0, 0); topLayout->addWidget( m_chordsGroupBox ); auto mainLayout = new QGridLayout(m_chordsGroupBox); @@ -109,7 +109,7 @@ InstrumentFunctionArpeggioView::InstrumentFunctionArpeggioView( InstrumentFuncti m_arpModeComboBox( new ComboBox() ) { auto topLayout = new QHBoxLayout(this); - topLayout->setMargin( 0 ); + topLayout->setContentsMargins(0, 0, 0, 0); topLayout->addWidget( m_arpGroupBox ); auto mainLayout = new QGridLayout(m_arpGroupBox); diff --git a/src/gui/instrument/InstrumentMidiIOView.cpp b/src/gui/instrument/InstrumentMidiIOView.cpp index 8d7cf9dda..fd9d6fc54 100644 --- a/src/gui/instrument/InstrumentMidiIOView.cpp +++ b/src/gui/instrument/InstrumentMidiIOView.cpp @@ -48,7 +48,7 @@ InstrumentMidiIOView::InstrumentMidiIOView( QWidget* parent ) : m_wpBtn( nullptr ) { auto layout = new QVBoxLayout(this); - layout->setMargin( 5 ); + layout->setContentsMargins(5, 5, 5, 5); m_midiInputGroupBox = new GroupBox( tr( "ENABLE MIDI INPUT" ) ); layout->addWidget( m_midiInputGroupBox ); diff --git a/src/gui/instrument/InstrumentMiscView.cpp b/src/gui/instrument/InstrumentMiscView.cpp index 1b4f82333..514db579c 100644 --- a/src/gui/instrument/InstrumentMiscView.cpp +++ b/src/gui/instrument/InstrumentMiscView.cpp @@ -44,7 +44,7 @@ InstrumentMiscView::InstrumentMiscView(InstrumentTrack *it, QWidget *parent) : QWidget(parent) { auto layout = new QVBoxLayout(this); - layout->setMargin(5); + layout->setContentsMargins(5, 5, 5, 5); // Master pitch toggle m_pitchGroupBox = new GroupBox(tr("GLOBAL TRANSPOSITION")); diff --git a/src/gui/instrument/InstrumentTrackWindow.cpp b/src/gui/instrument/InstrumentTrackWindow.cpp index 70c11976a..1d26dd9dc 100644 --- a/src/gui/instrument/InstrumentTrackWindow.cpp +++ b/src/gui/instrument/InstrumentTrackWindow.cpp @@ -90,7 +90,7 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : // init own layout + widgets setFocusPolicy( Qt::StrongFocus ); auto vlayout = new QVBoxLayout(this); - vlayout->setMargin( 0 ); + vlayout->setContentsMargins(0, 0, 0, 0); vlayout->setSpacing( 0 ); auto generalSettingsWidget = new TabWidget(tr("GENERAL SETTINGS"), this); @@ -246,7 +246,7 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : // FUNC tab auto instrumentFunctions = new QWidget(m_tabWidget); auto instrumentFunctionsLayout = new QVBoxLayout(instrumentFunctions); - instrumentFunctionsLayout->setMargin( 5 ); + instrumentFunctionsLayout->setContentsMargins(5, 5, 5, 5); m_noteStackingView = new InstrumentFunctionNoteStackingView( &m_track->m_noteStacking ); m_arpeggioView = new InstrumentFunctionArpeggioView( &m_track->m_arpeggio ); diff --git a/src/gui/instrument/PianoView.cpp b/src/gui/instrument/PianoView.cpp index 7478c8204..a2df50e47 100644 --- a/src/gui/instrument/PianoView.cpp +++ b/src/gui/instrument/PianoView.cpp @@ -147,7 +147,7 @@ PianoView::PianoView(QWidget *parent) : // create a layout for ourselves auto layout = new QVBoxLayout(this); layout->setSpacing( 0 ); - layout->setMargin( 0 ); + layout->setContentsMargins(0, 0, 0, 0); layout->addSpacing( PIANO_BASE+PW_WHITE_KEY_HEIGHT ); layout->addWidget( m_pianoScroll ); diff --git a/src/gui/modals/ControllerConnectionDialog.cpp b/src/gui/modals/ControllerConnectionDialog.cpp index 149303da8..06f6a5708 100644 --- a/src/gui/modals/ControllerConnectionDialog.cpp +++ b/src/gui/modals/ControllerConnectionDialog.cpp @@ -215,7 +215,7 @@ ControllerConnectionDialog::ControllerConnectionDialog( QWidget * _parent, auto btn_layout = new QHBoxLayout(buttons); btn_layout->setSpacing( 0 ); - btn_layout->setMargin( 0 ); + btn_layout->setContentsMargins(0, 0, 0, 0); auto select_btn = new QPushButton(embed::getIconPixmap("add"), tr("OK"), buttons); connect( select_btn, SIGNAL(clicked()), diff --git a/src/gui/modals/EffectSelectDialog.cpp b/src/gui/modals/EffectSelectDialog.cpp index 9ce3f90b6..eac5a3783 100644 --- a/src/gui/modals/EffectSelectDialog.cpp +++ b/src/gui/modals/EffectSelectDialog.cpp @@ -213,14 +213,14 @@ void EffectSelectDialog::rowChanged( const QModelIndex & _idx, hbox->addWidget(textualInfoWidget); auto textWidgetLayout = new QVBoxLayout(textualInfoWidget); - textWidgetLayout->setMargin( 4 ); + textWidgetLayout->setContentsMargins(4, 4, 4, 4); textWidgetLayout->setSpacing( 0 ); if ( m_currentSelection.desc->subPluginFeatures ) { auto subWidget = new QWidget(textualInfoWidget); auto subLayout = new QVBoxLayout(subWidget); - subLayout->setMargin( 4 ); + subLayout->setContentsMargins(4, 4, 4, 4); subLayout->setSpacing( 0 ); m_currentSelection.desc->subPluginFeatures-> fillDescriptionWidget( subWidget, &m_currentSelection ); diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index 5140a63b5..44eaf87b0 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -175,12 +175,12 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : // Vertical layout. auto vlayout = new QVBoxLayout(this); vlayout->setSpacing(0); - vlayout->setMargin(0); + vlayout->setContentsMargins(0, 0, 0, 0); // Horizontal layout. auto hlayout = new QHBoxLayout(main_w); hlayout->setSpacing(0); - hlayout->setMargin(0); + hlayout->setContentsMargins(0, 0, 0, 0); // Tab bar for the main tabs. m_tabBar = new TabBar(main_w, QBoxLayout::TopToBottom); @@ -195,7 +195,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : auto general_w = new QWidget(settings_w); auto general_layout = new QVBoxLayout(general_w); general_layout->setSpacing(10); - general_layout->setMargin(0); + general_layout->setContentsMargins(0, 0, 0, 0); labelWidget(general_w, tr("General")); auto addLedCheckBox = [&XDelta, &YDelta, this](const QString& ledText, TabWidget* tw, int& counter, @@ -324,7 +324,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : auto performance_w = new QWidget(settings_w); auto performance_layout = new QVBoxLayout(performance_w); performance_layout->setSpacing(10); - performance_layout->setMargin(0); + performance_layout->setContentsMargins(0, 0, 0, 0); labelWidget(performance_w, tr("Performance")); @@ -442,7 +442,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : auto audio_w = new QWidget(settings_w); auto audio_layout = new QVBoxLayout(audio_w); audio_layout->setSpacing(10); - audio_layout->setMargin(0); + audio_layout->setContentsMargins(0, 0, 0, 0); labelWidget(audio_w, tr("Audio")); @@ -460,7 +460,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : auto as_w_layout = new QHBoxLayout(as_w); as_w_layout->setSpacing(0); - as_w_layout->setMargin(0); + as_w_layout->setContentsMargins(0, 0, 0, 0); #ifdef LMMS_HAVE_JACK m_audioIfaceSetupWidgets[AudioJack::name()] = @@ -592,7 +592,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : auto midi_w = new QWidget(settings_w); auto midi_layout = new QVBoxLayout(midi_w); midi_layout->setSpacing(10); - midi_layout->setMargin(0); + midi_layout->setContentsMargins(0, 0, 0, 0); labelWidget(midi_w, tr("MIDI")); @@ -609,7 +609,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : auto ms_w_layout = new QHBoxLayout(ms_w); ms_w_layout->setSpacing(0); - ms_w_layout->setMargin(0); + ms_w_layout->setContentsMargins(0, 0, 0, 0); #ifdef LMMS_HAVE_ALSA m_midiIfaceSetupWidgets[MidiAlsaSeq::name()] = @@ -709,7 +709,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : auto paths_layout = new QVBoxLayout(paths_w); paths_layout->setSpacing(10); - paths_layout->setMargin(0); + paths_layout->setContentsMargins(0, 0, 0, 0); labelWidget(paths_w, tr("Paths")); @@ -823,7 +823,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : auto extras_w = new QWidget(this); auto extras_layout = new QHBoxLayout(extras_w); extras_layout->setSpacing(0); - extras_layout->setMargin(0); + extras_layout->setContentsMargins(0, 0, 0, 0); // Restart warning label. restartWarningLbl = new QLabel( diff --git a/src/gui/tracks/SampleTrackView.cpp b/src/gui/tracks/SampleTrackView.cpp index 08ddee863..fbdd41ded 100644 --- a/src/gui/tracks/SampleTrackView.cpp +++ b/src/gui/tracks/SampleTrackView.cpp @@ -82,7 +82,7 @@ SampleTrackView::SampleTrackView( SampleTrack * _t, TrackContainerView* tcv ) : m_panningKnob->show(); m_activityIndicator = new FadeButton( - QApplication::palette().color(QPalette::Active, QPalette::Background), + QApplication::palette().color(QPalette::Active, QPalette::Window), QApplication::palette().color(QPalette::Active, QPalette::BrightText), QApplication::palette().color(QPalette::Active, QPalette::BrightText).darker(), getTrackSettingsWidget() diff --git a/src/gui/tracks/TrackView.cpp b/src/gui/tracks/TrackView.cpp index 0aabc705d..3e9257a0d 100644 --- a/src/gui/tracks/TrackView.cpp +++ b/src/gui/tracks/TrackView.cpp @@ -75,7 +75,7 @@ TrackView::TrackView( Track * track, TrackContainerView * tcv ) : m_trackSettingsWidget.setAutoFillBackground( true ); auto layout = new QHBoxLayout(this); - layout->setMargin( 0 ); + layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing( 0 ); layout->addWidget( &m_trackOperationsWidget ); layout->addWidget( &m_trackSettingsWidget ); diff --git a/src/gui/widgets/LcdFloatSpinBox.cpp b/src/gui/widgets/LcdFloatSpinBox.cpp index e57012e10..6391f314a 100644 --- a/src/gui/widgets/LcdFloatSpinBox.cpp +++ b/src/gui/widgets/LcdFloatSpinBox.cpp @@ -38,6 +38,7 @@ #include #include "CaptionMenu.h" +#include "DeprecationHelper.h" #include "embed.h" #include "GuiApplication.h" #include "gui_templates.h" @@ -179,7 +180,7 @@ void LcdFloatSpinBox::mouseReleaseEvent(QMouseEvent*) void LcdFloatSpinBox::wheelEvent(QWheelEvent *event) { // switch between integer and fractional step based on cursor position - if (event->x() < m_wholeDisplay.width()) { m_intStep = true; } + if (position(event).x() < m_wholeDisplay.width()) { m_intStep = true; } else { m_intStep = false; } event->accept(); @@ -239,9 +240,9 @@ void LcdFloatSpinBox::paintEvent(QPaintEvent*) { p.setFont(pointSizeF(p.font(), 6.5)); p.setPen(m_wholeDisplay.textShadowColor()); - p.drawText(width() / 2 - p.fontMetrics().width(m_label) / 2 + 1, height(), m_label); + p.drawText(width() / 2 - horizontalAdvance(p.fontMetrics(), m_label) / 2 + 1, height(), m_label); p.setPen(m_wholeDisplay.textColor()); - p.drawText(width() / 2 - p.fontMetrics().width(m_label) / 2, height() - 1, m_label); + p.drawText(width() / 2 - horizontalAdvance(p.fontMetrics(), m_label) / 2, height() - 1, m_label); } } diff --git a/src/gui/widgets/MeterDialog.cpp b/src/gui/widgets/MeterDialog.cpp index 938177dce..ced08382e 100644 --- a/src/gui/widgets/MeterDialog.cpp +++ b/src/gui/widgets/MeterDialog.cpp @@ -43,12 +43,12 @@ MeterDialog::MeterDialog( QWidget * _parent, bool _simple ) : { auto vlayout = new QVBoxLayout(this); vlayout->setSpacing( 0 ); - vlayout->setMargin( 0 ); + vlayout->setContentsMargins(0, 0, 0, 0); auto num = new QWidget(this); auto num_layout = new QHBoxLayout(num); num_layout->setSpacing( 0 ); - num_layout->setMargin( 0 ); + num_layout->setContentsMargins(0, 0, 0, 0); m_numerator = new LcdSpinBox( 2, num, tr( "Meter Numerator" ) ); @@ -69,7 +69,7 @@ MeterDialog::MeterDialog( QWidget * _parent, bool _simple ) : auto den = new QWidget(this); auto den_layout = new QHBoxLayout(den); den_layout->setSpacing( 0 ); - den_layout->setMargin( 0 ); + den_layout->setContentsMargins(0, 0, 0, 0); m_denominator = new LcdSpinBox( 2, den, tr( "Meter Denominator" ) ); m_denominator->setToolTip(tr("Meter denominator")); diff --git a/src/gui/widgets/TabBar.cpp b/src/gui/widgets/TabBar.cpp index d3c1fa0c5..806a93252 100644 --- a/src/gui/widgets/TabBar.cpp +++ b/src/gui/widgets/TabBar.cpp @@ -37,7 +37,7 @@ TabBar::TabBar( QWidget * _parent, QBoxLayout::Direction _dir ) : m_layout( new QBoxLayout( _dir, this ) ), m_exclusive( false ) { - m_layout->setMargin( 8 ); + m_layout->setContentsMargins(8, 8, 8, 8); m_layout->setSpacing( 0 ); setLayout( m_layout ); diff --git a/src/gui/widgets/TabWidget.cpp b/src/gui/widgets/TabWidget.cpp index 106387e42..5ab56fee7 100644 --- a/src/gui/widgets/TabWidget.cpp +++ b/src/gui/widgets/TabWidget.cpp @@ -60,9 +60,9 @@ TabWidget::TabWidget(const QString & caption, QWidget * parent, bool usePixmap, setFont( pointSize<8>( font() ) ); setAutoFillBackground( true ); - QColor bg_color = QApplication::palette().color( QPalette::Active, QPalette::Background ). darker( 132 ); + QColor bg_color = QApplication::palette().color( QPalette::Active, QPalette::Window ). darker( 132 ); QPalette pal = palette(); - pal.setColor( QPalette::Background, bg_color ); + pal.setColor( QPalette::Window, bg_color ); setPalette( pal ); } diff --git a/src/gui/widgets/TimeDisplayWidget.cpp b/src/gui/widgets/TimeDisplayWidget.cpp index cefa0fa8f..cf139d4a8 100644 --- a/src/gui/widgets/TimeDisplayWidget.cpp +++ b/src/gui/widgets/TimeDisplayWidget.cpp @@ -43,7 +43,7 @@ TimeDisplayWidget::TimeDisplayWidget() : m_milliSecondsLCD( 3, this ) { m_spinBoxesLayout.setSpacing( 0 ); - m_spinBoxesLayout.setMargin( 0 ); + m_spinBoxesLayout.setContentsMargins(0, 0, 0, 0); m_spinBoxesLayout.addWidget( &m_majorLCD ); m_spinBoxesLayout.addWidget( &m_minorLCD ); m_spinBoxesLayout.addWidget( &m_milliSecondsLCD ); From 22eb7a1364309af13423abaed134df35498ec551 Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Sun, 1 Jan 2023 02:08:29 +0100 Subject: [PATCH 011/308] clang-tidy: Apply readability-const-return-type --- .clang-tidy | 1 + include/AutomationClip.h | 2 +- include/PluginFactory.h | 10 +++++----- src/core/AutomationClip.cpp | 4 ++-- src/core/PluginFactory.cpp | 10 +++++----- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index aff46bba6..804bc28f1 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -9,6 +9,7 @@ Checks: > modernize-use-equals-delete, modernize-use-override, performance-trivially-destructible, + readability-const-return-type, readability-identifier-naming, readability-misleading-indentation, readability-simplify-boolean-expr, diff --git a/include/AutomationClip.h b/include/AutomationClip.h index 3e253d85f..6f7c6291d 100644 --- a/include/AutomationClip.h +++ b/include/AutomationClip.h @@ -154,7 +154,7 @@ public: float valueAt( const TimePos & _time ) const; float *valuesAfter( const TimePos & _time ) const; - const QString name() const; + QString name() const; // settings-management void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; diff --git a/include/PluginFactory.h b/include/PluginFactory.h index 15c8882ac..8a8a22c68 100644 --- a/include/PluginFactory.h +++ b/include/PluginFactory.h @@ -47,7 +47,7 @@ class LMMS_EXPORT PluginFactory public: struct PluginInfo { - const QString name() const; + QString name() const; QFileInfo file; std::shared_ptr library = nullptr; Plugin::Descriptor* descriptor = nullptr; @@ -67,8 +67,8 @@ public: static PluginFactory* instance(); /// Returns a list of all found plugins' descriptors. - const Plugin::DescriptorList descriptors() const; - const Plugin::DescriptorList descriptors(Plugin::PluginTypes type) const; + Plugin::DescriptorList descriptors() const; + Plugin::DescriptorList descriptors(Plugin::PluginTypes type) const; struct PluginInfoAndKey { @@ -80,12 +80,12 @@ public: /// Returns a list of all found plugins' PluginFactory::PluginInfo objects. const PluginInfoList& pluginInfos() const; /// Returns a plugin that support the given file extension - const PluginInfoAndKey pluginSupportingExtension(const QString& ext); + PluginInfoAndKey pluginSupportingExtension(const QString& ext); /// Returns the PluginInfo object of the plugin with the given name. /// If the plugin is not found, an empty PluginInfo is returned (use /// PluginInfo::isNull() to check this). - const PluginInfo pluginInfo(const char* name) const; + PluginInfo pluginInfo(const char* name) const; /// When loading a library fails during discovery, the error string is saved. /// It can be retrieved by calling this function. diff --git a/src/core/AutomationClip.cpp b/src/core/AutomationClip.cpp index fb2d7dbb0..c031c5a41 100644 --- a/src/core/AutomationClip.cpp +++ b/src/core/AutomationClip.cpp @@ -857,7 +857,7 @@ void AutomationClip::loadSettings( const QDomElement & _this ) -const QString AutomationClip::name() const +QString AutomationClip::name() const { QMutexLocker m(&m_clipMutex); @@ -1173,4 +1173,4 @@ void AutomationClip::generateTangents(timeMap::iterator it, int numToGenerate) } } -} // namespace lmms \ No newline at end of file +} // namespace lmms diff --git a/src/core/PluginFactory.cpp b/src/core/PluginFactory.cpp index 81a6122d1..ece589274 100644 --- a/src/core/PluginFactory.cpp +++ b/src/core/PluginFactory.cpp @@ -105,12 +105,12 @@ PluginFactory* getPluginFactory() return PluginFactory::instance(); } -const Plugin::DescriptorList PluginFactory::descriptors() const +Plugin::DescriptorList PluginFactory::descriptors() const { return m_descriptors.values(); } -const Plugin::DescriptorList PluginFactory::descriptors(Plugin::PluginTypes type) const +Plugin::DescriptorList PluginFactory::descriptors(Plugin::PluginTypes type) const { return m_descriptors.values(type); } @@ -120,12 +120,12 @@ const PluginFactory::PluginInfoList& PluginFactory::pluginInfos() const return m_pluginInfos; } -const PluginFactory::PluginInfoAndKey PluginFactory::pluginSupportingExtension(const QString& ext) +PluginFactory::PluginInfoAndKey PluginFactory::pluginSupportingExtension(const QString& ext) { return m_pluginByExt.value(ext, PluginInfoAndKey()); } -const PluginFactory::PluginInfo PluginFactory::pluginInfo(const char* name) const +PluginFactory::PluginInfo PluginFactory::pluginInfo(const char* name) const { for (const PluginInfo& info : m_pluginInfos) { @@ -248,7 +248,7 @@ void PluginFactory::discoverPlugins() -const QString PluginFactory::PluginInfo::name() const +QString PluginFactory::PluginInfo::name() const { return descriptor ? descriptor->name : QString(); } From 50a4297c9718dc8f919781af8f792f5542f124f1 Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Sat, 21 Jan 2023 16:39:17 +0100 Subject: [PATCH 012/308] [ci skip] Update .clang-format This adds previously applied checks to the `.clang-format` file and also reorders the checks alphabetically. --- .clang-tidy | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 804bc28f1..5de9376e5 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -2,18 +2,22 @@ Checks: > bugprone-macro-parentheses, bugprone-macro-repeated-side-effects, + modernize-avoid-c-arrays, + modernize-loop-convert, modernize-redundant-void-arg, + modernize-use-auto, modernize-use-bool-literals, modernize-use-emplace, modernize-use-equals-default, modernize-use-equals-delete, modernize-use-override, + modernize-use-using, performance-trivially-destructible, + readability-braces-around-statements, readability-const-return-type, readability-identifier-naming, readability-misleading-indentation, - readability-simplify-boolean-expr, - readability-braces-around-statements + readability-simplify-boolean-expr WarningsAsErrors: '' HeaderFilterRegex: '' # don't show errors from headers AnalyzeTemporaryDtors: false From c8a9d45ef05e06e813c813debbfd9ed1c0c96883 Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Tue, 24 Jan 2023 10:46:11 +0900 Subject: [PATCH 013/308] [ci skip] Remove the reorganization disclaimer --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 7090a6a15..c64ca0a97 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,6 @@ [![Join the chat at Discord](https://img.shields.io/badge/chat-on%20discord-7289DA.svg)](https://discord.gg/3sc5su7) [![Localise on transifex](https://img.shields.io/badge/localise-on_transifex-green.svg)](https://www.transifex.com/lmms/lmms/) -**New PRs may be affected by ongoing reorganization ([#5592](https://github.com/LMMS/lmms/issues/5592)). Please be prepared to rebase your PR as necessary.** - What is LMMS? -------------- From 4d1d8871cd0bca162787d55473b94a0454085cc5 Mon Sep 17 00:00:00 2001 From: Lost Robot <34612565+LostRobotMusic@users.noreply.github.com> Date: Thu, 26 Jan 2023 11:29:41 -0800 Subject: [PATCH 014/308] Add HIIR library to LMMS (#6553) --- .gitmodules | 3 +++ src/3rdparty/CMakeLists.txt | 1 + src/3rdparty/hiir/CMakeLists.txt | 3 +++ src/3rdparty/hiir/hiir | 1 + 4 files changed, 8 insertions(+) create mode 100644 src/3rdparty/hiir/CMakeLists.txt create mode 160000 src/3rdparty/hiir/hiir diff --git a/.gitmodules b/.gitmodules index 2ccfcbcdf..ee6e7eac9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -49,3 +49,6 @@ [submodule "plugins/LadspaEffect/cmt/cmt"] path = plugins/LadspaEffect/cmt/cmt url = https://github.com/lmms/cmt +[submodule "src/3rdparty/hiir/hiir"] + path = src/3rdparty/hiir/hiir + url = https://github.com/LostRobotMusic/hiir diff --git a/src/3rdparty/CMakeLists.txt b/src/3rdparty/CMakeLists.txt index 24d156095..7a6b88775 100644 --- a/src/3rdparty/CMakeLists.txt +++ b/src/3rdparty/CMakeLists.txt @@ -3,6 +3,7 @@ IF(LMMS_BUILD_LINUX AND WANT_VST) add_subdirectory(qt5-x11embed) ENDIF() +ADD_SUBDIRECTORY(hiir) ADD_SUBDIRECTORY(rpmalloc) ADD_SUBDIRECTORY(weakjack) diff --git a/src/3rdparty/hiir/CMakeLists.txt b/src/3rdparty/hiir/CMakeLists.txt new file mode 100644 index 000000000..e954ff187 --- /dev/null +++ b/src/3rdparty/hiir/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(hiir INTERFACE) +target_include_directories(hiir INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +target_compile_features(hiir INTERFACE cxx_std_17) diff --git a/src/3rdparty/hiir/hiir b/src/3rdparty/hiir/hiir new file mode 160000 index 000000000..54a41371d --- /dev/null +++ b/src/3rdparty/hiir/hiir @@ -0,0 +1 @@ +Subproject commit 54a41371d9da47e62d669ac86bd0b2e726a2a057 From cf13cfa57aaa8a314f34670913395d9da6425d4d Mon Sep 17 00:00:00 2001 From: Lost Robot <34612565+LostRobotMusic@users.noreply.github.com> Date: Thu, 26 Jan 2023 12:28:37 -0800 Subject: [PATCH 015/308] Update HIIR submodule to latest (#6622) --- src/3rdparty/hiir/hiir | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdparty/hiir/hiir b/src/3rdparty/hiir/hiir index 54a41371d..4a9a1e67f 160000 --- a/src/3rdparty/hiir/hiir +++ b/src/3rdparty/hiir/hiir @@ -1 +1 @@ -Subproject commit 54a41371d9da47e62d669ac86bd0b2e726a2a057 +Subproject commit 4a9a1e67fa6f8ce7688e1c0c8a2b017cecd206a3 From 9d5d86d863ad9d55ee1d70fe6065f1f215d5b436 Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Fri, 27 Jan 2023 21:55:43 +0900 Subject: [PATCH 016/308] Update Docker image version for ShellCheck --- .github/workflows/checks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 1d893989e..3f7700674 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -21,7 +21,7 @@ jobs: run: tests/scripted/check-namespace shellcheck: runs-on: ubuntu-latest - container: koalaman/shellcheck-alpine:v0.4.6 + container: koalaman/shellcheck-alpine:v0.9.0 steps: - name: Check out uses: actions/checkout@v3 From 507fa239ddffd2ed1f186d0a51016c85d9c2b5a9 Mon Sep 17 00:00:00 2001 From: Bimal Poudel Date: Wed, 8 Feb 2023 00:16:10 -0700 Subject: [PATCH 017/308] Update BashCompletion.cmake (#6634) --- cmake/modules/BashCompletion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/modules/BashCompletion.cmake b/cmake/modules/BashCompletion.cmake index c3916f201..7301e82aa 100644 --- a/cmake/modules/BashCompletion.cmake +++ b/cmake/modules/BashCompletion.cmake @@ -24,7 +24,7 @@ # - Windows does not support bash completion # - macOS support should eventually be added for Homebrew (TODO) IF(WIN32) - MESSAGE(STATUS "Bash competion is not supported on this platform.") + MESSAGE(STATUS "Bash completion is not supported on this platform.") ELSEIF(APPLE) MESSAGE(STATUS "Bash completion is not yet implemented for this platform.") ELSE() From 8ba6a5f89e044bfcb893455f6ac146e2eb7e2aac Mon Sep 17 00:00:00 2001 From: Lost Robot <34612565+LostRobotMusic@users.noreply.github.com> Date: Sat, 18 Feb 2023 07:22:16 -0800 Subject: [PATCH 018/308] Draggable effects (#6648) Reorder effects in Mixer with the mouse via click and drag --- include/EffectView.h | 9 ++++++++ src/gui/EffectView.cpp | 51 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/include/EffectView.h b/include/EffectView.h index 90bb54896..b2b5985ad 100644 --- a/include/EffectView.h +++ b/include/EffectView.h @@ -30,6 +30,7 @@ #include "PluginView.h" #include "Effect.h" +class QGraphicsOpacityEffect; class QGroupBox; class QLabel; class QPushButton; @@ -61,6 +62,11 @@ public: } static constexpr int DEFAULT_WIDTH = 215; + static constexpr int DEFAULT_HEIGHT = 60; + + void mouseMoveEvent(QMouseEvent* event) override; + void mousePressEvent(QMouseEvent* event) override; + void mouseReleaseEvent(QMouseEvent* event) override; public slots: void editControls(); @@ -90,6 +96,9 @@ private: Knob * m_gate; QMdiSubWindow * m_subWindow; EffectControlDialog * m_controlView; + + bool m_dragging; + QGraphicsOpacityEffect* m_opacityEffect; } ; diff --git a/src/gui/EffectView.cpp b/src/gui/EffectView.cpp index fed1ce4e9..f2caaadd5 100644 --- a/src/gui/EffectView.cpp +++ b/src/gui/EffectView.cpp @@ -23,9 +23,11 @@ * */ +#include +#include +#include #include #include -#include #include "EffectView.h" #include "DummyEffect.h" @@ -47,9 +49,10 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) : PluginView( _model, _parent ), m_bg( embed::getIconPixmap( "effect_plugin" ) ), m_subWindow( nullptr ), - m_controlView( nullptr ) + m_controlView(nullptr), + m_dragging(false) { - setFixedSize( EffectView::DEFAULT_WIDTH, 60 ); + setFixedSize(EffectView::DEFAULT_WIDTH, EffectView::DEFAULT_HEIGHT); // Disable effects that are of type "DummyEffect" bool isEnabled = !dynamic_cast( effect() ); @@ -116,7 +119,10 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) : m_subWindow->hide(); } } - + + m_opacityEffect = new QGraphicsOpacityEffect(this); + m_opacityEffect->setOpacity(1); + setGraphicsEffect(m_opacityEffect); //move above vst effect view creation //setModel( _model ); @@ -208,6 +214,43 @@ void EffectView::contextMenuEvent( QContextMenuEvent * ) +void EffectView::mousePressEvent(QMouseEvent* event) +{ + if (event->button() == Qt::LeftButton) + { + m_dragging = true; + m_opacityEffect->setOpacity(0.3); + QCursor c(Qt::SizeVerCursor); + QApplication::setOverrideCursor(c); + update(); + } +} + +void EffectView::mouseReleaseEvent(QMouseEvent* event) +{ + if (event->button() == Qt::LeftButton) + { + m_dragging = false; + m_opacityEffect->setOpacity(1); + QApplication::restoreOverrideCursor(); + update(); + } +} + +void EffectView::mouseMoveEvent(QMouseEvent* event) +{ + if (!m_dragging) { return; } + if (event->pos().y() < 0) + { + moveUp(); + } + else if (event->pos().y() > EffectView::DEFAULT_HEIGHT) + { + moveDown(); + } +} + + void EffectView::paintEvent( QPaintEvent * ) { From 1a68aee149565e86af23ce2d4654d8ea689b7f86 Mon Sep 17 00:00:00 2001 From: Proud Electrics Studios Date: Mon, 16 Jan 2023 10:13:35 +0100 Subject: [PATCH 019/308] PatternClips now use startTimeOffset, too, and can be resized on their start [FIX 7] --- src/core/PatternClip.cpp | 2 ++ src/gui/clips/ClipView.cpp | 37 +++++++++++++++++++++++-------- src/gui/clips/PatternClipView.cpp | 14 +++++++----- src/tracks/PatternTrack.cpp | 18 ++++++++++----- 4 files changed, 52 insertions(+), 19 deletions(-) diff --git a/src/core/PatternClip.cpp b/src/core/PatternClip.cpp index 9af9bda6a..a0752b0aa 100644 --- a/src/core/PatternClip.cpp +++ b/src/core/PatternClip.cpp @@ -60,6 +60,7 @@ void PatternClip::saveSettings(QDomDocument& doc, QDomElement& element) element.setAttribute( "pos", startPosition() ); } element.setAttribute( "len", length() ); + element.setAttribute("off", startTimeOffset()); element.setAttribute( "muted", isMuted() ); if( usesCustomClipColor() ) { @@ -78,6 +79,7 @@ void PatternClip::loadSettings(const QDomElement& element) movePosition( element.attribute( "pos" ).toInt() ); } changeLength( element.attribute( "len" ).toInt() ); + setStartTimeOffset(element.attribute("off").toInt()); if( element.attribute( "muted" ).toInt() != isMuted() ) { toggleMute(); diff --git a/src/gui/clips/ClipView.cpp b/src/gui/clips/ClipView.cpp index e2da11439..8c4f704bc 100644 --- a/src/gui/clips/ClipView.cpp +++ b/src/gui/clips/ClipView.cpp @@ -43,6 +43,8 @@ #include "MidiClip.h" #include "MidiClipView.h" #include "Note.h" +#include "PatternClip.h" +#include "PatternStore.h" #include "SampleClip.h" #include "Song.h" #include "SongEditor.h" @@ -502,10 +504,11 @@ void ClipView::dropEvent( QDropEvent * de ) void ClipView::updateCursor(QMouseEvent * me) { auto sClip = dynamic_cast(m_clip); + auto pClip = dynamic_cast(m_clip); // If we are at the edges, use the resize cursor if (!me->buttons() && !m_clip->getAutoResize() && !isSelected() - && ((me->x() > width() - RESIZE_GRIP_WIDTH) || (me->x() < RESIZE_GRIP_WIDTH && sClip))) + && ((me->x() > width() - RESIZE_GRIP_WIDTH) || (me->x() < RESIZE_GRIP_WIDTH && (sClip || pClip)))) { setCursor(Qt::SizeHorCursor); } @@ -633,6 +636,7 @@ void ClipView::mousePressEvent( QMouseEvent * me ) if( !fixedClips() && me->button() == Qt::LeftButton ) { auto sClip = dynamic_cast(m_clip); + auto pClip = dynamic_cast(m_clip); const bool knifeMode = m_trackView->trackContainerView()->knifeMode(); if ( me->modifiers() & Qt::ControlModifier && !(sClip && knifeMode) ) @@ -677,7 +681,7 @@ void ClipView::mousePressEvent( QMouseEvent * me ) m_action = Resize; setCursor( Qt::SizeHorCursor ); } - else if( me->x() < RESIZE_GRIP_WIDTH && sClip ) + else if( me->x() < RESIZE_GRIP_WIDTH && (sClip || pClip) ) { m_action = ResizeLeft; setCursor( Qt::SizeHorCursor ); @@ -836,7 +840,6 @@ void ClipView::mouseMoveEvent( QMouseEvent * me ) if( m_action == Move ) { TimePos newPos = draggedClipPos( me ); - m_clip->movePosition(newPos); newPos = m_clip->startPosition(); // Get the real position the Clip was dragged to for the label m_trackView->getTrackContentWidget()->changePosition(); @@ -916,7 +919,8 @@ void ClipView::mouseMoveEvent( QMouseEvent * me ) else { auto sClip = dynamic_cast(m_clip); - if( sClip ) + auto pClip = dynamic_cast(m_clip); + if( sClip || pClip ) { const int x = mapToParent( me->pos() ).x() - m_initialMousePos.x(); @@ -948,12 +952,27 @@ void ClipView::mouseMoveEvent( QMouseEvent * me ) t = qMin( m_initialClipEnd - minLength, m_initialClipPos + offset ); } - TimePos oldPos = m_clip->startPosition(); - if( m_clip->length() + ( oldPos - t ) >= 1 ) + TimePos positionOffset = m_clip->startPosition() - t; + if (m_clip->length() + positionOffset >= 1) { - m_clip->movePosition( t ); - m_clip->changeLength( m_clip->length() + ( oldPos - t ) ); - sClip->setStartTimeOffset( sClip->startTimeOffset() + ( oldPos - t ) ); + m_clip->movePosition(t); + m_clip->changeLength(m_clip->length() + positionOffset); + if (sClip) + { + sClip->setStartTimeOffset(sClip->startTimeOffset() + positionOffset); + } + else if (pClip) + { + // Modulus the start time offset as we need it only for offsets + // inside the pattern length. This is done to prevent a value overflow. + // The start time offset may still become larger than the pattern length + // whenever the pattern length decreases without a clip resize following. + // To deal safely with it, always modulus before use. + tick_t patternLength = Engine::patternStore()->lengthOfPattern(pClip->patternIndex()) + * TimePos::ticksPerBar(); + TimePos position = (pClip->startTimeOffset() + positionOffset) % patternLength; + pClip->setStartTimeOffset(position); + } } } } diff --git a/src/gui/clips/PatternClipView.cpp b/src/gui/clips/PatternClipView.cpp index 477a90052..bf12440c7 100644 --- a/src/gui/clips/PatternClipView.cpp +++ b/src/gui/clips/PatternClipView.cpp @@ -115,14 +115,18 @@ void PatternClipView::paintEvent(QPaintEvent*) // bar lines const int lineSize = 3; + int pixelsPerPattern = Engine::patternStore()->lengthOfPattern(m_patternClip->patternIndex()) * pixelsPerBar(); + int offset = static_cast(m_patternClip->startTimeOffset() * (pixelsPerBar() / TimePos::ticksPerBar())) + % pixelsPerPattern; + if (offset < 2) { + offset += pixelsPerPattern; + } + p.setPen( c.darker( 200 ) ); - bar_t t = Engine::patternStore()->lengthOfPattern(m_patternClip->patternIndex()); - if (m_patternClip->length() > TimePos::ticksPerBar() && t > 0) + if (pixelsPerPattern > 0) { - for( int x = static_cast( t * pixelsPerBar() ); - x < width() - 2; - x += static_cast( t * pixelsPerBar() ) ) + for (int x = offset; x < width() - 2; x += pixelsPerPattern) { p.drawLine( x, BORDER_WIDTH, x, BORDER_WIDTH + lineSize ); p.drawLine( x, rect().bottom() - ( BORDER_WIDTH + lineSize ), diff --git a/src/tracks/PatternTrack.cpp b/src/tracks/PatternTrack.cpp index 9fcc2c831..cdcd108ff 100644 --- a/src/tracks/PatternTrack.cpp +++ b/src/tracks/PatternTrack.cpp @@ -108,19 +108,27 @@ bool PatternTrack::play( const TimePos & _start, const fpp_t _frames, } TimePos lastPosition; - TimePos lastLen; + TimePos lastLength; + tick_t lastOffset = 0; for (const auto& clip : clips) { if (!clip->isMuted() && clip->startPosition() >= lastPosition) { lastPosition = clip->startPosition(); - lastLen = clip->length(); + lastLength = clip->length(); + tick_t patternLength = Engine::patternStore()->lengthOfPattern(static_cast(clip)->patternIndex()) + * TimePos::ticksPerBar(); + lastOffset = patternLength - (clip->startTimeOffset() % patternLength); + if (lastOffset == patternLength) + { + lastOffset = 0; + } } } - if( _start - lastPosition < lastLen ) + if( _start - lastPosition < lastLength ) { - return Engine::patternStore()->play(_start - lastPosition, _frames, _offset, s_infoMap[this]); + return Engine::patternStore()->play(_start - lastPosition + lastOffset, _frames, _offset, s_infoMap[this]); } return false; } @@ -240,4 +248,4 @@ void PatternTrack::swapPatternTracks(Track* track1, Track* track2) } -} // namespace lmms \ No newline at end of file +} // namespace lmms From 1ddd204250b944af73ad231014947cdf849977fe Mon Sep 17 00:00:00 2001 From: dj-pixus Date: Mon, 13 Dec 2021 17:27:25 +0100 Subject: [PATCH 020/308] workize output note setting --- src/core/midi/MidiPort.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/core/midi/MidiPort.cpp b/src/core/midi/MidiPort.cpp index 63ca817e0..b656d9541 100644 --- a/src/core/midi/MidiPort.cpp +++ b/src/core/midi/MidiPort.cpp @@ -169,6 +169,12 @@ void MidiPort::processOutEvent( const MidiEvent& event, const TimePos& time ) outEvent.setVelocity( fixedOutputVelocity() ); } + if( fixedOutputNote() >= 0 && + ( event.type() == MidiNoteOn || event.type() == MidiNoteOff || event.type() == MidiKeyPressure ) ) + { + outEvent.setKey( fixedOutputNote() ); + } + m_midiClient->processOutEvent( outEvent, time, this ); } } @@ -238,6 +244,7 @@ void MidiPort::loadSettings( const QDomElement& thisElement ) m_outputControllerModel.loadSettings( thisElement, "outputcontroller" ); m_fixedInputVelocityModel.loadSettings( thisElement, "fixedinputvelocity" ); m_fixedOutputVelocityModel.loadSettings( thisElement, "fixedoutputvelocity" ); + m_fixedOutputNoteModel.loadSettings( thisElement, "fixedoutputnote" ); m_outputProgramModel.loadSettings( thisElement, "outputprogram" ); m_baseVelocityModel.loadSettings( thisElement, "basevelocity" ); m_readableModel.loadSettings( thisElement, "readable" ); From 192119621f1d321ac3eb853ec5ba54a1b3ba67e6 Mon Sep 17 00:00:00 2001 From: dev Date: Wed, 10 Mar 2021 13:33:31 +0530 Subject: [PATCH 021/308] Save Piano Roll behaviour at stop state --- include/TimeLineWidget.h | 5 +++++ src/gui/editors/PianoRoll.cpp | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/include/TimeLineWidget.h b/include/TimeLineWidget.h index 0f9b1e23a..061a31081 100644 --- a/include/TimeLineWidget.h +++ b/include/TimeLineWidget.h @@ -121,6 +121,11 @@ public: return m_behaviourAtStop; } + void setBehaviourAtStop (int state) + { + emit loadBehaviourAtStop (state); + } + bool loopPointsEnabled() const { return m_loopPoints == LoopPointsEnabled; diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 5f294d6e8..1dbbe1cf4 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -5180,6 +5180,8 @@ void PianoRollWindow::saveSettings( QDomDocument & doc, QDomElement & de ) de.appendChild(markedSemiTonesRoot); } + de.setAttribute("stopbehaviour", m_editor->m_timeLine->behaviourAtStop()); + MainWindow::saveWidgetState( this, de ); } @@ -5193,6 +5195,8 @@ void PianoRollWindow::loadSettings( const QDomElement & de ) MainWindow::restoreWidgetState( this, de ); + m_editor->m_timeLine->setBehaviourAtStop(de.attribute("stopbehaviour").toInt()); + // update margins here because we're later in the startup process // We can't earlier because everything is still starting with the // WHITE_KEY_WIDTH default From 9bcf63c5da3132c669af1f237d98770e766aaa6f Mon Sep 17 00:00:00 2001 From: madisonsilver Date: Sat, 18 Feb 2023 18:01:11 -0800 Subject: [PATCH 022/308] Fix issues #6383 and #4410 (pause issues). (#6590) Fixes #6383 and fixes #4410. Co-authored-by: Hyunjin Song --- src/core/Song.cpp | 1 + src/gui/editors/PianoRoll.cpp | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/Song.cpp b/src/core/Song.cpp index 06ac15633..fef66f193 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -620,6 +620,7 @@ void Song::togglePause() { m_playing = false; m_paused = true; + Engine::audioEngine()->clear(); } m_vstSyncController.setPlaybackState( m_playing ); diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 1dbbe1cf4..d4781eccd 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -858,8 +858,7 @@ void PianoRoll::setCurrentMidiClip( MidiClip* newMidiClip ) } // force the song-editor to stop playing if it played a MIDI clip before - if( Engine::getSong()->isPlaying() && - Engine::getSong()->playMode() == Song::Mode_PlayMidiClip ) + if (Engine::getSong()->playMode() == Song::Mode_PlayMidiClip) { Engine::getSong()->playMidiClip( nullptr ); } From 7649f5ed240dc97d9a9a66fb8effdcf15360c4d5 Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Sat, 4 Jun 2022 23:50:57 +0200 Subject: [PATCH 023/308] Lv2ControlBase: Remove unused virtuals They were never used. Possibly they were just in the code because the code originated from #4662 (where the virtuals would also be omittable...). --- include/Lv2ControlBase.h | 5 ----- plugins/Lv2Effect/Lv2FxControls.cpp | 16 ---------------- plugins/Lv2Effect/Lv2FxControls.h | 3 --- plugins/Lv2Instrument/Lv2Instrument.cpp | 16 ---------------- plugins/Lv2Instrument/Lv2Instrument.h | 2 -- 5 files changed, 42 deletions(-) diff --git a/include/Lv2ControlBase.h b/include/Lv2ControlBase.h index 93b3b21ef..353941f3d 100644 --- a/include/Lv2ControlBase.h +++ b/include/Lv2ControlBase.h @@ -142,11 +142,6 @@ protected: const class TimePos &time, f_cnt_t offset); private: - //! Return the DataFile settings type - virtual DataFile::Types settingsType() = 0; - //! Inform the plugin about a file name change - virtual void setNameFromFile(const QString &fname) = 0; - //! Independent processors //! If this is a mono effect, the vector will have size 2 in order to //! fulfill LMMS' requirement of having stereo input and output diff --git a/plugins/Lv2Effect/Lv2FxControls.cpp b/plugins/Lv2Effect/Lv2FxControls.cpp index a865151dd..a7fbfc782 100644 --- a/plugins/Lv2Effect/Lv2FxControls.cpp +++ b/plugins/Lv2Effect/Lv2FxControls.cpp @@ -86,20 +86,4 @@ void Lv2FxControls::changeControl() // TODO: what is that? } - - -DataFile::Types Lv2FxControls::settingsType() -{ - return DataFile::EffectSettings; -} - - - - -void Lv2FxControls::setNameFromFile(const QString &name) -{ - effect()->setDisplayName(name); -} - - } // namespace lmms diff --git a/plugins/Lv2Effect/Lv2FxControls.h b/plugins/Lv2Effect/Lv2FxControls.h index 952e4db6c..1d7553a34 100644 --- a/plugins/Lv2Effect/Lv2FxControls.h +++ b/plugins/Lv2Effect/Lv2FxControls.h @@ -60,9 +60,6 @@ private slots: void changeControl(); private: - DataFile::Types settingsType() override; - void setNameFromFile(const QString &name) override; - friend class gui::Lv2FxControlDialog; friend class Lv2Effect; }; diff --git a/plugins/Lv2Instrument/Lv2Instrument.cpp b/plugins/Lv2Instrument/Lv2Instrument.cpp index ae7e37119..77130bcc2 100644 --- a/plugins/Lv2Instrument/Lv2Instrument.cpp +++ b/plugins/Lv2Instrument/Lv2Instrument.cpp @@ -196,25 +196,9 @@ QString Lv2Instrument::nodeName() const -DataFile::Types Lv2Instrument::settingsType() -{ - return DataFile::InstrumentTrackSettings; -} - - - - -void Lv2Instrument::setNameFromFile(const QString &name) -{ - instrumentTrack()->setName(name); -} - - - namespace gui { - /* Lv2InsView */ diff --git a/plugins/Lv2Instrument/Lv2Instrument.h b/plugins/Lv2Instrument/Lv2Instrument.h index e9a6cc2fd..38ffdd680 100644 --- a/plugins/Lv2Instrument/Lv2Instrument.h +++ b/plugins/Lv2Instrument/Lv2Instrument.h @@ -97,8 +97,6 @@ private slots: private: QString nodeName() const override; - DataFile::Types settingsType() override; - void setNameFromFile(const QString &name) override; #ifdef LV2_INSTRUMENT_USE_MIDI std::array m_runningNotes = {}; From f48dd0fb1f424e06cd7bff1cb3d4c37f5d9a11a7 Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Sat, 4 Jun 2022 23:11:04 +0200 Subject: [PATCH 024/308] Fixes #6401: Reload Lv2 plugin on SR change This also includes banning blop's wavedata plugins, because they crash on reloading. Reference: https://gitlab.com/drobilla/blop-lv2/-/issues/3 --- include/Lv2ControlBase.h | 6 +- include/Lv2Features.h | 2 + include/Lv2Proc.h | 4 +- plugins/Lv2Effect/Lv2FxControlDialog.cpp | 6 +- plugins/Lv2Effect/Lv2FxControlDialog.h | 2 +- plugins/Lv2Effect/Lv2FxControls.cpp | 22 ++++++- plugins/Lv2Effect/Lv2FxControls.h | 5 ++ plugins/Lv2Instrument/Lv2Instrument.cpp | 39 +++++++++++- plugins/Lv2Instrument/Lv2Instrument.h | 5 ++ src/core/lv2/Lv2ControlBase.cpp | 80 ++++++++++++++---------- src/core/lv2/Lv2Features.cpp | 8 +++ src/core/lv2/Lv2Manager.cpp | 6 ++ src/core/lv2/Lv2Proc.cpp | 24 +++++++ 13 files changed, 168 insertions(+), 41 deletions(-) diff --git a/include/Lv2ControlBase.h b/include/Lv2ControlBase.h index 353941f3d..b1482afcb 100644 --- a/include/Lv2ControlBase.h +++ b/include/Lv2ControlBase.h @@ -77,6 +77,9 @@ public: static Plugin::PluginTypes check(const LilvPlugin* m_plugin, std::vector &issues); + void shutdown(); + void init(Model* meAsModel); + const LilvPlugin* getPlugin() const { return m_plugin; } Lv2Proc *control(std::size_t idx) { return m_procs[idx].get(); } @@ -95,6 +98,7 @@ protected: Lv2ControlBase(class Model *that, const QString& uri); Lv2ControlBase(const Lv2ControlBase&) = delete; ~Lv2ControlBase() override; + void reload(); Lv2ControlBase& operator=(const Lv2ControlBase&) = delete; @@ -129,8 +133,6 @@ protected: void saveSettings(QDomDocument &doc, QDomElement &that); void loadSettings(const QDomElement &that); void loadFile(const QString &file); - //! TODO: not implemented - void reloadPlugin(); /* more functions that must be called from virtuals diff --git a/include/Lv2Features.h b/include/Lv2Features.h index b4fd6c06d..b5bc284c8 100644 --- a/include/Lv2Features.h +++ b/include/Lv2Features.h @@ -69,6 +69,8 @@ public: { return m_featurePointers.data(); } + //! Clear everything + void clear(); private: //! feature storage diff --git a/include/Lv2Proc.h b/include/Lv2Proc.h index 7e6342ec4..8e6d2ad44 100644 --- a/include/Lv2Proc.h +++ b/include/Lv2Proc.h @@ -68,10 +68,12 @@ public: std::vector &issues); /* - ctor/dtor + ctor/dtor/reload */ Lv2Proc(const LilvPlugin* plugin, Model *parent); ~Lv2Proc() override; + void reload(); + void onSampleRateChanged(); //! Must be checked after ctor or reload bool isValid() const { return m_valid; } diff --git a/plugins/Lv2Effect/Lv2FxControlDialog.cpp b/plugins/Lv2Effect/Lv2FxControlDialog.cpp index d10c01cd4..1b0c05bb8 100644 --- a/plugins/Lv2Effect/Lv2FxControlDialog.cpp +++ b/plugins/Lv2Effect/Lv2FxControlDialog.cpp @@ -38,7 +38,7 @@ Lv2FxControlDialog::Lv2FxControlDialog(Lv2FxControls *controls) : { if (m_reloadPluginButton) { connect(m_reloadPluginButton, &QPushButton::clicked, - this, [this](){ lv2Controls()->reloadPlugin(); }); + this, [this](){ lv2Controls()->reload(); }); } if (m_toggleUIButton) { connect(m_toggleUIButton, &QPushButton::toggled, @@ -67,7 +67,9 @@ Lv2FxControls *Lv2FxControlDialog::lv2Controls() void Lv2FxControlDialog::modelChanged() { Lv2ViewBase::modelChanged(lv2Controls()); + connect(lv2Controls(), &Lv2FxControls::modelChanged, + this, [this](){ this->modelChanged();} ); } -} // namespace lmms::gui \ No newline at end of file +} // namespace lmms::gui diff --git a/plugins/Lv2Effect/Lv2FxControlDialog.h b/plugins/Lv2Effect/Lv2FxControlDialog.h index c749dc124..208a4c86a 100644 --- a/plugins/Lv2Effect/Lv2FxControlDialog.h +++ b/plugins/Lv2Effect/Lv2FxControlDialog.h @@ -45,7 +45,7 @@ public: private: Lv2FxControls *lv2Controls(); - void modelChanged() override; + void modelChanged() final; }; diff --git a/plugins/Lv2Effect/Lv2FxControls.cpp b/plugins/Lv2Effect/Lv2FxControls.cpp index a7fbfc782..2fde949d4 100644 --- a/plugins/Lv2Effect/Lv2FxControls.cpp +++ b/plugins/Lv2Effect/Lv2FxControls.cpp @@ -41,13 +41,33 @@ Lv2FxControls::Lv2FxControls(class Lv2Effect *effect, const QString& uri) : if (isValid()) { connect(Engine::audioEngine(), &AudioEngine::sampleRateChanged, - this, [this](){Lv2ControlBase::reloadPlugin();}); + this, [this](){onSampleRateChanged();}); } } +void Lv2FxControls::reload() +{ + Lv2ControlBase::reload(); + emit modelChanged(); +} + + + + +void Lv2FxControls::onSampleRateChanged() +{ + // TODO: once lv2 options are implemented, + // plugins that support it might allow changing their samplerate + // through it instead of reloading + reload(); +} + + + + void Lv2FxControls::saveSettings(QDomDocument &doc, QDomElement &that) { Lv2ControlBase::saveSettings(doc, that); diff --git a/plugins/Lv2Effect/Lv2FxControls.h b/plugins/Lv2Effect/Lv2FxControls.h index 1d7553a34..0ae57de94 100644 --- a/plugins/Lv2Effect/Lv2FxControls.h +++ b/plugins/Lv2Effect/Lv2FxControls.h @@ -43,8 +43,11 @@ class Lv2FxControlDialog; class Lv2FxControls : public EffectControls, public Lv2ControlBase { Q_OBJECT +signals: + void modelChanged(); public: Lv2FxControls(Lv2Effect *effect, const QString &uri); + void reload(); void saveSettings(QDomDocument &_doc, QDomElement &_parent) override; void loadSettings(const QDomElement &that) override; @@ -60,6 +63,8 @@ private slots: void changeControl(); private: + void onSampleRateChanged(); + friend class gui::Lv2FxControlDialog; friend class Lv2Effect; }; diff --git a/plugins/Lv2Instrument/Lv2Instrument.cpp b/plugins/Lv2Instrument/Lv2Instrument.cpp index 77130bcc2..e766924ec 100644 --- a/plugins/Lv2Instrument/Lv2Instrument.cpp +++ b/plugins/Lv2Instrument/Lv2Instrument.cpp @@ -78,10 +78,12 @@ Lv2Instrument::Lv2Instrument(InstrumentTrack *instrumentTrackArg, { if (Lv2ControlBase::isValid()) { + clearRunningNotes(); + connect(instrumentTrack()->pitchRangeModel(), SIGNAL(dataChanged()), this, SLOT(updatePitchRange()), Qt::DirectConnection); connect(Engine::audioEngine(), &AudioEngine::sampleRateChanged, - this, [this](){Lv2ControlBase::reloadPlugin();}); + this, [this](){onSampleRateChanged();}); // now we need a play-handle which cares for calling play() auto iph = new InstrumentPlayHandle(this, instrumentTrackArg); @@ -101,6 +103,37 @@ Lv2Instrument::~Lv2Instrument() +void Lv2Instrument::reload() +{ + Lv2ControlBase::reload(); + clearRunningNotes(); + emit modelChanged(); +} + + + + +void Lv2Instrument::clearRunningNotes() +{ +#ifdef LV2_INSTRUMENT_USE_MIDI + for (int i = 0; i < NumKeys; ++i) { m_runningNotes[i] = 0; } +#endif +} + + + + +void Lv2Instrument::onSampleRateChanged() +{ + // TODO: once lv2 options are implemented, + // plugins that support it might allow changing their samplerate + // through it instead of reloading + reload(); +} + + + + bool Lv2Instrument::isValid() const { return Lv2ControlBase::isValid(); } @@ -211,7 +244,7 @@ Lv2InsView::Lv2InsView(Lv2Instrument *_instrument, QWidget *_parent) : setAutoFillBackground(true); if (m_reloadPluginButton) { connect(m_reloadPluginButton, &QPushButton::clicked, - this, [this](){ this->castModel()->reloadPlugin();} ); + this, [this](){ this->castModel()->reload();} ); } if (m_toggleUIButton) { connect(m_toggleUIButton, &QPushButton::toggled, @@ -267,6 +300,8 @@ void Lv2InsView::dropEvent(QDropEvent *_de) void Lv2InsView::modelChanged() { Lv2ViewBase::modelChanged(castModel()); + connect(castModel(), &Lv2Instrument::modelChanged, + this, [this](){ this->modelChanged();} ); } diff --git a/plugins/Lv2Instrument/Lv2Instrument.h b/plugins/Lv2Instrument/Lv2Instrument.h index 38ffdd680..8eaf9b1d4 100644 --- a/plugins/Lv2Instrument/Lv2Instrument.h +++ b/plugins/Lv2Instrument/Lv2Instrument.h @@ -50,6 +50,8 @@ class Lv2InsView; class Lv2Instrument : public Instrument, public Lv2ControlBase { Q_OBJECT +signals: + void modelChanged(); public: /* initialization @@ -57,6 +59,8 @@ public: Lv2Instrument(InstrumentTrack *instrumentTrackArg, Descriptor::SubPluginFeatures::Key* key); ~Lv2Instrument() override; + void reload(); + void onSampleRateChanged(); //! Must be checked after ctor or reload bool isValid() const; @@ -101,6 +105,7 @@ private: #ifdef LV2_INSTRUMENT_USE_MIDI std::array m_runningNotes = {}; #endif + void clearRunningNotes(); friend class gui::Lv2InsView; }; diff --git a/src/core/lv2/Lv2ControlBase.cpp b/src/core/lv2/Lv2ControlBase.cpp index 3ab8b278c..7764313fc 100644 --- a/src/core/lv2/Lv2ControlBase.cpp +++ b/src/core/lv2/Lv2ControlBase.cpp @@ -54,30 +54,7 @@ Lv2ControlBase::Lv2ControlBase(Model* that, const QString &uri) : { if (m_plugin) { - int channelsLeft = DEFAULT_CHANNELS; // LMMS plugins are stereo - while (channelsLeft > 0) - { - std::unique_ptr newOne = std::make_unique(m_plugin, that); - if (newOne->isValid()) - { - channelsLeft -= std::max( - 1 + static_cast(newOne->inPorts().m_right), - 1 + static_cast(newOne->outPorts().m_right)); - Q_ASSERT(channelsLeft >= 0); - m_procs.push_back(std::move(newOne)); - } - else - { - qCritical() << "Failed instantiating LV2 processor"; - m_valid = false; - channelsLeft = 0; - } - } - if (m_valid) - { - m_channelsPerProc = DEFAULT_CHANNELS / m_procs.size(); - linkAllModels(); - } + init(that); } else { @@ -94,6 +71,53 @@ Lv2ControlBase::~Lv2ControlBase() = default; +void Lv2ControlBase::init(Model* meAsModel) +{ + int channelsLeft = DEFAULT_CHANNELS; // LMMS plugins are stereo + while (channelsLeft > 0) + { + std::unique_ptr newOne = std::make_unique(m_plugin, meAsModel); + if (newOne->isValid()) + { + channelsLeft -= std::max( + 1 + static_cast(newOne->inPorts().m_right), + 1 + static_cast(newOne->outPorts().m_right)); + Q_ASSERT(channelsLeft >= 0); + m_procs.push_back(std::move(newOne)); + } + else + { + qCritical() << "Failed instantiating LV2 processor"; + m_valid = false; + channelsLeft = 0; + } + } + if (m_valid) + { + m_channelsPerProc = DEFAULT_CHANNELS / m_procs.size(); + linkAllModels(); + } +} + + + + +void Lv2ControlBase::shutdown() +{ + // currently nothing to do here +} + + + + +void Lv2ControlBase::reload() +{ + for (const auto& c : m_procs) { c->reload(); } +} + + + + LinkedModelGroup *Lv2ControlBase::getGroup(std::size_t idx) { return (m_procs.size() > idx) ? m_procs[idx].get() : nullptr; @@ -183,14 +207,6 @@ void Lv2ControlBase::loadFile(const QString &file) -void Lv2ControlBase::reloadPlugin() -{ - // TODO -} - - - - std::size_t Lv2ControlBase::controlCount() const { std::size_t res = 0; for (const auto& c : m_procs) { res += c->controlCount(); } diff --git a/src/core/lv2/Lv2Features.cpp b/src/core/lv2/Lv2Features.cpp index be7fb6e28..6e74a8936 100644 --- a/src/core/lv2/Lv2Features.cpp +++ b/src/core/lv2/Lv2Features.cpp @@ -105,6 +105,14 @@ void *&Lv2Features::operator[](const char *featName) } + + +void Lv2Features::clear() +{ + m_featureByUri.clear(); +} + + } // namespace lmms #endif // LMMS_HAVE_LV2 diff --git a/src/core/lv2/Lv2Manager.cpp b/src/core/lv2/Lv2Manager.cpp index b1391b065..d60bf6c49 100644 --- a/src/core/lv2/Lv2Manager.cpp +++ b/src/core/lv2/Lv2Manager.cpp @@ -60,6 +60,12 @@ const std::set Lv2Manager::pluginBlacklist = "http://calf.sourceforge.net/plugins/TransientDesigner", "http://calf.sourceforge.net/plugins/Vinyl", + // https://gitlab.com/drobilla/blop-lv2/-/issues/3 + "http://drobilla.net/plugins/blop/pulse", + "http://drobilla.net/plugins/blop/sawtooth", + "http://drobilla.net/plugins/blop/square", + "http://drobilla.net/plugins/blop/triangle", + // Visualization, meters, and scopes etc., won't work until we have gui support "http://distrho.sf.net/plugins/ProM", "http://distrho.sf.net/plugins/glBars", diff --git a/src/core/lv2/Lv2Proc.cpp b/src/core/lv2/Lv2Proc.cpp index cbb4be2d2..31af47a63 100644 --- a/src/core/lv2/Lv2Proc.cpp +++ b/src/core/lv2/Lv2Proc.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "AudioEngine.h" @@ -175,6 +176,26 @@ Lv2Proc::~Lv2Proc() { shutdownPlugin(); } +void Lv2Proc::reload() +{ + // save controls, which we want to keep + QDomDocument doc; + QDomElement controls = doc.createElement("controls"); + saveValues(doc, controls); + // backup construction variables + const LilvPlugin* plugin = m_plugin; + Model* parent = Model::parentModel(); + // destroy everything using RAII ... + this->~Lv2Proc(); + // ... and reuse it ("placement new") + new (this) Lv2Proc(plugin, parent); + // reload the controls + loadValues(controls); +} + + + + void Lv2Proc::dumpPorts() { std::size_t num = 0; @@ -424,7 +445,10 @@ void Lv2Proc::shutdownPlugin() lilv_instance_deactivate(m_instance); lilv_instance_free(m_instance); m_instance = nullptr; + + m_features.clear(); } + m_valid = true; } From 49a6abb343e26e82ab89287dca0ee3cadc8c440b Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Thu, 1 Dec 2022 15:17:27 +0100 Subject: [PATCH 025/308] Lv2: Add/improve some comments --- include/LinkedModelGroups.h | 2 ++ include/Lv2Proc.h | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/LinkedModelGroups.h b/include/LinkedModelGroups.h index 3f274d10c..c537d7fca 100644 --- a/include/LinkedModelGroups.h +++ b/include/LinkedModelGroups.h @@ -131,6 +131,8 @@ public: private: //! models for the controls + //! @note The AutomatableModels behind the ModelInfo are not owned, + //! but referenced after `addModel` is being called. std::map m_models; }; diff --git a/include/Lv2Proc.h b/include/Lv2Proc.h index 8e6d2ad44..1be284ced 100644 --- a/include/Lv2Proc.h +++ b/include/Lv2Proc.h @@ -59,8 +59,8 @@ namespace Lv2Ports } -//! Class representing one Lv2 processor, i.e. one Lv2 handle -//! For Mono effects, 1 Lv2ControlBase references 2 Lv2Proc +//! Class representing one Lv2 processor, i.e. one Lv2 handle. +//! For Mono effects, 1 Lv2ControlBase references 2 Lv2Proc. class Lv2Proc : public LinkedModelGroup { public: @@ -197,6 +197,8 @@ private: static int32_t defaultEvbufSize() { return 1 << 15; /* ardour uses this*/ } //! models for the controls, sorted by port symbols + //! @note These are not owned, but rather link to the models in + //! ControlPorts in `m_ports` std::map m_connectedModels; void initMOptions(); //!< initialize m_options From 5b84b65236d2933f70aba6878ad77a6599ed8125 Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Sun, 5 Jun 2022 01:22:32 +0200 Subject: [PATCH 026/308] Lv2: Update copyright --- include/Lv2Basics.h | 2 +- include/Lv2ControlBase.h | 2 +- include/Lv2Manager.h | 2 +- include/Lv2SubPluginFeatures.h | 2 +- include/Lv2ViewBase.h | 2 +- plugins/Lv2Effect/Lv2Effect.cpp | 2 +- plugins/Lv2Effect/Lv2Effect.h | 2 +- plugins/Lv2Effect/Lv2FxControlDialog.cpp | 2 +- plugins/Lv2Effect/Lv2FxControlDialog.h | 2 +- plugins/Lv2Effect/Lv2FxControls.cpp | 2 +- plugins/Lv2Effect/Lv2FxControls.h | 2 +- plugins/Lv2Instrument/Lv2Instrument.cpp | 2 +- plugins/Lv2Instrument/Lv2Instrument.h | 2 +- src/core/lv2/Lv2ControlBase.cpp | 2 +- src/core/lv2/Lv2Manager.cpp | 2 +- src/core/lv2/Lv2SubPluginFeatures.cpp | 2 +- src/gui/Lv2ViewBase.cpp | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/include/Lv2Basics.h b/include/Lv2Basics.h index 3dae4c9f2..9a958d973 100644 --- a/include/Lv2Basics.h +++ b/include/Lv2Basics.h @@ -1,7 +1,7 @@ /* * Lv2Basics.h - basic Lv2 utils * - * Copyright (c) 2018-2020 Johannes Lorenz + * Copyright (c) 2018-2023 Johannes Lorenz * * This file is part of LMMS - https://lmms.io * diff --git a/include/Lv2ControlBase.h b/include/Lv2ControlBase.h index b1482afcb..f5cb0cdb4 100644 --- a/include/Lv2ControlBase.h +++ b/include/Lv2ControlBase.h @@ -1,7 +1,7 @@ /* * Lv2ControlBase.h - Lv2 control base class * - * Copyright (c) 2018-2020 Johannes Lorenz + * Copyright (c) 2018-2023 Johannes Lorenz * * This file is part of LMMS - https://lmms.io * diff --git a/include/Lv2Manager.h b/include/Lv2Manager.h index b62e989cf..89f6a0efd 100644 --- a/include/Lv2Manager.h +++ b/include/Lv2Manager.h @@ -1,7 +1,7 @@ /* * Lv2Manager.h - Implementation of Lv2Manager class * - * Copyright (c) 2018-2020 Johannes Lorenz + * Copyright (c) 2018-2023 Johannes Lorenz * * This file is part of LMMS - https://lmms.io * diff --git a/include/Lv2SubPluginFeatures.h b/include/Lv2SubPluginFeatures.h index 497c72830..57eab8715 100644 --- a/include/Lv2SubPluginFeatures.h +++ b/include/Lv2SubPluginFeatures.h @@ -3,7 +3,7 @@ * Plugin::Descriptor::SubPluginFeatures for * hosting LV2 plugins * - * Copyright (c) 2018-2020 Johannes Lorenz + * Copyright (c) 2018-2023 Johannes Lorenz * * This file is part of LMMS - https://lmms.io * diff --git a/include/Lv2ViewBase.h b/include/Lv2ViewBase.h index d27f35cec..f7d0e9bcb 100644 --- a/include/Lv2ViewBase.h +++ b/include/Lv2ViewBase.h @@ -1,7 +1,7 @@ /* * Lv2ViewBase.h - base class for Lv2 plugin views * - * Copyright (c) 2018-2020 Johannes Lorenz + * Copyright (c) 2018-2023 Johannes Lorenz * * This file is part of LMMS - https://lmms.io * diff --git a/plugins/Lv2Effect/Lv2Effect.cpp b/plugins/Lv2Effect/Lv2Effect.cpp index 1a25c718a..ec2dc1f48 100644 --- a/plugins/Lv2Effect/Lv2Effect.cpp +++ b/plugins/Lv2Effect/Lv2Effect.cpp @@ -1,7 +1,7 @@ /* * Lv2Effect.cpp - implementation of LV2 effect * - * Copyright (c) 2018-2020 Johannes Lorenz + * Copyright (c) 2018-2023 Johannes Lorenz * * This file is part of LMMS - https://lmms.io * diff --git a/plugins/Lv2Effect/Lv2Effect.h b/plugins/Lv2Effect/Lv2Effect.h index 521a7df74..3bcded355 100644 --- a/plugins/Lv2Effect/Lv2Effect.h +++ b/plugins/Lv2Effect/Lv2Effect.h @@ -1,7 +1,7 @@ /* * Lv2Effect.h - implementation of LV2 effect * - * Copyright (c) 2018-2020 Johannes Lorenz + * Copyright (c) 2018-2023 Johannes Lorenz * * This file is part of LMMS - https://lmms.io * diff --git a/plugins/Lv2Effect/Lv2FxControlDialog.cpp b/plugins/Lv2Effect/Lv2FxControlDialog.cpp index 1b0c05bb8..5265cb181 100644 --- a/plugins/Lv2Effect/Lv2FxControlDialog.cpp +++ b/plugins/Lv2Effect/Lv2FxControlDialog.cpp @@ -1,7 +1,7 @@ /* * Lv2FxControlDialog.cpp - Lv2FxControlDialog implementation * - * Copyright (c) 2018-2020 Johannes Lorenz + * Copyright (c) 2018-2023 Johannes Lorenz * * This file is part of LMMS - https://lmms.io * diff --git a/plugins/Lv2Effect/Lv2FxControlDialog.h b/plugins/Lv2Effect/Lv2FxControlDialog.h index 208a4c86a..45c14c2c0 100644 --- a/plugins/Lv2Effect/Lv2FxControlDialog.h +++ b/plugins/Lv2Effect/Lv2FxControlDialog.h @@ -1,7 +1,7 @@ /* * Lv2FxControlDialog.h - Lv2FxControlDialog implementation * - * Copyright (c) 2018-2020 Johannes Lorenz + * Copyright (c) 2018-2023 Johannes Lorenz * * This file is part of LMMS - https://lmms.io * diff --git a/plugins/Lv2Effect/Lv2FxControls.cpp b/plugins/Lv2Effect/Lv2FxControls.cpp index 2fde949d4..3ec7dbe23 100644 --- a/plugins/Lv2Effect/Lv2FxControls.cpp +++ b/plugins/Lv2Effect/Lv2FxControls.cpp @@ -1,7 +1,7 @@ /* * Lv2FxControls.cpp - Lv2FxControls implementation * - * Copyright (c) 2018-2020 Johannes Lorenz + * Copyright (c) 2018-2023 Johannes Lorenz * * This file is part of LMMS - https://lmms.io * diff --git a/plugins/Lv2Effect/Lv2FxControls.h b/plugins/Lv2Effect/Lv2FxControls.h index 0ae57de94..9f3736292 100644 --- a/plugins/Lv2Effect/Lv2FxControls.h +++ b/plugins/Lv2Effect/Lv2FxControls.h @@ -1,7 +1,7 @@ /* * Lv2FxControls.h - Lv2FxControls implementation * - * Copyright (c) 2018-2020 Johannes Lorenz + * Copyright (c) 2018-2023 Johannes Lorenz * * This file is part of LMMS - https://lmms.io * diff --git a/plugins/Lv2Instrument/Lv2Instrument.cpp b/plugins/Lv2Instrument/Lv2Instrument.cpp index e766924ec..052445844 100644 --- a/plugins/Lv2Instrument/Lv2Instrument.cpp +++ b/plugins/Lv2Instrument/Lv2Instrument.cpp @@ -1,7 +1,7 @@ /* * Lv2Instrument.cpp - implementation of LV2 instrument * - * Copyright (c) 2018-2020 Johannes Lorenz + * Copyright (c) 2018-2023 Johannes Lorenz * * This file is part of LMMS - https://lmms.io * diff --git a/plugins/Lv2Instrument/Lv2Instrument.h b/plugins/Lv2Instrument/Lv2Instrument.h index 8eaf9b1d4..7b521e1b0 100644 --- a/plugins/Lv2Instrument/Lv2Instrument.h +++ b/plugins/Lv2Instrument/Lv2Instrument.h @@ -1,7 +1,7 @@ /* * Lv2Instrument.h - implementation of LV2 instrument * - * Copyright (c) 2018-2020 Johannes Lorenz + * Copyright (c) 2018-2023 Johannes Lorenz * * This file is part of LMMS - https://lmms.io * diff --git a/src/core/lv2/Lv2ControlBase.cpp b/src/core/lv2/Lv2ControlBase.cpp index 7764313fc..3d21474b0 100644 --- a/src/core/lv2/Lv2ControlBase.cpp +++ b/src/core/lv2/Lv2ControlBase.cpp @@ -1,7 +1,7 @@ /* * Lv2ControlBase.cpp - Lv2 control base class * - * Copyright (c) 2018-2020 Johannes Lorenz + * Copyright (c) 2018-2023 Johannes Lorenz * * This file is part of LMMS - https://lmms.io * diff --git a/src/core/lv2/Lv2Manager.cpp b/src/core/lv2/Lv2Manager.cpp index d60bf6c49..cc90f5e05 100644 --- a/src/core/lv2/Lv2Manager.cpp +++ b/src/core/lv2/Lv2Manager.cpp @@ -1,7 +1,7 @@ /* * Lv2Manager.cpp - Implementation of Lv2Manager class * - * Copyright (c) 2018-2020 Johannes Lorenz + * Copyright (c) 2018-2023 Johannes Lorenz * * This file is part of LMMS - https://lmms.io * diff --git a/src/core/lv2/Lv2SubPluginFeatures.cpp b/src/core/lv2/Lv2SubPluginFeatures.cpp index 8c3c98711..4e02bc698 100644 --- a/src/core/lv2/Lv2SubPluginFeatures.cpp +++ b/src/core/lv2/Lv2SubPluginFeatures.cpp @@ -3,7 +3,7 @@ * Plugin::Descriptor::SubPluginFeatures for * hosting LV2 plugins * - * Copyright (c) 2018-2020 Johannes Lorenz + * Copyright (c) 2018-2023 Johannes Lorenz * * This file is part of LMMS - https://lmms.io * diff --git a/src/gui/Lv2ViewBase.cpp b/src/gui/Lv2ViewBase.cpp index 4347c37cd..3fd1d44b1 100644 --- a/src/gui/Lv2ViewBase.cpp +++ b/src/gui/Lv2ViewBase.cpp @@ -1,7 +1,7 @@ /* * Lv2ViewBase.cpp - base class for Lv2 plugin views * - * Copyright (c) 2018-2020 Johannes Lorenz + * Copyright (c) 2018-2023 Johannes Lorenz * * This file is part of LMMS - https://lmms.io * From ac080513fdf552a8f43b1ed09eece880c02617fa Mon Sep 17 00:00:00 2001 From: JGHFunRun <52897905+JGHFunRun@users.noreply.github.com> Date: Thu, 23 Feb 2023 16:31:07 -0600 Subject: [PATCH 027/308] Fixed typo (#6652) --- plugins/VstBase/RemoteVstPlugin32.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/VstBase/RemoteVstPlugin32.cmake b/plugins/VstBase/RemoteVstPlugin32.cmake index 466752aa5..f39bd93d0 100644 --- a/plugins/VstBase/RemoteVstPlugin32.cmake +++ b/plugins/VstBase/RemoteVstPlugin32.cmake @@ -51,7 +51,7 @@ ELSEIF(LMMS_BUILD_LINUX) INCLUDE(CheckWineGcc) CheckWineGcc(32 "${WINEGCC}" WINEGCC_WORKING) IF(NOT WINEGCC_WORKING) - MESSAGE(WARNING "winegcc fails to complie 32-bit binaries, please make sure you have 32-bit GCC libraries") + MESSAGE(WARNING "winegcc fails to compile 32-bit binaries, please make sure you have 32-bit GCC libraries") RETURN() ENDIF() ExternalProject_Add(RemoteVstPlugin32 From 2baa23ee1a45373cbe91a8ccf55e010954af922b Mon Sep 17 00:00:00 2001 From: Arash Partow Date: Thu, 16 Feb 2023 22:52:16 +1100 Subject: [PATCH 028/308] Update ExprTk package --- plugins/Xpressive/exprtk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/Xpressive/exprtk b/plugins/Xpressive/exprtk index 93a9f44f9..f46bffcd6 160000 --- a/plugins/Xpressive/exprtk +++ b/plugins/Xpressive/exprtk @@ -1 +1 @@ -Subproject commit 93a9f44f99b910bfe07cd1e933371e83cea3841c +Subproject commit f46bffcd6966d38a09023fb37ba9335214c9b959 From fb529a19c5c6ab615c266eafa27c7b6bb29efa42 Mon Sep 17 00:00:00 2001 From: Lost Robot <34612565+LostRobotMusic@users.noreply.github.com> Date: Sun, 26 Mar 2023 12:30:12 -0700 Subject: [PATCH 029/308] Make note octave highlight in piano roll obey microtonality (#6663) --- include/PianoRoll.h | 2 ++ src/gui/editors/PianoRoll.cpp | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/include/PianoRoll.h b/include/PianoRoll.h index 23fe7ddc6..25b4166c4 100644 --- a/include/PianoRoll.h +++ b/include/PianoRoll.h @@ -149,6 +149,8 @@ public: { return m_midiClip != nullptr; } + + int trackOctaveSize() const; Song::PlayModes desiredPlayModeForAccompany() const; diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index d4781eccd..b5a7e74b0 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -600,7 +600,7 @@ void PianoRoll::markSemiTone(int i, bool fromMenu) const int first = chord->isScale() ? 0 : key; const int last = chord->isScale() ? NumKeys : key + chord->last(); - const int cap = ( chord->isScale() || chord->last() == 0 ) ? KeysPerOctave : chord->last(); + const int cap = (chord->isScale() || chord->last() == 0) ? trackOctaveSize() : chord->last(); for( int i = first; i <= last; i++ ) { @@ -937,6 +937,14 @@ void PianoRoll::hideMidiClip( MidiClip* clip ) } } + +int PianoRoll::trackOctaveSize() const +{ + auto ut = m_midiClip->instrumentTrack()->microtuner(); + return ut->enabled() ? ut->octaveSize() : KeysPerOctave; +} + + void PianoRoll::selectRegionFromPixels( int xStart, int xEnd ) { @@ -3950,7 +3958,8 @@ QList PianoRoll::getAllOctavesForKey( int keyToMirror ) const { QList keys; - for (int i=keyToMirror % KeysPerOctave; i < NumKeys; i += KeysPerOctave) + int trackKeysPerOctave = trackOctaveSize(); + for (int i = keyToMirror % trackKeysPerOctave; i < NumKeys; i += trackKeysPerOctave) { keys.append(i); } From 2e572caa58a0fecf521865a0330687b8b7462285 Mon Sep 17 00:00:00 2001 From: Lost Robot <34612565+LostRobotMusic@users.noreply.github.com> Date: Wed, 5 Apr 2023 21:08:24 -0700 Subject: [PATCH 030/308] Add Dispersion effect (#6683) --- cmake/modules/PluginList.cmake | 1 + plugins/Dispersion/CMakeLists.txt | 3 + plugins/Dispersion/Dispersion.cpp | 162 ++++++++++++++++++ plugins/Dispersion/Dispersion.h | 78 +++++++++ .../Dispersion/DispersionControlDialog.cpp | 82 +++++++++ plugins/Dispersion/DispersionControlDialog.h | 52 ++++++ plugins/Dispersion/DispersionControls.cpp | 73 ++++++++ plugins/Dispersion/DispersionControls.h | 81 +++++++++ plugins/Dispersion/artwork.png | Bin 0 -> 8757 bytes plugins/Dispersion/dc_active.png | Bin 0 -> 9043 bytes plugins/Dispersion/dc_inactive.png | Bin 0 -> 8948 bytes plugins/Dispersion/logo.png | Bin 0 -> 774 bytes 12 files changed, 532 insertions(+) create mode 100644 plugins/Dispersion/CMakeLists.txt create mode 100644 plugins/Dispersion/Dispersion.cpp create mode 100644 plugins/Dispersion/Dispersion.h create mode 100644 plugins/Dispersion/DispersionControlDialog.cpp create mode 100644 plugins/Dispersion/DispersionControlDialog.h create mode 100644 plugins/Dispersion/DispersionControls.cpp create mode 100644 plugins/Dispersion/DispersionControls.h create mode 100644 plugins/Dispersion/artwork.png create mode 100644 plugins/Dispersion/dc_active.png create mode 100644 plugins/Dispersion/dc_inactive.png create mode 100644 plugins/Dispersion/logo.png diff --git a/cmake/modules/PluginList.cmake b/cmake/modules/PluginList.cmake index fe98a64b4..6b2c7519a 100644 --- a/cmake/modules/PluginList.cmake +++ b/cmake/modules/PluginList.cmake @@ -33,6 +33,7 @@ SET(LMMS_PLUGIN_LIST Compressor CrossoverEQ Delay + Dispersion DualFilter DynamicsProcessor Eq diff --git a/plugins/Dispersion/CMakeLists.txt b/plugins/Dispersion/CMakeLists.txt new file mode 100644 index 000000000..a40e04b80 --- /dev/null +++ b/plugins/Dispersion/CMakeLists.txt @@ -0,0 +1,3 @@ +INCLUDE(BuildPlugin) + +BUILD_PLUGIN(dispersion Dispersion.cpp DispersionControls.cpp DispersionControlDialog.cpp MOCFILES DispersionControls.h DispersionControlDialog.h EMBEDDED_RESOURCES *.png) diff --git a/plugins/Dispersion/Dispersion.cpp b/plugins/Dispersion/Dispersion.cpp new file mode 100644 index 000000000..9b98877e5 --- /dev/null +++ b/plugins/Dispersion/Dispersion.cpp @@ -0,0 +1,162 @@ +/* + * Dispersion.cpp + * + * Copyright (c) 2023 Lost Robot + * + * 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 "Dispersion.h" + +#include "embed.h" +#include "plugin_export.h" + +namespace lmms +{ + +extern "C" +{ + +Plugin::Descriptor PLUGIN_EXPORT dispersion_plugin_descriptor = +{ + LMMS_STRINGIFY(PLUGIN_NAME), + "Dispersion", + QT_TRANSLATE_NOOP("PluginBrowser", "An all-pass filter allowing for extremely high orders."), + "Lost Robot ", + 0x0100, + Plugin::Effect, + new PluginPixmapLoader("logo"), + nullptr, + nullptr +}; + +} + + +DispersionEffect::DispersionEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key) : + Effect(&dispersion_plugin_descriptor, parent, key), + m_dispersionControls(this), + m_sampleRate(Engine::audioEngine()->processingSampleRate()), + m_amountVal(0) +{ +} + + +bool DispersionEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames) +{ + if (!isEnabled() || !isRunning()) + { + return false; + } + + double outSum = 0.0; + const float d = dryLevel(); + const float w = wetLevel(); + + const int amount = m_dispersionControls.m_amountModel.value(); + const float freq = m_dispersionControls.m_freqModel.value(); + const float reso = m_dispersionControls.m_resoModel.value(); + float feedback = m_dispersionControls.m_feedbackModel.value(); + const bool dc = m_dispersionControls.m_dcModel.value(); + + // All-pass coefficient calculation + const float w0 = (F_2PI / m_sampleRate) * freq; + const float a0 = 1 + (std::sin(w0) / (reso * 2.f)); + float apCoeff1 = (1 - (a0 - 1)) / a0; + float apCoeff2 = (-2 * std::cos(w0)) / a0; + + float dcCoeff = 0.001 * (44100.f / m_sampleRate); + + if (amount != m_amountVal) + { + if (amount < m_amountVal) + { + // Flush filter buffers when they're no longer in use + for (int i = amount * 2; i < m_amountVal * 2; ++i) + { + m_state.x0[i] = m_state.x1[i] = m_state.y0[i] = m_state.y1[i] = 0; + } + } + m_amountVal = amount; + } + + if (amount == 0) + { + feedback = 0; + m_feedbackVal[0] = m_feedbackVal[1] = 0; + } + + for (fpp_t f = 0; f < frames; ++f) + { + std::array s = { buf[f][0] + m_feedbackVal[0], buf[f][1] + m_feedbackVal[1] }; + + runDispersionAP(m_amountVal, apCoeff1, apCoeff2, s); + m_feedbackVal[0] = s[0] * feedback; + m_feedbackVal[1] = s[1] * feedback; + + if (dc) + { + // DC offset removal + for (int i = 0; i < 2; ++i) + { + m_integrator[i] = m_integrator[i] * (1.f - dcCoeff) + s[i] * dcCoeff; + s[i] -= m_integrator[i]; + } + } + + buf[f][0] = d * buf[f][0] + w * s[0]; + buf[f][1] = d * buf[f][1] + w * s[1]; + outSum += buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1]; + } + + checkGate(outSum / frames); + return isRunning(); +} + + +void DispersionEffect::runDispersionAP(const int filtNum, const float apCoeff1, const float apCoeff2, std::array &put) +{ + for (int i = 0; i < filtNum * 2; ++i) + { + const int channel = i % 2; + const sample_t currentInput = put[channel]; + const sample_t filterOutput = apCoeff1 * (currentInput - m_state.y1[i]) + + apCoeff2 * (m_state.x0[i] - m_state.y0[i]) + m_state.x1[i]; + m_state.x1[i] = m_state.x0[i]; + m_state.x0[i] = currentInput; + m_state.y1[i] = m_state.y0[i]; + m_state.y0[i] = filterOutput; + + put[channel] = filterOutput; + } +} + + +extern "C" +{ + +// necessary for getting instance out of shared lib +PLUGIN_EXPORT Plugin * lmms_plugin_main(Model* parent, void* data) +{ + return new DispersionEffect(parent, static_cast(data)); +} + +} + +} // namespace lmms diff --git a/plugins/Dispersion/Dispersion.h b/plugins/Dispersion/Dispersion.h new file mode 100644 index 000000000..9e2014baf --- /dev/null +++ b/plugins/Dispersion/Dispersion.h @@ -0,0 +1,78 @@ +/* + * Dispersion.h + * + * Copyright (c) 2023 Lost Robot + * + * 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_DISPERSION_H +#define LMMS_DISPERSION_H + +#include "DispersionControls.h" +#include "Effect.h" + +#include "lmms_math.h" + +namespace lmms +{ + +constexpr inline int MAX_DISPERSION_FILTERS = 999; + +class DispersionEffect : public Effect +{ +public: + DispersionEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key); + ~DispersionEffect() override = default; + bool processAudioBuffer(sampleFrame* buf, const fpp_t frames) override; + + EffectControls* controls() override + { + return &m_dispersionControls; + } + + void runDispersionAP(const int filtNum, const float apCoeff1, const float apCoeff2, std::array &put); + +private: + DispersionControls m_dispersionControls; + + float m_sampleRate; + + int m_amountVal; + + using Filter = std::array; + struct FilterState { + Filter x0{}; + Filter x1{}; + Filter y0{}; + Filter y1{}; + }; + FilterState m_state = {}; + + std::array m_feedbackVal{}; + std::array m_integrator{}; + + friend class DispersionControls; +}; + + +} // namespace lmms + +#endif // LMMS_DISPERSION_H diff --git a/plugins/Dispersion/DispersionControlDialog.cpp b/plugins/Dispersion/DispersionControlDialog.cpp new file mode 100644 index 000000000..b9f04baa2 --- /dev/null +++ b/plugins/Dispersion/DispersionControlDialog.cpp @@ -0,0 +1,82 @@ +/* + * DispersionControlDialog.cpp + * + * Copyright (c) 2023 Lost Robot + * + * 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 "DispersionControlDialog.h" +#include "DispersionControls.h" + +#include "embed.h" +#include "Knob.h" +#include "LcdSpinBox.h" +#include "PixmapButton.h" + + +namespace lmms::gui +{ + + +DispersionControlDialog::DispersionControlDialog(DispersionControls* controls) : + EffectControlDialog(controls) +{ + setAutoFillBackground(true); + QPalette pal; + pal.setBrush(backgroundRole(), PLUGIN_NAME::getIconPixmap("artwork")); + setPalette(pal); + setFixedSize(207, 50); + + LcdSpinBox * m_amountBox = new LcdSpinBox(3, this, "Amount"); + m_amountBox->setModel(&controls->m_amountModel); + m_amountBox->move(5, 10); + m_amountBox->setLabel(tr("AMOUNT")); + m_amountBox->setToolTip(tr("Number of all-pass filters")); + + Knob * freqKnob = new Knob(knobBright_26, 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); + 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); + feedbackKnob->move(139, 8); + feedbackKnob->setModel(&controls->m_feedbackModel); + feedbackKnob->setLabel(tr("FEED")); + feedbackKnob->setHintText(tr("Feedback:") , ""); + + PixmapButton * dcButton = new PixmapButton(this, tr("DC Offset Removal")); + dcButton->move(176, 16); + dcButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("dc_active")); + dcButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("dc_inactive")); + dcButton->setCheckable(true); + dcButton->setModel(&controls->m_dcModel); + dcButton->setToolTip(tr("Remove DC Offset")); +} + + +} // namespace lmms::gui diff --git a/plugins/Dispersion/DispersionControlDialog.h b/plugins/Dispersion/DispersionControlDialog.h new file mode 100644 index 000000000..0d55678bd --- /dev/null +++ b/plugins/Dispersion/DispersionControlDialog.h @@ -0,0 +1,52 @@ +/* + * DispersionControlDialog.h + * + * Copyright (c) 2023 Lost Robot + * + * 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_DISPERSION_CONTROL_DIALOG_H +#define LMMS_GUI_DISPERSION_CONTROL_DIALOG_H + +#include "EffectControlDialog.h" + +namespace lmms +{ + +class DispersionControls; + + +namespace gui +{ + +class DispersionControlDialog : public EffectControlDialog +{ + Q_OBJECT +public: + DispersionControlDialog(DispersionControls* controls); + ~DispersionControlDialog() override = default; +}; + + +} // namespace gui + +} // namespace lmms + +#endif // LMMS_GUI_DISPERSION_CONTROL_DIALOG_H diff --git a/plugins/Dispersion/DispersionControls.cpp b/plugins/Dispersion/DispersionControls.cpp new file mode 100644 index 000000000..771ffb89d --- /dev/null +++ b/plugins/Dispersion/DispersionControls.cpp @@ -0,0 +1,73 @@ +/* + * DispersionControls.cpp + * + * Copyright (c) 2023 Lost Robot + * + * 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 "DispersionControls.h" +#include "Dispersion.h" + +#include + +namespace lmms +{ + +DispersionControls::DispersionControls(DispersionEffect* effect) : + EffectControls(effect), + m_effect(effect), + m_amountModel(0, 0, MAX_DISPERSION_FILTERS, this, tr("Amount")), + m_freqModel(200, 20, 20000, 0.001, this, tr("Frequency")), + m_resoModel(0.707, 0.01, 8, 0.0001, this, tr("Resonance")), + m_feedbackModel(0.f, -1.f, 1.f, 0.0001, this, tr("Feedback")), + m_dcModel(false, this, tr("DC Offset Removal")) +{ + m_freqModel.setScaleLogarithmic(true); + m_resoModel.setScaleLogarithmic(true); +} + + + +void DispersionControls::loadSettings(const QDomElement& parent) +{ + m_amountModel.loadSettings(parent, "amount"); + m_freqModel.loadSettings(parent, "freq"); + m_resoModel.loadSettings(parent, "reso"); + m_feedbackModel.loadSettings(parent, "feedback"); + m_dcModel.loadSettings(parent, "dc"); +} + + + + +void DispersionControls::saveSettings(QDomDocument& doc, QDomElement& parent) +{ + m_amountModel.saveSettings(doc, parent, "amount"); + m_freqModel.saveSettings(doc, parent, "freq"); + m_resoModel.saveSettings(doc, parent, "reso"); + m_feedbackModel.saveSettings(doc, parent, "feedback"); + m_dcModel.saveSettings(doc, parent, "dc"); +} + + +} // namespace lmms + + diff --git a/plugins/Dispersion/DispersionControls.h b/plugins/Dispersion/DispersionControls.h new file mode 100644 index 000000000..e815e1115 --- /dev/null +++ b/plugins/Dispersion/DispersionControls.h @@ -0,0 +1,81 @@ +/* + * DispersionControls.h + * + * Copyright (c) 2023 Lost Robot + * + * 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_DISPERSION_CONTROLS_H +#define LMMS_DISPERSION_CONTROLS_H + +#include "DispersionControlDialog.h" +#include "EffectControls.h" + +namespace lmms +{ + +class DispersionEffect; + +namespace gui +{ +class DispersionControlDialog; +} + + +class DispersionControls : public EffectControls +{ + Q_OBJECT +public: + DispersionControls(DispersionEffect* effect); + ~DispersionControls() override = default; + + void saveSettings(QDomDocument & doc, QDomElement & parent) override; + void loadSettings(const QDomElement & parent) override; + inline QString nodeName() const override + { + return "DispersionControls"; + } + + int controlCount() override + { + return 5; + } + + gui::EffectControlDialog* createView() override + { + return new gui::DispersionControlDialog(this); + } + +private: + DispersionEffect* m_effect; + IntModel m_amountModel; + FloatModel m_freqModel; + FloatModel m_resoModel; + FloatModel m_feedbackModel; + BoolModel m_dcModel; + + friend class gui::DispersionControlDialog; + friend class DispersionEffect; +}; + + +} // namespace lmms + +#endif // LMMS_DISPERSION_CONTROLS_H diff --git a/plugins/Dispersion/artwork.png b/plugins/Dispersion/artwork.png new file mode 100644 index 0000000000000000000000000000000000000000..17e3b9a118973f04f70c8a813f0c4667a7eb6f5d GIT binary patch literal 8757 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 F{s*w2i^Ko` literal 0 HcmV?d00001 diff --git a/plugins/Dispersion/dc_active.png b/plugins/Dispersion/dc_active.png new file mode 100644 index 0000000000000000000000000000000000000000..d9c8c93784521b5310d745be52a6a876d1782627 GIT binary patch literal 9043 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 O08G7I{{I0n?sE$O literal 0 HcmV?d00001 diff --git a/plugins/Dispersion/dc_inactive.png b/plugins/Dispersion/dc_inactive.png new file mode 100644 index 0000000000000000000000000000000000000000..9a0ee069399c47b10bdfc291a79e573eccf98591 GIT binary patch literal 8948 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 HfAfC;^8!HH literal 0 HcmV?d00001 diff --git a/plugins/Dispersion/logo.png b/plugins/Dispersion/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..9340da708dd79ed97111eb535f51b81a91d6a15b GIT binary patch literal 774 zcmV+h1Nr=kP)7WEc)VQ)zLm`B#lSD% z0Wg;#IH?7|3b0p&fj_`2;A{cm@zx+(Ge?s$@EN$6LtMjg>;+(boCbaXw;ja=b6mQ?gRp67Yf18(18niCN0v&eY^{Cr&#;#IcF{ks?!* z&o!_q>9xbSw`QytRI!M?zP_o#K-8ExJaV?vi znPt?~0KhTu23U+Gy8^Tw;^SzWSet9n Date: Sun, 9 Apr 2023 16:42:18 +0200 Subject: [PATCH 031/308] Coding conventions Adjust the code style of the adjusted and created classes according to the coding conventions. --- include/SimpleTextFloat.h | 14 ++++---- include/TextFloat.h | 27 +++++++------- src/gui/widgets/Fader.cpp | 2 +- src/gui/widgets/SimpleTextFloat.cpp | 8 ++--- src/gui/widgets/TextFloat.cpp | 56 ++++++++++++++--------------- 5 files changed, 53 insertions(+), 54 deletions(-) diff --git a/include/SimpleTextFloat.h b/include/SimpleTextFloat.h index 1d029c189..f720d0b3e 100644 --- a/include/SimpleTextFloat.h +++ b/include/SimpleTextFloat.h @@ -2,8 +2,8 @@ * TextFloat.h - class textFloat, a floating text-label * * Copyright (c) 2023 LMMS team - * - * This file is part of LMMS - https://lmms.io +* +* 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 @@ -20,7 +20,7 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * - */ +*/ #ifndef SIMPLE_TEXT_FLOAT_H @@ -42,13 +42,13 @@ public: SimpleTextFloat(); ~SimpleTextFloat() override = default; - void setText( const QString & _text ); + void setText(const QString & text); - void setVisibilityTimeOut( int _msecs ); + void setVisibilityTimeOut(int msecs); - void moveGlobal( QWidget * _w, const QPoint & _offset ) + void moveGlobal(QWidget * w, const QPoint & offset) { - move( _w->mapToGlobal( QPoint( 0, 0 ) ) + _offset ); + move(w->mapToGlobal(QPoint(0, 0)) + offset); } private: diff --git a/include/TextFloat.h b/include/TextFloat.h index fccd10ae8..4b97fa3fc 100644 --- a/include/TextFloat.h +++ b/include/TextFloat.h @@ -42,31 +42,30 @@ public: TextFloat(); ~TextFloat() override = default; - void setTitle( const QString & _title ); - void setText( const QString & _text ); - void setPixmap( const QPixmap & _pixmap ); + void setTitle(const QString & title); + void setText(const QString & text); + void setPixmap(const QPixmap & pixmap); - void setVisibilityTimeOut( int _msecs ); + void setVisibilityTimeOut(int msecs); - static TextFloat * displayMessage( const QString & _title, - const QString & _msg, - const QPixmap & _pixmap = - QPixmap(), - int _timeout = 2000, - QWidget * _parent = nullptr ); + static TextFloat * displayMessage(const QString & title, + const QString & msg, + const QPixmap & pixmap = QPixmap(), + int timeout = 2000, + QWidget * parent = nullptr); - void moveGlobal( QWidget * _w, const QPoint & _offset ) + void moveGlobal(QWidget * w, const QPoint & offset) { - move( _w->mapToGlobal( QPoint( 0, 0 ) )+_offset ); + move(w->mapToGlobal(QPoint(0, 0)) + offset); } protected: - void mousePressEvent( QMouseEvent * _me ) override; + void mousePressEvent(QMouseEvent * me) override; private: - TextFloat(const QString & _title, const QString & _text, const QPixmap & _pixmap); + TextFloat(const QString & title, const QString & text, const QPixmap & pixmap); QLabel * m_pixmapLabel; QLabel * m_titleLabel; diff --git a/src/gui/widgets/Fader.cpp b/src/gui/widgets/Fader.cpp index 4cc5802a4..dcf648c37 100644 --- a/src/gui/widgets/Fader.cpp +++ b/src/gui/widgets/Fader.cpp @@ -329,7 +329,7 @@ void Fader::updateTextFloat() s_textFloat->setText( m_description + " " + QString("%1 ").arg( model()->value() * m_conversionFactor ) + " " + m_unit ); } - s_textFloat->moveGlobal( this, QPoint( width() + 2, knobPosY() - s_textFloat->height() / 2 ) ); + s_textFloat->moveGlobal(this, QPoint(width() + 2, knobPosY() - s_textFloat->height() / 2)); } diff --git a/src/gui/widgets/SimpleTextFloat.cpp b/src/gui/widgets/SimpleTextFloat.cpp index e6625063b..d1f490b5e 100644 --- a/src/gui/widgets/SimpleTextFloat.cpp +++ b/src/gui/widgets/SimpleTextFloat.cpp @@ -47,15 +47,15 @@ SimpleTextFloat::SimpleTextFloat() : layout->addWidget(m_textLabel); } -void SimpleTextFloat::setText( const QString & _text ) +void SimpleTextFloat::setText(const QString & text) { - m_textLabel->setText(_text); + m_textLabel->setText(text); } -void SimpleTextFloat::setVisibilityTimeOut( int _msecs ) +void SimpleTextFloat::setVisibilityTimeOut(int msecs) { - QTimer::singleShot( _msecs, this, SLOT(hide())); + QTimer::singleShot(msecs, this, SLOT(hide())); show(); } diff --git a/src/gui/widgets/TextFloat.cpp b/src/gui/widgets/TextFloat.cpp index 6588902f9..4eb14bd50 100644 --- a/src/gui/widgets/TextFloat.cpp +++ b/src/gui/widgets/TextFloat.cpp @@ -43,8 +43,8 @@ TextFloat::TextFloat() : { } -TextFloat::TextFloat(const QString & _title, const QString & _text, const QPixmap & _pixmap) : - QWidget( getGUI()->mainWindow(), Qt::ToolTip ) +TextFloat::TextFloat(const QString & title, const QString & text, const QPixmap & pixmap) : + QWidget(getGUI()->mainWindow(), Qt::ToolTip) { QHBoxLayout * mainLayout = new QHBoxLayout(); setLayout(mainLayout); @@ -68,66 +68,66 @@ TextFloat::TextFloat(const QString & _title, const QString & _text, const QPixma mainLayout->addWidget(titleAndTextWidget); // Call the setters so that the hidden state is updated - setTitle(_title); - setText(_text); - setPixmap(_pixmap); + setTitle(title); + setText(text); + setPixmap(pixmap); } -void TextFloat::setTitle( const QString & _title ) +void TextFloat::setTitle(const QString & title) { - m_titleLabel->setText(_title); - m_titleLabel->setHidden(_title.isEmpty()); + m_titleLabel->setText(title); + m_titleLabel->setHidden(title.isEmpty()); } -void TextFloat::setText( const QString & _text ) +void TextFloat::setText(const QString & text) { - m_textLabel->setText(_text); - m_textLabel->setHidden(_text.isEmpty()); + m_textLabel->setText(text); + m_textLabel->setHidden(text.isEmpty()); } -void TextFloat::setPixmap( const QPixmap & _pixmap ) +void TextFloat::setPixmap(const QPixmap & pixmap) { - m_pixmapLabel->setPixmap(_pixmap); - m_pixmapLabel->setHidden(_pixmap.isNull()); + m_pixmapLabel->setPixmap(pixmap); + m_pixmapLabel->setHidden(pixmap.isNull()); } -void TextFloat::setVisibilityTimeOut( int _msecs ) +void TextFloat::setVisibilityTimeOut(int msecs) { - QTimer::singleShot( _msecs, this, SLOT(hide())); + QTimer::singleShot(msecs, this, SLOT(hide())); show(); } -TextFloat * TextFloat::displayMessage( const QString & _title, - const QString & _msg, - const QPixmap & _pixmap, - int _timeout, QWidget * _parent ) +TextFloat * TextFloat::displayMessage(const QString & title, + const QString & msg, + const QPixmap & pixmap, + int timeout, QWidget * parent) { - auto tf = new TextFloat(_title, _msg, _pixmap); + auto tf = new TextFloat(title, msg, pixmap); // Show the widget so that the correct height is calculated in the code that follows tf->show(); - if( _parent != nullptr ) + if(parent != nullptr) { - tf->moveGlobal( _parent, QPoint( _parent->width() + 2, 0 ) ); + tf->moveGlobal(parent, QPoint(parent->width() + 2, 0)); } else { // If no parent is given move the window to the lower left area of the main window QWidget * mw = getGUI()->mainWindow(); - tf->moveGlobal( mw, QPoint( 32, mw->height() - tf->height() - 8 ) ); + tf->moveGlobal(mw, QPoint(32, mw->height() - tf->height() - 8)); } - if( _timeout > 0 ) + if (timeout > 0) { - tf->setAttribute( Qt::WA_DeleteOnClose, true ); - QTimer::singleShot( _timeout, tf, SLOT(close())); + tf->setAttribute(Qt::WA_DeleteOnClose, true); + QTimer::singleShot(timeout, tf, SLOT(close())); } return tf; } -void TextFloat::mousePressEvent( QMouseEvent * ) +void TextFloat::mousePressEvent(QMouseEvent *) { close(); } From 95cd028e5d1bb265ca6250df51066ba69e472f39 Mon Sep 17 00:00:00 2001 From: Gregaras <69623172+Gregaras@users.noreply.github.com> Date: Tue, 18 Apr 2023 05:39:15 +0300 Subject: [PATCH 032/308] Update InstrumentTrackView.cpp (#6687) --- src/gui/tracks/InstrumentTrackView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/tracks/InstrumentTrackView.cpp b/src/gui/tracks/InstrumentTrackView.cpp index 5daa51381..17adc99a6 100644 --- a/src/gui/tracks/InstrumentTrackView.cpp +++ b/src/gui/tracks/InstrumentTrackView.cpp @@ -211,7 +211,7 @@ InstrumentTrackWindow * InstrumentTrackView::topLevelInstrumentTrackWindow() getGUI()->mainWindow()->workspace()->subWindowList( QMdiArea::ActivationHistoryOrder ) ) { - if( sw->isVisible() && sw->widget()->inherits( "InstrumentTrackWindow" ) ) + if( sw->isVisible() && sw->widget()->inherits( "lmms::gui::InstrumentTrackWindow" ) ) { w = qobject_cast( sw->widget() ); } From 64003fb004419a318eae8e532278f1885d7c8fbf Mon Sep 17 00:00:00 2001 From: Dalton Messmer Date: Mon, 20 Mar 2023 18:11:24 -0400 Subject: [PATCH 033/308] Fix FreeBoy CPU time bug (#6680) --- plugins/FreeBoy/CMakeLists.txt | 4 +- plugins/FreeBoy/FreeBoy.cpp | 216 +++++++++--------- plugins/FreeBoy/FreeBoy.h | 26 +-- .../{Gb_Apu_Buffer.cpp => GbApuWrapper.cpp} | 44 ++-- .../{Gb_Apu_Buffer.h => GbApuWrapper.h} | 36 +-- 5 files changed, 168 insertions(+), 158 deletions(-) rename plugins/FreeBoy/{Gb_Apu_Buffer.cpp => GbApuWrapper.cpp} (57%) rename plugins/FreeBoy/{Gb_Apu_Buffer.h => GbApuWrapper.h} (59%) diff --git a/plugins/FreeBoy/CMakeLists.txt b/plugins/FreeBoy/CMakeLists.txt index fb5093ee0..485ed3cc2 100644 --- a/plugins/FreeBoy/CMakeLists.txt +++ b/plugins/FreeBoy/CMakeLists.txt @@ -4,8 +4,8 @@ INCLUDE_DIRECTORIES(game-music-emu/gme) BUILD_PLUGIN(freeboy FreeBoy.cpp FreeBoy.h - Gb_Apu_Buffer.cpp - Gb_Apu_Buffer.h + GbApuWrapper.cpp + GbApuWrapper.h game-music-emu/gme/Gb_Apu.cpp game-music-emu/gme/Gb_Apu.h game-music-emu/gme/Gb_Oscs.cpp diff --git a/plugins/FreeBoy/FreeBoy.cpp b/plugins/FreeBoy/FreeBoy.cpp index 0d639d3a6..f9ef2c5aa 100644 --- a/plugins/FreeBoy/FreeBoy.cpp +++ b/plugins/FreeBoy/FreeBoy.cpp @@ -2,7 +2,7 @@ * FreeBoy.cpp - GameBoy papu based instrument * * Copyright (c) 2008 Attila Herman - * Csaba Hruska + * Csaba Hruska * * This file is part of LMMS - https://lmms.io * @@ -23,11 +23,12 @@ * */ -#include - -#include #include "FreeBoy.h" -#include "Gb_Apu_Buffer.h" + +#include +#include + +#include "GbApuWrapper.h" #include "base64.h" #include "InstrumentTrack.h" #include "Knob.h" @@ -45,8 +46,11 @@ namespace lmms { -const blip_time_t FRAME_LENGTH = 70224; -const long CLOCK_RATE = 4194304; +namespace +{ +constexpr blip_time_t FRAME_LENGTH = 70224; +constexpr long CLOCK_RATE = 4194304; +} extern "C" { @@ -118,9 +122,7 @@ FreeBoyInstrument::FreeBoyInstrument( InstrumentTrack * _instrument_track ) : m_trebleModel( -20.0f, -100.0f, 200.0f, 1.0f, this, tr( "Treble" ) ), m_bassModel( 461.0f, -1.0f, 600.0f, 1.0f, this, tr( "Bass" ) ), - m_graphModel( 0, 15, 32, this, false, 1 ), - - m_time(0) + m_graphModel( 0, 15, 32, this, false, 1 ) { } @@ -238,189 +240,189 @@ f_cnt_t FreeBoyInstrument::desiredReleaseFrames() const -void FreeBoyInstrument::playNote( NotePlayHandle * _n, - sampleFrame * _working_buffer ) +void FreeBoyInstrument::playNote(NotePlayHandle* nph, sampleFrame* workingBuffer) { - const f_cnt_t tfp = _n->totalFramesPlayed(); + const f_cnt_t tfp = nph->totalFramesPlayed(); const int samplerate = Engine::audioEngine()->processingSampleRate(); - const fpp_t frames = _n->framesLeftForCurrentPeriod(); - const f_cnt_t offset = _n->noteOffset(); + const fpp_t frames = nph->framesLeftForCurrentPeriod(); + const f_cnt_t offset = nph->noteOffset(); int data = 0; - int freq = _n->frequency(); + int freq = nph->frequency(); if ( tfp == 0 ) { - auto papu = new Gb_Apu_Buffer(); - papu->set_sample_rate( samplerate, CLOCK_RATE ); + auto papu = new GbApuWrapper{}; + papu->setSampleRate(samplerate, CLOCK_RATE); // Master sound circuitry power control - papu->write_register( fakeClock(), 0xff26, 0x80 ); + papu->writeRegister(0xff26, 0x80); data = m_ch1VolumeModel.value(); - data = data<<1; + data = data << 1; data += m_ch1VolSweepDirModel.value(); - data = data<<3; + data = data << 3; data += m_ch1SweepStepLengthModel.value(); - papu->write_register( fakeClock(), 0xff12, data ); + papu->writeRegister(0xff12, data); data = m_ch2VolumeModel.value(); - data = data<<1; + data = data << 1; data += m_ch2VolSweepDirModel.value(); - data = data<<3; + data = data << 3; data += m_ch2SweepStepLengthModel.value(); - papu->write_register( fakeClock(), 0xff17, data ); + papu->writeRegister(0xff17, data); //channel 4 - noise data = m_ch4VolumeModel.value(); - data = data<<1; + data = data << 1; data += m_ch4VolSweepDirModel.value(); - data = data<<3; + data = data << 3; data += m_ch4SweepStepLengthModel.value(); - papu->write_register( fakeClock(), 0xff21, data ); + papu->writeRegister(0xff21, data); - _n->m_pluginData = papu; + nph->m_pluginData = papu; } - auto papu = static_cast(_n->m_pluginData); + auto papu = static_cast(nph->m_pluginData); - papu->treble_eq( m_trebleModel.value() ); - papu->bass_freq( m_bassModel.value() ); + papu->trebleEq(m_trebleModel.value()); + papu->bassFreq(m_bassModel.value()); //channel 1 - square data = m_ch1SweepTimeModel.value(); - data = data<<1; + data = data << 1; data += m_ch1SweepDirModel.value(); data = data << 3; data += m_ch1SweepRtShiftModel.value(); - papu->write_register( fakeClock(), 0xff10, data ); + papu->writeRegister(0xff10, data); data = m_ch1WavePatternDutyModel.value(); - data = data<<6; - papu->write_register( fakeClock(), 0xff11, data ); - + data = data << 6; + papu->writeRegister(0xff11, data); //channel 2 - square data = m_ch2WavePatternDutyModel.value(); - data = data<<6; - papu->write_register( fakeClock(), 0xff16, data ); - + data = data << 6; + papu->writeRegister(0xff16, data); //channel 3 - wave - //data = m_ch3OnModel.value()?128:0; + //data = m_ch3OnModel.value() ? 128 : 0; data = 128; - papu->write_register( fakeClock(), 0xff1a, data ); + papu->writeRegister(0xff1a, data); auto ch3voldata = std::array{0, 3, 2, 1}; data = ch3voldata[(int)m_ch3VolumeModel.value()]; - data = data<<5; - papu->write_register( fakeClock(), 0xff1c, data ); - + data = data << 5; + papu->writeRegister(0xff1c, data); //controls data = m_so1VolumeModel.value(); - data = data<<4; + data = data << 4; data += m_so2VolumeModel.value(); - papu->write_register( fakeClock(), 0xff24, data ); + papu->writeRegister(0xff24, data); - data = m_ch4So2Model.value()?128:0; - data += m_ch3So2Model.value()?64:0; - data += m_ch2So2Model.value()?32:0; - data += m_ch1So2Model.value()?16:0; - data += m_ch4So1Model.value()?8:0; - data += m_ch3So1Model.value()?4:0; - data += m_ch2So1Model.value()?2:0; - data += m_ch1So1Model.value()?1:0; - papu->write_register( fakeClock(), 0xff25, data ); + data = m_ch4So2Model.value() ? 128 : 0; + data += m_ch3So2Model.value() ? 64 : 0; + data += m_ch2So2Model.value() ? 32 : 0; + data += m_ch1So2Model.value() ? 16 : 0; + data += m_ch4So1Model.value() ? 8 : 0; + data += m_ch3So1Model.value() ? 4 : 0; + data += m_ch2So1Model.value() ? 2 : 0; + data += m_ch1So1Model.value() ? 1 : 0; + papu->writeRegister(0xff25, data); - const float * wpm = m_graphModel.samples(); + const float* wpm = m_graphModel.samples(); - for( char i=0; i<16; i++ ) + for (char i = 0; i < 16; ++i) { - data = (int)floor(wpm[i*2]) << 4; - data += (int)floor(wpm[i*2+1]); - papu->write_register( fakeClock(), 0xff30 + i, data ); + data = static_cast(std::floor(wpm[i * 2])) << 4; + data += static_cast(std::floor(wpm[(i * 2) + 1])); + papu->writeRegister(0xff30 + i, data); } - if( ( freq >= 65 ) && ( freq <=4000 ) ) + if ((freq >= 65) && (freq <= 4000)) { - int initflag = (tfp==0)?128:0; - // Hz = 4194304 / ( ( 2048 - ( 11-bit-freq ) ) << 5 ) - data = 2048 - ( ( 4194304 / freq )>>5 ); - if( tfp==0 ) + int initFlag = (tfp == 0) ? 128 : 0; + // Hz = 4194304 / ((2048 - (11-bit-freq)) << 5) + data = 2048 - ((4194304 / freq) >> 5); + if (tfp == 0) { - papu->write_register( fakeClock(), 0xff13, data & 0xff ); - papu->write_register( fakeClock(), 0xff14, (data>>8) | initflag ); + papu->writeRegister(0xff13, data & 0xff); + papu->writeRegister(0xff14, (data >> 8) | initFlag); } - papu->write_register( fakeClock(), 0xff18, data & 0xff ); - papu->write_register( fakeClock(), 0xff19, (data>>8) | initflag ); - papu->write_register( fakeClock(), 0xff1d, data & 0xff ); - papu->write_register( fakeClock(), 0xff1e, (data>>8) | initflag ); + papu->writeRegister(0xff18, data & 0xff); + papu->writeRegister(0xff19, (data >> 8) | initFlag); + papu->writeRegister(0xff1d, data & 0xff); + papu->writeRegister(0xff1e, (data >> 8) | initFlag); } - if( tfp == 0 ) + if (tfp == 0) { //PRNG Frequency = (1048576 Hz / (ratio + 1)) / 2 ^ (shiftclockfreq + 1) - char sopt=0; - char ropt=1; - float fopt = 524288.0 / ( ropt * pow( 2.0, sopt + 1.0 ) ); + char sopt = 0; + char ropt = 1; + float fopt = 524288.0 / (ropt * std::pow(2.0, sopt + 1.0)); float f; - for ( char s=0; s<16; s++ ) - for ( char r=0; r<8; r++ ) { - f = 524288.0 / ( r * pow( 2.0, s + 1.0 ) ); - if( fabs( freq-fopt ) > fabs( freq-f ) ) { - fopt = f; - ropt = r; - sopt = s; + for (char s = 0; s < 16; ++s) + { + for (char r = 0; r < 8; ++r) + { + f = 524288.0 / (r * std::pow(2.0, s + 1.0)); + if (std::fabs(freq - fopt) > std::fabs(freq - f)) + { + fopt = f; + ropt = r; + sopt = s; + } } } + data = sopt; data = data << 1; data += m_ch4ShiftRegWidthModel.value(); data = data << 3; data += ropt; - papu->write_register( fakeClock(), 0xff22, data ); + papu->writeRegister(0xff22, data); //channel 4 init - papu->write_register( fakeClock(), 0xff23, 128 ); + papu->writeRegister(0xff23, 128); } - int const buf_size = 2048; - int framesleft = frames; - int datalen = 0; - auto buf = std::array{}; - while( framesleft > 0 ) + constexpr int bufSize = 2048; + int framesLeft = frames; + int dataLen = 0; + auto buf = std::array{}; + while (framesLeft > 0) { - int avail = papu->samples_avail(); - if( avail <= 0 ) + int avail = papu->samplesAvail(); + if (avail <= 0) { - m_time = 0; - papu->end_frame(FRAME_LENGTH); - avail = papu->samples_avail(); + papu->endFrame(FRAME_LENGTH); + avail = papu->samplesAvail(); } - datalen = framesleft>avail?avail:framesleft; - datalen = datalen>buf_size?buf_size:datalen; + dataLen = framesLeft > avail ? avail : framesLeft; + dataLen = dataLen > bufSize ? bufSize : dataLen; - long count = papu->read_samples(buf.data(), datalen * 2) / 2; + long count = papu->readSamples(buf.data(), dataLen * 2) / 2; - for( fpp_t frame = 0; frame < count; ++frame ) + for (fpp_t frame = 0; frame < count; ++frame) { - for( ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch ) + for (ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch) { - sample_t s = float(buf[frame*2+ch])/32768.0; - _working_buffer[frames-framesleft+frame+offset][ch] = s; + sample_t s = static_cast(buf[(frame * 2) + ch]) / 32768.0f; + workingBuffer[frames - framesLeft + frame + offset][ch] = s; } } - framesleft -= count; + framesLeft -= count; } - instrumentTrack()->processAudioBuffer( _working_buffer, frames + offset, _n ); + instrumentTrack()->processAudioBuffer(workingBuffer, frames + offset, nph); } -void FreeBoyInstrument::deleteNotePluginData( NotePlayHandle * _n ) +void FreeBoyInstrument::deleteNotePluginData(NotePlayHandle* nph) { - delete static_cast( _n->m_pluginData ); + delete static_cast(nph->m_pluginData); } @@ -736,4 +738,4 @@ PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * ) } -} // namespace lmms \ No newline at end of file +} // namespace lmms diff --git a/plugins/FreeBoy/FreeBoy.h b/plugins/FreeBoy/FreeBoy.h index aecd2b188..747305414 100644 --- a/plugins/FreeBoy/FreeBoy.h +++ b/plugins/FreeBoy/FreeBoy.h @@ -1,8 +1,8 @@ /* - * FreeBoyInstrument.h - GameBoy papu based instrument + * FreeBoy.h - GameBoy papu based instrument * - * Copyright (c) 2008 - * Csaba Hruska + * Copyright (c) 2008 Attila Herman + * Csaba Hruska * * This file is part of LMMS - https://lmms.io * @@ -23,8 +23,8 @@ * */ -#ifndef FREEBOY_H -#define FREEBOY_H +#ifndef LMMS_FREEBOY_H +#define LMMS_FREEBOY_H #include "AutomatableModel.h" #include "Blip_Buffer.h" @@ -54,10 +54,8 @@ public: FreeBoyInstrument( InstrumentTrack * _instrument_track ); ~FreeBoyInstrument() override = default; - void playNote( NotePlayHandle * _n, - sampleFrame * _working_buffer ) override; - void deleteNotePluginData( NotePlayHandle * _n ) override; - + void playNote(NotePlayHandle* nph, sampleFrame* workingBuffer) override; + void deleteNotePluginData(NotePlayHandle* nph) override; void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override; void loadSettings( const QDomElement & _this ) override; @@ -112,12 +110,8 @@ private: graphModel m_graphModel; - // Fake CPU timing - blip_time_t m_time; - blip_time_t fakeClock() { return m_time += 4; } - friend class gui::FreeBoyInstrumentView; -} ; +}; namespace gui @@ -172,11 +166,11 @@ private: /*protected slots: void updateKnobHint(); void updateKnobToolTip();*/ -} ; +}; } // namespace gui } // namespace lmms -#endif +#endif // LMMS_FREEBOY_H diff --git a/plugins/FreeBoy/Gb_Apu_Buffer.cpp b/plugins/FreeBoy/GbApuWrapper.cpp similarity index 57% rename from plugins/FreeBoy/Gb_Apu_Buffer.cpp rename to plugins/FreeBoy/GbApuWrapper.cpp index ec1a36479..790cf96e2 100644 --- a/plugins/FreeBoy/Gb_Apu_Buffer.cpp +++ b/plugins/FreeBoy/GbApuWrapper.cpp @@ -1,7 +1,7 @@ /* - * Gb_Apu_Buffer.cpp - Gb_Apu subclass which allows direct buffer access + * GbApuWrapper.cpp - Gb_Apu subclass which allows direct buffer access * Copyright (c) 2017 Tres Finocchiaro - * + * * This file is part of LMMS - https://lmms.io * * This program is free software; you can redistribute it and/or @@ -20,37 +20,45 @@ * Boston, MA 02110-1301 USA. * */ -#include "Gb_Apu_Buffer.h" + +#include "GbApuWrapper.h" namespace lmms { -void Gb_Apu_Buffer::end_frame(blip_time_t end_time) { - Gb_Apu::end_frame(end_time); - m_buf.end_frame(end_time); +// Sets specified sample rate and clock rate in Stereo_Buffer +blargg_err_t GbApuWrapper::setSampleRate(long sampleRate, long clockRate) +{ + Gb_Apu::output(m_buf.center(), m_buf.left(), m_buf.right()); + m_buf.clock_rate(clockRate); + return m_buf.set_sample_rate(sampleRate); } -// Sets specified sample rate and clock rate in Multi_Buffer -blargg_err_t Gb_Apu_Buffer::set_sample_rate(long sample_rate, long clock_rate) { - Gb_Apu_Buffer::output(m_buf.center(), m_buf.left(), m_buf.right()); - m_buf.clock_rate(clock_rate); - return m_buf.set_sample_rate(sample_rate); -} - -// Wrap Multi_Buffer::samples_avail() -long Gb_Apu_Buffer::samples_avail() const { +// Wrap Stereo_Buffer::samples_avail() +long GbApuWrapper::samplesAvail() const +{ return m_buf.samples_avail(); } -// Wrap Multi_Buffer::read_samples(...) -long Gb_Apu_Buffer::read_samples(sample_t* out, long count) { +// Wrap Stereo_Buffer::read_samples(...) +long GbApuWrapper::readSamples(blip_sample_t* out, long count) +{ return m_buf.read_samples(out, count); } -void Gb_Apu_Buffer::bass_freq(int freq) { +// Wrap Stereo_Buffer::bass_freq(...) +void GbApuWrapper::bassFreq(int freq) +{ m_buf.bass_freq(freq); } +void GbApuWrapper::endFrame(blip_time_t endTime) +{ + m_time = 0; + Gb_Apu::end_frame(endTime); + m_buf.end_frame(endTime); +} + } // namespace lmms diff --git a/plugins/FreeBoy/Gb_Apu_Buffer.h b/plugins/FreeBoy/GbApuWrapper.h similarity index 59% rename from plugins/FreeBoy/Gb_Apu_Buffer.h rename to plugins/FreeBoy/GbApuWrapper.h index 760e0920d..493a28731 100644 --- a/plugins/FreeBoy/Gb_Apu_Buffer.h +++ b/plugins/FreeBoy/GbApuWrapper.h @@ -1,7 +1,7 @@ /* - * Gb_Apu_Buffer.cpp - Gb_Apu subclass which allows direct buffer access + * GbApuWrapper.h - Gb_Apu subclass which allows direct buffer access * Copyright (c) 2017 Tres Finocchiaro - * + * * This file is part of LMMS - https://lmms.io * * This program is free software; you can redistribute it and/or @@ -20,8 +20,9 @@ * Boston, MA 02110-1301 USA. * */ -#ifndef GB_APU_BUFFER_H -#define GB_APU_BUFFER_H + +#ifndef LMMS_GB_APU_WRAPPER_H +#define LMMS_GB_APU_WRAPPER_H #include "Gb_Apu.h" #include "Multi_Buffer.h" @@ -31,25 +32,30 @@ namespace lmms { -class Gb_Apu_Buffer : public Gb_Apu { +class GbApuWrapper : private Gb_Apu +{ MM_OPERATORS public: - Gb_Apu_Buffer() = default; - ~Gb_Apu_Buffer() = default; + GbApuWrapper() = default; + ~GbApuWrapper() = default; - void end_frame(blip_time_t); + blargg_err_t setSampleRate(long sampleRate, long clockRate); + void writeRegister(unsigned addr, int data) { Gb_Apu::write_register(fakeClock(), addr, data); } + long samplesAvail() const; + long readSamples(blip_sample_t* out, long count); + void trebleEq(const blip_eq_t& eq) { Gb_Apu::treble_eq(eq); } + void bassFreq(int freq); + void endFrame(blip_time_t endTime); - blargg_err_t set_sample_rate(long sample_rate, long clock_rate); - long samples_avail() const; - using sample_t = blip_sample_t; - long read_samples(sample_t* out, long count); - void bass_freq(int freq); private: Stereo_Buffer m_buf; + + // Fake CPU timing + blip_time_t fakeClock() { return m_time += 4; } + blip_time_t m_time = 0; }; } // namespace lmms -#endif - +#endif // LMMS_GB_APU_WRAPPER_H From 1f93dbc1248cb8d6679c3941e5df62aa68ce5b4f Mon Sep 17 00:00:00 2001 From: Lost Robot <34612565+LostRobotMusic@users.noreply.github.com> Date: Fri, 21 Apr 2023 11:17:53 -0700 Subject: [PATCH 034/308] EQ default shelf reso (#6694) --- plugins/Eq/EqControls.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/Eq/EqControls.cpp b/plugins/Eq/EqControls.cpp index ad1ffa2ac..04fb9bd3a 100644 --- a/plugins/Eq/EqControls.cpp +++ b/plugins/Eq/EqControls.cpp @@ -46,12 +46,12 @@ EqControls::EqControls( EqEffect *effect ) : m_para4GainModel( 0.0 , -18, 18, 0.001, this, tr( "Peak 4 gain" ) ), m_highShelfGainModel( 0.0 , -18, 18, 0.001, this, tr( "High-shelf gain" ) ), m_hpResModel( 0.707,0.003, 10.0 , 0.001, this, tr( "HP res" ) ), - m_lowShelfResModel( 1.4,0.55, 10.0 , 0.001, this , tr( "Low-shelf res" ) ), + m_lowShelfResModel( 0.707, 0.55, 10.0 , 0.001, this , tr( "Low-shelf res" ) ), m_para1BwModel( 0.3, 0.1, 4 , 0.001, this , tr( "Peak 1 BW" ) ), m_para2BwModel( 0.3, 0.1, 4 , 0.001, this , tr( "Peak 2 BW" ) ), m_para3BwModel( 0.3, 0.1, 4 , 0.001, this , tr( "Peak 3 BW" ) ), m_para4BwModel( 0.3, 0.1, 4 , 0.001, this , tr( "Peak 4 BW" ) ), - m_highShelfResModel( 1.4, 0.55, 10.0 , 0.001, this , tr( "High-shelf res" ) ), + m_highShelfResModel( 0.707, 0.55, 10.0 , 0.001, this , tr( "High-shelf res" ) ), m_lpResModel( 0.707,0.003, 10.0 , 0.001, this , tr( "LP res" ) ), m_hpFeqModel( 31.0, 20.0, 20000, 0.001, this , tr( "HP freq" ) ), m_lowShelfFreqModel( 80.0, 20.0, 20000, 0.001, this , tr( "Low-shelf freq" ) ), From f13e95932df72748fd2d2afa2030490a169a79bc Mon Sep 17 00:00:00 2001 From: Lost Robot <34612565+LostRobotMusic@users.noreply.github.com> Date: Tue, 25 Apr 2023 11:06:15 -0700 Subject: [PATCH 035/308] Include cstdint (#6697) --- plugins/MidiImport/portsmf/allegro.h | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/MidiImport/portsmf/allegro.h b/plugins/MidiImport/portsmf/allegro.h index ca5859aef..6210652e2 100644 --- a/plugins/MidiImport/portsmf/allegro.h +++ b/plugins/MidiImport/portsmf/allegro.h @@ -49,6 +49,7 @@ #ifndef ALLEGRO_H #define ALLEGRO_H #include +#include #include #include #include From 3440d49aa8e915ba1bf00ae060a30ba9fff76d0c Mon Sep 17 00:00:00 2001 From: Bimal Poudel Date: Sat, 29 Apr 2023 22:07:13 -0600 Subject: [PATCH 036/308] Fix comparing int with bool (#6637) Co-authored-by: Hyunjin Song --- src/core/PatternClip.cpp | 2 +- src/tracks/MidiClip.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/PatternClip.cpp b/src/core/PatternClip.cpp index a0752b0aa..1058da6ba 100644 --- a/src/core/PatternClip.cpp +++ b/src/core/PatternClip.cpp @@ -80,7 +80,7 @@ void PatternClip::loadSettings(const QDomElement& element) } changeLength( element.attribute( "len" ).toInt() ); setStartTimeOffset(element.attribute("off").toInt()); - if( element.attribute( "muted" ).toInt() != isMuted() ) + if (static_cast(element.attribute("muted").toInt()) != isMuted()) { toggleMute(); } diff --git a/src/tracks/MidiClip.cpp b/src/tracks/MidiClip.cpp index e5bff8b6f..08e76ae59 100644 --- a/src/tracks/MidiClip.cpp +++ b/src/tracks/MidiClip.cpp @@ -424,7 +424,7 @@ void MidiClip::loadSettings( const QDomElement & _this ) { movePosition( _this.attribute( "pos" ).toInt() ); } - if( _this.attribute( "muted" ).toInt() != isMuted() ) + if (static_cast(_this.attribute("muted").toInt()) != isMuted()) { toggleMute(); } From 87a57db593d23d0549012278aea87ffcbfb40265 Mon Sep 17 00:00:00 2001 From: Lost Robot <34612565+LostRobotMusic@users.noreply.github.com> Date: Fri, 5 May 2023 21:16:07 -0700 Subject: [PATCH 037/308] Add instrument plugins to Song Editor via right click (#6698) --- include/PluginBrowser.h | 3 ++- src/gui/PluginBrowser.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/include/PluginBrowser.h b/include/PluginBrowser.h index dd2e0a5cb..2bb1b6d5c 100644 --- a/include/PluginBrowser.h +++ b/include/PluginBrowser.h @@ -63,13 +63,14 @@ public: using PluginKey = Plugin::Descriptor::SubPluginFeatures::Key; PluginDescWidget( const PluginKey & _pk, QWidget * _parent ); QString name() const; - + void openInNewInstrumentTrack(QString value); protected: void enterEvent( QEvent * _e ) override; void leaveEvent( QEvent * _e ) override; void mousePressEvent( QMouseEvent * _me ) override; void paintEvent( QPaintEvent * _pe ) override; + void contextMenuEvent(QContextMenuEvent* e) override; private: constexpr static int DEFAULT_HEIGHT{24}; diff --git a/src/gui/PluginBrowser.cpp b/src/gui/PluginBrowser.cpp index afb74dcd3..b59064f05 100644 --- a/src/gui/PluginBrowser.cpp +++ b/src/gui/PluginBrowser.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -34,7 +35,10 @@ #include "embed.h" #include "Engine.h" +#include "InstrumentTrack.h" +#include "Song.h" #include "StringPairDrag.h" +#include "TrackContainerView.h" #include "PluginFactory.h" namespace lmms::gui @@ -287,4 +291,24 @@ void PluginDescWidget::mousePressEvent( QMouseEvent * _me ) } +void PluginDescWidget::contextMenuEvent(QContextMenuEvent* e) +{ + QMenu contextMenu(this); + contextMenu.addAction( + tr("Send to new instrument track"), + [=]{ openInNewInstrumentTrack(m_pluginKey.desc->name); } + ); + contextMenu.exec(e->globalPos()); +} + + +void PluginDescWidget::openInNewInstrumentTrack(QString value) +{ + TrackContainer* tc = Engine::getSong(); + auto it = dynamic_cast(Track::create(Track::InstrumentTrack, tc)); + auto ilt = new InstrumentLoaderThread(this, it, value); + ilt->start(); +} + + } // namespace lmms::gui From d551938cbd3a7bad3e7859ab7abd1499d7326b3b Mon Sep 17 00:00:00 2001 From: superpaik <68785450+superpaik@users.noreply.github.com> Date: Wed, 10 May 2023 13:14:24 +0200 Subject: [PATCH 038/308] Add confirm removal on mixer channels (#6691) * Add confirm removal on mixer channels Add confirm removal popup when the user calls the action "remove channel" on a mixer channel that is in use (receives audio from other channel or track). Set a config variable to keep track if the user don't want to be asked again. Adding a scroll on settings-general tab because there weren't enough space on the area. * Core Mixer function channel in use New core Mixer function to check if a given channel is in use (receives audio) --------- Co-authored-by: Hyunjin Song Co-authored-by: saker --- include/Mixer.h | 4 ++ include/MixerView.h | 1 + include/SetupDialog.h | 2 + src/core/Mixer.cpp | 36 ++++++++++++++ src/gui/MixerView.cpp | 88 ++++++++++++++++++++++------------ src/gui/modals/SetupDialog.cpp | 46 +++++++++++++++--- 6 files changed, 140 insertions(+), 37 deletions(-) diff --git a/include/Mixer.h b/include/Mixer.h index d84a11063..6589836c4 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -202,6 +202,10 @@ public: // rename channels when moving etc. if they still have their original name void validateChannelName( int index, int oldIndex ); + // check if the index channel receives audio from any other channel + // or from any instrument or sample track + bool isChannelInUse(int index); + void toggledSolo(); void activateSolo(); void deactivateSolo(); diff --git a/include/MixerView.h b/include/MixerView.h index 9dc5abeee..2bb5ed417 100644 --- a/include/MixerView.h +++ b/include/MixerView.h @@ -95,6 +95,7 @@ public: // notify the view that a mixer channel was deleted void deleteChannel(int index); + bool confirmRemoval(int index); // delete all unused channels void deleteUnusedChannels(); diff --git a/include/SetupDialog.h b/include/SetupDialog.h index 6a9986d64..27a4ce4f9 100644 --- a/include/SetupDialog.h +++ b/include/SetupDialog.h @@ -82,6 +82,7 @@ private slots: void toggleLetPreviewsFinish(bool enabled); void toggleSoloLegacyBehavior(bool enabled); void toggleTrackDeletionWarning(bool enabled); + void toggleMixerChannelDeletionWarning(bool enabled); void toggleMMPZ(bool enabled); void toggleDisableBackup(bool enabled); void toggleOpenLastProject(bool enabled); @@ -141,6 +142,7 @@ private: bool m_letPreviewsFinish; bool m_soloLegacyBehavior; bool m_trackDeletionWarning; + bool m_mixerChannelDeletionWarning; bool m_MMPZ; bool m_disableBackup; bool m_openLastProject; diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 52ce2732c..9354687a8 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -825,5 +825,41 @@ 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()) + { + 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(); + + for (const auto t : tracks) + { + if (t->type() == Track::InstrumentTrack) + { + auto inst = dynamic_cast(t); + if (inst->mixerChannelModel()->value() == index) + { + return true; + } + } + else if (t->type() == Track::SampleTrack) + { + auto strack = dynamic_cast(t); + if (strack->mixerChannelModel()->value() == index) + { + return true; + } + } + } + + return false; +} + } // namespace lmms diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index a9b7bf992..a9582b4e2 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -23,7 +23,9 @@ */ +#include #include +#include #include #include #include @@ -385,6 +387,12 @@ void MixerView::deleteChannel(int index) // can't delete master if( index == 0 ) return; + // if there is no user confirmation, do nothing + if (!confirmRemoval(index)) + { + return; + } + // remember selected line int selLine = m_currentMixerLine->channelIndex(); @@ -397,7 +405,7 @@ void MixerView::deleteChannel(int index) // delete the view chLayout->removeWidget(m_mixerChannelViews[index]->m_mixerLine); - m_racksLayout->removeWidget( m_mixerChannelViews[index]->m_rackView ); + m_racksLayout->removeWidget(m_mixerChannelViews[index]->m_rackView); delete m_mixerChannelViews[index]->m_fader; delete m_mixerChannelViews[index]->m_muteBtn; delete m_mixerChannelViews[index]->m_soloBtn; @@ -409,56 +417,74 @@ void MixerView::deleteChannel(int index) m_channelAreaWidget->adjustSize(); // make sure every channel knows what index it is - for(int i=index + 1; im_mixerLine->setChannelIndex(i-1); + m_mixerChannelViews[i]->m_mixerLine->setChannelIndex(i - 1); } m_mixerChannelViews.remove(index); // select the next channel - if( selLine >= m_mixerChannelViews.size() ) + if (selLine >= m_mixerChannelViews.size()) { - selLine = m_mixerChannelViews.size()-1; + selLine = m_mixerChannelViews.size() - 1; } setCurrentMixerLine(selLine); updateMaxChannelSelector(); } +bool MixerView::confirmRemoval(int index) +{ + // if config variable is set to false, there is no need for user confirmation + bool needConfirm = ConfigManager::inst()->value("ui", "mixerchanneldeletionwarning", "1").toInt(); + if (!needConfirm) { return true; } + + Mixer* mix = Engine::mixer(); + + if (!mix->isChannelInUse(index)) + { + // is the channel is not in use, there is no need for user confirmation + return true; + } + + QString messageRemoveTrack = tr("This Mixer Channel is being used.\n" + "Are you sure you want to remove this channel?\n\n" + "Warning: This operation can not be undone."); + + QString messageTitleRemoveTrack = tr("Confirm removal"); + QString askAgainText = tr("Don't ask again"); + auto askAgainCheckBox = new QCheckBox(askAgainText, nullptr); + connect(askAgainCheckBox, &QCheckBox::stateChanged, [this](int state) { + // Invert button state, if it's checked we *shouldn't* ask again + ConfigManager::inst()->setValue("ui", "mixerchanneldeletionwarning", state ? "0" : "1"); + }); + + QMessageBox mb(this); + mb.setText(messageRemoveTrack); + mb.setWindowTitle(messageTitleRemoveTrack); + mb.setIcon(QMessageBox::Warning); + mb.addButton(QMessageBox::Cancel); + mb.addButton(QMessageBox::Ok); + mb.setCheckBox(askAgainCheckBox); + mb.setDefaultButton(QMessageBox::Cancel); + + int answer = mb.exec(); + + return answer == QMessageBox::Ok; +} void MixerView::deleteUnusedChannels() { - TrackContainer::TrackList tracks; - tracks += Engine::getSong()->tracks(); - tracks += Engine::patternStore()->tracks(); + Mixer* mix = Engine::mixer(); - std::vector inUse(m_mixerChannelViews.size(), false); - - //Populate inUse by checking the destination channel for every track - for (Track* t: tracks) + // Check all channels except master, delete those with no incoming sends + for (int i = m_mixerChannelViews.size() - 1; i > 0; --i) { - //The channel that this track sends to. Since master channel is always in use, - //setting this to 0 is a safe default (for tracks that don't sent to the mixer). - int channel = 0; - if (t->type() == Track::InstrumentTrack) + if (!mix->isChannelInUse(i)) { - auto inst = dynamic_cast(t); - channel = inst->mixerChannelModel()->value(); + deleteChannel(i); } - else if (t->type() == Track::SampleTrack) - { - auto strack = dynamic_cast(t); - channel = strack->mixerChannelModel()->value(); - } - inUse[channel] = true; - } - - //Check all channels except master, delete those with no incoming sends - for(int i = m_mixerChannelViews.size()-1; i > 0; --i) - { - if (!inUse[i] && Engine::mixer()->mixerChannel(i)->m_receives.isEmpty()) - { deleteChannel(i); } } } diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index 44eaf87b0..33505c399 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -112,6 +112,8 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : "app", "sololegacybehavior", "0").toInt()), m_trackDeletionWarning(ConfigManager::inst()->value( "ui", "trackdeletionwarning", "1").toInt()), + m_mixerChannelDeletionWarning(ConfigManager::inst()->value( + "ui", "mixerchanneldeletionwarning", "1").toInt()), m_MMPZ(!ConfigManager::inst()->value( "app", "nommpz").toInt()), m_disableBackup(!ConfigManager::inst()->value( @@ -198,6 +200,18 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : general_layout->setContentsMargins(0, 0, 0, 0); labelWidget(general_w, tr("General")); + // General scroll area. + auto generalScroll = new QScrollArea(general_w); + generalScroll->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + generalScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + // General controls widget. + auto generalControls = new QWidget(general_w); + + // Path selectors layout. + auto generalControlsLayout = new QVBoxLayout; + generalControlsLayout->setSpacing(10); + auto addLedCheckBox = [&XDelta, &YDelta, this](const QString& ledText, TabWidget* tw, int& counter, bool initialState, const char* toggledSlot, bool showRestartWarning) { auto checkBox = new LedCheckBox(ledText, tw); @@ -214,7 +228,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : int counter = 0; // GUI tab. - auto gui_tw = new TabWidget(tr("Graphical user interface (GUI)"), general_w); + auto gui_tw = new TabWidget(tr("Graphical user interface (GUI)"), generalControls); addLedCheckBox(tr("Display volume as dBFS "), gui_tw, counter, m_displaydBFS, SLOT(toggleDisplaydBFS(bool)), true); @@ -236,14 +250,19 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : m_soloLegacyBehavior, SLOT(toggleSoloLegacyBehavior(bool)), false); addLedCheckBox(tr("Show warning when deleting tracks"), gui_tw, counter, m_trackDeletionWarning, SLOT(toggleTrackDeletionWarning(bool)), false); + addLedCheckBox(tr("Show warning when deleting a mixer channel that is in use"), gui_tw, counter, + m_mixerChannelDeletionWarning, SLOT(toggleMixerChannelDeletionWarning(bool)), false); gui_tw->setFixedHeight(YDelta + YDelta * counter); + generalControlsLayout->addWidget(gui_tw); + generalControlsLayout->addSpacing(10); + counter = 0; // Projects tab. - auto projects_tw = new TabWidget(tr("Projects"), general_w); + auto projects_tw = new TabWidget(tr("Projects"), generalControls); addLedCheckBox(tr("Compress project files by default"), projects_tw, counter, m_MMPZ, SLOT(toggleMMPZ(bool)), true); @@ -254,8 +273,12 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : projects_tw->setFixedHeight(YDelta + YDelta * counter); + generalControlsLayout->addWidget(projects_tw); + generalControlsLayout->addSpacing(10); + + // Language tab. - auto lang_tw = new TabWidget(tr("Language"), general_w); + auto lang_tw = new TabWidget(tr("Language"), generalControls); lang_tw->setFixedHeight(48); auto changeLang = new QComboBox(lang_tw); changeLang->move(XDelta, 20); @@ -310,11 +333,15 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : connect(changeLang, SIGNAL(currentIndexChanged(int)), this, SLOT(showRestartWarning())); + generalControlsLayout->addWidget(lang_tw); + generalControlsLayout->addSpacing(10); // General layout ordering. - general_layout->addWidget(gui_tw); - general_layout->addWidget(projects_tw); - general_layout->addWidget(lang_tw); + generalControlsLayout->addStretch(); + generalControls->setLayout(generalControlsLayout); + generalScroll->setWidget(generalControls); + generalScroll->setWidgetResizable(true); + general_layout->addWidget(generalScroll); general_layout->addStretch(); @@ -896,6 +923,8 @@ void SetupDialog::accept() QString::number(m_soloLegacyBehavior)); ConfigManager::inst()->setValue("ui", "trackdeletionwarning", QString::number(m_trackDeletionWarning)); + ConfigManager::inst()->setValue("ui", "mixerchanneldeletionwarning", + QString::number(m_mixerChannelDeletionWarning)); ConfigManager::inst()->setValue("app", "nommpz", QString::number(!m_MMPZ)); ConfigManager::inst()->setValue("app", "disablebackup", @@ -1017,6 +1046,11 @@ void SetupDialog::toggleTrackDeletionWarning(bool enabled) m_trackDeletionWarning = enabled; } +void SetupDialog::toggleMixerChannelDeletionWarning(bool enabled) +{ + m_mixerChannelDeletionWarning = enabled; +} + void SetupDialog::toggleMMPZ(bool enabled) { From b322f8022e9873ea0d09a7e3bb5cf785605fa793 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Tue, 23 May 2023 03:14:28 -0400 Subject: [PATCH 039/308] Add .DirIcon to AppImage (#6715) * Add .DirIcon to AppImage * Add X-AppImage-Version to .desktop file * Closes #6695 --- cmake/linux/package_linux.sh.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmake/linux/package_linux.sh.in b/cmake/linux/package_linux.sh.in index 89e500060..16cd5719b 100644 --- a/cmake/linux/package_linux.sh.in +++ b/cmake/linux/package_linux.sh.in @@ -149,6 +149,7 @@ fi # Patch the desktop file sed -i 's/.*Exec=.*/Exec=lmms.real/' "$DESKTOPFILE" +echo "X-AppImage-Version=@VERSION@" >> "$DESKTOPFILE" # Fix linking for soft-linked plugins for file in "${APPDIR}usr/lib/lmms/"*.so; do @@ -201,6 +202,9 @@ fi rm -f "${APPDIR}/AppRun" ln -sr "${APPDIR}/usr/bin/lmms" "${APPDIR}/AppRun" +# Add icon +ln -srf "${APPDIR}/lmms.png" "${APPDIR}/.DirIcon" + # Create AppImage echo -e "\nFinishing the AppImage..." run_and_log "$APPIMAGETOOL" "${APPDIR}" "@APPIMAGE_FILE@" From 75627a15f9fc23fe0a652175406c79dafd879e46 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Fri, 26 May 2023 10:52:35 +0200 Subject: [PATCH 040/308] Fix automation crash (#6711) Fix a crash that occurs if the zooming or snapping model of the Song Editor is used for automation. The crash is caused by a failed static_cast to a Model* in Model::parentModel(). The cast fails because in the constructor of SongEditor the SongEditor is set as the parent of the zooming and snapping model: m_zoomingModel->setParent(this); m_snappingModel->setParent(this); This commit is rather a "band aid" fix because it only fixes the crash by changing the static_cast to a dynamic_cast. However this means that the name of the automation clip is initially empty. A better solution would be to not use the Qt parent/child relationships to implement the model hierarchies. --- include/Model.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/Model.h b/include/Model.h index 3e304297f..cc3079796 100644 --- a/include/Model.h +++ b/include/Model.h @@ -54,7 +54,7 @@ public: Model* parentModel() const { - return static_cast( parent() ); + return dynamic_cast( parent() ); } virtual QString displayName() const From 43319a8d793aca70b7a06090d24ac5dfb834910f Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Fri, 26 May 2023 11:11:45 +0200 Subject: [PATCH 041/308] Move implementations of Model into cpp file (#6711) Move the implementation of the Model methods into Model.cpp so that recompiles after changes are much quicker. Make Model:: isDefaultConstructed const. --- include/Model.h | 29 ++++++----------------------- src/core/Model.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/include/Model.h b/include/Model.h index cc3079796..6db8f9f30 100644 --- a/include/Model.h +++ b/include/Model.h @@ -37,35 +37,18 @@ class LMMS_EXPORT Model : public QObject { Q_OBJECT public: - Model( Model * _parent, QString _display_name = QString(), - bool _default_constructed = false ) : - QObject( _parent ), - m_displayName( _display_name ), - m_defaultConstructed( _default_constructed ) - { - } + Model(Model * _parent, QString _display_name = QString(), + bool _default_constructed = false ); ~Model() override = default; - bool isDefaultConstructed() - { - return m_defaultConstructed; - } + bool isDefaultConstructed() const; - Model* parentModel() const - { - return dynamic_cast( parent() ); - } + Model* parentModel() const; - virtual QString displayName() const - { - return m_displayName; - } + virtual QString displayName() const; - virtual void setDisplayName( const QString& displayName ) - { - m_displayName = displayName; - } + virtual void setDisplayName(const QString& displayName); virtual QString fullDisplayName() const; diff --git a/src/core/Model.cpp b/src/core/Model.cpp index dd277bc4e..83602bd08 100644 --- a/src/core/Model.cpp +++ b/src/core/Model.cpp @@ -27,6 +27,33 @@ namespace lmms { +Model::Model(Model * _parent, QString _display_name, bool _default_constructed) : + QObject( _parent ), + m_displayName( _display_name ), + m_defaultConstructed( _default_constructed ) +{ +} + +bool Model::isDefaultConstructed() const +{ + return m_defaultConstructed; +} + +Model* Model::parentModel() const +{ + return dynamic_cast( parent() ); +} + +QString Model::displayName() const +{ + return m_displayName; +} + +void Model::setDisplayName( const QString& displayName ) +{ + m_displayName = displayName; +} + QString Model::fullDisplayName() const { const QString & n = displayName(); From 8a07328a93e973357851169b81248d3c7b5f56a7 Mon Sep 17 00:00:00 2001 From: Lost Robot <34612565+LostRobotMusic@users.noreply.github.com> Date: Thu, 1 Jun 2023 12:31:00 -0500 Subject: [PATCH 042/308] Remove non-directory expansion --- src/gui/FileBrowser.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/gui/FileBrowser.cpp b/src/gui/FileBrowser.cpp index a104d3265..88932af19 100644 --- a/src/gui/FileBrowser.cpp +++ b/src/gui/FileBrowser.cpp @@ -235,10 +235,6 @@ void FileBrowser::expandItems( QTreeWidgetItem * item, QList expandedDi for (int i = 0; i < numChildren; ++i) { QTreeWidgetItem * it = item ? item->child( i ) : m_fileBrowserTreeWidget->topLevelItem(i); - if ( m_recurse ) - { - it->setExpanded( true ); - } auto d = dynamic_cast(it); if (d) { @@ -1282,4 +1278,4 @@ QString FileItem::extension(const QString & file ) } -} // namespace lmms::gui \ No newline at end of file +} // namespace lmms::gui From fda938fccaf543a480561c7c4e759731690ee299 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Fri, 2 Jun 2023 20:31:38 +0200 Subject: [PATCH 043/308] Code review changes (#6711) Remove underscores and whitespace in the Model files. --- include/Model.h | 4 ++-- src/core/Model.cpp | 20 ++++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/include/Model.h b/include/Model.h index 6db8f9f30..e481fbdf1 100644 --- a/include/Model.h +++ b/include/Model.h @@ -37,8 +37,8 @@ class LMMS_EXPORT Model : public QObject { Q_OBJECT public: - Model(Model * _parent, QString _display_name = QString(), - bool _default_constructed = false ); + Model(Model * parent, QString displayName = QString(), + bool defaultConstructed = false ); ~Model() override = default; diff --git a/src/core/Model.cpp b/src/core/Model.cpp index 83602bd08..c59887702 100644 --- a/src/core/Model.cpp +++ b/src/core/Model.cpp @@ -27,10 +27,10 @@ namespace lmms { -Model::Model(Model * _parent, QString _display_name, bool _default_constructed) : - QObject( _parent ), - m_displayName( _display_name ), - m_defaultConstructed( _default_constructed ) +Model::Model(Model * parent, QString displayName, bool defaultConstructed) : + QObject(parent), + m_displayName(displayName), + m_defaultConstructed(defaultConstructed) { } @@ -41,7 +41,7 @@ bool Model::isDefaultConstructed() const Model* Model::parentModel() const { - return dynamic_cast( parent() ); + return dynamic_cast(parent()); } QString Model::displayName() const @@ -57,19 +57,23 @@ void Model::setDisplayName( const QString& displayName ) QString Model::fullDisplayName() const { const QString & n = displayName(); - if( parentModel() ) + + if(parentModel()) { const QString p = parentModel()->fullDisplayName(); - if( n.isEmpty() && p.isEmpty() ) + + if(n.isEmpty() && p.isEmpty()) { return QString(); } - else if( p.isEmpty() ) + else if(p.isEmpty()) { return n; } + return p + ">" + n; } + return n; } From 9fe7fbd69eabc98f6fe63ef4c4b018fae09442f0 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Fri, 2 Jun 2023 20:45:58 +0200 Subject: [PATCH 044/308] Simplify logic of Model::fullDisplayName (#6711) Simplify the logic of the method Model::fullDisplayName. Please note that this shows that with the current logic if the parent model has a non-empty name like "parentmodel" and the name of the child model is empty the result is the name "parentmodel >" which might not be what's wanted. --- src/core/Model.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/core/Model.cpp b/src/core/Model.cpp index c59887702..7a7919bb8 100644 --- a/src/core/Model.cpp +++ b/src/core/Model.cpp @@ -56,22 +56,16 @@ void Model::setDisplayName( const QString& displayName ) QString Model::fullDisplayName() const { - const QString & n = displayName(); + const QString n = displayName(); if(parentModel()) { const QString p = parentModel()->fullDisplayName(); - if(n.isEmpty() && p.isEmpty()) + if (!p.isEmpty()) { - return QString(); + return p + ">" + n; } - else if(p.isEmpty()) - { - return n; - } - - return p + ">" + n; } return n; From 0ebc18941b934893f82e322b8bd09efea139b05d Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Fri, 2 Jun 2023 22:17:03 +0200 Subject: [PATCH 045/308] More whitespace adjustments (#6711) More whitespace adjustments as proposed in the code review. --- include/Model.h | 4 ++-- src/core/Model.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/Model.h b/include/Model.h index e481fbdf1..ce7b751e7 100644 --- a/include/Model.h +++ b/include/Model.h @@ -37,8 +37,8 @@ class LMMS_EXPORT Model : public QObject { Q_OBJECT public: - Model(Model * parent, QString displayName = QString(), - bool defaultConstructed = false ); + Model(Model* parent, QString displayName = QString(), + bool defaultConstructed = false); ~Model() override = default; diff --git a/src/core/Model.cpp b/src/core/Model.cpp index 7a7919bb8..634e2fbed 100644 --- a/src/core/Model.cpp +++ b/src/core/Model.cpp @@ -27,7 +27,7 @@ namespace lmms { -Model::Model(Model * parent, QString displayName, bool defaultConstructed) : +Model::Model(Model* parent, QString displayName, bool defaultConstructed) : QObject(parent), m_displayName(displayName), m_defaultConstructed(defaultConstructed) @@ -41,7 +41,7 @@ bool Model::isDefaultConstructed() const Model* Model::parentModel() const { - return dynamic_cast(parent()); + return dynamic_cast(parent()); } QString Model::displayName() const @@ -49,7 +49,7 @@ QString Model::displayName() const return m_displayName; } -void Model::setDisplayName( const QString& displayName ) +void Model::setDisplayName(const QString& displayName) { m_displayName = displayName; } @@ -58,7 +58,7 @@ QString Model::fullDisplayName() const { const QString n = displayName(); - if(parentModel()) + if (parentModel()) { const QString p = parentModel()->fullDisplayName(); From bd5f1b9ea18dfe9fc61563274a8f893827a42ca8 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Mon, 5 Jun 2023 05:44:48 +0200 Subject: [PATCH 046/308] Fix uninitialized variable "pCurPreset" (#6639) (#6723) Fix the uninitialized variable pCurPreset by setting it to nullptr. Please note that it looks as if the nullptr is now being passed to the function fluid_sfont_iteration_next_wrapper. However, the function does not use the parameter anyway and then the variable is set to the result of that function. --- plugins/Sf2Player/PatchesDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/Sf2Player/PatchesDialog.cpp b/plugins/Sf2Player/PatchesDialog.cpp index 9c9a689a0..c3ffe2d29 100644 --- a/plugins/Sf2Player/PatchesDialog.cpp +++ b/plugins/Sf2Player/PatchesDialog.cpp @@ -154,7 +154,7 @@ void PatchesDialog::setup ( fluid_synth_t * pSynth, int iChan, fluid_preset_t preset; fluid_preset_t *pCurPreset = &preset; #else - fluid_preset_t *pCurPreset; + fluid_preset_t *pCurPreset = nullptr; #endif while ((pCurPreset = fluid_sfont_iteration_next_wrapper(pSoundFont, pCurPreset))) { int iBank = fluid_preset_get_banknum(pCurPreset); From 20c83e50213fcb831ec3629d0397c3ba9cb204e6 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Mon, 5 Jun 2023 20:09:30 +0200 Subject: [PATCH 047/308] Fix automated base notes and their automations (#6548) Fix all base notes that are used in automations and their corresponding automation values. Base notes that are automated are stored as elements in the save file whereas non-automated base notes are stored as attributes. So far the method `upgrade_extendedNoteRange` only upgraded the non-automated base notes that are stored in attributes. This commit fixes the automated ones which are stored in elements. The fix works as follows: * Collect all base note elements. * Store their ids in a set so that we can later identify automations that reference them. * Collect all automation pattern and check if they reference a base note. * Adjust the values and out values of all automations that reference base notes. Note: for many older files the out values will be introduced by the upgrade `method upgrade_automationNodes` and do not appear in the files themselves! --- src/core/DataFile.cpp | 73 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/src/core/DataFile.cpp b/src/core/DataFile.cpp index 2e7b21e8b..a39db430b 100644 --- a/src/core/DataFile.cpp +++ b/src/core/DataFile.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -1723,6 +1724,71 @@ void DataFile::upgrade_extendedNoteRange() } } } + + // Fix the base notes that are used in automations and the automations that use them. + + // First fix the base notes used in automations and collect their ids while doing so. + // Base notes that are used in automations appear as elements in the document. + // 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. + std::set baseNoteIds; + + QDomNodeList baseNotes = elementsByTagName("basenote"); + for (int j = 0; j < baseNotes.size(); ++j) + { + QDomElement baseNote = baseNotes.item(j).toElement(); + if (!baseNote.isNull()) + { + if (baseNote.hasAttribute("value")) + { + int const value = baseNote.attribute("value").toInt(); + 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(); + baseNoteIds.insert(id); + } + } + + // Now collect all automation patterns and correct all their automations that + // use the corrected base notes. + QDomNodeList automationPatterns = elementsByTagName("automationpattern"); + for (int j = 0; j < automationPatterns.size(); ++j) + { + QDomElement automationPattern = automationPatterns.item(j).toElement(); + if (!automationPattern.isNull()) + { + // 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(); + if (baseNoteIds.find(id) != baseNoteIds.end()) + { + // The automation pattern belongs to a corrected base note. + // Collect all time elements to correct their values and out + // values. + QDomElement time = automationPattern.firstChildElement("time"); + while(!time.isNull()) { + // Value is in fact a float but if we save automations for + // base notes we in fact save integer values. + int const value = time.attribute("value").toInt(); + time.setAttribute("value", value + 12); + + // The method "upgrade_automationNodes" adds some attributes + // with the name "outValue". We have to correct these as well. + int const outValue = time.attribute("outValue").toInt(); + time.setAttribute("outValue", outValue + 12); + + time = time.nextSiblingElement("time"); + } + } + + object = object.nextSiblingElement("object"); + } + } + } } else { @@ -1837,8 +1903,11 @@ void DataFile::upgrade_bbTcoRename() void DataFile::upgrade() { // Runs all necessary upgrade methods - std::size_t max = std::min(static_cast(m_fileVersion), UPGRADE_METHODS.size()); - std::for_each( UPGRADE_METHODS.begin() + max, UPGRADE_METHODS.end(), + size_t const upgradedVersion = static_cast(m_fileVersion); + size_t const numberOfVersions = UPGRADE_METHODS.size(); + std::size_t offsetToUpgradeStart = std::min(upgradedVersion, numberOfVersions); + auto upgradeMethodIt = UPGRADE_VERSIONS.begin() + offsetToUpgradeStart; + std::for_each( UPGRADE_METHODS.begin() + offsetToUpgradeStart, UPGRADE_METHODS.end(), [this](UpgradeMethod um) { (this->*um)(); From 9f34c5cfa336a03d78a8783829357e15cd84107b Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Mon, 5 Jun 2023 20:20:34 +0200 Subject: [PATCH 048/308] Remove debug code from DataFile::upgrade Remove debug code from DataFile::upgrade which was accidentally committed. --- src/core/DataFile.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/core/DataFile.cpp b/src/core/DataFile.cpp index a39db430b..68058fb7f 100644 --- a/src/core/DataFile.cpp +++ b/src/core/DataFile.cpp @@ -1903,11 +1903,8 @@ void DataFile::upgrade_bbTcoRename() void DataFile::upgrade() { // Runs all necessary upgrade methods - size_t const upgradedVersion = static_cast(m_fileVersion); - size_t const numberOfVersions = UPGRADE_METHODS.size(); - std::size_t offsetToUpgradeStart = std::min(upgradedVersion, numberOfVersions); - auto upgradeMethodIt = UPGRADE_VERSIONS.begin() + offsetToUpgradeStart; - std::for_each( UPGRADE_METHODS.begin() + offsetToUpgradeStart, UPGRADE_METHODS.end(), + std::size_t max = std::min(static_cast(m_fileVersion), UPGRADE_METHODS.size()); + std::for_each( UPGRADE_METHODS.begin() + max, UPGRADE_METHODS.end(), [this](UpgradeMethod um) { (this->*um)(); From bceee6c4271016d35fda0b634ed712059114eea5 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Mon, 5 Jun 2023 16:22:05 -0400 Subject: [PATCH 049/308] Look for libcarla_native-plugin.dll on Windows (#6726) Closes #5984 --- plugins/CarlaBase/CMakeLists.txt | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/plugins/CarlaBase/CMakeLists.txt b/plugins/CarlaBase/CMakeLists.txt index f60804719..d4f7939c9 100644 --- a/plugins/CarlaBase/CMakeLists.txt +++ b/plugins/CarlaBase/CMakeLists.txt @@ -15,14 +15,13 @@ if(LMMS_HAVE_WEAKCARLA) ${CMAKE_CURRENT_SOURCE_DIR}/carla/source/backend ) + # force "lib" prefix IF(LMMS_BUILD_WIN32) - # use carla.dll - SET(CMAKE_SHARED_LIBRARY_PREFIX "") - SET(CARLA_NATIVE_LIB carla) - ELSE() - # use libcarla_native-plugin - SET(CARLA_NATIVE_LIB carla_native-plugin) + SET(CMAKE_SHARED_LIBRARY_PREFIX "lib") ENDIF() + + SET(CARLA_NATIVE_LIB carla_native-plugin) + ADD_LIBRARY(${CARLA_NATIVE_LIB} SHARED DummyCarla.cpp) TARGET_INCLUDE_DIRECTORIES(${CARLA_NATIVE_LIB} PUBLIC ${CARLA_INCLUDE_DIRS}) INSTALL(TARGETS ${CARLA_NATIVE_LIB} From 02fef122ae5158658be142d962c09889ef1c3d1a Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Thu, 8 Jun 2023 10:48:02 +0200 Subject: [PATCH 050/308] Extend fix for mixed automation tracks/patterns (#6548) Move the fix for the automated base notes to the code that fixes the non-automated base notes. Improve the fix for automation tracks and patterns by potentially splitting them into two tracks: * The original track which is adjusted to only contain patterns with targets that are not base notes. * A cloned track that only contains patterns with base note targets. This is done by iterating over all automation tracks and checking which types of automations they contain: * Base note automations * Automations of other targets The result for each automation track are then evaluated as follows. * If an automation track does not contain any base note automations it is kept as it is, i.e. nothing is done. * If an automation track only contains patterns with base note automations its patterns are corrected in place. * If an automation track contains patterns with base note automations and other targets then the track is duplicated so that we can split it as described above. This split and correction is done on a per pattern level. Patterns that would become empty are removed. Cloned tracks will keep the same names and attributes as their original tracks. TODOs ------ * Base notes are read as integers, corrected by an integer value of 12 and then stored back as an integer. In some files base notes have float values, i.e. if the file was stored after the base notes have been automated linearly. * B&B tracks are not corrected although they can contain instruments with (automated) base notes! * Nested for-loops with "i" as their running variables. (Fix in a separate commit) --- src/core/DataFile.cpp | 337 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 276 insertions(+), 61 deletions(-) diff --git a/src/core/DataFile.cpp b/src/core/DataFile.cpp index 68058fb7f..e8d4c9941 100644 --- a/src/core/DataFile.cpp +++ b/src/core/DataFile.cpp @@ -1670,6 +1670,76 @@ void DataFile::upgrade_automationNodes() } } +/** + * @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); +} + +/** + * @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"); + }; +} /** \brief Note range has been extended to match MIDI specification * @@ -1680,37 +1750,100 @@ 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"; + assert(instrument.hasAttribute("name")); + QString const name = instrument.attribute("name"); + + return name == "zynaddsubfx" || + name == "vestige" || name == "lv2instrument" || + name == "carlapatchbay" || name == "carlarack"; }; if (!elementsByTagName("song").item(0).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; + // Dealing with a project file, go through all the tracks QDomNodeList tracks = elementsByTagName("track"); - for (int i = 0; !tracks.item(i).isNull(); i++) + for (int i = 0; i < tracks.size(); ++i) { - // Ignore BB container tracks - if (tracks.item(i).toElement().attribute("type").toInt() == 1) { continue; } + QDomElement currentTrack = tracks.item(i).toElement(); + if (!currentTrack.hasAttribute("type")) + { + continue; + } + Track::TrackTypes const trackType = static_cast(currentTrack.attribute("type").toInt()); + + // Ignore BB container tracks + if (trackType == Track::PatternTrack) + { + continue; + } + + QDomNodeList instruments = currentTrack.elementsByTagName("instrument"); + + if (instruments.isEmpty()) + { + continue; + } + + assert(instruments.size() < 2 && "More than one instrument found in a track!"); - QDomNodeList instruments = tracks.item(i).toElement().elementsByTagName("instrument"); - if (instruments.isEmpty()) { continue; } QDomElement instrument = instruments.item(0).toElement(); + + if (instrument.isNull()) + { + continue; + } + // 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); + 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")) + { + // TODO Base notes can have float values in the save file! This might need to be changed! + int const value = baseNote.attribute("value").toInt(); + 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); + } + } + } + // 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"); + QDomNodeList patterns = currentTrack.elementsByTagName("pattern"); for (int i = 0; !patterns.item(i).isNull(); i++) { QDomNodeList notes = patterns.item(i).toElement().elementsByTagName("note"); @@ -1725,69 +1858,151 @@ void DataFile::upgrade_extendedNoteRange() } } - // Fix the base notes that are used in automations and the automations that use them. + // Now fix all the automation tracks. + // 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()); - // First fix the base notes used in automations and collect their ids while doing so. - // Base notes that are used in automations appear as elements in the document. - // 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. - std::set baseNoteIds; - - QDomNodeList baseNotes = elementsByTagName("basenote"); - for (int j = 0; j < baseNotes.size(); ++j) + // Iterate the tracks again. This time work on all automation tracks. + for (int i = 0; i < tracks.size(); ++i) { - QDomElement baseNote = baseNotes.item(j).toElement(); - if (!baseNote.isNull()) + QDomElement currentTrack = tracks.item(i).toElement(); + if (currentTrack.attribute("type").toInt() != Track::AutomationTrack) { - if (baseNote.hasAttribute("value")) - { - int const value = baseNote.attribute("value").toInt(); - baseNote.setAttribute("value", value + 12); - } + continue; + } - // 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(); - baseNoteIds.insert(id); + // 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 collect all automation patterns and correct all their automations that - // use the corrected base notes. - QDomNodeList automationPatterns = elementsByTagName("automationpattern"); - for (int j = 0; j < automationPatterns.size(); ++j) + // Now fix the tracks that need duplication/splitting + for (QDomElement & track : tracksToDuplicate) { - QDomElement automationPattern = automationPatterns.item(j).toElement(); - if (!automationPattern.isNull()) + // 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()) { - // 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(); - if (baseNoteIds.find(id) != baseNoteIds.end()) + 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()) { - // The automation pattern belongs to a corrected base note. - // Collect all time elements to correct their values and out - // values. - QDomElement time = automationPattern.firstChildElement("time"); - while(!time.isNull()) { - // Value is in fact a float but if we save automations for - // base notes we in fact save integer values. - int const value = time.attribute("value").toInt(); - time.setAttribute("value", value + 12); + unsigned int const id = object.attribute("id").toUInt(); - // The method "upgrade_automationNodes" adds some attributes - // with the name "outValue". We have to correct these as well. - int const outValue = time.attribute("outValue").toInt(); - time.setAttribute("outValue", outValue + 12); - - time = time.nextSiblingElement("time"); + if (automatedBaseNoteIds.find(id) != automatedBaseNoteIds.end()) + { + QDomElement objectToRemove = object; + object = object.nextSiblingElement("object"); + automationPattern.removeChild(objectToRemove); + } + else + { + object = object.nextSiblingElement("object"); } } - 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); } } else From 502e95d5b4cf5dac0d02c49793154c0ec165e66b Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Thu, 8 Jun 2023 11:09:38 +0200 Subject: [PATCH 051/308] Try to fix GitHub builds The GitHub builds seem to need the explicit include which for some reason is not needed on my developer machine. --- src/core/DataFile.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/DataFile.cpp b/src/core/DataFile.cpp index e8d4c9941..b3884c9e0 100644 --- a/src/core/DataFile.cpp +++ b/src/core/DataFile.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include From cf83b52783e172aaddc2befb01df97b463f2ef9d Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Thu, 8 Jun 2023 11:27:04 +0200 Subject: [PATCH 052/308] Fix nested for loops with identical variables (#6548) Fix the problem with the nested for loops that all had variables called "i" by extracting a helper method with a corrected nesting. Due the extraction we do not have to care anymore if the correction is running beneath another for loop with potentially the same variable names. --- src/core/DataFile.cpp | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/core/DataFile.cpp b/src/core/DataFile.cpp index b3884c9e0..009a8fe81 100644 --- a/src/core/DataFile.cpp +++ b/src/core/DataFile.cpp @@ -1719,6 +1719,23 @@ static PatternAnalysisResult analyzeAutomationPattern(QDomElement const & automa 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); + } + } + } +} + /** * @brief Helper method that fixes the values and out values for an automation pattern. * @param automationPattern The automation pattern to be fixed. @@ -1845,17 +1862,7 @@ void DataFile::upgrade_extendedNoteRange() if (!affected(instrument)) { QDomNodeList patterns = currentTrack.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 - ); - } - } + fixNotePatterns(patterns); } } From 4f01094d9865ee5e4f929b903d38d1f2686804bf Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Thu, 8 Jun 2023 14:25:20 +0200 Subject: [PATCH 053/308] Fix base notes of B+B tracks (#6548) Fix the base notes and automations of B+B tracks. This fixes for example the problem that when a TripleOscillator had been put into a B+B track, e.g. with version 1.2 that it sounded too high when being loaded with a current master version. The cause seems to be that the notes of the instrument pattern are corrected/transposed too often (likely due to the collection of all tracks starting from the song/document root). The multiple correction of notes is fixed by traversing the song structure in a more consise way. First all track containers of the song are collected and for each of them the tracks are collected. These tracks are then fixed one by one. B+B tracks are getting a special handling while doing so. It is assumed that a B+B track cannot have other B+B tracks inside and therefore all sub tracks of the B+B track are searched for so that they can be fixed recursively. Refactor some more functionality into static helper methods: * Everything beneath a track is now fixed by the helper method `fixTrack`. * The fix of the base notes of the instruments themselves and the extraction of the ids of automated base notes has been moved into `fixInstrumentBaseNoteAndCollectIds`. * The lambda `affected` has been converted into a static method because it is must be accessible by one of the static helper methods. * The code for fixing the automation tracks of a song has been moved into the helper function `fixAutomationTracks`. --- src/core/DataFile.cpp | 473 ++++++++++++++++++++++-------------------- 1 file changed, 252 insertions(+), 221 deletions(-) diff --git a/src/core/DataFile.cpp b/src/core/DataFile.cpp index 009a8fe81..2d28a3090 100644 --- a/src/core/DataFile.cpp +++ b/src/core/DataFile.cpp @@ -1736,6 +1736,51 @@ static void fixNotePatterns(QDomNodeList & patterns) } } +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. @@ -1759,101 +1804,45 @@ static void fixAutomationPattern(QDomElement & automationPattern) }; } -/** \brief Note range has been extended to match MIDI specification - * - * The non-standard note range previously affected all MIDI-based instruments - * except OpulenZ, and made them sound an octave lower than they should (#1857). - */ -void DataFile::upgrade_extendedNoteRange() +static bool affected(QDomElement & instrument) { - auto affected = [](const 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")) { - assert(instrument.hasAttribute("name")); - QString const name = instrument.attribute("name"); + return; + } - return name == "zynaddsubfx" || - name == "vestige" || name == "lv2instrument" || - name == "carlapatchbay" || name == "carlarack"; - }; + Track::TrackTypes const trackType = static_cast(track.attribute("type").toInt()); - if (!elementsByTagName("song").item(0).isNull()) + // BB tracks need special handling because they container a track container of their own + if (trackType == Track::PatternTrack) { - // 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; - - // Dealing with a project file, go through all the tracks - QDomNodeList tracks = elementsByTagName("track"); - for (int i = 0; i < tracks.size(); ++i) + // 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 currentTrack = tracks.item(i).toElement(); - if (!currentTrack.hasAttribute("type")) - { - continue; - } - Track::TrackTypes const trackType = static_cast(currentTrack.attribute("type").toInt()); + QDomElement subTrack = subTracks.item(i).toElement(); + fixTrack(subTrack, automatedBaseNoteIds); + } + } + else + { + QDomNodeList instruments = track.elementsByTagName("instrument"); - // Ignore BB container tracks - if (trackType == Track::PatternTrack) - { - continue; - } + for (int i = 0; i < instruments.size(); ++i) + { + QDomElement instrument = instruments.item(i).toElement(); - QDomNodeList instruments = currentTrack.elementsByTagName("instrument"); - - if (instruments.isEmpty()) - { - continue; - } - - assert(instruments.size() < 2 && "More than one instrument found in a track!"); - - QDomElement instrument = instruments.item(0).toElement(); - - if (instrument.isNull()) - { - continue; - } - - // 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")) - { - // TODO Base notes can have float values in the save file! This might need to be changed! - int const value = baseNote.attribute("value").toInt(); - 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); - } - } - } + 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, @@ -1861,159 +1850,201 @@ void DataFile::upgrade_extendedNoteRange() // pitch in existing projects. if (!affected(instrument)) { - QDomNodeList patterns = currentTrack.elementsByTagName("pattern"); + QDomNodeList patterns = track.elementsByTagName("pattern"); fixNotePatterns(patterns); } } + } +} - // Now fix all the automation tracks. - // 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()); +static void fixAutomationTracks(QDomElement & song, std::set const & automatedBaseNoteIds) +{ + // Now fix all the automation tracks. + QDomNodeList tracks = song.elementsByTagName("track"); - // Iterate the tracks again. This time work on all automation tracks. - for (int i = 0; i < tracks.size(); ++i) + // 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 (currentTrack.attribute("type").toInt() != Track::AutomationTrack) { - QDomElement currentTrack = tracks.item(i).toElement(); - if (currentTrack.attribute("type").toInt() != Track::AutomationTrack) - { - 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); - } - } + continue; } - // Now fix the tracks that need duplication/splitting - for (QDomElement & track : tracksToDuplicate) + // 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()) { - // First clone the original track - QDomNode cloneOfTrack = track.cloneNode(); + auto const analysis = analyzeAutomationPattern(automationPattern, automatedBaseNoteIds); + containsPatternsWithBaseNoteTargets |= analysis.hasBaseNoteAutomations; + containsPatternsWithNonBaseNoteTargets |= analysis.hasNonBaseNoteAutomations; - // 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()) + 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) { - auto const analysis = analyzeAutomationPattern(automationPattern, automatedBaseNoteIds); - if (!analysis.hasBaseNoteAutomations) + // Only base note targets. This means we can simply keep the track and fix it. + automationPattern = currentTrack.firstChildElement("automationpattern"); + while (!automationPattern.isNull()) { - // 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); + 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); + } } } - else + + // 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); + } +} + +/** \brief Note range has been extended to match MIDI specification + * + * The non-standard note range previously affected all MIDI-based instruments + * except OpulenZ, and made them sound an octave lower than they should (#1857). + */ +void DataFile::upgrade_extendedNoteRange() +{ + QDomElement song = documentElement().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 (elementsByTagName("song").item(0).isNull()) { // Dealing with a preset, not a song QDomNodeList presets = elementsByTagName("instrumenttrack"); From 5debf982ef8c5a3a5e476d3ed492aae2ac150e8d Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Thu, 8 Jun 2023 17:15:53 +0200 Subject: [PATCH 054/308] Add SID filter image back (#6729) Add the image for the disabled SID filter back. According to a comment in the issue it seems to have gone missing during commit c1e6b313. --- plugins/Sid/filter.png | Bin 0 -> 1422 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 plugins/Sid/filter.png diff --git a/plugins/Sid/filter.png b/plugins/Sid/filter.png new file mode 100644 index 0000000000000000000000000000000000000000..ff5c760db9b5a3ac31c164751132ec05da1cae5f GIT binary patch literal 1422 zcmV;91#$X`P)V>IRB3Hx05CEyGB7VPFflal!xDV}002aEMObu0Z*X~XX=iA307F9{ zL3DI-X<~JBX>V>IXmoUNIxjC{a%Ew3X?A5}Z*6UFZgVbga%V4WX=7z>b7gZcVtFq! zE-)|j$M56-00at2L_t(Ijdhh>Y?Eaa$A8cBzTMiwR`&ty1BVJ5IN6+?D47{f6A8x8 zXfU9Xn5Y+O)Wi$o1tBP0NJ64_-gu`m1~q|!28c1+%DOKW<~9;>2##Pk&48}kx^``! z|@Bj4^1f0YGq1#uzNET#<9vi*)iP&es?L5!c@m zRWc^C$Vb}oIRP?=qCGtH$5$dE04fhq&{{16XhhH|FS0C~)Iut+y98X$1|uk~QQ3b) z1f`st$rVE!T>-Sp`_r}^%A`|!!$X(tX!bp8)K9`dM09+W>`9aPr6F+`DlTjZHxS5{Y?^ z9XZ7QgNKR7U1XVFtp^i-6{tyv~-&yvgQ z!QeJ#W@7Y*&(qV@0YFP@865N}boe4apE`l1 zG^>k>Nu^SJ|Lxb*ZoZ%9N466Vbvjkg5k~R6)|O2?nWi+6AP@+!wXTi?kji8zOC*>} zrVw#>v;DDF-hAhM%Ga!23K4w=KwM6#MY5J1ZM^;N2d=$Rir}_Kxo=Y~BSRNm7Q1v5 znr*MoheT%p=!-b`7}PIJZm&7cPG7TByRv^iH%!IhE{hDu90UQvOq!C&Zc zNSilW5kT#hdUieY0u4<;XU*jFvh)CGYzp$+OS^gEsaS`(~tLXam7b>f&= Date: Wed, 14 Jun 2023 13:38:34 -0700 Subject: [PATCH 055/308] Partially revert #6721, improve performance of Directory::addItems (#6738) * Fix expandItems & speed up Directory addItems --- src/gui/FileBrowser.cpp | 118 +++++++++++----------------------------- 1 file changed, 32 insertions(+), 86 deletions(-) diff --git a/src/gui/FileBrowser.cpp b/src/gui/FileBrowser.cpp index 88932af19..0672cd347 100644 --- a/src/gui/FileBrowser.cpp +++ b/src/gui/FileBrowser.cpp @@ -229,22 +229,22 @@ void FileBrowser::reloadTree() -void FileBrowser::expandItems( QTreeWidgetItem * item, QList expandedDirs ) +void FileBrowser::expandItems(QTreeWidgetItem* item, QList expandedDirs) { int numChildren = item ? item->childCount() : m_fileBrowserTreeWidget->topLevelItemCount(); for (int i = 0; i < numChildren; ++i) { - QTreeWidgetItem * it = item ? item->child( i ) : m_fileBrowserTreeWidget->topLevelItem(i); + auto it = item ? item->child(i) : m_fileBrowserTreeWidget->topLevelItem(i); auto d = dynamic_cast(it); if (d) { - d->update(); - bool expand = expandedDirs.contains( d->fullName() ); - d->setExpanded( expand ); - } - if (m_recurse && it->childCount()) - { - expandItems(it, expandedDirs); + // Expanding is required when recursive to load in its contents, even if it's collapsed right afterward + if (m_recurse) { d->setExpanded(true); } + d->setExpanded(expandedDirs.contains(d->fullName())); + if (m_recurse && it->childCount()) + { + expandItems(it, expandedDirs); + } } } } @@ -1002,88 +1002,34 @@ void Directory::update() -bool Directory::addItems(const QString & path ) +bool Directory::addItems(const QString& path) { - QDir thisDir( path ); - if( !thisDir.isReadable() ) + QDir thisDir(path); + if (!thisDir.isReadable()) { return false; } + + treeWidget()->setUpdatesEnabled(false); + + QFileInfoList entries = thisDir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot, QDir::LocaleAware | QDir::DirsFirst | QDir::Name); + for (auto& entry : entries) { - return false; - } - - treeWidget()->setUpdatesEnabled( false ); - - bool added_something = false; - - // try to add all directories from file system alphabetically into the tree - QStringList files = thisDir.entryList( QDir::Dirs, QDir::Name ); - for( QStringList::const_iterator it = files.constBegin(); - it != files.constEnd(); ++it ) - { - QString cur_file = *it; - if( cur_file[0] != '.' ) + QString fileName = entry.fileName(); + if (entry.isDir()) { - bool orphan = true; - for( int i = 0; i < childCount(); ++i ) - { - auto d = dynamic_cast(child(i)); - if( d == nullptr || cur_file < d->text( 0 ) ) - { - // insert before item, we're done - insertChild( i, new Directory( cur_file, - path, m_filter ) ); - orphan = false; - m_dirCount++; - break; - } - else if( cur_file == d->text( 0 ) ) - { - // imagine we have top-level subdirs named "TripleOscillator" in - // two directories from FileBrowser::m_directories - // and imagine both have a sub folder named "xyz" - // then only add one tree widget for both - // so we don't add a new Directory - we just - // add the path to the current directory - d->addDirectory( path ); - orphan = false; - break; - } - } - if( orphan ) - { - // it has not yet been added yet, so it's (lexically) - // larger than all other dirs => append it at the bottom - addChild( new Directory( cur_file, path, - m_filter ) ); - m_dirCount++; - } - - added_something = true; + auto dir = new Directory(fileName, path, m_filter); + addChild(dir); + m_dirCount++; + } + else if (entry.isFile() && thisDir.match(m_filter, fileName.toLower())) + { + auto fileItem = new FileItem(fileName, path); + addChild(fileItem); } } - - // sorts the path alphabetically instead of just appending to the bottom (see "orphans") - if (added_something) - sortChildren(0, Qt::AscendingOrder); - - QList items; - files = thisDir.entryList( QDir::Files, QDir::Name ); - files.sort(Qt::CaseInsensitive); - for( QStringList::const_iterator it = files.constBegin(); - it != files.constEnd(); ++it ) - { - QString cur_file = *it; - if( cur_file[0] != '.' && - thisDir.match( m_filter, cur_file.toLower() ) ) - { - items << new FileItem( cur_file, path ); - added_something = true; - } - } - addChildren( items ); - - treeWidget()->setUpdatesEnabled( true ); - - return added_something; + + treeWidget()->setUpdatesEnabled(true); + + // return true if we added any child items + return childCount() > 0; } From c8546633a27bb0208268d244d4a8d43cd3c1b9b2 Mon Sep 17 00:00:00 2001 From: superpaik <68785450+superpaik@users.noreply.github.com> Date: Sat, 24 Jun 2023 04:57:52 +0200 Subject: [PATCH 056/308] Adding new FX channel while in solo (#6717) * Adding FX channel while in solo New FX channel is muted when there is a soloed FX line. Fixes #6311 * Move var initialization to constructor --- src/core/Mixer.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 9354687a8..b2a9f9e3f 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -190,11 +190,11 @@ void MixerChannel::doProcessing() Mixer::Mixer() : Model( nullptr ), JournallingObject(), - m_mixerChannels() + m_mixerChannels(), + m_lastSoloed(-1) { // create master channel createChannel(); - m_lastSoloed = -1; } @@ -224,6 +224,13 @@ int Mixer::createChannel() // reset channel state clearChannel( index ); + // if there is a soloed channel, mute the new track + if (m_lastSoloed != -1 && m_mixerChannels[m_lastSoloed]->m_soloModel.value()) + { + m_mixerChannels[index]->m_muteBeforeSolo = m_mixerChannels[index]->m_muteModel.value(); + m_mixerChannels[index]->m_muteModel.setValue(true); + } + return index; } From 405738f66f28dcb1e192fb8f3d60b0a54e1d891b Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Sat, 24 Jun 2023 11:58:56 +0900 Subject: [PATCH 057/308] Fix STK rawwave installation in Windows builds (#6705) * Fix STK rawwave path detection and installation * Use the CMake logic for rawwave installation on Win and Mac --- cmake/apple/install_apple.sh.in | 5 ----- cmake/install/CMakeLists.txt | 10 ++++++++++ cmake/modules/FindSTK.cmake | 7 +++++++ cmake/nsis/CMakeLists.txt | 6 ------ 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/cmake/apple/install_apple.sh.in b/cmake/apple/install_apple.sh.in index e1921b1a5..df9300712 100644 --- a/cmake/apple/install_apple.sh.in +++ b/cmake/apple/install_apple.sh.in @@ -6,9 +6,6 @@ set -e -# STK rawwaves directory -STK_RAWWAVE=$(brew --prefix stk)/share/stk/rawwaves - # Place to create ".app" bundle APP="@CMAKE_BINARY_DIR@/@PROJECT_NAME_UCASE@.app" @@ -29,11 +26,9 @@ command cp "@CMAKE_BINARY_DIR@/Info.plist" "@CMAKE_INSTALL_PREFIX@/" mkdir -p "$APP/Contents/MacOS" mkdir -p "$APP/Contents/Frameworks" mkdir -p "$APP/Contents/Resources" -mkdir -p "$APP/Contents/share/stk/rawwaves" cd "@CMAKE_INSTALL_PREFIX@" cp -R ./* "$APP/Contents" cp "@CMAKE_SOURCE_DIR@/cmake/apple/"*.icns "$APP/Contents/Resources/" -cp "$STK_RAWWAVE"/*.raw "$APP/Contents/share/stk/rawwaves" > /dev/null 2>&1 # Make all libraries writable for macdeployqt cd "$APP" diff --git a/cmake/install/CMakeLists.txt b/cmake/install/CMakeLists.txt index cd4100c9b..5ee731d16 100644 --- a/cmake/install/CMakeLists.txt +++ b/cmake/install/CMakeLists.txt @@ -36,6 +36,16 @@ IF(LMMS_BUILD_WIN32 OR LMMS_INSTALL_DEPENDENCIES) ) ENDIF() +# Install STK rawwaves +if(LMMS_HAVE_STK AND (LMMS_BUILD_WIN32 OR LMMS_BUILD_APPLE)) + if(STK_RAWWAVE_ROOT) + file(GLOB RAWWAVES "${STK_RAWWAVE_ROOT}/*.raw") + install(FILES ${RAWWAVES} DESTINATION "${DATA_DIR}/stk/rawwaves") + else() + message(WARNING "Can't find STK rawwave root!") + endif() +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)") diff --git a/cmake/modules/FindSTK.cmake b/cmake/modules/FindSTK.cmake index 80ed0da42..0718f5039 100644 --- a/cmake/modules/FindSTK.cmake +++ b/cmake/modules/FindSTK.cmake @@ -26,6 +26,13 @@ else() endif() endif() +# find STK rawwave path +find_path(STK_RAWWAVE_ROOT + NAMES silence.raw sinewave.raw + HINTS "${STK_INCLUDE_DIR}/.." + PATH_SUFFIXES share/stk/rawwaves share/libstk/rawwaves +) + include(FindPackageHandleStandardArgs) find_package_handle_standard_args(STK REQUIRED_VARS STK_LIBRARY STK_INCLUDE_DIR diff --git a/cmake/nsis/CMakeLists.txt b/cmake/nsis/CMakeLists.txt index 9dca3495d..ee1bd45c3 100644 --- a/cmake/nsis/CMakeLists.txt +++ b/cmake/nsis/CMakeLists.txt @@ -73,12 +73,6 @@ SET(CPACK_NSIS_MUI_ICON "${CPACK_NSIS_MUI_ICON}" PARENT_SCOPE) CONFIGURE_FILE("lmms.rc.in" "${CMAKE_BINARY_DIR}/lmms.rc") CONFIGURE_FILE("zynaddsubfx.rc.in" "${CMAKE_BINARY_DIR}/plugins/ZynAddSubFx/zynaddsubfx.rc") -IF(LMMS_HAVE_STK) - FILE(GLOB RAWWAVES "${MINGW_PREFIX}/share/stk/rawwaves/*.raw") - LIST(SORT RAWWAVES) - INSTALL(FILES ${RAWWAVES} DESTINATION "${DATA_DIR}/stk/rawwaves") -ENDIF() - INSTALL(FILES "lmms.exe.manifest" DESTINATION .) INSTALL(FILES "lmms.VisualElementsManifest.xml" DESTINATION .) INSTALL(DIRECTORY "assets" DESTINATION .) From 4ea8a70de61e006651f7982f082ffbbf60fcd56b Mon Sep 17 00:00:00 2001 From: Lost Robot <34612565+LostRobotMusic@users.noreply.github.com> Date: Mon, 26 Jun 2023 17:23:47 -0700 Subject: [PATCH 058/308] Fix Equalizer LP/HP curve display (#6748) --- plugins/Eq/EqCurve.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/plugins/Eq/EqCurve.cpp b/plugins/Eq/EqCurve.cpp index 704231284..b9fa3f519 100644 --- a/plugins/Eq/EqCurve.cpp +++ b/plugins/Eq/EqCurve.cpp @@ -316,8 +316,7 @@ float EqHandle::getLowCutCurve( float x ) double c = cosf( w0 ); double s = sinf( w0 ); double resonance = getResonance(); - double A = pow( 10, yPixelToGain( EqHandle::y(), m_heigth, m_pixelsPerUnitHeight ) / 20); - double alpha = s / 2 * sqrt ( ( A +1/A ) * ( 1 / resonance -1 ) +2 ); + double alpha = s / (2 * resonance); double a0, a1, a2, b0, b1, b2; // coeffs to calculate b0 = ( 1 + c ) * 0.5; @@ -360,8 +359,7 @@ float EqHandle::getHighCutCurve( float x ) double c = cosf( w0 ); double s = sinf( w0 ); double resonance = getResonance(); - double A = pow( 10, yPixelToGain( EqHandle::y(), m_heigth, m_pixelsPerUnitHeight ) / 20 ); - double alpha = s / 2 * sqrt ( ( A + 1 / A ) * ( 1 / resonance -1 ) +2 ); + double alpha = s / (2 * resonance); double a0, a1, a2, b0, b1, b2; // coeffs to calculate b0 = ( 1 - c ) * 0.5; From 7f43e3b98240cfe4989db3089655ce6103cc34e5 Mon Sep 17 00:00:00 2001 From: chkno Date: Fri, 30 Jun 2023 05:51:43 -0700 Subject: [PATCH 059/308] Detect hiir fetch (#6755) --- cmake/modules/CheckSubmodules.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/modules/CheckSubmodules.cmake b/cmake/modules/CheckSubmodules.cmake index f36189c38..b9ea20778 100644 --- a/cmake/modules/CheckSubmodules.cmake +++ b/cmake/modules/CheckSubmodules.cmake @@ -18,7 +18,7 @@ # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # Files which confirm a successful clone -SET(VALID_CRUMBS "CMakeLists.txt;Makefile;Makefile.in;Makefile.am;configure.ac;configure.py;autogen.sh;.gitignore;LICENSE;Home.md") +SET(VALID_CRUMBS "CMakeLists.txt;Makefile;Makefile.in;Makefile.am;configure.ac;configure.py;autogen.sh;.gitignore;LICENSE;Home.md;license.txt") OPTION(NO_SHALLOW_CLONE "Disable shallow cloning of submodules" OFF) From b7027fecbb5ced293eea1840d266b9a5b97990cb Mon Sep 17 00:00:00 2001 From: Dalton Messmer <33463986+messmerd@users.noreply.github.com> Date: Sat, 1 Jul 2023 22:57:09 -0400 Subject: [PATCH 060/308] Fix occasional crash when clicking Key button in piano roll with no clip (#6757) --- src/gui/editors/PianoRoll.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 8fdf958c0..adc1997b9 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -941,6 +941,7 @@ void PianoRoll::hideMidiClip( MidiClip* clip ) int PianoRoll::trackOctaveSize() const { + if (!m_midiClip) { return KeysPerOctave; } auto ut = m_midiClip->instrumentTrack()->microtuner(); return ut->enabled() ? ut->octaveSize() : KeysPerOctave; } From 1f30ffc5e4dddbd6ffb843bd8c56a8b4de859675 Mon Sep 17 00:00:00 2001 From: Aidan Mueller <10082900+aidan-mueller@users.noreply.github.com> Date: Sat, 1 Jul 2023 22:28:40 -0500 Subject: [PATCH 061/308] Fixed issue #5734 (FreeBoy Division by zero) (#6053) * Fixed issue #5734 (FreeBoy Division by zero). Added comments and used more descriptive variable names for noise channel initialization block. Also indented the nested for loop to improve code clarity. The reasons for doing this can be found in this answer: https://softwareengineering.stackexchange.com/a/362796 * Better initial div_ratio guess Allows us to skip r = 0 and a conditional in the loop below. --------- Co-authored-by: Spekular --- plugins/FreeBoy/FreeBoy.cpp | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/plugins/FreeBoy/FreeBoy.cpp b/plugins/FreeBoy/FreeBoy.cpp index f9ef2c5aa..1fd3f2513 100644 --- a/plugins/FreeBoy/FreeBoy.cpp +++ b/plugins/FreeBoy/FreeBoy.cpp @@ -358,30 +358,34 @@ void FreeBoyInstrument::playNote(NotePlayHandle* nph, sampleFrame* workingBuffer if (tfp == 0) { - //PRNG Frequency = (1048576 Hz / (ratio + 1)) / 2 ^ (shiftclockfreq + 1) - char sopt = 0; - char ropt = 1; - float fopt = 524288.0 / (ropt * std::pow(2.0, sopt + 1.0)); - float f; + // Initialize noise channel... + // PRNG Frequency = (1048576 Hz / (ratio + 1)) / 2 ^ (shiftclockfreq + 1) + // When div_ratio = 0 the ratio should be 0.5. Since s = 0 is the only case where r = 0 gives + // a unique frequency, we can start by guessing s = r = 0 here and then skip r = 0 in the loop. + char clock_freq = 0; + char div_ratio = 0; + float closest_freq = 524288.0 / (0.5 * std::pow(2.0, clock_freq + 1.0)); + // This nested for loop iterates over all possible combinations of clock frequency and dividing + // ratio and chooses the combination whose resulting frequency is closest to the note frequency for (char s = 0; s < 16; ++s) { - for (char r = 0; r < 8; ++r) + for (char r = 1; r < 8; ++r) { - f = 524288.0 / (r * std::pow(2.0, s + 1.0)); - if (std::fabs(freq - fopt) > std::fabs(freq - f)) + float f = 524288.0 / (r * std::pow(2.0, s + 1.0)); + if (std::fabs(freq - closest_freq) > std::fabs(freq - f)) { - fopt = f; - ropt = r; - sopt = s; + closest_freq = f; + div_ratio = r; + clock_freq = s; } } } - data = sopt; + data = clock_freq; data = data << 1; data += m_ch4ShiftRegWidthModel.value(); data = data << 3; - data += ropt; + data += div_ratio; papu->writeRegister(0xff22, data); //channel 4 init From 5ccc8d952ac90ab5a4abfaf7b3a29701a5dec4ed Mon Sep 17 00:00:00 2001 From: Kevin Zander Date: Sun, 2 Jul 2023 01:02:37 -0500 Subject: [PATCH 062/308] Remove redundant nameChanged signal from InstrumentTrack (#6742) --- include/InstrumentTrack.h | 1 - src/tracks/InstrumentTrack.cpp | 2 -- 2 files changed, 3 deletions(-) diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index 7c6d1d795..f21723363 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -244,7 +244,6 @@ signals: void instrumentChanged(); void midiNoteOn( const lmms::Note& ); void midiNoteOff( const lmms::Note& ); - void nameChanged(); void newNote(); void endNote(); diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 0e75c990a..7eb6bba11 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -609,8 +609,6 @@ void InstrumentTrack::setName( const QString & _new_name ) Track::setName( _new_name ); m_midiPort.setName( name() ); m_audioPort.setName( name() ); - - emit nameChanged(); } From c53f3d981b9710bb1601e9213f925d95bdd9bd72 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Tue, 11 Jul 2023 12:52:32 -0400 Subject: [PATCH 063/308] Bump cmt submodule (#6151) * Bump cmt submodule Closes #6006 --- plugins/LadspaEffect/cmt/cmt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 4908bfe1a646ce1b9687c83dd05b4a9d30471ac3 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sun, 16 Jul 2023 14:11:24 +0200 Subject: [PATCH 064/308] Scalable Setup Dialog Make the setup dialog resizable and use widgets that dynamically adjust to the font size set by the user. Current status of the tabs: * General: Done * Performance: Plugins group needs adjustments * Audio: Individual settings dialogs need adjustments * MIDI: Not started yet * Paths: Done The "Autosave" and "Buffer size" tabs have been slightly redesigned so that the revert/reset button is next to the slider. Technical details ------------------ Setting a fixed size has been removed from the setup dialog so that it can be resized. The settings widget (`settings_w`) now has a layout to which the sub dialogs are added. This is done so that the layout sizes are propagated upwards, i.e. all widgets along the chain now have a layout so that size hints are determined correctly. Instances of `TabWidget` are replaced with instances of `QGroupBox`. Each group box has a layout to which its children, e.g. check boxes, are added. These group boxes are then added to the layouts of their parents. Doing so also removes the need to count how many instances have been added and calculations on where to put the children. Instances of `LedCheckBox` are replaced with instances of `QCheckBox`. This is done in the new helper lambda `addCheckBox`. It's very similar to the previously used `addLedCheckBox` but creates a `QCheckBox` instead of a `LedCheckBox`. It returns the created `QCheckBox` as a result. If a layout is provided the created check box is also added to the layout before it is returned. The helper lambda `addPathEntry` has been adjusted to create a `QGroupBox` and to put all its children in a layout. The helper method `labelWidget` has been adjusted to not set the font size of the label. The method `TabBar::addTab` had to be extended with a new default parameter which controls if the added widget is fixed to the size of it's parent or not. In the case of the setup dialog we do not want this. So far the method is only used by the setup dialog and the `LadspaBrowser` class. So once the `LadspaBrowser` has been made resizable the default parameter can be removed again and treated as always being set to false. Add `QCheckBox` to the `style.css` so that it does not get a green font due to the palette magic that's done. --- data/themes/default/style.css | 2 +- include/SetupDialog.h | 5 +- include/TabBar.h | 7 +- src/gui/modals/SetupDialog.cpp | 254 ++++++++++++++++++--------------- src/gui/widgets/TabBar.cpp | 12 +- 5 files changed, 153 insertions(+), 127 deletions(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index a9646cfe4..ee5681f43 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -3,7 +3,7 @@ ********************/ /* most foreground text items */ -QLabel, QTreeWidget, QListWidget, QGroupBox, QMenuBar { +QLabel, QTreeWidget, QListWidget, QGroupBox, QMenuBar, QCheckBox { color: #d1d8e4; } diff --git a/include/SetupDialog.h b/include/SetupDialog.h index 27a4ce4f9..7fa59d244 100644 --- a/include/SetupDialog.h +++ b/include/SetupDialog.h @@ -40,6 +40,7 @@ class QComboBox; class QLabel; class QLineEdit; class QSlider; +class QCheckBox; namespace lmms::gui @@ -155,8 +156,8 @@ private: bool m_enableRunningAutoSave; QSlider * m_saveIntervalSlider; QLabel * m_saveIntervalLbl; - LedCheckBox * m_autoSave; - LedCheckBox * m_runningAutoSave; + QCheckBox * m_autoSave; + QCheckBox * m_runningAutoSave; bool m_smoothScroll; bool m_animateAFP; QLabel * m_vstEmbedLbl; diff --git a/include/TabBar.h b/include/TabBar.h index fa2703287..29c100e0c 100644 --- a/include/TabBar.h +++ b/include/TabBar.h @@ -49,7 +49,12 @@ public: TabButton * addTab( QWidget * _w, const QString & _text, int _id, bool _add_stretch = false, - bool _text_is_tooltip = false ); + bool _text_is_tooltip = false, + // TODO Remove fixWidgetToParentSize once it is used + // with false everywhere. + // At the time of writing it is only used in + // LadspaBrowser with default parameters. + bool fixWidgetToParentSize = true ); void removeTab( int _id ); inline void setExclusive( bool _on ) diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index 33505c399..97de349c4 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include "AudioDeviceSetupWidget.h" #include "AudioEngine.h" @@ -79,13 +81,12 @@ inline void labelWidget(QWidget * w, const QString & txt) auto title = new QLabel(txt, w); QFont f = title->font(); f.setBold(true); - title->setFont(pointSize<12>(f)); + title->setFont(f); + QBoxLayout * boxLayout = dynamic_cast(w->layout()); + assert(boxLayout); - assert(dynamic_cast(w->layout()) != nullptr); - - dynamic_cast(w->layout())->addSpacing(5); - dynamic_cast(w->layout())->addWidget(title); + boxLayout->addWidget(title); } @@ -162,7 +163,6 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : // TODO: Equivalent to the new setWindowFlag(Qt::WindowContextHelpButtonHint, false) setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); setModal(true); - setFixedSize(454, 400); Engine::projectJournal()->setJournalling(false); @@ -191,7 +191,8 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : // Settings widget. auto settings_w = new QWidget(main_w); - settings_w->setFixedSize(360, 360); + + QVBoxLayout * settingsLayout = new QVBoxLayout(settings_w); // General widget. auto general_w = new QWidget(settings_w); @@ -212,6 +213,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : auto generalControlsLayout = new QVBoxLayout; generalControlsLayout->setSpacing(10); + // TODO Remove once it is not used anymore auto addLedCheckBox = [&XDelta, &YDelta, this](const QString& ledText, TabWidget* tw, int& counter, bool initialState, const char* toggledSlot, bool showRestartWarning) { auto checkBox = new LedCheckBox(ledText, tw); @@ -225,63 +227,77 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : } }; - int counter = 0; + auto addCheckBox = [this](const QString& ledText, QWidget* parent, QBoxLayout * layout, + bool initialState, const char* toggledSlot, bool showRestartWarning) -> QCheckBox * { + auto checkBox = new QCheckBox(ledText, parent); + checkBox->setChecked(initialState); + connect(checkBox, SIGNAL(toggled(bool)), this, toggledSlot); + + if (showRestartWarning) + { + connect(checkBox, SIGNAL(toggled(bool)), this, SLOT(showRestartWarning())); + } + + if (layout) + { + layout->addWidget(checkBox); + } + + return checkBox; + }; // GUI tab. - auto gui_tw = new TabWidget(tr("Graphical user interface (GUI)"), generalControls); + QGroupBox * guiGroupBox = new QGroupBox(tr("Graphical user interface (GUI)"), generalControls); + QVBoxLayout * guiGroupLayout = new QVBoxLayout(guiGroupBox); - addLedCheckBox(tr("Display volume as dBFS "), gui_tw, counter, + addCheckBox(tr("Display volume as dBFS "), guiGroupBox, guiGroupLayout, m_displaydBFS, SLOT(toggleDisplaydBFS(bool)), true); - addLedCheckBox(tr("Enable tooltips"), gui_tw, counter, + addCheckBox(tr("Enable tooltips"), guiGroupBox, guiGroupLayout, m_tooltips, SLOT(toggleTooltips(bool)), true); - addLedCheckBox(tr("Enable master oscilloscope by default"), gui_tw, counter, + addCheckBox(tr("Enable master oscilloscope by default"), guiGroupBox, guiGroupLayout, m_displayWaveform, SLOT(toggleDisplayWaveform(bool)), true); - addLedCheckBox(tr("Enable all note labels in piano roll"), gui_tw, counter, + addCheckBox(tr("Enable all note labels in piano roll"), guiGroupBox, guiGroupLayout, m_printNoteLabels, SLOT(toggleNoteLabels(bool)), false); - addLedCheckBox(tr("Enable compact track buttons"), gui_tw, counter, + addCheckBox(tr("Enable compact track buttons"), guiGroupBox, guiGroupLayout, m_compactTrackButtons, SLOT(toggleCompactTrackButtons(bool)), true); - addLedCheckBox(tr("Enable one instrument-track-window mode"), gui_tw, counter, + addCheckBox(tr("Enable one instrument-track-window mode"), guiGroupBox, guiGroupLayout, m_oneInstrumentTrackWindow, SLOT(toggleOneInstrumentTrackWindow(bool)), true); - addLedCheckBox(tr("Show sidebar on the right-hand side"), gui_tw, counter, + addCheckBox(tr("Show sidebar on the right-hand side"), guiGroupBox, guiGroupLayout, m_sideBarOnRight, SLOT(toggleSideBarOnRight(bool)), true); - addLedCheckBox(tr("Let sample previews continue when mouse is released"), gui_tw, counter, + addCheckBox(tr("Let sample previews continue when mouse is released"), guiGroupBox, guiGroupLayout, m_letPreviewsFinish, SLOT(toggleLetPreviewsFinish(bool)), false); - addLedCheckBox(tr("Mute automation tracks during solo"), gui_tw, counter, + addCheckBox(tr("Mute automation tracks during solo"), guiGroupBox, guiGroupLayout, m_soloLegacyBehavior, SLOT(toggleSoloLegacyBehavior(bool)), false); - addLedCheckBox(tr("Show warning when deleting tracks"), gui_tw, counter, + addCheckBox(tr("Show warning when deleting tracks"), guiGroupBox, guiGroupLayout, m_trackDeletionWarning, SLOT(toggleTrackDeletionWarning(bool)), false); - addLedCheckBox(tr("Show warning when deleting a mixer channel that is in use"), gui_tw, counter, + addCheckBox(tr("Show warning when deleting a mixer channel that is in use"), guiGroupBox, guiGroupLayout, m_mixerChannelDeletionWarning, SLOT(toggleMixerChannelDeletionWarning(bool)), false); - gui_tw->setFixedHeight(YDelta + YDelta * counter); + generalControlsLayout->addWidget(guiGroupBox); - generalControlsLayout->addWidget(gui_tw); generalControlsLayout->addSpacing(10); - - counter = 0; - // Projects tab. - auto projects_tw = new TabWidget(tr("Projects"), generalControls); + QGroupBox * projectsGroupBox = new QGroupBox(tr("Projects"), generalControls); + QVBoxLayout * projectsGroupLayout = new QVBoxLayout(projectsGroupBox); - addLedCheckBox(tr("Compress project files by default"), projects_tw, counter, + addCheckBox(tr("Compress project files by default"), projectsGroupBox, projectsGroupLayout, m_MMPZ, SLOT(toggleMMPZ(bool)), true); - addLedCheckBox(tr("Create a backup file when saving a project"), projects_tw, counter, + addCheckBox(tr("Create a backup file when saving a project"), projectsGroupBox, projectsGroupLayout, m_disableBackup, SLOT(toggleDisableBackup(bool)), false); - addLedCheckBox(tr("Reopen last project on startup"), projects_tw, counter, + addCheckBox(tr("Reopen last project on startup"), projectsGroupBox, projectsGroupLayout, m_openLastProject, SLOT(toggleOpenLastProject(bool)), false); - projects_tw->setFixedHeight(YDelta + YDelta * counter); + generalControlsLayout->addWidget(projectsGroupBox); - generalControlsLayout->addWidget(projects_tw); generalControlsLayout->addSpacing(10); - // Language tab. - auto lang_tw = new TabWidget(tr("Language"), generalControls); - lang_tw->setFixedHeight(48); - auto changeLang = new QComboBox(lang_tw); - changeLang->move(XDelta, 20); + QGroupBox * languageGroupBox = new QGroupBox(tr("Language"), generalControls); + QVBoxLayout * languageGroupLayout = new QVBoxLayout(languageGroupBox); + + auto changeLang = new QComboBox(languageGroupBox); + languageGroupLayout->addWidget(changeLang); QDir dir(ConfigManager::inst()->localeDir()); QStringList fileNames = dir.entryList(QStringList("*.qm")); @@ -333,7 +349,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : connect(changeLang, SIGNAL(currentIndexChanged(int)), this, SLOT(showRestartWarning())); - generalControlsLayout->addWidget(lang_tw); + generalControlsLayout->addWidget(languageGroupBox); generalControlsLayout->addSpacing(10); // General layout ordering. @@ -341,7 +357,9 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : generalControls->setLayout(generalControlsLayout); generalScroll->setWidget(generalControls); generalScroll->setWidgetResizable(true); - general_layout->addWidget(generalScroll); + general_layout->addWidget(generalScroll, 1); + + // TODO Does not really seem to be needed general_layout->addStretch(); @@ -357,61 +375,54 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : // Autosave tab. - auto auto_save_tw = new TabWidget(tr("Autosave"), performance_w); - auto_save_tw->setFixedHeight(106); + QGroupBox * autoSaveBox = new QGroupBox(tr("Autosave"), performance_w); + QVBoxLayout * autoSaveLayout = new QVBoxLayout(autoSaveBox); + QHBoxLayout * autoSaveSubLayout = new QHBoxLayout(); - m_saveIntervalSlider = new QSlider(Qt::Horizontal, auto_save_tw); + m_saveIntervalSlider = new QSlider(Qt::Horizontal, autoSaveBox); m_saveIntervalSlider->setValue(m_saveInterval); m_saveIntervalSlider->setRange(1, 20); m_saveIntervalSlider->setTickInterval(1); m_saveIntervalSlider->setPageStep(1); - m_saveIntervalSlider->setGeometry(10, 18, 340, 18); m_saveIntervalSlider->setTickPosition(QSlider::TicksBelow); connect(m_saveIntervalSlider, SIGNAL(valueChanged(int)), this, SLOT(setAutoSaveInterval(int))); - m_saveIntervalLbl = new QLabel(auto_save_tw); - m_saveIntervalLbl->setGeometry(10, 40, 200, 24); - setAutoSaveInterval(m_saveIntervalSlider->value()); - - m_autoSave = new LedCheckBox( - tr("Enable autosave"), auto_save_tw); - m_autoSave->move(10, 70); - m_autoSave->setChecked(m_enableAutoSave); - connect(m_autoSave, SIGNAL(toggled(bool)), - this, SLOT(toggleAutoSave(bool))); - - m_runningAutoSave = new LedCheckBox( - tr("Allow autosave while playing"), auto_save_tw); - m_runningAutoSave->move(20, 88); - m_runningAutoSave->setChecked(m_enableRunningAutoSave); - connect(m_runningAutoSave, SIGNAL(toggled(bool)), - this, SLOT(toggleRunningAutoSave(bool))); - - auto autoSaveResetBtn = new QPushButton(embed::getIconPixmap("reload"), "", auto_save_tw); - autoSaveResetBtn->setGeometry(320, 70, 28, 28); + auto autoSaveResetBtn = new QPushButton(embed::getIconPixmap("reload"), "", autoSaveBox); connect(autoSaveResetBtn, SIGNAL(clicked()), - this, SLOT(resetAutoSave())); + this, SLOT(resetAutoSave())); + + autoSaveSubLayout->addWidget(m_saveIntervalSlider); + autoSaveSubLayout->addWidget(autoSaveResetBtn); + + autoSaveLayout->addLayout(autoSaveSubLayout); + + m_saveIntervalLbl = new QLabel(autoSaveBox); + setAutoSaveInterval(m_saveIntervalSlider->value()); + autoSaveLayout->addWidget(m_saveIntervalLbl); + + m_autoSave = addCheckBox(tr("Enable autosave"), autoSaveBox, autoSaveLayout, + m_enableAutoSave, SLOT(toggleAutoSave(bool)), false); + + m_runningAutoSave = addCheckBox(tr("Allow autosave while playing"), autoSaveBox, autoSaveLayout, + m_enableRunningAutoSave, SLOT(toggleRunningAutoSave(bool)), false); m_saveIntervalSlider->setEnabled(m_enableAutoSave); m_runningAutoSave->setVisible(m_enableAutoSave); - counter = 0; - // UI effect vs. performance tab. - auto ui_fx_tw = new TabWidget(tr("User interface (UI) effects vs. performance"), performance_w); + QGroupBox * uiFxBox = new QGroupBox(tr("User interface (UI) effects vs. performance"), performance_w); + QVBoxLayout * uiFxLayout = new QVBoxLayout(uiFxBox); - addLedCheckBox(tr("Smooth scroll in song editor"), ui_fx_tw, counter, + addCheckBox(tr("Smooth scroll in song editor"), uiFxBox, uiFxLayout, m_smoothScroll, SLOT(toggleSmoothScroll(bool)), false); - addLedCheckBox(tr("Display playback cursor in AudioFileProcessor"), ui_fx_tw, counter, + addCheckBox(tr("Display playback cursor in AudioFileProcessor"), uiFxBox, uiFxLayout, m_animateAFP, SLOT(toggleAnimateAFP(bool)), false); - ui_fx_tw->setFixedHeight(YDelta + YDelta * counter); - - counter = 0; + int counter = 0; // Plugins tab. auto plugins_tw = new TabWidget(tr("Plugins"), performance_w); @@ -458,8 +469,8 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : // Performance layout ordering. - performance_layout->addWidget(auto_save_tw); - performance_layout->addWidget(ui_fx_tw); + performance_layout->addWidget(autoSaveBox); + performance_layout->addWidget(uiFxBox); performance_layout->addWidget(plugins_tw); performance_layout->addStretch(); @@ -473,13 +484,12 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : labelWidget(audio_w, tr("Audio")); - // Audio interface tab. - auto audioiface_tw = new TabWidget(tr("Audio interface"), audio_w); - audioiface_tw->setFixedHeight(56); - - m_audioInterfaces = new QComboBox(audioiface_tw); - m_audioInterfaces->setGeometry(10, 20, 240, 28); + // Audio interface group + QGroupBox * audioInterfaceBox = new QGroupBox(tr("Audio interface"), audio_w); + QVBoxLayout * audioInterfaceLayout = new QVBoxLayout(audioInterfaceBox); + m_audioInterfaces = new QComboBox(audioInterfaceBox); + audioInterfaceLayout->addWidget(m_audioInterfaces); // Ifaces-settings-widget. auto as_w = new QWidget(audio_w); @@ -569,24 +579,20 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : useNaNHandler->setChecked(m_NaNHandler); } - // HQ mode LED. - auto hqaudio = new LedCheckBox(tr("HQ mode for output audio device"), audio_w); - hqaudio->move(10, 0); - hqaudio->setChecked(m_hqAudioDev); - connect(hqaudio, SIGNAL(toggled(bool)), - this, SLOT(toggleHQAudioDev(bool))); + // HQ mode checkbox + auto hqaudio = addCheckBox(tr("HQ mode for output audio device"), audioInterfaceBox, nullptr, + m_hqAudioDev, SLOT(toggleHQAudioDev(bool)), false); + // Buffer size group + QGroupBox * bufferSizeBox = new QGroupBox(tr("Buffer size"), audio_w); + QVBoxLayout * bufferSizeLayout = new QVBoxLayout(bufferSizeBox); + QHBoxLayout * bufferSizeSubLayout = new QHBoxLayout(); - // Buffer size tab. - auto bufferSize_tw = new TabWidget(tr("Buffer size"), audio_w); - bufferSize_tw->setFixedHeight(76); - - m_bufferSizeSlider = new QSlider(Qt::Horizontal, bufferSize_tw); + m_bufferSizeSlider = new QSlider(Qt::Horizontal, bufferSizeBox); m_bufferSizeSlider->setRange(1, 128); m_bufferSizeSlider->setTickInterval(8); m_bufferSizeSlider->setPageStep(8); m_bufferSizeSlider->setValue(m_bufferSize / BUFFERSIZE_RESOLUTION); - m_bufferSizeSlider->setGeometry(10, 18, 340, 18); m_bufferSizeSlider->setTickPosition(QSlider::TicksBelow); connect(m_bufferSizeSlider, SIGNAL(valueChanged(int)), @@ -594,23 +600,28 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : connect(m_bufferSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(showRestartWarning())); - m_bufferSizeLbl = new QLabel(bufferSize_tw); - m_bufferSizeLbl->setGeometry(10, 40, 200, 24); + bufferSizeSubLayout->addWidget(m_bufferSizeSlider, 1); + + auto bufferSize_reset_btn = new QPushButton(embed::getIconPixmap("reload"), "", bufferSizeBox); + connect(bufferSize_reset_btn, SIGNAL(clicked()), + this, SLOT(resetBufferSize())); + bufferSize_reset_btn->setToolTip( + tr("Reset to default value")); + + bufferSizeSubLayout->addWidget(bufferSize_reset_btn); + bufferSizeLayout->addLayout(bufferSizeSubLayout); + + m_bufferSizeLbl = new QLabel(bufferSizeBox); setBufferSize(m_bufferSizeSlider->value()); - auto bufferSize_reset_btn = new QPushButton(embed::getIconPixmap("reload"), "", bufferSize_tw); - bufferSize_reset_btn->setGeometry(320, 40, 28, 28); - connect(bufferSize_reset_btn, SIGNAL(clicked()), - this, SLOT(resetBufferSize())); - bufferSize_reset_btn->setToolTip( - tr("Reset to default value")); + bufferSizeLayout->addWidget(m_bufferSizeLbl); // Audio layout ordering. - audio_layout->addWidget(audioiface_tw); + audio_layout->addWidget(audioInterfaceBox); audio_layout->addWidget(as_w); audio_layout->addWidget(hqaudio); - audio_layout->addWidget(bufferSize_tw); + audio_layout->addWidget(bufferSizeBox); audio_layout->addStretch(); @@ -749,29 +760,28 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : // Path selectors widget. auto pathSelectors = new QWidget(paths_w); - const int txtLength = 284; - const int btnStart = 300; - // Path selectors layout. auto pathSelectorsLayout = new QVBoxLayout; pathSelectorsLayout->setSpacing(10); auto addPathEntry = [&](const QString& caption, const QString& content, const char* setSlot, const char* openSlot, QLineEdit*& lineEdit, const char* pixmap = "project_open") { - auto newTw = new TabWidget(caption, pathSelectors); - newTw->setFixedHeight(48); + auto pathEntryGroupBox = new QGroupBox(caption, pathSelectors); + QHBoxLayout * pathEntryLayout = new QHBoxLayout(pathEntryGroupBox); - lineEdit = new QLineEdit(content, newTw); - lineEdit->setGeometry(10, 20, txtLength, 16); + lineEdit = new QLineEdit(content, pathEntryGroupBox); connect(lineEdit, SIGNAL(textChanged(const QString&)), this, setSlot); - auto selectBtn = new QPushButton(embed::getIconPixmap(pixmap, 16, 16), "", newTw); + pathEntryLayout->addWidget(lineEdit, 1); + + auto selectBtn = new QPushButton(embed::getIconPixmap(pixmap, 16, 16), "", pathEntryGroupBox); selectBtn->setFixedSize(24, 24); - selectBtn->move(btnStart, 16); connect(selectBtn, SIGNAL(clicked()), this, openSlot); - pathSelectorsLayout->addWidget(newTw); + pathEntryLayout->addWidget(selectBtn, 0); + + pathSelectorsLayout->addWidget(pathEntryGroupBox); pathSelectorsLayout->addSpacing(10); }; @@ -820,21 +830,29 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : paths_layout->addWidget(pathsScroll); paths_layout->addStretch(); + // Add all main widgets to the layout of the settings widget + // This is needed so that we automatically get the correct sizes. + settingsLayout->addWidget(general_w); + settingsLayout->addWidget(performance_w); + settingsLayout->addWidget(audio_w); + settingsLayout->addWidget(midi_w); + settingsLayout->addWidget(paths_w); + // Major tabs ordering. m_tabBar->addTab(general_w, - tr("General"), 0, false, true)->setIcon( + tr("General"), 0, false, true, false)->setIcon( embed::getIconPixmap("setup_general")); m_tabBar->addTab(performance_w, - tr("Performance"), 1, false, true)->setIcon( + tr("Performance"), 1, false, true, false)->setIcon( embed::getIconPixmap("setup_performance")); m_tabBar->addTab(audio_w, - tr("Audio"), 2, false, true)->setIcon( + tr("Audio"), 2, false, true, false)->setIcon( embed::getIconPixmap("setup_audio")); m_tabBar->addTab(midi_w, - tr("MIDI"), 3, false, true)->setIcon( + tr("MIDI"), 3, false, true, false)->setIcon( embed::getIconPixmap("setup_midi")); m_tabBar->addTab(paths_w, - tr("Paths"), 4, true, true)->setIcon( + tr("Paths"), 4, true, true, false)->setIcon( embed::getIconPixmap("setup_directories")); m_tabBar->setActiveTab(tab_to_open); @@ -877,9 +895,9 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : extras_layout->addSpacing(10); // Vertical layout ordering. - vlayout->addWidget(main_w); + vlayout->addWidget(main_w, 0); vlayout->addSpacing(10); - vlayout->addWidget(extras_w); + vlayout->addWidget(extras_w), 1; vlayout->addSpacing(10); show(); diff --git a/src/gui/widgets/TabBar.cpp b/src/gui/widgets/TabBar.cpp index 806a93252..e29494551 100644 --- a/src/gui/widgets/TabBar.cpp +++ b/src/gui/widgets/TabBar.cpp @@ -44,7 +44,7 @@ TabBar::TabBar( QWidget * _parent, QBoxLayout::Direction _dir ) : } TabButton * TabBar::addTab( QWidget * _w, const QString & _text, int _id, - bool _add_stretch, bool _text_is_tooltip ) + bool _add_stretch, bool _text_is_tooltip, bool fixWidgetToParentSize ) { // already tab with id? if( m_tabs.contains( _id ) ) @@ -83,10 +83,12 @@ TabButton * TabBar::addTab( QWidget * _w, const QString & _text, int _id, m_layout->addStretch(); } - - // we assume, parent-widget is a widget acting as widget-stack so all - // widgets have the same size and only the one on the top is visible - _w->setFixedSize( _w->parentWidget()->size() ); + if (fixWidgetToParentSize) + { + // we assume, parent-widget is a widget acting as widget-stack so all + // widgets have the same size and only the one on the top is visible + _w->setFixedSize( _w->parentWidget()->size() ); + } b->setFont( pointSize<8>( b->font() ) ); From c5c459f54f576d99a5c80094b1f36a5a13c29424 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sun, 16 Jul 2023 20:02:11 +0200 Subject: [PATCH 065/308] Adjust Plugins group/tab Adjust the plugins group to also use a QGroupBox and QCheckBoxes. This finishes the "Performance" page and also finally enables the removal of the local variables `XDelta` and `YDelta` as well as the lambda `addLedCheckBox`. Other changes -------------- Add a TODO to some unused code for some advanced setting. Fix layout of the main widget and the buttons widget. Remove an erroneous ",1" after a statement. --- include/SetupDialog.h | 3 +- src/gui/modals/SetupDialog.cpp | 56 +++++++++------------------------- 2 files changed, 16 insertions(+), 43 deletions(-) diff --git a/include/SetupDialog.h b/include/SetupDialog.h index 7fa59d244..a68fe89cf 100644 --- a/include/SetupDialog.h +++ b/include/SetupDialog.h @@ -30,7 +30,6 @@ #include "AudioDevice.h" #include "AudioDeviceSetupWidget.h" -#include "LedCheckBox.h" #include "lmmsconfig.h" #include "MidiClient.h" #include "MidiSetupWidget.h" @@ -163,7 +162,7 @@ private: QLabel * m_vstEmbedLbl; QComboBox* m_vstEmbedComboBox; QString m_vstEmbedMethod; - LedCheckBox * m_vstAlwaysOnTopCheckBox; + QCheckBox * m_vstAlwaysOnTopCheckBox; bool m_vstAlwaysOnTop; bool m_disableAutoQuit; diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index 97de349c4..b9a92ab78 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -39,6 +39,7 @@ #include "Engine.h" #include "FileDialog.h" #include "gui_templates.h" +#include "LedCheckBox.h" #include "MainWindow.h" #include "MidiSetupWidget.h" #include "ProjectJournal.h" @@ -167,10 +168,6 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : Engine::projectJournal()->setJournalling(false); - // Constants for positioning LED check boxes. - const int XDelta = 10; - const int YDelta = 18; - // Main widget. auto main_w = new QWidget(this); @@ -213,20 +210,6 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : auto generalControlsLayout = new QVBoxLayout; generalControlsLayout->setSpacing(10); - // TODO Remove once it is not used anymore - auto addLedCheckBox = [&XDelta, &YDelta, this](const QString& ledText, TabWidget* tw, int& counter, - bool initialState, const char* toggledSlot, bool showRestartWarning) { - auto checkBox = new LedCheckBox(ledText, tw); - counter++; - checkBox->move(XDelta, YDelta * counter); - checkBox->setChecked(initialState); - connect(checkBox, SIGNAL(toggled(bool)), this, toggledSlot); - if (showRestartWarning) - { - connect(checkBox, SIGNAL(toggled(bool)), this, SLOT(showRestartWarning())); - } - }; - auto addCheckBox = [this](const QString& ledText, QWidget* parent, QBoxLayout * layout, bool initialState, const char* toggledSlot, bool showRestartWarning) -> QCheckBox * { auto checkBox = new QCheckBox(ledText, parent); @@ -422,17 +405,15 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : m_animateAFP, SLOT(toggleAnimateAFP(bool)), false); - int counter = 0; + // Plugins group + QGroupBox * pluginsBox = new QGroupBox(tr("Plugins"), performance_w); + QVBoxLayout * pluginsLayout = new QVBoxLayout(pluginsBox); - // Plugins tab. - auto plugins_tw = new TabWidget(tr("Plugins"), performance_w); - - m_vstEmbedLbl = new QLabel(plugins_tw); - m_vstEmbedLbl->move(XDelta, YDelta * ++counter); + m_vstEmbedLbl = new QLabel(pluginsBox); m_vstEmbedLbl->setText(tr("VST plugins embedding:")); + pluginsLayout->addWidget(m_vstEmbedLbl); - m_vstEmbedComboBox = new QComboBox(plugins_tw); - m_vstEmbedComboBox->move(XDelta, YDelta * ++counter); + m_vstEmbedComboBox = new QComboBox(pluginsBox); QStringList embedMethods = ConfigManager::availableVstEmbedMethods(); m_vstEmbedComboBox->addItem(tr("No embedding"), "none"); @@ -451,27 +432,19 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : m_vstEmbedComboBox->setCurrentIndex(m_vstEmbedComboBox->findData(m_vstEmbedMethod)); connect(m_vstEmbedComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(vstEmbedMethodChanged())); + pluginsLayout->addWidget(m_vstEmbedComboBox); - counter += 2; + m_vstAlwaysOnTopCheckBox = addCheckBox(tr("Keep plugin windows on top when not embedded"), pluginsBox, pluginsLayout, + m_vstAlwaysOnTop, SLOT(toggleVSTAlwaysOnTop(bool)), false); - m_vstAlwaysOnTopCheckBox = new LedCheckBox( - tr("Keep plugin windows on top when not embedded"), plugins_tw); - m_vstAlwaysOnTopCheckBox->move(20, 66); - m_vstAlwaysOnTopCheckBox->setChecked(m_vstAlwaysOnTop); - m_vstAlwaysOnTopCheckBox->setVisible(m_vstEmbedMethod == "none"); - connect(m_vstAlwaysOnTopCheckBox, SIGNAL(toggled(bool)), - this, SLOT(toggleVSTAlwaysOnTop(bool))); - - addLedCheckBox(tr("Keep effects running even without input"), plugins_tw, counter, + addCheckBox(tr("Keep effects running even without input"), pluginsBox, pluginsLayout, m_disableAutoQuit, SLOT(toggleDisableAutoQuit(bool)), false); - plugins_tw->setFixedHeight(YDelta + YDelta * counter); - // Performance layout ordering. performance_layout->addWidget(autoSaveBox); performance_layout->addWidget(uiFxBox); - performance_layout->addWidget(plugins_tw); + performance_layout->addWidget(pluginsBox); performance_layout->addStretch(); @@ -575,6 +548,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : // Advanced setting, hidden for now if(false) { + // TODO Handle or remove. auto useNaNHandler = new LedCheckBox(tr("Use built-in NaN handler"), audio_w); useNaNHandler->setChecked(m_NaNHandler); } @@ -895,9 +869,9 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : extras_layout->addSpacing(10); // Vertical layout ordering. - vlayout->addWidget(main_w, 0); + vlayout->addWidget(main_w, 1); vlayout->addSpacing(10); - vlayout->addWidget(extras_w), 1; + vlayout->addWidget(extras_w); vlayout->addSpacing(10); show(); From cbea8f30fc4d1a821e99f67b78ab2d124431fbea Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sun, 16 Jul 2023 20:04:55 +0200 Subject: [PATCH 066/308] Make "Paths" scroll area expandable Make the "Paths" scroll area take as much space as there is. --- src/gui/modals/SetupDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index b9a92ab78..37c5db748 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -801,7 +801,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : pathsScroll->setWidget(pathSelectors); pathsScroll->setWidgetResizable(true); - paths_layout->addWidget(pathsScroll); + paths_layout->addWidget(pathsScroll, 1); paths_layout->addStretch(); // Add all main widgets to the layout of the settings widget From c06d9d488319f88eaa698a33f61495f77722235f Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sun, 16 Jul 2023 23:04:09 +0200 Subject: [PATCH 067/308] First adjustments to MIDI page Use group boxes and layouts for the "MIDI interface" and automatic assignment tabs. The configuration/information dialogs for the different drivers still need adjustments. --- src/gui/modals/SetupDialog.cpp | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index 37c5db748..0565b8238 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -605,15 +605,14 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : auto midi_layout = new QVBoxLayout(midi_w); midi_layout->setSpacing(10); midi_layout->setContentsMargins(0, 0, 0, 0); - labelWidget(midi_w, - tr("MIDI")); + labelWidget(midi_w, tr("MIDI")); - // MIDI interface tab. - auto midiiface_tw = new TabWidget(tr("MIDI interface"), midi_w); - midiiface_tw->setFixedHeight(56); + // MIDI interface group + QGroupBox * midiInterfaceBox = new QGroupBox(tr("MIDI interface"), midi_w); + QVBoxLayout * midiInterfaceLayout = new QVBoxLayout(midiInterfaceBox); - m_midiInterfaces = new QComboBox(midiiface_tw); - m_midiInterfaces->setGeometry(10, 20, 240, 28); + m_midiInterfaces = new QComboBox(midiInterfaceBox); + midiInterfaceLayout->addWidget(m_midiInterfaces); // Ifaces-settings-widget. auto ms_w = new QWidget(midi_w); @@ -687,12 +686,12 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : this, SLOT(midiInterfaceChanged(const QString&))); - // MIDI autoassign tab. - auto midiAutoAssign_tw = new TabWidget(tr("Automatically assign MIDI controller to selected track"), midi_w); - midiAutoAssign_tw->setFixedHeight(56); + // MIDI autoassign group + QGroupBox * midiAutoAssignBox = new QGroupBox(tr("Automatically assign MIDI controller to selected track"), midi_w); + QVBoxLayout * midiAutoAssignLayout = new QVBoxLayout(midiAutoAssignBox); - m_assignableMidiDevices = new QComboBox(midiAutoAssign_tw); - m_assignableMidiDevices->setGeometry(10, 20, 240, 28); + m_assignableMidiDevices = new QComboBox(midiAutoAssignBox); + midiAutoAssignLayout->addWidget(m_assignableMidiDevices); m_assignableMidiDevices->addItem("none"); if ( !Engine::audioEngine()->midiClient()->isRaw() ) { @@ -709,9 +708,9 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : } // MIDI layout ordering. - midi_layout->addWidget(midiiface_tw); + midi_layout->addWidget(midiInterfaceBox); midi_layout->addWidget(ms_w); - midi_layout->addWidget(midiAutoAssign_tw); + midi_layout->addWidget(midiAutoAssignBox); midi_layout->addStretch(); From b53290344b358380b40d273f3c9dc0f31fdf13ef Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sat, 22 Jul 2023 22:55:02 +0200 Subject: [PATCH 068/308] Adjust most audio driver settings dialogs Adjust the dialogs of most audio driver settings dialogs by showing them in a QGroupBox and adjusting their layouts. All dialogs now use `QFormLayout` to layout their labels and input widgets. Technical details ------------------ Introduce `AudioDeviceSetupGroupWidget` which is intended to functionally replace `AudioDeviceSetupWidget` in the long run. This is likely a temporary replacement in the sense that `AudioDeviceSetupGroupWidget` will be renamed to `AudioDeviceSetupWidget` once the latter has been replaced everywhere. Both classes are very similar and the only difference is that the former inherits from `QGroupBox` instead of `TabWidget`. Adjust the using of AswMap so that it is now defined as a map from `QString` to `AudioDeviceSetupGroupWidget`. Use `QFormLayout` to layout the widgets of the setup dialogs instead of hard coding geometries and placement. TODOs ------ Adjust the widgets for the SoundIO and SndIo cases. These will be a bit more effort as they are not compiled on my machine. --- include/AudioAlsaSetupWidget.h | 4 +- include/AudioDeviceSetupGroupWidget.h | 49 +++++++++++++++++++++++++ include/AudioDummy.h | 6 +-- include/AudioJack.h | 4 +- include/AudioOss.h | 4 +- include/AudioPortAudio.h | 4 +- include/AudioPulseAudio.h | 4 +- include/AudioSdl.h | 4 +- include/SetupDialog.h | 4 +- src/core/audio/AudioJack.cpp | 15 ++++---- src/core/audio/AudioOss.cpp | 16 ++++---- src/core/audio/AudioPortAudio.cpp | 20 ++++------ src/core/audio/AudioPulseAudio.cpp | 19 ++++------ src/core/audio/AudioSdl.cpp | 12 +++--- src/gui/AudioAlsaSetupWidget.cpp | 14 +++---- src/gui/AudioDeviceSetupGroupWidget.cpp | 42 +++++++++++++++++++++ src/gui/CMakeLists.txt | 1 + src/gui/modals/SetupDialog.cpp | 5 ++- 18 files changed, 152 insertions(+), 75 deletions(-) create mode 100644 include/AudioDeviceSetupGroupWidget.h create mode 100644 src/gui/AudioDeviceSetupGroupWidget.cpp diff --git a/include/AudioAlsaSetupWidget.h b/include/AudioAlsaSetupWidget.h index cbe99ba01..9795a3588 100644 --- a/include/AudioAlsaSetupWidget.h +++ b/include/AudioAlsaSetupWidget.h @@ -29,7 +29,7 @@ #ifdef LMMS_HAVE_ALSA -#include "AudioDeviceSetupWidget.h" +#include "AudioDeviceSetupGroupWidget.h" #include "AudioAlsa.h" @@ -41,7 +41,7 @@ namespace lmms::gui class LcdSpinBox; -class AudioAlsaSetupWidget : public AudioDeviceSetupWidget +class AudioAlsaSetupWidget : public AudioDeviceSetupGroupWidget { Q_OBJECT diff --git a/include/AudioDeviceSetupGroupWidget.h b/include/AudioDeviceSetupGroupWidget.h new file mode 100644 index 000000000..8980d0a65 --- /dev/null +++ b/include/AudioDeviceSetupGroupWidget.h @@ -0,0 +1,49 @@ +/* + * AudioDeviceSetupGroupWidget.h - Base class for audio device setup widgets using group box + * + * Copyright (c) 2004-2015 Tobias Doerffel + * Copyright (c) 2004-2015 Michael Gregorius + * + * 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_AUDIO_DEVICE_SETUP_GROUP_WIDGET_H +#define LMMS_GUI_AUDIO_DEVICE_SETUP_GROUP_WIDGET_H + +#include + +namespace lmms::gui +{ + +class AudioDeviceSetupGroupWidget : public QGroupBox +{ + Q_OBJECT +public: + AudioDeviceSetupGroupWidget( const QString & _caption, QWidget * _parent ); + + ~AudioDeviceSetupGroupWidget() override = default; + + virtual void saveSettings() = 0; + + virtual void show(); +}; + +} // namespace lmms::gui + +#endif // LMMS_GUI_AUDIO_DEVICE_SETUP_GROUP_WIDGET_H diff --git a/include/AudioDummy.h b/include/AudioDummy.h index e34260171..c7ac3d67f 100644 --- a/include/AudioDummy.h +++ b/include/AudioDummy.h @@ -26,7 +26,7 @@ #define LMMS_AUDIO_DUMMY_H #include "AudioDevice.h" -#include "AudioDeviceSetupWidget.h" +#include "AudioDeviceSetupGroupWidget.h" #include "AudioEngine.h" #include "MicroTimer.h" @@ -54,11 +54,11 @@ public: } - class setupWidget : public gui::AudioDeviceSetupWidget + class setupWidget : public gui::AudioDeviceSetupGroupWidget { public: setupWidget( QWidget * _parent ) : - gui::AudioDeviceSetupWidget( AudioDummy::name(), _parent ) + gui::AudioDeviceSetupGroupWidget( AudioDummy::name(), _parent ) { } diff --git a/include/AudioJack.h b/include/AudioJack.h index 2ef0f665c..4135dc5e0 100644 --- a/include/AudioJack.h +++ b/include/AudioJack.h @@ -38,7 +38,7 @@ #include #include "AudioDevice.h" -#include "AudioDeviceSetupWidget.h" +#include "AudioDeviceSetupGroupWidget.h" class QLineEdit; @@ -74,7 +74,7 @@ public: } -class setupWidget : public gui::AudioDeviceSetupWidget +class setupWidget : public gui::AudioDeviceSetupGroupWidget { public: setupWidget( QWidget * _parent ); diff --git a/include/AudioOss.h b/include/AudioOss.h index 55f64de85..953c72a4f 100644 --- a/include/AudioOss.h +++ b/include/AudioOss.h @@ -32,7 +32,7 @@ #include #include "AudioDevice.h" -#include "AudioDeviceSetupWidget.h" +#include "AudioDeviceSetupGroupWidget.h" class QLineEdit; @@ -61,7 +61,7 @@ public: static QString probeDevice(); -class setupWidget : public gui::AudioDeviceSetupWidget +class setupWidget : public gui::AudioDeviceSetupGroupWidget { public: setupWidget( QWidget * _parent ); diff --git a/include/AudioPortAudio.h b/include/AudioPortAudio.h index 01b8f3fd7..a926b1bf0 100644 --- a/include/AudioPortAudio.h +++ b/include/AudioPortAudio.h @@ -35,7 +35,7 @@ # include # include "AudioDevice.h" -# include "AudioDeviceSetupWidget.h" +# include "AudioDeviceSetupGroupWidget.h" # if defined paNeverDropInput || defined paNonInterleaved # define PORTAUDIO_V19 @@ -90,7 +90,7 @@ public: unsigned long _framesPerBuffer ); - class setupWidget : public gui::AudioDeviceSetupWidget + class setupWidget : public gui::AudioDeviceSetupGroupWidget { public: setupWidget( QWidget * _parent ); diff --git a/include/AudioPulseAudio.h b/include/AudioPulseAudio.h index b6a998274..22e47896d 100644 --- a/include/AudioPulseAudio.h +++ b/include/AudioPulseAudio.h @@ -34,7 +34,7 @@ #include #include "AudioDevice.h" -#include "AudioDeviceSetupWidget.h" +#include "AudioDeviceSetupGroupWidget.h" class QLineEdit; @@ -62,7 +62,7 @@ public: static QString probeDevice(); - class setupWidget : public gui::AudioDeviceSetupWidget + class setupWidget : public gui::AudioDeviceSetupGroupWidget { public: setupWidget( QWidget * _parent ); diff --git a/include/AudioSdl.h b/include/AudioSdl.h index 62db8b68a..5f29596a5 100644 --- a/include/AudioSdl.h +++ b/include/AudioSdl.h @@ -37,7 +37,7 @@ #endif #include "AudioDevice.h" -#include "AudioDeviceSetupWidget.h" +#include "AudioDeviceSetupGroupWidget.h" class QLineEdit; @@ -57,7 +57,7 @@ public: } - class setupWidget : public gui::AudioDeviceSetupWidget + class setupWidget : public gui::AudioDeviceSetupGroupWidget { public: setupWidget( QWidget * _parent ); diff --git a/include/SetupDialog.h b/include/SetupDialog.h index a68fe89cf..7097b3206 100644 --- a/include/SetupDialog.h +++ b/include/SetupDialog.h @@ -29,7 +29,7 @@ #include #include "AudioDevice.h" -#include "AudioDeviceSetupWidget.h" +#include "AudioDeviceSetupGroupWidget.h" #include "lmmsconfig.h" #include "MidiClient.h" #include "MidiSetupWidget.h" @@ -166,7 +166,7 @@ private: bool m_vstAlwaysOnTop; bool m_disableAutoQuit; - using AswMap = QMap; + using AswMap = QMap; using MswMap = QMap; using trMap = QMap; diff --git a/src/core/audio/AudioJack.cpp b/src/core/audio/AudioJack.cpp index 222ebf10d..00024de63 100644 --- a/src/core/audio/AudioJack.cpp +++ b/src/core/audio/AudioJack.cpp @@ -27,8 +27,8 @@ #ifdef LMMS_HAVE_JACK #include -#include #include +#include #include "Engine.h" #include "GuiApplication.h" @@ -452,19 +452,18 @@ void AudioJack::shutdownCallback( void * _udata ) AudioJack::setupWidget::setupWidget( QWidget * _parent ) : - AudioDeviceSetupWidget( AudioJack::name(), _parent ) + AudioDeviceSetupGroupWidget( AudioJack::name(), _parent ) { + QFormLayout * form = new QFormLayout(this); + QString cn = ConfigManager::inst()->value( "audiojack", "clientname" ); if( cn.isEmpty() ) { cn = "lmms"; } m_clientName = new QLineEdit( cn, this ); - m_clientName->setGeometry( 10, 20, 160, 20 ); - auto cn_lbl = new QLabel(tr("Client name"), this); - cn_lbl->setFont( pointSize<7>( cn_lbl->font() ) ); - cn_lbl->setGeometry( 10, 40, 160, 10 ); + form->addRow(tr("Client name"), m_clientName); auto m = new gui::LcdSpinBoxModel(/* this */); m->setRange( DEFAULT_CHANNELS, SURROUND_CHANNELS ); @@ -474,8 +473,8 @@ AudioJack::setupWidget::setupWidget( QWidget * _parent ) : m_channels = new gui::LcdSpinBox( 1, this ); m_channels->setModel( m ); - m_channels->setLabel( tr( "Channels" ) ); - m_channels->move( 180, 20 ); + + form->addRow(tr("Channels"), m_channels); } diff --git a/src/core/audio/AudioOss.cpp b/src/core/audio/AudioOss.cpp index 5166bad79..5e0a8fc89 100644 --- a/src/core/audio/AudioOss.cpp +++ b/src/core/audio/AudioOss.cpp @@ -27,7 +27,7 @@ #ifdef LMMS_HAVE_OSS #include -#include +#include > #include #include "endian_handling.h" @@ -318,14 +318,13 @@ void AudioOss::run() AudioOss::setupWidget::setupWidget( QWidget * _parent ) : - AudioDeviceSetupWidget( AudioOss::name(), _parent ) + AudioDeviceSetupGroupWidget( AudioOss::name(), _parent ) { - m_device = new QLineEdit( probeDevice(), this ); - m_device->setGeometry( 10, 20, 160, 20 ); + QFormLayout * form = new QFormLayout(this); - auto dev_lbl = new QLabel(tr("Device"), this); - dev_lbl->setFont( pointSize<7>( dev_lbl->font() ) ); - dev_lbl->setGeometry( 10, 40, 160, 10 ); + m_device = new QLineEdit( probeDevice(), this ); + + form->addRow(tr("Device"), m_device); auto m = new gui::LcdSpinBoxModel(/* this */); m->setRange( DEFAULT_CHANNELS, SURROUND_CHANNELS ); @@ -335,9 +334,8 @@ AudioOss::setupWidget::setupWidget( QWidget * _parent ) : m_channels = new gui::LcdSpinBox( 1, this ); m_channels->setModel( m ); - m_channels->setLabel( tr( "Channels" ) ); - m_channels->move( 180, 20 ); + form->addRow(tr("Channels"), m_channels); } diff --git a/src/core/audio/AudioPortAudio.cpp b/src/core/audio/AudioPortAudio.cpp index 0f5a4122f..cb0e4616c 100644 --- a/src/core/audio/AudioPortAudio.cpp +++ b/src/core/audio/AudioPortAudio.cpp @@ -49,7 +49,7 @@ void AudioPortAudioSetupUtil::updateChannels() #ifdef LMMS_HAVE_PORTAUDIO -#include +#include #include "Engine.h" #include "ConfigManager.h" @@ -415,23 +415,17 @@ void AudioPortAudioSetupUtil::updateChannels() AudioPortAudio::setupWidget::setupWidget( QWidget * _parent ) : - AudioDeviceSetupWidget( AudioPortAudio::name(), _parent ) + AudioDeviceSetupGroupWidget( AudioPortAudio::name(), _parent ) { using gui::ComboBox; - m_backend = new ComboBox( this, "BACKEND" ); - m_backend->setGeometry( 64, 15, 260, ComboBox::DEFAULT_HEIGHT ); + QFormLayout * form = new QFormLayout(this); - auto backend_lbl = new QLabel(tr("Backend"), this); - backend_lbl->setFont( pointSize<7>( backend_lbl->font() ) ); - backend_lbl->move( 8, 18 ); + m_backend = new ComboBox( this, "BACKEND" ); + form->addRow(tr("Backend"), m_backend); m_device = new ComboBox( this, "DEVICE" ); - m_device->setGeometry( 64, 35, 260, ComboBox::DEFAULT_HEIGHT ); - - auto dev_lbl = new QLabel(tr("Device"), this); - dev_lbl->setFont( pointSize<7>( dev_lbl->font() ) ); - dev_lbl->move( 8, 38 ); + form->addRow(tr("Device"), m_device); /* LcdSpinBoxModel * m = new LcdSpinBoxModel( ); m->setRange( DEFAULT_CHANNELS, SURROUND_CHANNELS ); @@ -505,7 +499,7 @@ void AudioPortAudio::setupWidget::show() m_setupUtil.m_deviceModel.setValue( i ); } - AudioDeviceSetupWidget::show(); + AudioDeviceSetupGroupWidget::show(); } } // namespace lmms diff --git a/src/core/audio/AudioPulseAudio.cpp b/src/core/audio/AudioPulseAudio.cpp index bac997075..24913c60f 100644 --- a/src/core/audio/AudioPulseAudio.cpp +++ b/src/core/audio/AudioPulseAudio.cpp @@ -23,7 +23,7 @@ */ #include -#include +#include #include "AudioPulseAudio.h" @@ -310,26 +310,23 @@ void AudioPulseAudio::signalConnected( bool connected ) AudioPulseAudio::setupWidget::setupWidget( QWidget * _parent ) : - AudioDeviceSetupWidget( AudioPulseAudio::name(), _parent ) + AudioDeviceSetupGroupWidget( AudioPulseAudio::name(), _parent ) { + QFormLayout * form = new QFormLayout(this); + m_device = new QLineEdit( AudioPulseAudio::probeDevice(), this ); - m_device->setGeometry( 10, 20, 160, 20 ); + form->addRow(tr("Device"), m_device); - auto dev_lbl = new QLabel(tr("Device"), this); - dev_lbl->setFont( pointSize<7>( dev_lbl->font() ) ); - dev_lbl->setGeometry( 10, 40, 160, 10 ); - - auto m = new gui::LcdSpinBoxModel(/* this */); + auto m = new gui::LcdSpinBoxModel(); m->setRange( DEFAULT_CHANNELS, SURROUND_CHANNELS ); m->setStep( 2 ); m->setValue( ConfigManager::inst()->value( "audiopa", - "channels" ).toInt() ); + "channels" ).toInt() ); m_channels = new gui::LcdSpinBox( 1, this ); m_channels->setModel( m ); - m_channels->setLabel( tr( "Channels" ) ); - m_channels->move( 180, 20 ); + form->addRow(tr("Channels"), m_channels); } diff --git a/src/core/audio/AudioSdl.cpp b/src/core/audio/AudioSdl.cpp index e73ccadc1..071877f0d 100644 --- a/src/core/audio/AudioSdl.cpp +++ b/src/core/audio/AudioSdl.cpp @@ -26,7 +26,7 @@ #ifdef LMMS_HAVE_SDL -#include +#include > #include #include @@ -325,16 +325,14 @@ void AudioSdl::sdlInputAudioCallback(Uint8 *_buf, int _len) { #endif AudioSdl::setupWidget::setupWidget( QWidget * _parent ) : - AudioDeviceSetupWidget( AudioSdl::name(), _parent ) + AudioDeviceSetupGroupWidget( AudioSdl::name(), _parent ) { + QFormLayout * form = new QFormLayout(this); + QString dev = ConfigManager::inst()->value( "audiosdl", "device" ); m_device = new QLineEdit( dev, this ); - m_device->setGeometry( 10, 20, 160, 20 ); - - auto dev_lbl = new QLabel(tr("Device"), this); - dev_lbl->setFont( pointSize<7>( dev_lbl->font() ) ); - dev_lbl->setGeometry( 10, 40, 160, 10 ); + form->addRow(tr("Device"), m_device); } diff --git a/src/gui/AudioAlsaSetupWidget.cpp b/src/gui/AudioAlsaSetupWidget.cpp index 4ea6d4c58..015f4e8ad 100644 --- a/src/gui/AudioAlsaSetupWidget.cpp +++ b/src/gui/AudioAlsaSetupWidget.cpp @@ -23,7 +23,7 @@ */ #include -#include +#include #include "AudioAlsaSetupWidget.h" @@ -37,9 +37,11 @@ namespace lmms::gui { AudioAlsaSetupWidget::AudioAlsaSetupWidget( QWidget * _parent ) : - AudioDeviceSetupWidget( AudioAlsa::name(), _parent ), + AudioDeviceSetupGroupWidget( AudioAlsa::name(), _parent ), m_selectedDevice(-1) { + QFormLayout * form = new QFormLayout(this); + m_deviceInfos = AudioAlsa::getAvailableDevices(); QString deviceText = ConfigManager::inst()->value( "audioalsa", "device" ); @@ -62,14 +64,11 @@ AudioAlsaSetupWidget::AudioAlsaSetupWidget( QWidget * _parent ) : m_selectedDevice = m_deviceComboBox->currentIndex(); - m_deviceComboBox->setGeometry( 10, 20, 160, 20 ); connect(m_deviceComboBox, SIGNAL(currentIndexChanged(int)), SLOT(onCurrentIndexChanged(int))); - auto dev_lbl = new QLabel(tr("DEVICE"), this); - dev_lbl->setFont( pointSize<7>( dev_lbl->font() ) ); - dev_lbl->setGeometry( 10, 40, 160, 10 ); + form->addRow(tr("Device"), m_deviceComboBox); auto m = new LcdSpinBoxModel(/* this */); m->setRange( DEFAULT_CHANNELS, SURROUND_CHANNELS ); @@ -79,9 +78,8 @@ AudioAlsaSetupWidget::AudioAlsaSetupWidget( QWidget * _parent ) : m_channels = new LcdSpinBox( 1, this ); m_channels->setModel( m ); - m_channels->setLabel( tr( "CHANNELS" ) ); - m_channels->move( 180, 20 ); + form->addRow(tr("Channels"), m_channels); } diff --git a/src/gui/AudioDeviceSetupGroupWidget.cpp b/src/gui/AudioDeviceSetupGroupWidget.cpp new file mode 100644 index 000000000..f84c8bb8b --- /dev/null +++ b/src/gui/AudioDeviceSetupGroupWidget.cpp @@ -0,0 +1,42 @@ +/* + * AudioDeviceSetupGroupWidget.cpp - Base class for audio device setup widgets using group box + * + * Copyright (c) 2004-2015 Tobias Doerffel + * Copyright (c) 2004-2015 Michael Gregorius + * + * 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 "AudioDeviceSetupGroupWidget.h" + +namespace lmms::gui +{ + +AudioDeviceSetupGroupWidget::AudioDeviceSetupGroupWidget(const QString & caption, QWidget * parent) : + QGroupBox(QGroupBox::tr("Settings for %1").arg(tr(caption.toUtf8())), parent) +{ +} + +void AudioDeviceSetupGroupWidget::show() +{ + parentWidget()->show(); + QWidget::show(); +} + +} // namespace lmms::gui diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 9f940c035..3ae16c573 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -3,6 +3,7 @@ SET(LMMS_SRCS gui/ActionGroup.cpp gui/AudioAlsaSetupWidget.cpp gui/AudioDeviceSetupWidget.cpp + gui/AudioDeviceSetupGroupWidget.cpp gui/AutomatableModelView.cpp gui/ControlLayout.cpp gui/ControllerDialog.cpp diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index 0565b8238..d1375c033 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -466,7 +466,6 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : // Ifaces-settings-widget. auto as_w = new QWidget(audio_w); - as_w->setFixedHeight(60); auto as_w_layout = new QHBoxLayout(as_w); as_w_layout->setSpacing(0); @@ -492,6 +491,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : new AudioPortAudio::setupWidget(as_w); #endif +// TODO !!! #ifdef LMMS_HAVE_SOUNDIO m_audioIfaceSetupWidgets[AudioSoundIo::name()] = new AudioSoundIo::setupWidget(as_w); @@ -507,6 +507,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : new AudioOss::setupWidget(as_w); #endif +// TODO !!! #ifdef LMMS_HAVE_SNDIO m_audioIfaceSetupWidgets[AudioSndio::name()] = new AudioSndio::setupWidget(as_w); @@ -520,7 +521,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : it != m_audioIfaceSetupWidgets.end(); ++it) { m_audioIfaceNames[ - AudioDeviceSetupWidget::tr(it.key().toUtf8())] = it.key(); + AudioDeviceSetupGroupWidget::tr(it.key().toUtf8())] = it.key(); } for(trMap::iterator it = m_audioIfaceNames.begin(); it != m_audioIfaceNames.end(); ++it) From 345886954ecd2e1639cf46af9b9b747237d66b3a Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sat, 22 Jul 2023 23:03:31 +0200 Subject: [PATCH 069/308] Adjust the MIDI setup dialog Adjust the MIDI setup dialog: * Show it in a QGroupBox * Make it use a `QFormLayout` to layout the label and line edit. Remove the hard coded height. --- include/MidiSetupWidget.h | 4 ++-- src/gui/MidiSetupWidget.cpp | 13 ++++++------- src/gui/modals/SetupDialog.cpp | 1 - 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/include/MidiSetupWidget.h b/include/MidiSetupWidget.h index a61b606ac..7b6606017 100644 --- a/include/MidiSetupWidget.h +++ b/include/MidiSetupWidget.h @@ -25,7 +25,7 @@ #ifndef LMMS_GUI_MIDI_SETUP_WIDGET_H #define LMMS_GUI_MIDI_SETUP_WIDGET_H -#include "TabWidget.h" +#include class QLineEdit; @@ -33,7 +33,7 @@ namespace lmms::gui { -class MidiSetupWidget : public TabWidget +class MidiSetupWidget : public QGroupBox { Q_OBJECT MidiSetupWidget( const QString & caption, const QString & configSection, diff --git a/src/gui/MidiSetupWidget.cpp b/src/gui/MidiSetupWidget.cpp index 4f620fb0e..d18c19bab 100644 --- a/src/gui/MidiSetupWidget.cpp +++ b/src/gui/MidiSetupWidget.cpp @@ -24,7 +24,7 @@ #include "MidiSetupWidget.h" -#include +#include > #include #include "ConfigManager.h" @@ -37,7 +37,7 @@ namespace lmms::gui MidiSetupWidget::MidiSetupWidget(const QString & caption, const QString & configSection, const QString & devName, QWidget * parent) : - TabWidget(TabWidget::tr("Settings for %1").arg(tr(caption.toUtf8())), parent), + QGroupBox(QGroupBox::tr("Settings for %1").arg(tr(caption.toUtf8())), parent), m_configSection(configSection), m_device(nullptr) { @@ -45,12 +45,11 @@ MidiSetupWidget::MidiSetupWidget(const QString & caption, const QString & config // to indicate that there is no editable device field if (!devName.isNull()) { - m_device = new QLineEdit(devName, this); - m_device->setGeometry(10, 20, 160, 20); + QFormLayout * form = new QFormLayout(this); - auto dev_lbl = new QLabel(tr("Device"), this); - dev_lbl->setFont(pointSize<7>(dev_lbl->font())); - dev_lbl->setGeometry(10, 40, 160, 10); + m_device = new QLineEdit(devName, this); + + form->addRow(tr("Device"), m_device); } } diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index d1375c033..2b6c199ba 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -617,7 +617,6 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : // Ifaces-settings-widget. auto ms_w = new QWidget(midi_w); - ms_w->setFixedHeight(60); auto ms_w_layout = new QHBoxLayout(ms_w); ms_w_layout->setSpacing(0); From 095b2066352171909b7810e05062c0d08f3cbabe Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Tue, 25 Jul 2023 17:36:48 +0200 Subject: [PATCH 070/308] Remove unused include Remove an unused include of "AudioDeviceSetupWidget.h". --- src/gui/modals/SetupDialog.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index 2b6c199ba..87a54a993 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -32,7 +32,6 @@ #include #include -#include "AudioDeviceSetupWidget.h" #include "AudioEngine.h" #include "debug.h" #include "embed.h" From 9282e6c91bd212bd9cbcfd0618e97164f1b80786 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Tue, 25 Jul 2023 18:03:18 +0200 Subject: [PATCH 071/308] Remove temporary AudioDeviceSetupGroupWidget Remove the temporary class `AudioDeviceSetupGroupWidget` and move its functionality into `AudioDeviceSetupWidget`. This means to let `AudioDeviceSetupWidget` inherit from `QGroupBox` instead of `TabWidget`. Adjust all inheriting classes accordingly. Adjust usages in SetupDialog. The result should be that even the cases for `LMMS_HAVE_SOUNDIO` and `LMMS_HAVE_SNDIO` should compile again. Although their layout might look weird. --- include/AudioAlsaSetupWidget.h | 4 +- include/AudioDeviceSetupGroupWidget.h | 49 ------------------------- include/AudioDeviceSetupWidget.h | 5 ++- include/AudioDummy.h | 6 +-- include/AudioJack.h | 4 +- include/AudioOss.h | 4 +- include/AudioPortAudio.h | 4 +- include/AudioPulseAudio.h | 4 +- include/AudioSdl.h | 4 +- include/SetupDialog.h | 4 +- src/core/audio/AudioJack.cpp | 2 +- src/core/audio/AudioOss.cpp | 2 +- src/core/audio/AudioPortAudio.cpp | 4 +- src/core/audio/AudioPulseAudio.cpp | 2 +- src/core/audio/AudioSdl.cpp | 2 +- src/gui/AudioAlsaSetupWidget.cpp | 2 +- src/gui/AudioDeviceSetupGroupWidget.cpp | 42 --------------------- src/gui/AudioDeviceSetupWidget.cpp | 4 +- src/gui/CMakeLists.txt | 1 - src/gui/modals/SetupDialog.cpp | 2 +- 20 files changed, 30 insertions(+), 121 deletions(-) delete mode 100644 include/AudioDeviceSetupGroupWidget.h delete mode 100644 src/gui/AudioDeviceSetupGroupWidget.cpp diff --git a/include/AudioAlsaSetupWidget.h b/include/AudioAlsaSetupWidget.h index 9795a3588..cbe99ba01 100644 --- a/include/AudioAlsaSetupWidget.h +++ b/include/AudioAlsaSetupWidget.h @@ -29,7 +29,7 @@ #ifdef LMMS_HAVE_ALSA -#include "AudioDeviceSetupGroupWidget.h" +#include "AudioDeviceSetupWidget.h" #include "AudioAlsa.h" @@ -41,7 +41,7 @@ namespace lmms::gui class LcdSpinBox; -class AudioAlsaSetupWidget : public AudioDeviceSetupGroupWidget +class AudioAlsaSetupWidget : public AudioDeviceSetupWidget { Q_OBJECT diff --git a/include/AudioDeviceSetupGroupWidget.h b/include/AudioDeviceSetupGroupWidget.h deleted file mode 100644 index 8980d0a65..000000000 --- a/include/AudioDeviceSetupGroupWidget.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * AudioDeviceSetupGroupWidget.h - Base class for audio device setup widgets using group box - * - * Copyright (c) 2004-2015 Tobias Doerffel - * Copyright (c) 2004-2015 Michael Gregorius - * - * 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_AUDIO_DEVICE_SETUP_GROUP_WIDGET_H -#define LMMS_GUI_AUDIO_DEVICE_SETUP_GROUP_WIDGET_H - -#include - -namespace lmms::gui -{ - -class AudioDeviceSetupGroupWidget : public QGroupBox -{ - Q_OBJECT -public: - AudioDeviceSetupGroupWidget( const QString & _caption, QWidget * _parent ); - - ~AudioDeviceSetupGroupWidget() override = default; - - virtual void saveSettings() = 0; - - virtual void show(); -}; - -} // namespace lmms::gui - -#endif // LMMS_GUI_AUDIO_DEVICE_SETUP_GROUP_WIDGET_H diff --git a/include/AudioDeviceSetupWidget.h b/include/AudioDeviceSetupWidget.h index f56fa07a6..acc99602d 100644 --- a/include/AudioDeviceSetupWidget.h +++ b/include/AudioDeviceSetupWidget.h @@ -2,6 +2,7 @@ * AudioDeviceSetupWidget.h - Base class for audio device setup widgets * * Copyright (c) 2004-2015 Tobias Doerffel + * Copyright (c) 2023- Michael Gregorius * * This file is part of LMMS - https://lmms.io * @@ -25,12 +26,12 @@ #ifndef LMMS_GUI_AUDIO_DEVICE_SETUP_WIDGET_H #define LMMS_GUI_AUDIO_DEVICE_SETUP_WIDGET_H -#include "TabWidget.h" +#include namespace lmms::gui { -class AudioDeviceSetupWidget : public TabWidget +class AudioDeviceSetupWidget : public QGroupBox { Q_OBJECT public: diff --git a/include/AudioDummy.h b/include/AudioDummy.h index c7ac3d67f..e34260171 100644 --- a/include/AudioDummy.h +++ b/include/AudioDummy.h @@ -26,7 +26,7 @@ #define LMMS_AUDIO_DUMMY_H #include "AudioDevice.h" -#include "AudioDeviceSetupGroupWidget.h" +#include "AudioDeviceSetupWidget.h" #include "AudioEngine.h" #include "MicroTimer.h" @@ -54,11 +54,11 @@ public: } - class setupWidget : public gui::AudioDeviceSetupGroupWidget + class setupWidget : public gui::AudioDeviceSetupWidget { public: setupWidget( QWidget * _parent ) : - gui::AudioDeviceSetupGroupWidget( AudioDummy::name(), _parent ) + gui::AudioDeviceSetupWidget( AudioDummy::name(), _parent ) { } diff --git a/include/AudioJack.h b/include/AudioJack.h index 4135dc5e0..2ef0f665c 100644 --- a/include/AudioJack.h +++ b/include/AudioJack.h @@ -38,7 +38,7 @@ #include #include "AudioDevice.h" -#include "AudioDeviceSetupGroupWidget.h" +#include "AudioDeviceSetupWidget.h" class QLineEdit; @@ -74,7 +74,7 @@ public: } -class setupWidget : public gui::AudioDeviceSetupGroupWidget +class setupWidget : public gui::AudioDeviceSetupWidget { public: setupWidget( QWidget * _parent ); diff --git a/include/AudioOss.h b/include/AudioOss.h index 953c72a4f..55f64de85 100644 --- a/include/AudioOss.h +++ b/include/AudioOss.h @@ -32,7 +32,7 @@ #include #include "AudioDevice.h" -#include "AudioDeviceSetupGroupWidget.h" +#include "AudioDeviceSetupWidget.h" class QLineEdit; @@ -61,7 +61,7 @@ public: static QString probeDevice(); -class setupWidget : public gui::AudioDeviceSetupGroupWidget +class setupWidget : public gui::AudioDeviceSetupWidget { public: setupWidget( QWidget * _parent ); diff --git a/include/AudioPortAudio.h b/include/AudioPortAudio.h index a926b1bf0..01b8f3fd7 100644 --- a/include/AudioPortAudio.h +++ b/include/AudioPortAudio.h @@ -35,7 +35,7 @@ # include # include "AudioDevice.h" -# include "AudioDeviceSetupGroupWidget.h" +# include "AudioDeviceSetupWidget.h" # if defined paNeverDropInput || defined paNonInterleaved # define PORTAUDIO_V19 @@ -90,7 +90,7 @@ public: unsigned long _framesPerBuffer ); - class setupWidget : public gui::AudioDeviceSetupGroupWidget + class setupWidget : public gui::AudioDeviceSetupWidget { public: setupWidget( QWidget * _parent ); diff --git a/include/AudioPulseAudio.h b/include/AudioPulseAudio.h index 22e47896d..b6a998274 100644 --- a/include/AudioPulseAudio.h +++ b/include/AudioPulseAudio.h @@ -34,7 +34,7 @@ #include #include "AudioDevice.h" -#include "AudioDeviceSetupGroupWidget.h" +#include "AudioDeviceSetupWidget.h" class QLineEdit; @@ -62,7 +62,7 @@ public: static QString probeDevice(); - class setupWidget : public gui::AudioDeviceSetupGroupWidget + class setupWidget : public gui::AudioDeviceSetupWidget { public: setupWidget( QWidget * _parent ); diff --git a/include/AudioSdl.h b/include/AudioSdl.h index 5f29596a5..62db8b68a 100644 --- a/include/AudioSdl.h +++ b/include/AudioSdl.h @@ -37,7 +37,7 @@ #endif #include "AudioDevice.h" -#include "AudioDeviceSetupGroupWidget.h" +#include "AudioDeviceSetupWidget.h" class QLineEdit; @@ -57,7 +57,7 @@ public: } - class setupWidget : public gui::AudioDeviceSetupGroupWidget + class setupWidget : public gui::AudioDeviceSetupWidget { public: setupWidget( QWidget * _parent ); diff --git a/include/SetupDialog.h b/include/SetupDialog.h index 7097b3206..a68fe89cf 100644 --- a/include/SetupDialog.h +++ b/include/SetupDialog.h @@ -29,7 +29,7 @@ #include #include "AudioDevice.h" -#include "AudioDeviceSetupGroupWidget.h" +#include "AudioDeviceSetupWidget.h" #include "lmmsconfig.h" #include "MidiClient.h" #include "MidiSetupWidget.h" @@ -166,7 +166,7 @@ private: bool m_vstAlwaysOnTop; bool m_disableAutoQuit; - using AswMap = QMap; + using AswMap = QMap; using MswMap = QMap; using trMap = QMap; diff --git a/src/core/audio/AudioJack.cpp b/src/core/audio/AudioJack.cpp index 00024de63..75d253671 100644 --- a/src/core/audio/AudioJack.cpp +++ b/src/core/audio/AudioJack.cpp @@ -452,7 +452,7 @@ void AudioJack::shutdownCallback( void * _udata ) AudioJack::setupWidget::setupWidget( QWidget * _parent ) : - AudioDeviceSetupGroupWidget( AudioJack::name(), _parent ) + AudioDeviceSetupWidget( AudioJack::name(), _parent ) { QFormLayout * form = new QFormLayout(this); diff --git a/src/core/audio/AudioOss.cpp b/src/core/audio/AudioOss.cpp index 5e0a8fc89..b1b50907b 100644 --- a/src/core/audio/AudioOss.cpp +++ b/src/core/audio/AudioOss.cpp @@ -318,7 +318,7 @@ void AudioOss::run() AudioOss::setupWidget::setupWidget( QWidget * _parent ) : - AudioDeviceSetupGroupWidget( AudioOss::name(), _parent ) + AudioDeviceSetupWidget( AudioOss::name(), _parent ) { QFormLayout * form = new QFormLayout(this); diff --git a/src/core/audio/AudioPortAudio.cpp b/src/core/audio/AudioPortAudio.cpp index cb0e4616c..c52ae8640 100644 --- a/src/core/audio/AudioPortAudio.cpp +++ b/src/core/audio/AudioPortAudio.cpp @@ -415,7 +415,7 @@ void AudioPortAudioSetupUtil::updateChannels() AudioPortAudio::setupWidget::setupWidget( QWidget * _parent ) : - AudioDeviceSetupGroupWidget( AudioPortAudio::name(), _parent ) + AudioDeviceSetupWidget( AudioPortAudio::name(), _parent ) { using gui::ComboBox; @@ -499,7 +499,7 @@ void AudioPortAudio::setupWidget::show() m_setupUtil.m_deviceModel.setValue( i ); } - AudioDeviceSetupGroupWidget::show(); + AudioDeviceSetupWidget::show(); } } // namespace lmms diff --git a/src/core/audio/AudioPulseAudio.cpp b/src/core/audio/AudioPulseAudio.cpp index 24913c60f..390bd0ba8 100644 --- a/src/core/audio/AudioPulseAudio.cpp +++ b/src/core/audio/AudioPulseAudio.cpp @@ -310,7 +310,7 @@ void AudioPulseAudio::signalConnected( bool connected ) AudioPulseAudio::setupWidget::setupWidget( QWidget * _parent ) : - AudioDeviceSetupGroupWidget( AudioPulseAudio::name(), _parent ) + AudioDeviceSetupWidget( AudioPulseAudio::name(), _parent ) { QFormLayout * form = new QFormLayout(this); diff --git a/src/core/audio/AudioSdl.cpp b/src/core/audio/AudioSdl.cpp index 071877f0d..794c486de 100644 --- a/src/core/audio/AudioSdl.cpp +++ b/src/core/audio/AudioSdl.cpp @@ -325,7 +325,7 @@ void AudioSdl::sdlInputAudioCallback(Uint8 *_buf, int _len) { #endif AudioSdl::setupWidget::setupWidget( QWidget * _parent ) : - AudioDeviceSetupGroupWidget( AudioSdl::name(), _parent ) + AudioDeviceSetupWidget( AudioSdl::name(), _parent ) { QFormLayout * form = new QFormLayout(this); diff --git a/src/gui/AudioAlsaSetupWidget.cpp b/src/gui/AudioAlsaSetupWidget.cpp index 015f4e8ad..7db822b4b 100644 --- a/src/gui/AudioAlsaSetupWidget.cpp +++ b/src/gui/AudioAlsaSetupWidget.cpp @@ -37,7 +37,7 @@ namespace lmms::gui { AudioAlsaSetupWidget::AudioAlsaSetupWidget( QWidget * _parent ) : - AudioDeviceSetupGroupWidget( AudioAlsa::name(), _parent ), + AudioDeviceSetupWidget( AudioAlsa::name(), _parent ), m_selectedDevice(-1) { QFormLayout * form = new QFormLayout(this); diff --git a/src/gui/AudioDeviceSetupGroupWidget.cpp b/src/gui/AudioDeviceSetupGroupWidget.cpp deleted file mode 100644 index f84c8bb8b..000000000 --- a/src/gui/AudioDeviceSetupGroupWidget.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * AudioDeviceSetupGroupWidget.cpp - Base class for audio device setup widgets using group box - * - * Copyright (c) 2004-2015 Tobias Doerffel - * Copyright (c) 2004-2015 Michael Gregorius - * - * 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 "AudioDeviceSetupGroupWidget.h" - -namespace lmms::gui -{ - -AudioDeviceSetupGroupWidget::AudioDeviceSetupGroupWidget(const QString & caption, QWidget * parent) : - QGroupBox(QGroupBox::tr("Settings for %1").arg(tr(caption.toUtf8())), parent) -{ -} - -void AudioDeviceSetupGroupWidget::show() -{ - parentWidget()->show(); - QWidget::show(); -} - -} // namespace lmms::gui diff --git a/src/gui/AudioDeviceSetupWidget.cpp b/src/gui/AudioDeviceSetupWidget.cpp index b78800cec..98d03638f 100644 --- a/src/gui/AudioDeviceSetupWidget.cpp +++ b/src/gui/AudioDeviceSetupWidget.cpp @@ -28,7 +28,7 @@ namespace lmms::gui { AudioDeviceSetupWidget::AudioDeviceSetupWidget(const QString & caption, QWidget * parent) : - TabWidget(TabWidget::tr("Settings for %1").arg(tr(caption.toUtf8())), parent) + QGroupBox(QGroupBox::tr("Settings for %1").arg(tr(caption.toUtf8())), parent) { } @@ -38,4 +38,4 @@ void AudioDeviceSetupWidget::show() QWidget::show(); } -} // namespace lmms::gui \ No newline at end of file +} // namespace lmms::gui diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 3ae16c573..9f940c035 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -3,7 +3,6 @@ SET(LMMS_SRCS gui/ActionGroup.cpp gui/AudioAlsaSetupWidget.cpp gui/AudioDeviceSetupWidget.cpp - gui/AudioDeviceSetupGroupWidget.cpp gui/AutomatableModelView.cpp gui/ControlLayout.cpp gui/ControllerDialog.cpp diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index 87a54a993..23e1fe5d5 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -520,7 +520,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : it != m_audioIfaceSetupWidgets.end(); ++it) { m_audioIfaceNames[ - AudioDeviceSetupGroupWidget::tr(it.key().toUtf8())] = it.key(); + AudioDeviceSetupWidget::tr(it.key().toUtf8())] = it.key(); } for(trMap::iterator it = m_audioIfaceNames.begin(); it != m_audioIfaceNames.end(); ++it) From a429c2f94f338579176a81f230f0253b13e84650 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Tue, 25 Jul 2023 18:15:37 +0200 Subject: [PATCH 072/308] Adjustment of AudioSndio Adjust the layout that's created in AudioSndio::setupWidget::setupWidget by using a QFormLayout. This was done in a "blind" fashion as I am not able to compile this code. Adjustments are very similar to the ones done in AudioPulseAudio::setupWidget::setupWidget with commit b53290344b3 though. --- src/core/audio/AudioSndio.cpp | 13 +++++-------- src/gui/modals/SetupDialog.cpp | 1 - 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/core/audio/AudioSndio.cpp b/src/core/audio/AudioSndio.cpp index a8ea34ce1..8a1e00653 100644 --- a/src/core/audio/AudioSndio.cpp +++ b/src/core/audio/AudioSndio.cpp @@ -28,7 +28,7 @@ #ifdef LMMS_HAVE_SNDIO #include -#include +#include #include #include "endian_handling.h" @@ -183,12 +183,10 @@ void AudioSndio::run() AudioSndio::setupWidget::setupWidget( QWidget * _parent ) : AudioDeviceSetupWidget( AudioSndio::name(), _parent ) { - m_device = new QLineEdit( "", this ); - m_device->setGeometry( 10, 20, 160, 20 ); + QFormLayout * form = new QFormLayout(this); - QLabel * dev_lbl = new QLabel( tr( "Device" ), this ); - dev_lbl->setFont( pointSize<6>( dev_lbl->font() ) ); - dev_lbl->setGeometry( 10, 40, 160, 10 ); + m_device = new QLineEdit( "", this ); + form->addRow(tr("Device"), m_device); gui::LcdSpinBoxModel * m = new gui::LcdSpinBoxModel( /* this */ ); m->setRange( DEFAULT_CHANNELS, SURROUND_CHANNELS ); @@ -198,9 +196,8 @@ AudioSndio::setupWidget::setupWidget( QWidget * _parent ) : m_channels = new gui::LcdSpinBox( 1, this ); m_channels->setModel( m ); - m_channels->setLabel( tr( "Channels" ) ); - m_channels->move( 180, 20 ); + form->addRow(tr("Channels"), m_channels); } diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index 23e1fe5d5..7da234d07 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -506,7 +506,6 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : new AudioOss::setupWidget(as_w); #endif -// TODO !!! #ifdef LMMS_HAVE_SNDIO m_audioIfaceSetupWidgets[AudioSndio::name()] = new AudioSndio::setupWidget(as_w); From 0759da2776139c59c98f16753d6ec1664cab44e8 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Tue, 25 Jul 2023 18:28:04 +0200 Subject: [PATCH 073/308] Layout adjustments for AudioSoundIo Use a QFormLayout in AudioSoundIo::setupWidget::setupWidget. Note: Changes have been done "blindly" as I am not able to compile this code. --- src/core/audio/AudioSoundIo.cpp | 16 +++++----------- src/gui/modals/SetupDialog.cpp | 1 - 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/core/audio/AudioSoundIo.cpp b/src/core/audio/AudioSoundIo.cpp index 633808204..23385960f 100644 --- a/src/core/audio/AudioSoundIo.cpp +++ b/src/core/audio/AudioSoundIo.cpp @@ -26,7 +26,7 @@ #ifdef LMMS_HAVE_SOUNDIO -#include +#include #include #include "Engine.h" @@ -451,19 +451,13 @@ AudioSoundIo::setupWidget::setupWidget( QWidget * _parent ) : { m_setupUtil.m_setupWidget = this; - m_backend = new gui::ComboBox( this, "BACKEND" ); - m_backend->setGeometry( 64, 15, 260, 20 ); + QFormLayout * form = new QFormLayout(this); - QLabel * backend_lbl = new QLabel( tr( "Backend" ), this ); - backend_lbl->setFont( pointSize<7>( backend_lbl->font() ) ); - backend_lbl->move( 8, 18 ); + m_backend = new gui::ComboBox( this, "BACKEND" ); + form->addRow(tr("Backend"), m_backend); m_device = new gui::ComboBox( this, "DEVICE" ); - m_device->setGeometry( 64, 35, 260, 20 ); - - QLabel * dev_lbl = new QLabel( tr( "Device" ), this ); - dev_lbl->setFont( pointSize<7>( dev_lbl->font() ) ); - dev_lbl->move( 8, 38 ); + form->addRow(tr("Device"), m_device); // Setup models m_soundio = soundio_create(); diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index 7da234d07..892155280 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -490,7 +490,6 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : new AudioPortAudio::setupWidget(as_w); #endif -// TODO !!! #ifdef LMMS_HAVE_SOUNDIO m_audioIfaceSetupWidgets[AudioSoundIo::name()] = new AudioSoundIo::setupWidget(as_w); From 4fac4c6c4a9a32a0d02dfd855c7685bcf1514fbb Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Tue, 25 Jul 2023 19:07:57 +0200 Subject: [PATCH 074/308] Fix a problem with some includes Remove a trailing ">" for some includes of `QFormLayout`. My local compiler did not complain but mingw rightfully does. --- src/core/audio/AudioOss.cpp | 2 +- src/core/audio/AudioSdl.cpp | 2 +- src/gui/MidiSetupWidget.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/audio/AudioOss.cpp b/src/core/audio/AudioOss.cpp index b1b50907b..0b7812fe6 100644 --- a/src/core/audio/AudioOss.cpp +++ b/src/core/audio/AudioOss.cpp @@ -27,7 +27,7 @@ #ifdef LMMS_HAVE_OSS #include -#include > +#include #include #include "endian_handling.h" diff --git a/src/core/audio/AudioSdl.cpp b/src/core/audio/AudioSdl.cpp index 794c486de..fa801f890 100644 --- a/src/core/audio/AudioSdl.cpp +++ b/src/core/audio/AudioSdl.cpp @@ -26,7 +26,7 @@ #ifdef LMMS_HAVE_SDL -#include > +#include #include #include diff --git a/src/gui/MidiSetupWidget.cpp b/src/gui/MidiSetupWidget.cpp index d18c19bab..2385def02 100644 --- a/src/gui/MidiSetupWidget.cpp +++ b/src/gui/MidiSetupWidget.cpp @@ -24,7 +24,7 @@ #include "MidiSetupWidget.h" -#include > +#include #include #include "ConfigManager.h" From a9d49d4ff70642c958380a0b2e4fc6180c1a1877 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Sat, 29 Jul 2023 12:22:32 +0800 Subject: [PATCH 075/308] CMakeLists: use flags for Apple correctly (#6784) --- plugins/CMakeLists.txt | 2 +- src/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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/src/CMakeLists.txt b/src/CMakeLists.txt index bd543779f..23923f616 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() From 5674bb58e2554e3cfc9e01951de27a81c82f7c67 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sat, 29 Jul 2023 09:58:40 +0200 Subject: [PATCH 076/308] Fix HiDPI issues for menus Menus now use the size that users have set globally for their applications. This is accomplished by removing the fixed font size definition (in points) for `QMenu` in `style.css`. In some places the menus had been set to hard coded font sizes. This code is also removed and applies to the following menus: * Combo box menus * Track operation widget (gear icon on tracks) * The MIDI port menu --- data/themes/default/style.css | 4 ---- src/gui/menus/MidiPortMenu.cpp | 1 - src/gui/tracks/TrackOperationsWidget.cpp | 1 - src/gui/widgets/ComboBox.cpp | 1 - 4 files changed, 7 deletions(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index a9646cfe4..12b63cfec 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -115,7 +115,6 @@ QSplashScreen QLabel { QMenu { border-top: 2px solid #08993E; background-color: #15191c; - font-size: 11px; } QMenu::separator { @@ -133,15 +132,12 @@ QMenu::item { QMenu::item:selected { color: #d1d8e4; - font-weight: normal; background-color: #21272b; } QMenu::item:disabled { color: #515459; background-color: #262b30; - font-size: 12px; - font-weight: normal; padding: 4px 32px 4px 20px; } diff --git a/src/gui/menus/MidiPortMenu.cpp b/src/gui/menus/MidiPortMenu.cpp index b1ddf71c9..67ad01f87 100644 --- a/src/gui/menus/MidiPortMenu.cpp +++ b/src/gui/menus/MidiPortMenu.cpp @@ -34,7 +34,6 @@ MidiPortMenu::MidiPortMenu( MidiPort::Modes _mode ) : ModelView( nullptr, this ), m_mode( _mode ) { - setFont( pointSize<9>( font() ) ); connect( this, SIGNAL(triggered(QAction*)), this, SLOT(activatedPort(QAction*))); } diff --git a/src/gui/tracks/TrackOperationsWidget.cpp b/src/gui/tracks/TrackOperationsWidget.cpp index ddbd2eacd..3e3654974 100644 --- a/src/gui/tracks/TrackOperationsWidget.cpp +++ b/src/gui/tracks/TrackOperationsWidget.cpp @@ -64,7 +64,6 @@ TrackOperationsWidget::TrackOperationsWidget( TrackView * parent ) : "to begin a new drag'n'drop action." ).arg(UI_CTRL_KEY) ); auto toMenu = new QMenu(this); - toMenu->setFont( pointSize<9>( toMenu->font() ) ); connect( toMenu, SIGNAL(aboutToShow()), this, SLOT(updateMenu())); diff --git a/src/gui/widgets/ComboBox.cpp b/src/gui/widgets/ComboBox.cpp index bdf78ccce..2377a37ab 100644 --- a/src/gui/widgets/ComboBox.cpp +++ b/src/gui/widgets/ComboBox.cpp @@ -70,7 +70,6 @@ ComboBox::ComboBox( QWidget * _parent, const QString & _name ) : } setFont( pointSize<9>( font() ) ); - m_menu.setFont( pointSize<8>( m_menu.font() ) ); connect( &m_menu, SIGNAL(triggered(QAction*)), this, SLOT(setItem(QAction*))); From 67dcdf2c65a306933e2b34379a04c2cee85ed8ce Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sat, 29 Jul 2023 10:19:47 +0200 Subject: [PATCH 077/308] Fix HiDPI issue of sample track window Fix one of the HiDPI issues of the sample track window by removing the hard coded font size of the name line edit. --- src/gui/SampleTrackWindow.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gui/SampleTrackWindow.cpp b/src/gui/SampleTrackWindow.cpp index 6fe70bf41..06afdfd3d 100644 --- a/src/gui/SampleTrackWindow.cpp +++ b/src/gui/SampleTrackWindow.cpp @@ -74,7 +74,6 @@ SampleTrackWindow::SampleTrackWindow(SampleTrackView * tv) : // setup line edit for changing sample track name m_nameLineEdit = new QLineEdit; - m_nameLineEdit->setFont(pointSize<9>(m_nameLineEdit->font())); connect(m_nameLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(textChanged(const QString&))); From 48cdaddd9dd1a9c1a3716995d752bed567b6c9ad Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sat, 29 Jul 2023 16:21:05 +0200 Subject: [PATCH 078/308] HiDPI fixes for elements based on QTreeView Fix the HiDPI problems for elements that are based on QTreeView by removing the fixed point based font size from the style sheet. This affects: * The file browser * The headings of the plugin browser * The patch selection dialogs for GigPlayer and SoundFont player Also make the text size of the check boxes for user content and factory content based on a point size instead of a pixel size. --- data/themes/default/style.css | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index a9646cfe4..52f60e4ed 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -9,7 +9,6 @@ QLabel, QTreeWidget, QListWidget, QGroupBox, QMenuBar { QTreeView { outline: none; - font-size: 12px; } QTreeWidget::item { @@ -42,7 +41,7 @@ QMdiArea { lmms--gui--FileBrowser QCheckBox { - font-size: 10px; + font-size: 8pt; color: white; } From 086e86490f26ace682e01e4109043faaccbf08bf Mon Sep 17 00:00:00 2001 From: Madadog <53168336+Madadog@users.noreply.github.com> Date: Sun, 30 Jul 2023 21:27:05 +1000 Subject: [PATCH 079/308] Fix scale highlighting during vertical zooming (#6761) Vertically zooming the piano roll caused highlighted semitones to drift from the actual note positions. This 2-line fix ensures the marked semitones are aligned with the grid lines and notes at all allowed vertical zoom levels. --- src/gui/editors/PianoRoll.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index adc1997b9..3ec008ecb 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -3355,11 +3355,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; } p.fillRect(m_whiteKeyWidth + 1, - y - m_keyLineHeight / 2, + y, width() - 10, m_keyLineHeight + 1, m_markedSemitoneColor); From 62a8c68736008e83e1be99c32e9c0748c74ec582 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Sun, 30 Jul 2023 23:42:53 -0400 Subject: [PATCH 080/308] Fix apple install script for zyn interface (#6782) * Fix apple install script for zyn interface * Add codesigning support to prevent crash --- cmake/apple/install_apple.sh.in | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) 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" From 57e7fdc5334f9089269296176f9184563bfcdef1 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Mon, 31 Jul 2023 12:38:35 +0800 Subject: [PATCH 081/308] MidiApple.cpp: fix getName to allow build with GCC (#6791) Fixes: https://github.com/LMMS/lmms/issues/6785 --- src/core/midi/MidiApple.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/midi/MidiApple.cpp b/src/core/midi/MidiApple.cpp index 01836c50b..4105f18f1 100644 --- a/src/core/midi/MidiApple.cpp +++ b/src/core/midi/MidiApple.cpp @@ -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; From 2ded48598f5db03461b09ee87b2514d24e6de1fe Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Thu, 3 Aug 2023 11:05:27 +0800 Subject: [PATCH 082/308] versioninfo.h: improve recognition of compiler and platforms (#6795) --- include/versioninfo.h | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) 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 From bc99728534c90fba25c5deedef1568dc5d9d6e62 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Wed, 2 Aug 2023 23:06:18 -0400 Subject: [PATCH 083/308] Consolidate and simplify CMAKE_POLICY entries (#6780) Simplify CMake Policies Per https://github.com/LMMS/lmms/pull/6758#discussion_r1271346366 --- CMakeLists.txt | 13 +------------ cmake/modules/DefineInstallVar.cmake | 2 +- cmake/modules/InstallDependencies.cmake | 4 ++-- plugins/CarlaBase/CMakeLists.txt | 8 -------- 4 files changed, 4 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c5de064a5..a68b788d6 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) 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/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 From 97c6ae1aa0eb0c7cd6c4b735f1cd667aa8a60510 Mon Sep 17 00:00:00 2001 From: Johannes Lorenz <1042576+JohannesLorenz@users.noreply.github.com> Date: Sat, 5 Aug 2023 22:20:23 +0200 Subject: [PATCH 084/308] Lv2: Improve control visualization (#6799) Previously, the Lv2 controls were checked for control types in this order: integer? enum? toggle? generic? This is bad because it goes from generic (integer) to specific (toggle), and then defaults to most generic. The order should be specific (toggle) to generic (integer, generic), which is fixed by this PR. This solves that controls which are marked "toggle" and "integer" were being displayed as a spinbox (#6798). Additional improvement: Only show search bar for more than 5 controls, previously more than 2 (#6798). --- src/core/lv2/Lv2Ports.cpp | 8 ++++---- src/gui/ControlLayout.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/lv2/Lv2Ports.cpp b/src/core/lv2/Lv2Ports.cpp index 1ce1d6956..2faee067d 100644 --- a/src/core/lv2/Lv2Ports.cpp +++ b/src/core/lv2/Lv2Ports.cpp @@ -114,12 +114,12 @@ 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; } 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(); } From 353221a02ca64e4809629cedfd56ddae4fe33229 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Sat, 5 Aug 2023 19:29:46 -0400 Subject: [PATCH 085/308] Allow Apple install step to fail CI (#6796) Fail CI if Apple install step fails --- cmake/install/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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() From dac1f773470123ee0d4f9708db165021f2e00a75 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Fri, 11 Aug 2023 17:55:26 +0200 Subject: [PATCH 086/308] Code review changes (#6548) Add a space after some while loops. Fix a typo in a comment. --- src/core/DataFile.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/DataFile.cpp b/src/core/DataFile.cpp index 2d28a3090..81bdc1fe2 100644 --- a/src/core/DataFile.cpp +++ b/src/core/DataFile.cpp @@ -1699,7 +1699,7 @@ static PatternAnalysisResult analyzeAutomationPattern(QDomElement const & automa // Iterate the objects. These contain the ids of the automated objects. QDomElement object = automationPattern.firstChildElement("object"); - while(!object.isNull()) + while (!object.isNull()) { unsigned int const id = object.attribute("id").toUInt(); @@ -1788,7 +1788,7 @@ static void fixInstrumentBaseNoteAndCollectIds(QDomElement & instrument, std::se static void fixAutomationPattern(QDomElement & automationPattern) { QDomElement time = automationPattern.firstChildElement("time"); - while(!time.isNull()) + while (!time.isNull()) { // Automation patterns can automate base notes as floats // so we read and correct them as floats here. @@ -1823,7 +1823,7 @@ static void fixTrack(QDomElement & track, std::set & automatedBase Track::TrackTypes const trackType = static_cast(track.attribute("type").toInt()); - // BB tracks need special handling because they container a track container of their own + // BB tracks need special handling because they contain a track container of their own if (trackType == Track::PatternTrack) { // Assuming that a BB track cannot contain another BB track here... @@ -1948,7 +1948,7 @@ static void fixAutomationTracks(QDomElement & song, std::set const { // The pattern itself is mixed. Remove the base note objects. QDomElement object = automationPattern.firstChildElement("object"); - while(!object.isNull()) + while (!object.isNull()) { unsigned int const id = object.attribute("id").toUInt(); @@ -1978,7 +1978,7 @@ static void fixAutomationTracks(QDomElement & song, std::set const { // This pattern has base note automations. Remove all other ones and fix the pattern. QDomElement object = automationPattern.firstChildElement("object"); - while(!object.isNull()) + while (!object.isNull()) { unsigned int const id = object.attribute("id").toUInt(); From 5335f6d8c6274f02957d8d7b4a0f7a8f1ebc6055 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Fri, 11 Aug 2023 18:33:35 +0200 Subject: [PATCH 087/308] Separate class for extended note range upgrade (#6548) Extract the code that upgrades the extended note range into its own class. This hides the helper functions that are related to the upgrade from the other upgrade methods in DataFile.cpp. The header file is put into the src/core directory as it is not part of the public interface and therefore should not be included in the "global" include directory. The whole thing is just an implementation detail of the upgrade in DataFile.cpp. --- src/core/CMakeLists.txt | 2 + src/core/DataFile.cpp | 391 +---------------------- src/core/UpgradeExtendedNoteRange.cpp | 431 ++++++++++++++++++++++++++ src/core/UpgradeExtendedNoteRange.h | 47 +++ 4 files changed, 483 insertions(+), 388 deletions(-) create mode 100644 src/core/UpgradeExtendedNoteRange.cpp create mode 100644 src/core/UpgradeExtendedNoteRange.h 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/DataFile.cpp b/src/core/DataFile.cpp index 81bdc1fe2..2361b1926 100644 --- a/src/core/DataFile.cpp +++ b/src/core/DataFile.cpp @@ -28,8 +28,6 @@ #include #include -#include -#include #include #include @@ -49,6 +47,7 @@ #include "TextFloat.h" #include "Track.h" #include "PathUtil.h" +#include "UpgradeExtendedNoteRange.h" #include "lmmsversion.h" @@ -1671,344 +1670,6 @@ void DataFile::upgrade_automationNodes() } } -/** - * @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::TrackTypes 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::PatternTrack) - { - // 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(); - 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 (currentTrack.attribute("type").toInt() != Track::AutomationTrack) - { - 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); - } -} /** \brief Note range has been extended to match MIDI specification * @@ -2017,54 +1678,8 @@ static void fixAutomationTracks(QDomElement & song, std::set const */ void DataFile::upgrade_extendedNoteRange() { - QDomElement song = documentElement().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 (elementsByTagName("song").item(0).isNull()) - { - // 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); - } - } + auto root = documentElement(); + UpgradeExtendedNoteRange upgradeExtendedNoteRange(root); } diff --git a/src/core/UpgradeExtendedNoteRange.cpp b/src/core/UpgradeExtendedNoteRange.cpp new file mode 100644 index 000000000..aab47f6b1 --- /dev/null +++ b/src/core/UpgradeExtendedNoteRange.cpp @@ -0,0 +1,431 @@ +/* + * 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 + +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::TrackTypes 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::PatternTrack) + { + // 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(); + 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 (currentTrack.attribute("type").toInt() != Track::AutomationTrack) + { + 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); + } + } +} + +} diff --git a/src/core/UpgradeExtendedNoteRange.h b/src/core/UpgradeExtendedNoteRange.h new file mode 100644 index 000000000..66f95419a --- /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; +}; + +} + +#endif // LMMS_UPGRADEEXTENDEDNOTERANGE_H From 5a6799314abf4cca8e8280eefef0f5ca5ca854fc Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Fri, 11 Aug 2023 18:44:13 +0200 Subject: [PATCH 088/308] Fix builds (#6548) Add the comment "// namespace lmms" to the closing scope of the lmms namespaces. The "scripted-checks" are quite strict. Perhaps they should be renamed to "strict-checks". ;) Include "cassert" in UpgradeExtendedNoteRange.cpp to hopefully fix the mingw builds. --- src/core/UpgradeExtendedNoteRange.cpp | 4 +++- src/core/UpgradeExtendedNoteRange.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/UpgradeExtendedNoteRange.cpp b/src/core/UpgradeExtendedNoteRange.cpp index aab47f6b1..41cbc5c26 100644 --- a/src/core/UpgradeExtendedNoteRange.cpp +++ b/src/core/UpgradeExtendedNoteRange.cpp @@ -27,6 +27,8 @@ #include #include +#include + namespace lmms { @@ -428,4 +430,4 @@ void UpgradeExtendedNoteRange::upgrade() } } -} +} // namespace lmms diff --git a/src/core/UpgradeExtendedNoteRange.h b/src/core/UpgradeExtendedNoteRange.h index 66f95419a..ae444e82a 100644 --- a/src/core/UpgradeExtendedNoteRange.h +++ b/src/core/UpgradeExtendedNoteRange.h @@ -42,6 +42,6 @@ private: QDomElement & m_domElement; }; -} +} // namespace lmms #endif // LMMS_UPGRADEEXTENDEDNOTERANGE_H From e87d44b42ca3a29bbc0ade8313deb6271cd5e166 Mon Sep 17 00:00:00 2001 From: IanCaio Date: Sat, 12 Aug 2023 11:54:26 -0300 Subject: [PATCH 089/308] Fixes bug from issue #6002 (#6803) * Fixes bug from issue 6002 Since the refactoring of the Copy/Paste features, it was not possible to paste inside the BBEditor (now Pattern Editor), as reported on issue #6002. The reason for that is better explained in the issue discussion. This PR fixes this by allowing pasting inside the Pattern Editor when the clipboard has a single Clip, which is what was allowed on the previous workflow, while at the same time avoiding the unexpected behavior of pasting multiple Clips that might invade the positions reserved for different Pattern Tracks. --- src/gui/tracks/TrackContentWidget.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/gui/tracks/TrackContentWidget.cpp b/src/gui/tracks/TrackContentWidget.cpp index 74ab016ea..26107c1ae 100644 --- a/src/gui/tracks/TrackContentWidget.cpp +++ b/src/gui/tracks/TrackContentWidget.cpp @@ -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(t->type()))) { return false; } @@ -360,6 +359,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++ ) { From 98c5e6af5d0241f458d6d6f5545ad76ca8b36485 Mon Sep 17 00:00:00 2001 From: consolegrl <5942029+consolegrl@users.noreply.github.com> Date: Fri, 18 Aug 2023 10:26:06 -0400 Subject: [PATCH 090/308] fix: Issue 6807: Marked notes bleed into note... (#6812) Issue was caused by an obiwan (off-by-one) The 'if (y > limit)' test was broken by an incorrect inequality, should be >=, and a graphical adjustment made previously in the 'y = ...' statement. I perserved the graphical adjustment and fixed the test to be 'if (y >= limit - 1) { break; }' --- src/gui/editors/PianoRoll.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 3ec008ecb..337b36b36 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -3357,7 +3357,7 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) const int key_num = m_markedSemiTones.at(x); 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, width() - 10, From b62a272d01dab2af66acdcf15c8ea77405e61f8e Mon Sep 17 00:00:00 2001 From: Dalton Messmer <33463986+messmerd@users.noreply.github.com> Date: Sat, 19 Aug 2023 02:47:26 -0400 Subject: [PATCH 091/308] Fix segfault when clicking "Auto Detect" in Connection Settings window (#6811) --- src/gui/modals/ControllerConnectionDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/modals/ControllerConnectionDialog.cpp b/src/gui/modals/ControllerConnectionDialog.cpp index 06f6a5708..6396c7ccb 100644 --- a/src/gui/modals/ControllerConnectionDialog.cpp +++ b/src/gui/modals/ControllerConnectionDialog.cpp @@ -406,7 +406,7 @@ void ControllerConnectionDialog::userSelected() void ControllerConnectionDialog::autoDetectToggled() { - if( m_midiAutoDetect.value() ) + if (m_midiAutoDetect.value() && m_midiController) { m_midiController->reset(); } From 793f096c4f6c01c9f48328530fe05320892835d1 Mon Sep 17 00:00:00 2001 From: Bimal Poudel Date: Sun, 20 Aug 2023 00:52:23 -0600 Subject: [PATCH 092/308] Update DummyCarla.cpp to use CARLA_PLUGIN_EXPORT (#6814) --- plugins/CarlaBase/DummyCarla.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) 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; } From 5cbf2c5287d62b018927f58d88b54c4462f551fb Mon Sep 17 00:00:00 2001 From: Dalton Messmer <33463986+messmerd@users.noreply.github.com> Date: Mon, 21 Aug 2023 23:07:09 -0400 Subject: [PATCH 093/308] Fix LMMS plugin issues (#6670) * Fix Organic automated harmonic parameter loading * Fix Kicker automated end distortion parameter loading * Fix AudioFileProcessor automated interpolation parameter loading * Fix Vibed automated volume parameter loading * Improve coding style/formatting * Fix #6671 * Fix Vibed memory leaks * Refactor Vibed instrument * Fix build * Try to fix build again * Revert previous commit * Replace more raw pointers with smart pointers * Remove unused files * Minor changes * Update plugins/Vibed/Vibed.cpp Co-authored-by: Kevin Zander * Implement suggestions from review * Minor changes * Only check plugin data pointer * Refactor NineButtonSelector * Fix memory leaks during heavy tempo automation * Fix build * Use s_stringCount * Replace some vectors with arrays * Use array instead of switch * Allow compiler to generate move assignment operator * Fix loading of old automated detune values * Fix member variable names * Address review comments --------- Co-authored-by: Kevin Zander --- .../AudioFileProcessor/AudioFileProcessor.cpp | 87 +- .../AudioFileProcessor/AudioFileProcessor.h | 12 +- plugins/BitInvader/BitInvader.cpp | 3 +- plugins/FreeBoy/FreeBoy.cpp | 2 +- plugins/GigPlayer/GigPlayer.cpp | 4 +- plugins/Kicker/Kicker.cpp | 84 +- plugins/Kicker/Kicker.h | 11 +- plugins/Lb302/Lb302.cpp | 2 +- plugins/Monstro/Monstro.cpp | 2 +- plugins/Nes/Nes.cpp | 2 +- plugins/Organic/Organic.cpp | 76 +- plugins/Organic/Organic.h | 11 +- plugins/Patman/Patman.cpp | 2 +- plugins/Sf2Player/Sf2Player.cpp | 4 +- plugins/Sfxr/Sfxr.cpp | 6 +- plugins/Sid/SidInstrument.cpp | 4 +- plugins/Stk/Mallets/Mallets.cpp | 2 +- plugins/TripleOscillator/TripleOscillator.cpp | 2 +- plugins/Vibed/CMakeLists.txt | 5 +- plugins/Vibed/NineButtonSelector.cpp | 234 +----- plugins/Vibed/NineButtonSelector.h | 89 +- plugins/Vibed/StringContainer.cpp | 108 --- plugins/Vibed/StringContainer.h | 86 -- plugins/Vibed/Vibed.cpp | 794 +++++++----------- plugins/Vibed/Vibed.h | 121 +-- plugins/Vibed/VibratingString.cpp | 150 ++-- plugins/Vibed/VibratingString.h | 299 +++---- plugins/Watsyn/Watsyn.cpp | 2 +- plugins/Xpressive/Xpressive.cpp | 2 +- 29 files changed, 781 insertions(+), 1425 deletions(-) delete mode 100644 plugins/Vibed/StringContainer.cpp delete mode 100644 plugins/Vibed/StringContainer.h diff --git a/plugins/AudioFileProcessor/AudioFileProcessor.cpp b/plugins/AudioFileProcessor/AudioFileProcessor.cpp index 2e2d7163b..2243683ce 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 { @@ -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(); @@ -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(); } diff --git a/plugins/AudioFileProcessor/AudioFileProcessor.h b/plugins/AudioFileProcessor/AudioFileProcessor.h index b80954577..6c696784a 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; @@ -303,4 +301,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_AUDIO_FILE_PROCESSOR_H diff --git a/plugins/BitInvader/BitInvader.cpp b/plugins/BitInvader/BitInvader.cpp index 947c6f5d6..d89383560 100644 --- a/plugins/BitInvader/BitInvader.cpp +++ b/plugins/BitInvader/BitInvader.cpp @@ -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() ) { diff --git a/plugins/FreeBoy/FreeBoy.cpp b/plugins/FreeBoy/FreeBoy.cpp index 1fd3f2513..c26cd79c4 100644 --- a/plugins/FreeBoy/FreeBoy.cpp +++ b/plugins/FreeBoy/FreeBoy.cpp @@ -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); diff --git a/plugins/GigPlayer/GigPlayer.cpp b/plugins/GigPlayer/GigPlayer.cpp index 24073ceea..42d64cf07 100644 --- a/plugins/GigPlayer/GigPlayer.cpp +++ b/plugins/GigPlayer/GigPlayer.cpp @@ -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; diff --git a/plugins/Kicker/Kicker.cpp b/plugins/Kicker/Kicker.cpp index 7d4c6fbb0..29f7dc8f1 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" @@ -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(), diff --git a/plugins/Kicker/Kicker.h b/plugins/Kicker/Kicker.h index 22413c4db..cef732adb 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,8 +59,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; QString nodeName() const override; @@ -135,4 +134,4 @@ private: } // namespace lmms -#endif +#endif // LMMS_KICKER_H diff --git a/plugins/Lb302/Lb302.cpp b/plugins/Lb302/Lb302.cpp index 140b84189..c0e477dcc 100644 --- a/plugins/Lb302/Lb302.cpp +++ b/plugins/Lb302/Lb302.cpp @@ -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; diff --git a/plugins/Monstro/Monstro.cpp b/plugins/Monstro/Monstro.cpp index 3a9737fdb..10dbf5b1f 100644 --- a/plugins/Monstro/Monstro.cpp +++ b/plugins/Monstro/Monstro.cpp @@ -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/Nes/Nes.cpp b/plugins/Nes/Nes.cpp index d47ebd728..4260bca1a 100644 --- a/plugins/Nes/Nes.cpp +++ b/plugins/Nes/Nes.cpp @@ -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/Organic/Organic.cpp b/plugins/Organic/Organic.cpp index 6c2cde773..476b24961 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 @@ -159,61 +155,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 +225,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{}; 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..7bcd46dcb 100644 --- a/plugins/Patman/Patman.cpp +++ b/plugins/Patman/Patman.cpp @@ -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 ); } diff --git a/plugins/Sf2Player/Sf2Player.cpp b/plugins/Sf2Player/Sf2Player.cpp index ab3729f7d..ef4f884ca 100644 --- a/plugins/Sf2Player/Sf2Player.cpp +++ b/plugins/Sf2Player/Sf2Player.cpp @@ -663,8 +663,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 +673,7 @@ void Sf2Instrument::playNote( NotePlayHandle * _n, sampleFrame * ) return; } - if (tfp == 0) + if (!_n->m_pluginData) { const int baseVelocity = instrumentTrack()->midiPort()->baseVelocity(); diff --git a/plugins/Sfxr/Sfxr.cpp b/plugins/Sfxr/Sfxr.cpp index d97217446..33f588521 100644 --- a/plugins/Sfxr/Sfxr.cpp +++ b/plugins/Sfxr/Sfxr.cpp @@ -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 ); } diff --git a/plugins/Sid/SidInstrument.cpp b/plugins/Sid/SidInstrument.cpp index 6e7473492..3b41d8972 100644 --- a/plugins/Sid/SidInstrument.cpp +++ b/plugins/Sid/SidInstrument.cpp @@ -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 ); diff --git a/plugins/Stk/Mallets/Mallets.cpp b/plugins/Stk/Mallets/Mallets.cpp index 8aa71d62e..be144e764 100644 --- a/plugins/Stk/Mallets/Mallets.cpp +++ b/plugins/Stk/Mallets/Mallets.cpp @@ -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 = diff --git a/plugins/TripleOscillator/TripleOscillator.cpp b/plugins/TripleOscillator/TripleOscillator.cpp index 25baea208..c66247541 100644 --- a/plugins/TripleOscillator/TripleOscillator.cpp +++ b/plugins/TripleOscillator/TripleOscillator.cpp @@ -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{}; 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..014ab1429 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, + 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(knobBright_26, this), + m_stiffnessKnob(knobBright_26, this), + m_pickKnob(knobBright_26, this), + m_pickupKnob(knobBright_26, this), + m_panKnob(knobBright_26, this), + m_detuneKnob(knobBright_26, this), + m_randomKnob(knobBright_26, this), + m_lengthKnob(knobBright_26, 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..308ae64d5 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 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/Watsyn/Watsyn.cpp b/plugins/Watsyn/Watsyn.cpp index 9ceaaddb8..7916eb45f 100644 --- a/plugins/Watsyn/Watsyn.cpp +++ b/plugins/Watsyn/Watsyn.cpp @@ -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); diff --git a/plugins/Xpressive/Xpressive.cpp b/plugins/Xpressive/Xpressive.cpp index 18ac8c052..3cc5564e6 100644 --- a/plugins/Xpressive/Xpressive.cpp +++ b/plugins/Xpressive/Xpressive.cpp @@ -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 From 2ca05d025cba536b5fc42ecf0ada9661ed8891f5 Mon Sep 17 00:00:00 2001 From: saker Date: Mon, 21 Aug 2023 23:08:18 -0400 Subject: [PATCH 094/308] Bump mingw-std-threads submodule (#6817) * Bump submodule and generate std headers * Commit submodule update * Downgrade to earlier commit Can be upgraded once a proper C++20 MinGW compiler is available for the docker images. * Downgrade to the correct commit * Append mingw_stdthreads to EXTRA_LIBRARIES Currently for this CMake version, it seems that there is no support to link other targets to object libraries. I'll add it to EXTRA_LIBRARIES instead. * Add LMMS_ prefix to USE_MINGW_STD_THREADS * Use built-in MINGW CMake variable * Use lowercase rather than uppercase --- src/3rdparty/CMakeLists.txt | 6 ++++++ src/3rdparty/mingw-std-threads | 2 +- src/CMakeLists.txt | 4 ++++ 3 files changed, 11 insertions(+), 1 deletion(-) 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 23923f616..f483d8b41 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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} From 9a0add49fb61f1bbac603e7e181221b7cef81c1b Mon Sep 17 00:00:00 2001 From: saker Date: Mon, 21 Aug 2023 23:08:56 -0400 Subject: [PATCH 095/308] Core Refactor: Replace ``QVector`` with ``std::vector`` (#6477) * Replace QVector with std::vector in AudioEngine * Replace QVector with std::vector in AudioEngineWorkerThread * Replace QVector with std::vector in AudioJack * Replace QVector with std::vector in AutomatableModel * Replace QVector with std::vector in AutomationClip * Replace QVector with std::vector in AutomationEditor * Replace QVector with std::vector in ConfigManager * Replace QVector with std::vector in Controller * Replace QVector with std::vector in ControllerConnection * Replace QVector with std::vector in EffectChain * Replace QVector with std::vector in EnvelopeAndLfoParameters * Replace QVector with std::vector in InstrumentFunctions * Replace QVector with std::vector in MidiClient * Replace QVector with std::vector in Mixer * Replace QVector with std::vector in Note * Replace QVector with std::vector in PeakController * Replace QVector with std::vector in PianoRoll * Replace QVector with std::vector in PluginFactory * Replace QVector with std::vector in RenderManager * Replace QVector with std::vector in StepRecorder * Replace QVector with std::vector in Track * Replace QVector with std::vector in TrackContainer * Replace QVector with std::vector in Song * Adapt QVector to std::vector changes in ControllerConnectionDialog * Phase 2: Use std::abs in panning.h Without this, the QVector changes will make the code not compile. * Phase 2: Replace QVector with std::vector in PeakControllerEffect * Phase 2: Replace QVector with std::vector in AutomatableModel * Phase 2: Replace QVector with std::vector in AutomationClip * Phase 2: Replace QVector with std::vector in ControllerConnection * Phase 2: Replace QVector with std::vector in EffectChain * Phase 2: Replace QVector with std::vector in Mixer * Phase 2: Replace QVector with std::vector in PeakController * Phase 2: Replace QVector with std::vector in RenderManager * Phase 2: Replace QVector with std::vector in Song * Phase 2: Replace QVector with std::vector in StepRecorder * Phase 2: Replace QVector with std::vector in Track * Phase 2: Replace QVector with std::vector in TrackContainer * Phase 2: Adapt QVector changes in EffectRackView * Phase 2: Adapt QVector changes in AutomationClipView * Phase 2: Adapt QVector changes in ClipView * Phase 2: Adapt QVector changes in AutomationEditor * Phase 2: Adapt QVector changes in PianoRoll * Phase 2: Adapt QVector changes in TrackContainerView * Phase 2: Adapt QVector changes in TrackContentWidget * Phase 2: Adapt QVector changes in InstrumentTrack * Phase 2: Adapt QVector changes in MidiClip * Phase 2: Adapt QVector changes in SampleTrack * Fix segmentation fault in ConfigManager::value * Fix unintended faulty std::vector insert in AutomationClip::resolveAllIDs * Resolve trailing whitespace in src/core/StepRecorder.cpp Co-authored-by: Hyunjin Song * Use std::next and std::prev in EffectChain::moveUp/moveDown * Introduce static "combineAllTracks" function in AutomationClip * Adjust variable name in Song::automatedValuesAt * Adjust removal of long step notes in StepRecorder::removeNotesReleasedForTooLong * Iterate over m_chords by const reference in src/core/InstrumentFunctions.cpp Co-authored-by: Hyunjin Song * Fix StepRecorder::removeNotesReleasedForTooLong again * Combine the ConfigManager::value overloads using std::optional * Revise StepRecorder::removeNotesReleasedForTooLong * Remove redundant std::optional in ConfigManager::value * Remove trailing whitespace in ConfigManager::value * Fix: Prevent incorrect use of std::distance when element not found * Chore: Remove trailing whitespace in edited files * Only set the id attribute if the controller was found Co-authored-by: Hyunjin Song * Remove extra indents from 84b8fe8a559855ed263b74cc582eab3655250c5f * Fix compilation issues * Add LMMS_ prefix for header guard in Track.h * Undo changes made to MixerView::deleteUnusedChannels * Simplify code to handle failure of finding tracks Co-authored-by: Hyunjin Song * Split ternary operator into separate if statement Co-authored-by: Hyunjin Song * Undo changes to indentation in MixerRoute * Do general clean-up Some of the changes made: + Use auto where benefical + Fix bug in AutomatableModel::globalAutomationValueAt (for loop should be looping over clips variable, not clipsInRange) + Undo out of focus whitespace changes * Always assign to m_steps regardless if clip is found or not Even when the clip is not found (i.e., currentClip is -1), m_steps still gets assigned to. * Insert at the end of tracks vector in src/core/Mixer.cpp Co-authored-by: Dominic Clark * Insert at the end of tracks vector in src/core/Mixer.cpp (2) Co-authored-by: Dominic Clark * Remove redundant template parameter * Use std::array for zoomLevels --------- Co-authored-by: Hyunjin Song Co-authored-by: Dominic Clark --- include/AudioEngine.h | 6 +- include/AudioEngineWorkerThread.h | 4 +- include/AudioJack.h | 4 +- include/AutomatableModel.h | 2 +- include/AutomationClip.h | 15 ++++- include/AutomationEditor.h | 3 +- include/ConfigManager.h | 11 ++-- include/Controller.h | 2 +- include/ControllerConnection.h | 5 +- include/EffectChain.h | 2 +- include/EnvelopeAndLfoParameters.h | 2 +- include/InstrumentFunctions.h | 8 ++- include/MidiClient.h | 4 +- include/Mixer.h | 4 +- include/Note.h | 4 +- include/PeakController.h | 2 +- include/PianoRoll.h | 9 +-- include/PluginFactory.h | 4 +- include/RenderManager.h | 4 +- include/StepRecorder.h | 4 +- include/Track.h | 5 +- include/TrackContainer.h | 2 +- include/panning.h | 4 +- .../PeakControllerEffect.cpp | 10 +-- src/core/AudioEngine.cpp | 4 +- src/core/AutomatableModel.cpp | 24 +++---- src/core/AutomationClip.cpp | 62 ++++++++++--------- src/core/ConfigManager.cpp | 18 +----- src/core/Controller.cpp | 12 ++-- src/core/ControllerConnection.cpp | 17 +++-- src/core/EffectChain.cpp | 24 +++---- src/core/InstrumentFunctions.cpp | 30 ++++----- src/core/Mixer.cpp | 60 +++++++++++------- src/core/PeakController.cpp | 23 +++---- src/core/RenderManager.cpp | 4 +- src/core/Song.cpp | 18 +++--- src/core/StepRecorder.cpp | 30 +++++---- src/core/Track.cpp | 8 +-- src/core/TrackContainer.cpp | 14 ++--- src/core/midi/MidiClient.cpp | 3 +- src/gui/clips/AutomationClipView.cpp | 4 +- src/gui/clips/ClipView.cpp | 9 ++- src/gui/editors/AutomationEditor.cpp | 2 +- src/gui/editors/PianoRoll.cpp | 39 ++++++------ src/gui/editors/TrackContainerView.cpp | 4 +- src/gui/modals/ControllerConnectionDialog.cpp | 6 +- src/gui/tracks/TrackContentWidget.cpp | 6 +- src/tracks/InstrumentTrack.cpp | 2 +- src/tracks/MidiClip.cpp | 44 ++++++------- 49 files changed, 314 insertions(+), 273 deletions(-) diff --git a/include/AudioEngine.h b/include/AudioEngine.h index d0f269d87..dec8f2592 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" @@ -416,7 +416,7 @@ private: bool m_renderOnly; - QVector m_audioPorts; + std::vector m_audioPorts; fpp_t m_framesPerPeriod; @@ -430,7 +430,7 @@ private: surroundSampleFrame * m_outputBufferWrite; // worker thread stuff - QVector m_workers; + std::vector m_workers; int m_numWorkers; // playhandle stuff diff --git a/include/AudioEngineWorkerThread.h b/include/AudioEngineWorkerThread.h index 112930808..16de6ff6f 100644 --- a/include/AudioEngineWorkerThread.h +++ b/include/AudioEngineWorkerThread.h @@ -100,9 +100,9 @@ public: JobQueue::OperationMode _opMode = JobQueue::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..2b93a514c 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -78,7 +78,7 @@ class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject Q_OBJECT MM_OPERATORS public: - using AutoModelVector = QVector; + using AutoModelVector = std::vector; enum ScaleType { diff --git a/include/AutomationClip.h b/include/AutomationClip.h index 10c714c3d..fc6a26d0e 100644 --- a/include/AutomationClip.h +++ b/include/AutomationClip.h @@ -62,7 +62,7 @@ public: } ; using timeMap = QMap; - using objectVector = QVector>; + using objectVector = std::vector>; using TimemapIterator = timeMap::const_iterator; @@ -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,7 +208,7 @@ 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. diff --git a/include/AutomationEditor.h b/include/AutomationEditor.h index c2ab98092..a1c4d694f 100644 --- a/include/AutomationEditor.h +++ b/include/AutomationEditor.h @@ -27,6 +27,7 @@ #define LMMS_GUI_AUTOMATION_EDITOR_H #include +#include #include "Editor.h" @@ -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; 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..b176b1f74 100644 --- a/include/Controller.h +++ b/include/Controller.h @@ -45,7 +45,7 @@ class ControllerDialog; } // namespace gui -using ControllerVector = QVector; +using ControllerVector = std::vector; class LMMS_EXPORT Controller : public Model, public JournallingObject { 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/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..02abd07e3 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" diff --git a/include/InstrumentFunctions.h b/include/InstrumentFunctions.h index f62b74e9a..61d625d83 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; + } }; 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/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..dd261b3af 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" @@ -249,7 +249,7 @@ private: DetuningHelper * m_detuning; }; -using NoteVector = QVector; +using NoteVector = std::vector; struct NoteBounds { 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/PianoRoll.h b/include/PianoRoll.h index 6100792d5..03b93d816 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" @@ -291,7 +292,7 @@ private: 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; @@ -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; diff --git a/include/PluginFactory.h b/include/PluginFactory.h index 001ea190a..10c76e4ee 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" @@ -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/RenderManager.h b/include/RenderManager.h index 5240e96a8..43f696f14 100644 --- a/include/RenderManager.h +++ b/include/RenderManager.h @@ -78,8 +78,8 @@ private: std::unique_ptr m_activeRenderer; - QVector m_tracksToRender; - QVector m_unmuted; + std::vector m_tracksToRender; + std::vector m_unmuted; } ; 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/Track.h b/include/Track.h index ff3c1ae00..000d564f7 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,7 +70,7 @@ 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 { diff --git a/include/TrackContainer.h b/include/TrackContainer.h index f99273ba2..8739a9e9f 100644 --- a/include/TrackContainer.h +++ b/include/TrackContainer.h @@ -49,7 +49,7 @@ class LMMS_EXPORT TrackContainer : public Model, public JournallingObject { Q_OBJECT public: - using TrackList = QVector; + using TrackList = std::vector; enum TrackContainerTypes { PatternContainer, 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/plugins/PeakControllerEffect/PeakControllerEffect.cpp b/plugins/PeakControllerEffect/PeakControllerEffect.cpp index d32a22320..bd99631b7 100644 --- a/plugins/PeakControllerEffect/PeakControllerEffect.cpp +++ b/plugins/PeakControllerEffect/PeakControllerEffect.cpp @@ -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/src/core/AudioEngine.cpp b/src/core/AudioEngine.cpp index a91e88f38..91a16ed12 100644 --- a/src/core/AudioEngine.cpp +++ b/src/core/AudioEngine.cpp @@ -419,7 +419,7 @@ const surroundSampleFrame * AudioEngine::renderNextBuffer() } // STAGE 2: process effects of all instrument- and sampletracks - AudioEngineWorkerThread::fillJobQueue >( m_audioPorts ); + AudioEngineWorkerThread::fillJobQueue(m_audioPorts); AudioEngineWorkerThread::startAndWaitForJobs(); @@ -663,7 +663,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); diff --git a/src/core/AutomatableModel.cpp b/src/core/AutomatableModel.cpp index 378ccd91e..fa4697c69 100644 --- a/src/core/AutomatableModel.cpp +++ b/src/core/AutomatableModel.cpp @@ -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 ); } @@ -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; @@ -588,7 +590,7 @@ float AutomatableModel::controllerValue( int frameOffset ) const return v; } - AutomatableModel* lm = m_linkedModels.first(); + AutomatableModel* lm = m_linkedModels.front(); if (lm->controllerConnection() && lm->useControllerValue()) { return fittedValue( lm->controllerValue( frameOffset ) ); @@ -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 diff --git a/src/core/AutomationClip.cpp b/src/core/AutomationClip.cpp index c031c5a41..7a161c355 100644 --- a/src/core/AutomationClip.cpp +++ b/src/core/AutomationClip.cpp @@ -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)), @@ -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; } @@ -380,11 +380,11 @@ void AutomationClip::removeNodes(const int tick0, const int 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) @@ -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,12 +888,8 @@ 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) { @@ -921,16 +917,13 @@ 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 ) @@ -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,9 +982,7 @@ 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) @@ -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 ) @@ -1173,4 +1163,18 @@ void AutomationClip::generateTangents(timeMap::iterator it, int numToGenerate) } } +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/ConfigManager.cpp b/src/core/ConfigManager.cpp index bfe9e31f1..c647a27e6 100644 --- a/src/core/ConfigManager.cpp +++ b/src/core/ConfigManager.cpp @@ -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; } diff --git a/src/core/Controller.cpp b/src/core/Controller.cpp index aee6481cc..e7031f20c 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,7 +40,7 @@ namespace lmms long Controller::s_periods = 0; -QVector Controller::s_controllers; +std::vector Controller::s_controllers; @@ -55,7 +55,7 @@ Controller::Controller( ControllerTypes _type, Model * _parent, { if( _type != DummyController && _type != MidiController ) { - 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(); diff --git a/src/core/ControllerConnection.cpp b/src/core/ControllerConnection.cpp index c65cd8ae9..a4477c563 100644 --- a/src/core/ControllerConnection.cpp +++ b/src/core/ControllerConnection.cpp @@ -53,7 +53,7 @@ ControllerConnection::ControllerConnection(Controller * _controller) : m_controller = Controller::create( Controller::DummyController, nullptr ); } - s_connections.append( this ); + s_connections.push_back(this); } @@ -64,7 +64,7 @@ ControllerConnection::ControllerConnection( int _controllerId ) : m_controllerId( _controllerId ), m_ownsController( false ) { - s_connections.append( this ); + s_connections.push_back(this); } @@ -76,7 +76,10 @@ ControllerConnection::~ControllerConnection() { 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; @@ -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); } } } diff --git a/src/core/EffectChain.cpp b/src/core/EffectChain.cpp index 024ddab64..b07a7227b 100644 --- a/src/core/EffectChain.cpp +++ b/src/core/EffectChain.cpp @@ -56,7 +56,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 +121,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 +136,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 +146,7 @@ void EffectChain::removeEffect( Effect * _effect ) Engine::audioEngine()->doneChangeInModel(); - if( m_effects.isEmpty() ) + if (m_effects.empty()) { m_enabledModel.setValue( false ); } @@ -159,10 +159,10 @@ 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); + std::swap(*std::next(it), *it); } } @@ -171,10 +171,10 @@ 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); + std::swap(*std::prev(it), *it); } } @@ -228,9 +228,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/InstrumentFunctions.cpp b/src/core/InstrumentFunctions.cpp index 06e56666c..d2fea9dbd 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()); } } @@ -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 ) @@ -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" ) ); @@ -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(); @@ -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 || diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index b2a9f9e3f..dba5c334e 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -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,8 +293,11 @@ 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 ) { @@ -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 ) @@ -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(); } @@ -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,15 +848,18 @@ 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) { diff --git a/src/core/PeakController.cpp b/src/core/PeakController.cpp index a9215325e..af0e7e69d 100644 --- a/src/core/PeakController.cpp +++ b/src/core/PeakController.cpp @@ -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/RenderManager.cpp b/src/core/RenderManager.cpp index 56b4ce9d7..8c031b970 100644 --- a/src/core/RenderManager.cpp +++ b/src/core/RenderManager.cpp @@ -69,7 +69,7 @@ void RenderManager::renderNextTrack() { m_activeRenderer.reset(); - if( m_tracksToRender.isEmpty() ) + if (m_tracksToRender.empty()) { // nothing left to render restoreMutedState(); @@ -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/Song.cpp b/src/core/Song.cpp index fef66f193..6f4c5212e 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -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); } @@ -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::DummyController, 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/Track.cpp b/src/core/Track.cpp index 084f302f8..33b9c8ef3 100644 --- a/src/core/Track.cpp +++ b/src/core/Track.cpp @@ -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 ); @@ -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(); } } diff --git a/src/core/TrackContainer.cpp b/src/core/TrackContainer.cpp index 0347773ed..33c695f48 100644 --- a/src/core/TrackContainer.cpp +++ b/src/core/TrackContainer.cpp @@ -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; } @@ -275,7 +275,7 @@ AutomatedValueMap TrackContainer::automatedValuesFromTracks(const TrackList &tra track->getClipsInRange(clips, 0, time); } else { Q_ASSERT(track->numOfClips() > clipNum); - clips << track->getClip(clipNum); + clips.push_back(track->getClip(clipNum)); } default: break; 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/gui/clips/AutomationClipView.cpp b/src/gui/clips/AutomationClipView.cpp index 6fa91efdb..a5d415a2e 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) diff --git a/src/gui/clips/ClipView.cpp b/src/gui/clips/ClipView.cpp index 8c4f704bc..871466a55 100644 --- a/src/gui/clips/ClipView.cpp +++ b/src/gui/clips/ClipView.cpp @@ -545,7 +545,7 @@ DataFile ClipView::createClipDataFiles( { // 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)); QDomElement clipElement = dataFile.createElement("clip"); clipElement.setAttribute( "trackIndex", trackIndex ); clipElement.setAttribute( "trackType", clipTrack->type() ); @@ -557,12 +557,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 ); diff --git a/src/gui/editors/AutomationEditor.cpp b/src/gui/editors/AutomationEditor.cpp index db56557a4..1289c5626 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 }; diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 337b36b36..753dfe77f 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -148,15 +148,14 @@ std::array PianoRoll::prKeyOrder 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(), @@ -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() ) { @@ -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 { @@ -1241,11 +1240,11 @@ void PianoRoll::shiftPos(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; } @@ -1645,7 +1644,7 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) if (note) { - n.append(note); + n.push_back(note); updateKnifePos(me); @@ -1723,7 +1722,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 ) @@ -1846,9 +1845,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 @@ -2036,7 +2035,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 +2053,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() ) @@ -2517,7 +2516,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; @@ -2579,7 +2578,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 ) @@ -2656,7 +2655,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() ) @@ -3789,7 +3788,7 @@ 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 ) diff --git a/src/gui/editors/TrackContainerView.cpp b/src/gui/editors/TrackContainerView.cpp index 38a6a36d5..83017fb1a 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(); diff --git a/src/gui/modals/ControllerConnectionDialog.cpp b/src/gui/modals/ControllerConnectionDialog.cpp index 6396c7ccb..55c0b476f 100644 --- a/src/gui/modals/ControllerConnectionDialog.cpp +++ b/src/gui/modals/ControllerConnectionDialog.cpp @@ -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(it, controllers.begin()); m_userGroupBox->model()->setValue( true ); m_userController->model()->setValue( idx ); } diff --git a/src/gui/tracks/TrackContentWidget.cpp b/src/gui/tracks/TrackContentWidget.cpp index 26107c1ae..ca7123bda 100644 --- a/src/gui/tracks/TrackContentWidget.cpp +++ b/src/gui/tracks/TrackContentWidget.cpp @@ -345,7 +345,8 @@ bool TrackContentWidget::canPasteSelection( TimePos clipPos, const QMimeData* md // Get the current track's index const TrackContainer::TrackList tracks = t->trackContainer()->tracks(); - const int currentTrackIndex = tracks.indexOf( t ); + 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(); @@ -443,7 +444,8 @@ bool TrackContentWidget::pasteSelection( TimePos clipPos, const QMimeData * md, // 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 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(); diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 7eb6bba11..1d2546288 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -739,7 +739,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..52a532028 100644 --- a/src/tracks/MidiClip.cpp +++ b/src/tracks/MidiClip.cpp @@ -115,11 +115,11 @@ void MidiClip::resizeToFirstTrack() { 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; } @@ -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(); @@ -354,15 +351,13 @@ 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(MelodyClip); return; } - ++it; } setType( BeatClip ); } @@ -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); } } @@ -477,9 +472,10 @@ MidiClip * MidiClip::nextMidiClip() const MidiClip * MidiClip::adjacentMidiClipByOffset(int offset) const { - QVector clips = m_instrumentTrack->getClips(); + std::vector 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]); } From da14de92fe6f7332206f1b0995f816b8fd54d9cf Mon Sep 17 00:00:00 2001 From: saker Date: Wed, 23 Aug 2023 16:52:35 -0400 Subject: [PATCH 096/308] Fix regressions in #6477 (#6826) * Fix if statement in ClipView * Move controllers.begin() to be the first argument It was the second argument, which means it could've returned negatives for random access iterators. --- src/gui/clips/ClipView.cpp | 2 +- src/gui/modals/ControllerConnectionDialog.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/clips/ClipView.cpp b/src/gui/clips/ClipView.cpp index 871466a55..8a190e2a7 100644 --- a/src/gui/clips/ClipView.cpp +++ b/src/gui/clips/ClipView.cpp @@ -559,7 +559,7 @@ DataFile ClipView::createClipDataFiles( // Add extra metadata needed for calculations later const auto initialTrackIt = std::find(tc->tracks().begin(), tc->tracks().end(), t); - if (initialTrackIt != tc->tracks().end()) + if (initialTrackIt == tc->tracks().end()) { printf("Failed to find selected track in the TrackContainer.\n"); return dataFile; diff --git a/src/gui/modals/ControllerConnectionDialog.cpp b/src/gui/modals/ControllerConnectionDialog.cpp index 55c0b476f..040ed9e0f 100644 --- a/src/gui/modals/ControllerConnectionDialog.cpp +++ b/src/gui/modals/ControllerConnectionDialog.cpp @@ -263,7 +263,7 @@ ControllerConnectionDialog::ControllerConnectionDialog( QWidget * _parent, if (it != controllers.end()) { - int idx = std::distance(it, controllers.begin()); + int idx = std::distance(controllers.begin(), it); m_userGroupBox->model()->setValue( true ); m_userController->model()->setValue( idx ); } From d6cf417a4d07c3f7c36bbfe881d5883c3a68aba0 Mon Sep 17 00:00:00 2001 From: superpaik <68785450+superpaik@users.noreply.github.com> Date: Thu, 24 Aug 2023 18:02:26 +0200 Subject: [PATCH 097/308] Change zoom in SongEditor to a Slider Zoom (#6664) Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com> Co-authored-by: Alex --- data/themes/classic/horizontal_slider.png | Bin 0 -> 1444 bytes data/themes/classic/style.css | 19 ++ data/themes/default/horizontal_slider.png | Bin 0 -> 1065 bytes data/themes/default/style.css | 19 ++ include/SongEditor.h | 17 +- src/gui/clips/ClipView.cpp | 9 +- src/gui/editors/SongEditor.cpp | 239 ++++++++++++---------- src/gui/editors/TimeLineWidget.cpp | 22 +- 8 files changed, 198 insertions(+), 127 deletions(-) create mode 100644 data/themes/classic/horizontal_slider.png create mode 100644 data/themes/default/horizontal_slider.png diff --git a/data/themes/classic/horizontal_slider.png b/data/themes/classic/horizontal_slider.png new file mode 100644 index 0000000000000000000000000000000000000000..49d16b9d869e01d2380a90b5615d9cc6d2d10fb0 GIT binary patch literal 1444 zcmeAS@N?(olHy`uVBq!ia0vp^Ahr|-8<6aKa#jsUNtU=qlmzFem6RtIr7}3Cer{{GxPyLrY6bkQqisxQ#zd*q`*i1nqJTosPzr0uz ztlrnx$}_LHBrz{J)zigR321^|W@d_&p`oR#i;*(J3ovn(~mttdZN0qkX~Ox$j9!f75< zZwhX=IOEi-4|I$^C}NQ!8YToxJs>7L*#bH6grAxROzlO$WZnEmY$^i-lZ2;>V@SoV zmf+oew*mxY<7Y3=$WUt8BC=3vnvzKV;rbSZ9}H4I`j^}?Q3!0fbm78>U(B=Cw7gi< z+rs3!X;Fl-0E+;B^IYrXb%x#(8E+S-_nkj8w_2w$cm6|rwWpsey(cYMy&!W|fsNcj z1D>esufOVZHC>v2DM5zEOOB7-Yu)v1rf*fYQQ8&BLd^T`zc)~l;1oNp+L6U0drX3L z*Im6OL7EJu+7cR*ISrz^qb^wXj*HC4Yj-|Yy#6+5pca?!lI zJzu(xKVGQtZAGTkiuWP24)6v9if}!$IQ7&>b)ulTN>A07s=WnPa}{Qv4Jt5^irrc? z^YLogIEVGelqb#gV-E>!t+1)9i`*r*D71qvGmuN z2C;uX&pREjo1`CgnDrFb`moikoi0rGKFQ@OSR~x?Q4m;gplo-m*HWi_nKS=n#+{!S zgqd~@CT#_BK)kuMo0Rp&*QJQnm@9$ZoLr%x%eaKW_!7<`*!r_zN0-$o!)78&q Iol`;+08;c5761SM literal 0 HcmV?d00001 diff --git a/data/themes/classic/style.css b/data/themes/classic/style.css index 2880fe661..d1f4d0588 100644 --- a/data/themes/classic/style.css +++ b/data/themes/classic/style.css @@ -418,6 +418,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/horizontal_slider.png b/data/themes/default/horizontal_slider.png new file mode 100644 index 0000000000000000000000000000000000000000..24f6098e517df6a8ae5c0372b117241437e2f4bb GIT binary patch literal 1065 zcmah|O-K|`9G_Z{TD7Q4W>UileNemevAg5Ur&gz*_o#fI`gKPx9w__ zU?|oh^ddnN9V#OFIw~G4>e3ZS(Ht+OBytTs)q>{O&hZbqPeALtJ(lSWDfKhR+RcSH&2m<9;MDiQcTK@gMOoJ z*a6+c9T{zSKofPUw2EPwWfeIVQaFVZ7*1ftgeWT&Zqjm*YH6UtH8!}) zrd%oR02M(e1L0t$dtLnyLAM{;WW1Xv51%nC9TwapUTMopfn%HpdcuJwS*nd>{1xBR zo`|u0f)5K}xm8rK`k0_3;%rEeg*ekHa1pA^)&G(Af4MXkLwk+=qtTTsJUyPdKDPL< zKKQ`G)9&E0zN)s*;U{r3DaSI!_qkuIt1Z4$#Dlk06P=?oS*Gp7_^vyXQ&Wp~CMRb0 zHqi%s)zwFRo%f^{Z)SJa3F2(s^_5j1jC_B2U~GAuPlAtbNTku zZP{DfZ@4}FsV#T?XYZTT*Jo!_`LPA!^w`Ly<^96g$VBGHg-;LfjX&vJ{<-LzZv5 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/src/gui/clips/ClipView.cpp b/src/gui/clips/ClipView.cpp index 8a190e2a7..b78605906 100644 --- a/src/gui/clips/ClipView.cpp +++ b/src/gui/clips/ClipView.cpp @@ -125,7 +125,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 +314,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(); } diff --git a/src/gui/editors/SongEditor.cpp b/src/gui/editors/SongEditor.cpp index 3e62cc238..939c1fdf4 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,14 +60,24 @@ 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 ), @@ -75,7 +88,7 @@ SongEditor::SongEditor( Song * song ) : 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,6 +96,7 @@ 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], @@ -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"); } } @@ -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 @@ -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->m_playPos[Song::Mode_PlaySong].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)); } @@ -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->m_playPos[Song::Mode_PlaySong].m_timeLine->setPixelsPerBar(ppb); realignTracks(); updateRubberband(); m_timeLine->setSnapSize(getSnapSize()); - - emit zoomingValueChanged( m_zoomLevels[m_zoomingModel->value()] ); + + emit pixelsPerBarChanged(ppb); } @@ -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(){ @@ -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..b051fa79b 100644 --- a/src/gui/editors/TimeLineWidget.cpp +++ b/src/gui/editors/TimeLineWidget.cpp @@ -22,23 +22,29 @@ * */ +#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; @@ -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 ); From 3aed361b82dba6246119c8fc9d929fd9a779a647 Mon Sep 17 00:00:00 2001 From: saker Date: Thu, 24 Aug 2023 12:28:34 -0400 Subject: [PATCH 098/308] Core: Replace global Qt declarations with standard equivalents (#6821) * Replace qAbs with std::abs * Replace qBound with std::clamp * Replace qMax with std::max * Replace qMin with std::min * Replace qRound with std::round * Replace qgetenv with std::getenv --------- Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com> --- include/AutomatableModel.h | 3 +- include/BasicFilters.h | 149 ++++++++++++-------------- include/ComboBoxModel.h | 4 +- include/Controller.h | 2 +- include/DspEffectLibrary.h | 4 +- include/Note.h | 2 +- include/lmms_math.h | 10 +- src/core/AudioEngine.cpp | 6 +- src/core/AudioEngineProfiler.cpp | 2 +- src/core/AutomatableModel.cpp | 10 +- src/core/AutomationClip.cpp | 10 +- src/core/BandLimitedWave.cpp | 6 +- src/core/Clip.cpp | 2 +- src/core/ConfigManager.cpp | 8 +- src/core/EnvelopeAndLfoParameters.cpp | 18 ++-- src/core/Instrument.cpp | 4 +- src/core/InstrumentSoundShaping.cpp | 2 +- src/core/LfoController.cpp | 2 +- src/core/MixHelpers.cpp | 2 +- src/core/Mixer.cpp | 4 +- src/core/Note.cpp | 16 +-- src/core/NotePlayHandle.cpp | 6 +- src/core/PatternStore.cpp | 4 +- src/core/PluginFactory.cpp | 3 +- src/core/ProjectVersion.cpp | 4 +- src/core/RemotePlugin.cpp | 10 +- src/core/SampleBuffer.cpp | 28 ++--- src/core/SampleClip.cpp | 2 +- src/core/TimePos.cpp | 2 +- src/core/TrackContainer.cpp | 2 +- src/core/audio/AudioAlsa.cpp | 10 +- src/core/audio/AudioFileFlac.cpp | 2 +- src/core/audio/AudioJack.cpp | 12 +-- src/core/audio/AudioOss.cpp | 6 +- src/core/audio/AudioPortAudio.cpp | 14 +-- src/core/audio/AudioPulseAudio.cpp | 6 +- src/core/audio/AudioSdl.cpp | 10 +- src/core/audio/AudioSndio.cpp | 6 +- src/core/audio/AudioSoundIo.cpp | 6 +- src/core/midi/MidiApple.cpp | 4 +- src/tracks/InstrumentTrack.cpp | 4 +- src/tracks/MidiClip.cpp | 8 +- 42 files changed, 204 insertions(+), 211 deletions(-) diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index 2b93a514c..292da3bec 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -27,6 +27,7 @@ #include #include +#include #include "JournallingObject.h" #include "Model.h" @@ -144,7 +145,7 @@ public: template static bool castValue( const float v ) { - return ( qRound( v ) != 0 ); + return (std::round(v) != 0); } diff --git a/include/BasicFilters.h b/include/BasicFilters.h index c10c47489..c54053c95 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; } @@ -340,22 +340,18 @@ public: // 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]; @@ -377,18 +373,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]; @@ -471,16 +464,16 @@ public: 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; @@ -496,13 +489,13 @@ public: 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; @@ -518,16 +511,16 @@ public: { // 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 +529,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; @@ -562,13 +555,13 @@ public: { // 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; @@ -579,13 +572,13 @@ public: ? 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; @@ -597,7 +590,7 @@ public: case Formantfilter: case 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; @@ -606,39 +599,39 @@ public: { // 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 +641,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; @@ -709,7 +702,7 @@ 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 || @@ -718,7 +711,7 @@ public: m_type == Bandpass_RC24 || m_type == 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 ); @@ -734,7 +727,7 @@ public: if( m_type == Formantfilter || m_type == 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 }, @@ -772,7 +765,7 @@ public: m_type == 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; @@ -789,7 +782,7 @@ public: if( m_type == 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; @@ -803,15 +796,15 @@ public: m_type == Highpass_SV || m_type == 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 ); 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/Controller.h b/include/Controller.h index b176b1f74..3387975b8 100644 --- a/include/Controller.h +++ b/include/Controller.h @@ -118,7 +118,7 @@ public: inline static float fittedValue( float _val ) { - return qBound( 0.0f, _val, 1.0f ); + return std::clamp(_val, 0.0f, 1.0f); } static long runningPeriods() 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/Note.h b/include/Note.h index dd261b3af..a5c60ef8b 100644 --- a/include/Note.h +++ b/include/Note.h @@ -198,7 +198,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 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/src/core/AudioEngine.cpp b/src/core/AudioEngine.cpp index 91a16ed12..59c7f2cd2 100644 --- a/src/core/AudioEngine.cpp +++ b/src/core/AudioEngine.cpp @@ -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; @@ -551,8 +551,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; diff --git a/src/core/AudioEngineProfiler.cpp b/src/core/AudioEngineProfiler.cpp index 5fd5a813c..9e05ff80a 100644 --- a/src/core/AudioEngineProfiler.cpp +++ b/src/core/AudioEngineProfiler.cpp @@ -41,7 +41,7 @@ void AudioEngineProfiler::finishPeriod( sample_rate_t sampleRate, fpp_t framesPe int periodElapsed = m_periodTimer.elapsed(); const float newCpuLoad = periodElapsed / 10000.0f * sampleRate / framesPerPeriod; - m_cpuLoad = qBound( 0, ( newCpuLoad * 0.1f + m_cpuLoad * 0.9f ), 100 ); + m_cpuLoad = std::clamp((newCpuLoad * 0.1f + m_cpuLoad * 0.9f), 0, 100); if( m_outputFile.isOpen() ) { diff --git a/src/core/AutomatableModel.cpp b/src/core/AutomatableModel.cpp index fa4697c69..c25e813cb 100644 --- a/src/core/AutomatableModel.cpp +++ b/src/core/AutomatableModel.cpp @@ -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 ) { @@ -585,7 +585,7 @@ float AutomatableModel::controllerValue( int frameOffset ) const } if( typeInfo::isEqual( m_step, 1 ) && m_hasStrictStepSize ) { - return qRound( v ); + return std::round(v); } return v; } @@ -794,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 7a161c355..e55fc5c1e 100644 --- a/src/core/AutomationClip.cpp +++ b/src/core/AutomationClip.cpp @@ -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,8 +374,8 @@ 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 @@ -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) { diff --git a/src/core/BandLimitedWave.cpp b/src/core/BandLimitedWave.cpp index a7dd650c0..a92b22e21 100644 --- a/src/core/BandLimitedWave.cpp +++ b/src/core/BandLimitedWave.cpp @@ -109,7 +109,7 @@ void BandLimitedWave::generateWaves() harm++; } while( hlen > 2.0 ); s_waveforms[ BandLimitedWave::BLSaw ].setSampleAt( i, ph, s ); - max = qMax( max, qAbs( s ) ); + max = std::max(max, std::abs(s)); } // normalize for( int ph = 0; ph < len; ph++ ) @@ -151,7 +151,7 @@ void BandLimitedWave::generateWaves() harm += 2; } while( hlen > 2.0 ); s_waveforms[ BandLimitedWave::BLSquare ].setSampleAt( i, ph, s ); - max = qMax( max, qAbs( s ) ); + max = std::max(max, std::abs(s)); } // normalize for( int ph = 0; ph < len; ph++ ) @@ -193,7 +193,7 @@ void BandLimitedWave::generateWaves() harm += 2; } while( hlen > 2.0 ); s_waveforms[ BandLimitedWave::BLTriangle ].setSampleAt( i, ph, s ); - max = qMax( max, qAbs( s ) ); + max = std::max(max, std::abs(s)); } // normalize for( int ph = 0; ph < len; ph++ ) 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 c647a27e6..05574ae35 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(); @@ -557,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); diff --git a/src/core/EnvelopeAndLfoParameters.cpp b/src/core/EnvelopeAndLfoParameters.cpp index 2aa77e6aa..a3f41b5aa 100644 --- a/src/core/EnvelopeAndLfoParameters.cpp +++ b/src/core/EnvelopeAndLfoParameters.cpp @@ -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/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/InstrumentSoundShaping.cpp b/src/core/InstrumentSoundShaping.cpp index edf3b403c..4aeea453a 100644 --- a/src/core/InstrumentSoundShaping.cpp +++ b/src/core/InstrumentSoundShaping.cpp @@ -317,7 +317,7 @@ f_cnt_t InstrumentSoundShaping::releaseFrames() const { 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/LfoController.cpp b/src/core/LfoController.cpp index 495ae54d4..c0fe65855 100644 --- a/src/core/LfoController.cpp +++ b/src/core/LfoController.cpp @@ -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; 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 dba5c334e..5edd88a0a 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 { diff --git a/src/core/Note.cpp b/src/core/Note.cpp index e4e5f0e5d..1198abdec 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(); diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index e87637476..31f7e81cb 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -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 ) { diff --git a/src/core/PatternStore.cpp b/src/core/PatternStore.cpp index f91c42b72..3d0b60acf 100644 --- a/src/core/PatternStore.cpp +++ b/src/core/PatternStore.cpp @@ -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()); } } @@ -125,7 +125,7 @@ void PatternStore::removePattern(int pattern) } if (pattern <= currentPattern()) { - setCurrentPattern(qMax(currentPattern() - 1, 0)); + setCurrentPattern(std::max(currentPattern() - 1, 0)); } } diff --git a/src/core/PluginFactory.cpp b/src/core/PluginFactory.cpp index ece589274..3790a7ec9 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"); 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/SampleBuffer.cpp b/src/core/SampleBuffer.cpp index 677366fdb..2f35b23a8 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,7 +736,7 @@ 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) { @@ -915,12 +915,12 @@ sampleFrame * SampleBuffer::getSampleFragment( } else if (loopMode == LoopOn) { - 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..87d6351bc 100644 --- a/src/core/SampleClip.cpp +++ b/src/core/SampleClip.cpp @@ -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)); } 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/TrackContainer.cpp b/src/core/TrackContainer.cpp index 33c695f48..af96ff1c4 100644 --- a/src/core/TrackContainer.cpp +++ b/src/core/TrackContainer.cpp @@ -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/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..9b49017c8 100644 --- a/src/core/audio/AudioFileFlac.cpp +++ b/src/core/audio/AudioFileFlac.cpp @@ -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/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/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/midi/MidiApple.cpp b/src/core/midi/MidiApple.cpp index 4105f18f1..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; diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 1d2546288..a688aed9a 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -265,7 +265,7 @@ void InstrumentTrack::processAudioBuffer( sampleFrame* buf, const fpp_t frames, 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 ) { @@ -666,7 +666,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); } diff --git a/src/tracks/MidiClip.cpp b/src/tracks/MidiClip.cpp index 52a532028..4fa2af5d8 100644 --- a/src/tracks/MidiClip.cpp +++ b/src/tracks/MidiClip.cpp @@ -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); } } @@ -591,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(); } From f10277715f6da1d3055a1ed75dc3b40a5cfac81d Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Thu, 24 Aug 2023 19:16:02 +0100 Subject: [PATCH 099/308] Classier enums (#6760) --- include/AudioEngine.h | 64 ++-- include/AudioEngineWorkerThread.h | 8 +- include/AutomatableModel.h | 6 +- include/AutomationClip.h | 14 +- include/AutomationEditor.h | 30 +- include/BandLimitedWave.h | 21 +- include/BasicFilters.h | 103 +++--- include/Clip.h | 7 - include/ClipView.h | 8 +- include/Controller.h | 27 +- include/CustomTextKnob.h | 2 +- include/DataFile.h | 8 +- include/EnvelopeAndLfoParameters.h | 5 +- include/ExportProjectDialog.h | 2 +- include/FileBrowser.h | 27 +- include/Flags.h | 83 +++++ include/Graph.h | 19 +- include/Instrument.h | 10 +- include/InstrumentFunctions.h | 21 +- include/InstrumentSoundShaping.h | 7 +- include/Knob.h | 16 +- include/LadspaBase.h | 20 +- include/LadspaManager.h | 14 +- include/LedCheckBox.h | 11 +- include/LmmsStyle.h | 30 -- include/Lv2ControlBase.h | 2 +- include/Lv2Manager.h | 6 +- include/Lv2Ports.h | 5 +- include/Lv2Proc.h | 2 +- include/Lv2SubPluginFeatures.h | 2 +- include/MainWindow.h | 2 +- include/MidiClip.h | 8 +- include/MidiPort.h | 9 +- include/MidiPortMenu.h | 4 +- include/Note.h | 44 ++- include/NotePlayHandle.h | 16 +- include/Oscillator.h | 47 +-- include/OutputSettings.h | 19 +- include/Piano.h | 6 +- include/PianoRoll.h | 96 ++--- include/PlayHandle.h | 21 +- include/Plugin.h | 10 +- include/PluginFactory.h | 4 +- include/PluginIssue.h | 40 +-- include/ProjectJournal.h | 2 +- include/ProjectRenderer.h | 21 +- include/ProjectVersion.h | 6 +- include/RenderManager.h | 4 +- include/SampleBuffer.h | 10 +- include/SetupDialog.h | 4 +- include/Song.h | 65 ++-- include/SongEditor.h | 8 +- include/TempoSyncKnob.h | 2 +- include/TempoSyncKnobModel.h | 34 +- include/TimeDisplayWidget.h | 6 +- include/TimeLineWidget.h | 32 +- include/Track.h | 26 +- include/TrackContainer.h | 14 +- include/TrackContainerView.h | 6 - include/TrackContentWidget.h | 2 +- include/TrackView.h | 12 +- include/fft_helpers.h | 12 +- include/lmms_constants.h | 22 +- plugins/Amplifier/Amplifier.cpp | 2 +- plugins/Amplifier/AmplifierControlDialog.cpp | 8 +- .../AudioFileProcessor/AudioFileProcessor.cpp | 46 +-- .../AudioFileProcessor/AudioFileProcessor.h | 28 +- plugins/BassBooster/BassBooster.cpp | 2 +- .../BassBooster/BassBoosterControlDialog.cpp | 6 +- plugins/BitInvader/BitInvader.cpp | 12 +- plugins/Bitcrush/Bitcrush.cpp | 2 +- plugins/Bitcrush/BitcrushControlDialog.cpp | 18 +- plugins/CarlaBase/Carla.cpp | 6 +- plugins/CarlaPatchbay/CarlaPatchbay.cpp | 2 +- plugins/CarlaRack/CarlaRack.cpp | 2 +- plugins/Compressor/Compressor.cpp | 14 +- plugins/Compressor/Compressor.h | 2 +- .../Compressor/CompressorControlDialog.cpp | 36 +- plugins/CrossoverEQ/CrossoverEQ.cpp | 2 +- .../CrossoverEQ/CrossoverEQControlDialog.cpp | 14 +- plugins/Delay/DelayControlsDialog.cpp | 8 +- plugins/Delay/DelayEffect.cpp | 2 +- plugins/Dispersion/Dispersion.cpp | 2 +- .../Dispersion/DispersionControlDialog.cpp | 6 +- plugins/DualFilter/DualFilter.cpp | 6 +- .../DualFilter/DualFilterControlDialog.cpp | 6 +- .../DynamicsProcessor/DynamicsProcessor.cpp | 10 +- .../DynamicsProcessorControlDialog.cpp | 10 +- .../DynamicsProcessorControls.h | 9 +- plugins/Eq/EqControlsDialog.cpp | 4 +- plugins/Eq/EqCurve.cpp | 30 +- plugins/Eq/EqCurve.h | 19 +- plugins/Eq/EqEffect.cpp | 2 +- plugins/Eq/EqParameterWidget.cpp | 16 +- plugins/Flanger/FlangerControlsDialog.cpp | 12 +- plugins/Flanger/FlangerEffect.cpp | 2 +- plugins/FreeBoy/FreeBoy.cpp | 6 +- plugins/GigPlayer/GigPlayer.cpp | 26 +- plugins/GigPlayer/GigPlayer.h | 6 +- plugins/HydrogenImport/HydrogenImport.cpp | 34 +- plugins/Kicker/Kicker.cpp | 12 +- plugins/Kicker/Kicker.h | 2 +- plugins/LadspaBrowser/LadspaBrowser.cpp | 12 +- plugins/LadspaBrowser/LadspaDescription.cpp | 14 +- plugins/LadspaEffect/LadspaControlDialog.cpp | 10 +- plugins/LadspaEffect/LadspaEffect.cpp | 64 ++-- .../LadspaEffect/LadspaSubPluginFeatures.cpp | 10 +- .../LadspaEffect/LadspaSubPluginFeatures.h | 2 +- plugins/Lb302/Lb302.cpp | 94 ++--- plugins/Lb302/Lb302.h | 20 +- plugins/Lv2Effect/Lv2Effect.cpp | 4 +- plugins/Lv2Instrument/Lv2Instrument.cpp | 6 +- plugins/Lv2Instrument/Lv2Instrument.h | 4 +- plugins/MidiExport/MidiExport.cpp | 16 +- plugins/MidiImport/MidiImport.cpp | 12 +- plugins/Monstro/Monstro.cpp | 2 +- plugins/Monstro/Monstro.h | 14 +- plugins/MultitapEcho/MultitapEcho.cpp | 2 +- .../MultitapEchoControlDialog.cpp | 12 +- plugins/Nes/Nes.cpp | 2 +- plugins/Nes/Nes.h | 2 +- plugins/OpulenZ/OpulenZ.cpp | 8 +- plugins/OpulenZ/OpulenZ.h | 2 +- plugins/Organic/Organic.cpp | 26 +- plugins/Patman/Patman.cpp | 32 +- plugins/Patman/Patman.h | 16 +- .../PeakControllerEffect.cpp | 2 +- .../PeakControllerEffectControlDialog.cpp | 12 +- plugins/ReverbSC/ReverbSC.cpp | 2 +- plugins/ReverbSC/ReverbSCControlDialog.cpp | 8 +- plugins/Sf2Player/Sf2Player.cpp | 10 +- plugins/Sf2Player/Sf2Player.h | 2 +- plugins/Sfxr/Sfxr.cpp | 6 +- plugins/Sfxr/Sfxr.h | 5 +- plugins/Sid/SidInstrument.cpp | 30 +- plugins/Sid/SidInstrument.h | 29 +- plugins/SpectrumAnalyzer/Analyzer.cpp | 2 +- plugins/SpectrumAnalyzer/SaControls.cpp | 4 +- plugins/SpectrumAnalyzer/SaControlsDialog.cpp | 16 +- plugins/SpectrumAnalyzer/SaProcessor.cpp | 50 +-- plugins/StereoEnhancer/StereoEnhancer.cpp | 2 +- .../StereoEnhancerControlDialog.cpp | 2 +- plugins/StereoMatrix/StereoMatrix.cpp | 2 +- .../StereoMatrixControlDialog.cpp | 8 +- plugins/Stk/Mallets/Mallets.cpp | 32 +- plugins/TripleOscillator/TripleOscillator.cpp | 10 +- plugins/Vectorscope/VecControlsDialog.cpp | 2 +- plugins/Vectorscope/Vectorscope.cpp | 2 +- plugins/Vestige/Vestige.cpp | 8 +- plugins/Vestige/Vestige.h | 2 +- plugins/Vibed/Vibed.cpp | 18 +- plugins/Vibed/Vibed.h | 2 +- plugins/VstBase/RemoteVstPlugin.cpp | 24 +- plugins/VstBase/VstPlugin.cpp | 16 +- plugins/VstBase/communication.h | 16 +- plugins/VstBase/vst_base.cpp | 2 +- plugins/VstEffect/VstEffect.cpp | 4 +- plugins/VstEffect/VstEffectControlDialog.cpp | 10 + plugins/VstEffect/VstEffectControls.cpp | 12 +- plugins/VstEffect/VstSubPluginFeatures.cpp | 2 +- plugins/VstEffect/VstSubPluginFeatures.h | 2 +- plugins/Watsyn/Watsyn.cpp | 10 +- plugins/Watsyn/Watsyn.h | 4 +- plugins/WaveShaper/WaveShaper.cpp | 2 +- .../WaveShaper/WaveShaperControlDialog.cpp | 8 +- plugins/Xpressive/Xpressive.cpp | 14 +- plugins/ZynAddSubFx/ZynAddSubFx.cpp | 22 +- plugins/ZynAddSubFx/ZynAddSubFx.h | 2 +- src/core/AudioEngine.cpp | 24 +- src/core/AudioEngineWorkerThread.cpp | 2 +- src/core/AutomatableModel.cpp | 30 +- src/core/AutomationClip.cpp | 34 +- src/core/BandLimitedWave.cpp | 42 +-- src/core/ConfigManager.cpp | 4 +- src/core/Controller.cpp | 24 +- src/core/ControllerConnection.cpp | 18 +- src/core/DataFile.cpp | 65 ++-- src/core/EnvelopeAndLfoParameters.cpp | 16 +- src/core/ImportFilter.cpp | 2 +- src/core/InstrumentFunctions.cpp | 38 +- src/core/InstrumentPlayHandle.cpp | 2 +- src/core/InstrumentSoundShaping.cpp | 40 +-- src/core/Ladspa2LMMS.cpp | 10 +- src/core/LadspaControl.cpp | 90 ++--- src/core/LadspaManager.cpp | 8 +- src/core/LfoController.cpp | 23 +- src/core/Mixer.cpp | 14 +- src/core/Note.cpp | 2 +- src/core/NotePlayHandle.cpp | 12 +- src/core/Oscillator.cpp | 277 +++++++-------- src/core/PatternStore.cpp | 8 +- src/core/PeakController.cpp | 2 +- src/core/Piano.cpp | 14 +- src/core/Plugin.cpp | 2 +- src/core/PluginFactory.cpp | 2 +- src/core/PluginIssue.cpp | 38 +- src/core/PresetPreviewPlayHandle.cpp | 6 +- src/core/ProjectJournal.cpp | 6 +- src/core/ProjectRenderer.cpp | 24 +- src/core/RenderManager.cpp | 10 +- src/core/SampleBuffer.cpp | 24 +- src/core/SampleClip.cpp | 8 +- src/core/SamplePlayHandle.cpp | 2 +- src/core/SampleRecordHandle.cpp | 2 +- src/core/Song.cpp | 160 ++++----- src/core/TempoSyncKnobModel.cpp | 36 +- src/core/ToolPlugin.cpp | 2 +- src/core/Track.cpp | 28 +- src/core/TrackContainer.cpp | 12 +- src/core/UpgradeExtendedNoteRange.cpp | 6 +- src/core/audio/AudioFileFlac.cpp | 6 +- src/core/audio/AudioFileMP3.cpp | 6 +- src/core/audio/AudioFileWave.cpp | 8 +- src/core/audio/AudioPort.cpp | 2 +- src/core/fft_helpers.cpp | 10 +- src/core/lv2/Lv2ControlBase.cpp | 2 +- src/core/lv2/Lv2Manager.cpp | 4 +- src/core/lv2/Lv2Ports.cpp | 30 +- src/core/lv2/Lv2Proc.cpp | 24 +- src/core/lv2/Lv2SubPluginFeatures.cpp | 2 +- src/core/main.cpp | 38 +- src/core/midi/MidiAlsaSeq.cpp | 6 +- src/core/midi/MidiController.cpp | 4 +- src/core/midi/MidiPort.cpp | 10 +- src/gui/ControllerView.cpp | 2 +- src/gui/Controls.cpp | 2 +- src/gui/EffectView.cpp | 8 +- src/gui/FileBrowser.cpp | 110 +++--- src/gui/LadspaControlView.cpp | 18 +- src/gui/LfoControllerDialog.cpp | 8 +- src/gui/MainWindow.cpp | 42 +-- src/gui/MicrotunerConfig.cpp | 10 + src/gui/MidiCCRackView.cpp | 2 +- src/gui/MixerLine.cpp | 2 +- src/gui/MixerView.cpp | 14 +- src/gui/PluginBrowser.cpp | 4 +- src/gui/SampleTrackWindow.cpp | 14 +- src/gui/clips/AutomationClipView.cpp | 2 +- src/gui/clips/ClipView.cpp | 102 +++--- src/gui/clips/MidiClipView.cpp | 12 +- src/gui/editors/AutomationEditor.cpp | 108 +++--- src/gui/editors/PatternEditor.cpp | 10 +- src/gui/editors/PianoRoll.cpp | 330 +++++++++--------- src/gui/editors/PositionLine.cpp | 4 +- src/gui/editors/SongEditor.cpp | 40 +-- src/gui/editors/TimeLineWidget.cpp | 56 +-- src/gui/editors/TrackContainerView.cpp | 10 +- src/gui/instrument/EnvelopeAndLfoView.cpp | 49 +-- .../instrument/InstrumentFunctionViews.cpp | 16 +- .../instrument/InstrumentSoundShapingView.cpp | 4 +- src/gui/instrument/InstrumentTrackWindow.cpp | 14 +- src/gui/instrument/PianoView.cpp | 40 +-- src/gui/menus/MidiPortMenu.cpp | 12 +- src/gui/modals/ControllerConnectionDialog.cpp | 6 +- src/gui/modals/EffectSelectDialog.cpp | 2 +- src/gui/modals/ExportProjectDialog.cpp | 32 +- src/gui/modals/SetupDialog.cpp | 4 +- src/gui/tracks/InstrumentTrackView.cpp | 8 +- src/gui/tracks/SampleTrackView.cpp | 4 +- src/gui/tracks/TrackContentWidget.cpp | 12 +- src/gui/tracks/TrackLabelButton.cpp | 2 +- src/gui/tracks/TrackOperationsWidget.cpp | 6 +- src/gui/tracks/TrackView.cpp | 16 +- src/gui/widgets/CustomTextKnob.cpp | 2 +- src/gui/widgets/Graph.cpp | 10 +- src/gui/widgets/Knob.cpp | 40 +-- src/gui/widgets/LedCheckBox.cpp | 12 +- src/gui/widgets/TempoSyncKnob.cpp | 60 ++-- src/gui/widgets/TimeDisplayWidget.cpp | 16 +- src/tracks/AutomationTrack.cpp | 4 +- src/tracks/InstrumentTrack.cpp | 20 +- src/tracks/MidiClip.cpp | 24 +- src/tracks/PatternTrack.cpp | 8 +- src/tracks/SampleTrack.cpp | 6 +- tests/src/core/ProjectVersionTest.cpp | 16 +- tests/src/tracks/AutomationTrackTest.cpp | 22 +- 276 files changed, 2607 insertions(+), 2521 deletions(-) create mode 100644 include/Flags.h diff --git a/include/AudioEngine.h b/include/AudioEngine.h index dec8f2592..030c5bce3 100644 --- a/include/AudioEngine.h +++ b/include/AudioEngine.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 diff --git a/include/AudioEngineWorkerThread.h b/include/AudioEngineWorkerThread.h index 16de6ff6f..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,7 +97,7 @@ 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 (const auto& job : _vec) diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index 292da3bec..2264a592e 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -81,7 +81,7 @@ class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject public: using AutoModelVector = std::vector; - enum ScaleType + enum class ScaleType { Linear, Logarithmic, @@ -232,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 fc6a26d0e..ceb5611c9 100644 --- a/include/AutomationClip.h +++ b/include/AutomationClip.h @@ -54,11 +54,11 @@ class LMMS_EXPORT AutomationClip : public Clip { Q_OBJECT public: - enum ProgressionTypes + enum class ProgressionType { - DiscreteProgression, - LinearProgression, - CubicHermiteProgression + Discrete, + Linear, + CubicHermite } ; using timeMap = QMap; @@ -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 { @@ -214,7 +214,7 @@ private: 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 a1c4d694f..ecefa8b26 100644 --- a/include/AutomationEditor.h +++ b/include/AutomationEditor.h @@ -87,11 +87,11 @@ public: return "automationeditor"; } - enum EditModes + enum class EditMode { - DRAW, - ERASE, - DRAW_OUTVALUES + Draw, + Erase, + DrawOutValues }; public slots: @@ -129,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(); @@ -146,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... @@ -201,7 +201,7 @@ private: TimePos m_currentPosition; - Actions m_action; + Action m_action; int m_moveXOffset; @@ -215,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 c54053c95..9351cbafb 100644 --- a/include/BasicFilters.h +++ b/include/BasicFilters.h @@ -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,7 +333,7 @@ public: sample_t out; switch( m_type ) { - case Moog: + case FilterType::Moog: { sample_t x = _in0 - m_r*m_y4[_chnl]; @@ -364,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; @@ -397,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; @@ -414,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; @@ -433,7 +432,7 @@ public: return hp; } - case Notch_SV: + case FilterType::Notch_SV: { float hp1, hp2; @@ -458,7 +457,7 @@ 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 ) @@ -482,8 +481,8 @@ 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 ) @@ -501,10 +500,10 @@ public: 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 ) @@ -547,8 +546,8 @@ 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 ) @@ -568,7 +567,7 @@ public: 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; @@ -584,17 +583,17 @@ public: 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 (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 @@ -681,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: @@ -704,12 +703,12 @@ public: // temp coef vars _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 = std::clamp(_freq, 50.0f, 20000.0f); const float sr = m_sampleRatio * 0.25f; @@ -724,8 +723,8 @@ public: return; } - if( m_type == Formantfilter || - m_type == FastFormant ) + if( m_type == FilterType::Formantfilter || + m_type == FilterType::FastFormant ) { _freq = std::clamp(_freq, minFreq(), 20000.0f); // limit freq and q for not getting bad noise out of the filter... @@ -750,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]; @@ -761,8 +760,8 @@ public: return; } - if( m_type == Moog || - m_type == DoubleMoog ) + if( m_type == FilterType::Moog || + m_type == FilterType::DoubleMoog ) { // [ 0 - 0.5 ] const float f = std::clamp(_freq, minFreq(), 20000.0f) * m_sampleRatio; @@ -780,7 +779,7 @@ public: return; } - if( m_type == Tripole ) + if( m_type == FilterType::Tripole ) { const float f = std::clamp(_freq, 20.0f, 20000.0f) * m_sampleRatio * 0.25f; @@ -791,10 +790,10 @@ 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(std::max(minFreq(), _freq) * m_sampleRatio * F_PI); m_svf1 = std::min(f, 0.825f); @@ -818,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; @@ -898,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/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/Controller.h b/include/Controller.h index 3387975b8..fe78c55cc 100644 --- a/include/Controller.h +++ b/include/Controller.h @@ -51,20 +51,19 @@ 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,7 +111,7 @@ 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 ); @@ -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/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/EnvelopeAndLfoParameters.h b/include/EnvelopeAndLfoParameters.h index 02abd07e3..7abc3910e 100644 --- a/include/EnvelopeAndLfoParameters.h +++ b/include/EnvelopeAndLfoParameters.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 61d625d83..59c651a68 100644 --- a/include/InstrumentFunctions.h +++ b/include/InstrumentFunctions.h @@ -176,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 ); @@ -202,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/Knob.h b/include/Knob.h index 289af8cd5..85a51e363 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; @@ -206,7 +206,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 95016b87f..e3629e143 100644 --- a/include/LedCheckBox.h +++ b/include/LedCheckBox.h @@ -38,20 +38,19 @@ 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 ); LedCheckBox( QWidget * _parent, const QString & _name = QString(), - LedColors _color = Yellow ); + LedColor _color = LedColor::Yellow ); ~LedCheckBox() override; @@ -75,7 +74,7 @@ private: QString m_text; - void initUi( LedColors _color ); //!< to be called by ctors + void initUi( LedColor _color ); //!< to be called by ctors void onTextUpdated(); //!< to be called when you updated @a m_text } ; 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/MidiClip.h b/include/MidiClip.h index bbb7d325d..43b322f80 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 @@ -82,7 +82,7 @@ public: void splitNotes(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/Note.h b/include/Note.h index a5c60ef8b..5e3a1b8a2 100644 --- a/include/Note.h +++ b/include/Note.h @@ -42,47 +42,53 @@ 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; diff --git a/include/NotePlayHandle.h b/include/NotePlayHandle.h index 29477705b..46b14c4cd 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 ) @@ -349,7 +347,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/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 03b93d816..9f3bbcd7d 100644 --- a/include/PianoRoll.h +++ b/include/PianoRoll.h @@ -104,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 */ @@ -153,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; @@ -221,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 ); @@ -248,46 +258,36 @@ 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; @@ -346,7 +346,7 @@ private: static QPixmap * s_toolOpen; static QPixmap* s_toolKnife; - static std::array prKeyOrder; + static std::array prKeyOrder; static SimpleTextFloat * s_textFloat; @@ -378,7 +378,7 @@ private: QList m_recordingNotes; Note * m_currentNote; - Actions m_action; + Action m_action; NoteEditMode m_noteEditMode; GridMode m_gridMode; @@ -429,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 10c76e4ee..7221f2b09 100644 --- a/include/PluginFactory.h +++ b/include/PluginFactory.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 { 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 43f696f14..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,7 +73,7 @@ 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; 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/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/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 867ff0f14..ee9e83f44 100644 --- a/include/SongEditor.h +++ b/include/SongEditor.h @@ -57,11 +57,11 @@ class SongEditor : public TrackContainerView { Q_OBJECT public: - enum EditMode + enum class EditMode { - DrawMode, - KnifeMode, - SelectMode + Draw, + Knife, + Select }; SongEditor( Song * song ); 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 000d564f7..33d1ad233 100644 --- a/include/Track.h +++ b/include/Track.h @@ -72,29 +72,29 @@ class LMMS_EXPORT Track : public Model, public JournallingObject public: 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; } @@ -224,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 8739a9e9f..01e94df54 100644 --- a/include/TrackContainer.h +++ b/include/TrackContainer.h @@ -50,10 +50,10 @@ class LMMS_EXPORT TrackContainer : public Model, public JournallingObject Q_OBJECT public: using TrackList = std::vector; - enum TrackContainerTypes + 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..763705599 100644 --- a/include/TrackView.h +++ b/include/TrackView.h @@ -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/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 2243683ce..a941e773f 100644 --- a/plugins/AudioFileProcessor/AudioFileProcessor.cpp +++ b/plugins/AudioFileProcessor/AudioFileProcessor.cpp @@ -64,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, @@ -516,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:" ), "%" ); @@ -567,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(); } @@ -619,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" ) ); @@ -787,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 ) { @@ -797,7 +797,7 @@ void AudioFileProcessorWaveView::mousePressEvent( QMouseEvent * _me ) } else { - m_draggingType = wave; + m_draggingType = DraggingType::Wave; updateCursor(_me); } } @@ -808,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); } @@ -828,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() ) ) @@ -983,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() ) @@ -1110,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, @@ -1121,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 ) @@ -1196,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 6c696784a..5fed10862 100644 --- a/plugins/AudioFileProcessor/AudioFileProcessor.h +++ b/plugins/AudioFileProcessor/AudioFileProcessor.h @@ -177,11 +177,11 @@ protected: public: - enum knobType + enum class Point { - start, - end, - loop + Start, + End, + Loop } ; class knob : public Knob @@ -192,7 +192,7 @@ public: public: knob( QWidget * _parent ) : - Knob( knobBright_26, _parent ), + Knob( KnobType::Bright26, _parent ), m_waveView( 0 ), m_relatedKnob( 0 ) { @@ -239,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; @@ -262,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; @@ -276,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 ); } 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 d89383560..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, @@ -345,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 ) ); @@ -431,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 ); @@ -556,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/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/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 c26cd79c4..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, } ; @@ -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 42d64cf07..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(); } @@ -341,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) @@ -366,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 ); } @@ -393,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 ); @@ -408,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; } @@ -680,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; } } @@ -906,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 29f7dc8f1..ef1d623c1 100644 --- a/plugins/Kicker/Kicker.cpp +++ b/plugins/Kicker/Kicker.cpp @@ -54,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, @@ -226,7 +226,7 @@ class KickerKnob : public Knob { public: KickerKnob( QWidget * _parent ) : - Knob( knobStyled, _parent ) + Knob( KnobType::Styled, _parent ) { setFixedSize( 29, 29 ); setObjectName( "smallKnob" ); @@ -238,7 +238,7 @@ class KickerEnvKnob : public TempoSyncKnob { public: KickerEnvKnob( QWidget * _parent ) : - TempoSyncKnob( knobStyled, _parent ) + TempoSyncKnob( KnobType::Styled, _parent ) { setFixedSize( 29, 29 ); setObjectName( "smallKnob" ); @@ -250,7 +250,7 @@ class KickerLargeKnob : public Knob { public: KickerLargeKnob( QWidget * _parent ) : - Knob( knobStyled, _parent ) + Knob( KnobType::Styled, _parent ) { setFixedSize( 34, 34 ); setObjectName( "largeKnob" ); @@ -315,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 cef732adb..b5d065598 100644 --- a/plugins/Kicker/Kicker.h +++ b/plugins/Kicker/Kicker.h @@ -66,7 +66,7 @@ public: Flags flags() const override { - return IsNotBendable; + return Flag::IsNotBendable; } f_cnt_t desiredReleaseFrames() const override 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/Lb302/Lb302.cpp b/plugins/Lb302/Lb302.cpp index c0e477dcc..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(); @@ -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 10dbf5b1f..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, 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 4260bca1a..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, 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 476b24961..f8a2b0d13 100644 --- a/plugins/Organic/Organic.cpp +++ b/plugins/Organic/Organic.cpp @@ -52,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, @@ -74,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" ) ) { @@ -403,7 +405,7 @@ class OrganicKnob : public Knob { public: OrganicKnob( QWidget * _parent ) : - Knob( knobStyled, _parent ) + Knob( KnobType::Styled, _parent ) { setFixedSize( 21, 21 ); } @@ -506,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 ); @@ -560,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, @@ -582,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/Patman/Patman.cpp b/plugins/Patman/Patman.cpp index 7bcd46dcb..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, @@ -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 bd99631b7..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, 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 ef4f884ca..1f0cb7c59 100644 --- a/plugins/Sf2Player/Sf2Player.cpp +++ b/plugins/Sf2Player/Sf2Player.cpp @@ -63,7 +63,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, @@ -200,8 +200,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 +616,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 ); } @@ -936,7 +936,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 33f588521..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" ) ) { } @@ -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 3b41d8972..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 ) { @@ -323,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 ); } @@ -360,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 @@ -406,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; @@ -459,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 be144e764..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, @@ -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/TripleOscillator/TripleOscillator.cpp b/plugins/TripleOscillator/TripleOscillator.cpp index c66247541..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), @@ -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/Vibed.cpp b/plugins/Vibed/Vibed.cpp index 014ab1429..3ed51fe79 100644 --- a/plugins/Vibed/Vibed.cpp +++ b/plugins/Vibed/Vibed.cpp @@ -56,7 +56,7 @@ Plugin::Descriptor PLUGIN_EXPORT vibedstrings_plugin_descriptor = QT_TRANSLATE_NOOP("PluginBrowser", "Vibrating string modeler"), "Danny McRae ", 0x0100, - Plugin::Instrument, + Plugin::Type::Instrument, new PluginPixmapLoader("logo"), nullptr, nullptr @@ -272,14 +272,14 @@ namespace gui VibedView::VibedView(Instrument* instrument, QWidget* parent) : InstrumentViewFixedSize(instrument, parent), - m_volumeKnob(knobBright_26, this), - m_stiffnessKnob(knobBright_26, this), - m_pickKnob(knobBright_26, this), - m_pickupKnob(knobBright_26, this), - m_panKnob(knobBright_26, this), - m_detuneKnob(knobBright_26, this), - m_randomKnob(knobBright_26, this), - m_lengthKnob(knobBright_26, this), + 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")), diff --git a/plugins/Vibed/Vibed.h b/plugins/Vibed/Vibed.h index 308ae64d5..18d334c4d 100644 --- a/plugins/Vibed/Vibed.h +++ b/plugins/Vibed/Vibed.h @@ -65,7 +65,7 @@ public: QString nodeName() const override; - Flags flags() const override { return IsNotBendable; } + Flags flags() const override { return Flag::IsNotBendable; } gui::PluginView* instantiateView(QWidget* parent) override; 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 7916eb45f..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, @@ -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 3cc5564e6..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 }; } @@ -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/core/AudioEngine.cpp b/src/core/AudioEngine.cpp index 59c7f2cd2..21a9a3598 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 ), @@ -357,7 +357,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 ); } @@ -405,7 +405,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 ); } @@ -464,12 +464,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 +534,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); } @@ -681,7 +681,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 +732,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 +749,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 +758,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/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 c25e813cb..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 ), @@ -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 ); } @@ -571,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; @@ -623,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] ); diff --git a/src/core/AutomationClip.cpp b/src/core/AutomationClip.cpp index e55fc5c1e..906cb148c 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 ); @@ -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(); @@ -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() ); @@ -891,7 +891,7 @@ bool AutomationClip::isAutomated( const AutomatableModel * _m ) 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()) { @@ -926,7 +926,7 @@ std::vector AutomationClip::clipsForModel(const AutomatableMod 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()) @@ -985,7 +985,7 @@ void AutomationClip::resolveAllIDs() 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()) { diff --git a/src/core/BandLimitedWave.cpp b/src/core/BandLimitedWave.cpp index a92b22e21..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 ); + 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 ); + 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 ); + 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/ConfigManager.cpp b/src/core/ConfigManager.cpp index 05574ae35..61d84770a 100644 --- a/src/core/ConfigManager.cpp +++ b/src/core/ConfigManager.cpp @@ -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(); } @@ -707,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 e7031f20c..3e1b596b8 100644 --- a/src/core/Controller.cpp +++ b/src/core/Controller.cpp @@ -44,7 +44,7 @@ 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,7 +53,7 @@ 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.push_back(this); // Determine which name to use @@ -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 a4477c563..fea907942 100644 --- a/src/core/ControllerConnection.cpp +++ b/src/core/ControllerConnection.cpp @@ -50,7 +50,7 @@ ControllerConnection::ControllerConnection(Controller * _controller) : } else { - m_controller = Controller::create( Controller::DummyController, + m_controller = Controller::create( Controller::ControllerType::Dummy, nullptr ); } s_connections.push_back(this); @@ -60,7 +60,7 @@ ControllerConnection::ControllerConnection(Controller * _controller) : 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 ) { @@ -72,7 +72,7 @@ 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 ); } @@ -104,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 { @@ -119,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()), @@ -127,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 @@ -168,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; @@ -228,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 2361b1926..6ad2f8526 100644 --- a/src/core/DataFile.cpp +++ b/src/core/DataFile.cpp @@ -26,6 +26,7 @@ #include "DataFile.h" +#include #include #include @@ -98,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" } }; } @@ -214,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()) || @@ -251,7 +251,7 @@ QString DataFile::nameWithExtension( const QString & _fn ) const switch( type() ) { - case SongProject: + case Type::SongProject: if( extension != "mmp" && extension != "mpt" && extension != "mmpz" ) @@ -264,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"; @@ -286,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() ); } @@ -585,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; } @@ -607,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; } @@ -1760,8 +1751,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")); } @@ -1789,7 +1780,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" ) ) @@ -1867,8 +1858,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/EnvelopeAndLfoParameters.cpp b/src/core/EnvelopeAndLfoParameters.cpp index a3f41b5aa..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; 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/InstrumentFunctions.cpp b/src/core/InstrumentFunctions.cpp index d2fea9dbd..431afd2fe 100644 --- a/src/core/InstrumentFunctions.cpp +++ b/src/core/InstrumentFunctions.cpp @@ -234,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() ) { @@ -263,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 ) ); } } @@ -321,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" ) ); @@ -336,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() ) { @@ -351,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() ); @@ -375,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() ) { @@ -397,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 @@ -418,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. :) @@ -427,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... @@ -456,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... :) @@ -469,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 ) ); @@ -479,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() ); @@ -507,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 4aeea453a..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,17 +303,17 @@ 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() ) { 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 c0fe65855..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 ), @@ -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/Mixer.cpp b/src/core/Mixer.cpp index 5edd88a0a..e14660e1f 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -301,7 +301,7 @@ void Mixer::deleteChannel( int index ) 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); @@ -317,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); @@ -401,7 +401,7 @@ void Mixer::moveChannelLeft( int index ) { 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); @@ -414,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); @@ -630,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(); @@ -863,7 +863,7 @@ bool Mixer::isChannelInUse(int index) 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) @@ -871,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 1198abdec..a4ad61412 100644 --- a/src/core/Note.cpp +++ b/src/core/Note.cpp @@ -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 31f7e81cb..70007ebf1 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 ); } @@ -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 ); @@ -575,8 +575,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 3d0b60acf..c5a352139 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); } @@ -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); } @@ -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(); } @@ -218,7 +218,7 @@ void PatternStore::currentPatternChanged() TrackList tl = Engine::getSong()->tracks(); for (Track * t : tl) { - if (t->type() == Track::PatternTrack) + if (t->type() == Track::Type::Pattern) { t->dataChanged(); } diff --git a/src/core/PeakController.cpp b/src/core/PeakController.cpp index af0e7e69d..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 ) { 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 3790a7ec9..ec0f4ec4e 100644 --- a/src/core/PluginFactory.cpp +++ b/src/core/PluginFactory.cpp @@ -109,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/RenderManager.cpp b/src/core/RenderManager.cpp index 8c031b970..969cad15b 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() ), @@ -102,11 +102,11 @@ void RenderManager::renderTracks() // 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); } @@ -115,11 +115,11 @@ void RenderManager::renderTracks() 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); } diff --git a/src/core/SampleBuffer.cpp b/src/core/SampleBuffer.cpp index 2f35b23a8..775db125b 100644 --- a/src/core/SampleBuffer.cpp +++ b/src/core/SampleBuffer.cpp @@ -738,7 +738,7 @@ bool SampleBuffer::play( // this holds the index of the first frame to play 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,13 +907,13 @@ 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 = std::min(frames, loopEnd - index); memcpy(*tmp, m_data + index, copied * BYTES_PER_FRAME); diff --git a/src/core/SampleClip.cpp b/src/core/SampleClip.cpp index 87d6351bc..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 ); @@ -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 6f4c5212e..e8073f225 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(); @@ -388,7 +388,7 @@ void Song::processAutomations(const TrackList &tracklist, TimePos timeStart, fpp 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 ); } @@ -859,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 ); } @@ -960,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(); @@ -1080,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() ) @@ -1119,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(); @@ -1167,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() ); } } } @@ -1185,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 @@ -1235,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" ); @@ -1253,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() ); @@ -1280,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(); @@ -1328,7 +1328,7 @@ void Song::restoreControllerStates( const QDomElement & element ) else { // Fix indices to ensure correct connections - m_controllers.push_back(Controller::create(Controller::DummyController, this)); + m_controllers.push_back(Controller::create(Controller::ControllerType::Dummy, this)); } node = node.nextSibling(); diff --git a/src/core/TempoSyncKnobModel.cpp b/src/core/TempoSyncKnobModel.cpp index 6fb457f2c..e89716ab2 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: ; @@ -138,18 +138,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 +174,7 @@ void TempoSyncKnobModel::setScale( float _new_scale ) void TempoSyncKnobModel::updateCustom() { - setSyncMode( SyncCustom ); + setSyncMode( SyncMode::Custom ); } 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 33b9c8ef3..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 */ @@ -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" ); @@ -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 af96ff1c4..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(); @@ -268,9 +268,9 @@ 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 { diff --git a/src/core/UpgradeExtendedNoteRange.cpp b/src/core/UpgradeExtendedNoteRange.cpp index 41cbc5c26..e61da3723 100644 --- a/src/core/UpgradeExtendedNoteRange.cpp +++ b/src/core/UpgradeExtendedNoteRange.cpp @@ -183,10 +183,10 @@ static void fixTrack(QDomElement & track, std::set & automatedBase return; } - Track::TrackTypes const trackType = static_cast(track.attribute("type").toInt()); + 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::PatternTrack) + if (trackType == Track::Type::Pattern) { // Assuming that a BB track cannot contain another BB track here... QDomNodeList subTracks = track.elementsByTagName("track"); @@ -233,7 +233,7 @@ static void fixAutomationTracks(QDomElement & song, std::set const for (int i = 0; i < tracks.size(); ++i) { QDomElement currentTrack = tracks.item(i).toElement(); - if (currentTrack.attribute("type").toInt() != Track::AutomationTrack) + if (static_cast(currentTrack.attribute("type").toInt()) != Track::Type::Automation) { continue; } diff --git a/src/core/audio/AudioFileFlac.cpp b/src/core/audio/AudioFileFlac.cpp index 9b49017c8..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) 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/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/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 2faee067d..a4625936e 100644 --- a/src/core/lv2/Lv2Ports.cpp +++ b/src/core/lv2/Lv2Ports.cpp @@ -126,7 +126,7 @@ std::vector Meta::get(const LilvPlugin *plugin, 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/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/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..559756169 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 ); @@ -377,7 +377,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 ) @@ -514,7 +514,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 +600,7 @@ void MainWindow::resetWindowTitle() title += '*'; } - if( getSession() == Recover ) + if( getSession() == SessionState::Recover ) { title += " - " + tr( "Recover session. Please save your work!" ); } @@ -618,7 +618,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 +635,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 +652,7 @@ bool MainWindow::mayChangeProject(bool stopPlayback) } else if( answer == QMessageBox::Discard ) { - if( getSession() == Recover ) + if( getSession() == SessionState::Recover ) { sessionCleanup(); } @@ -795,7 +795,7 @@ bool MainWindow::saveProject() } else if( this->guiSaveProject() ) { - if( getSession() == Recover ) + if( getSession() == SessionState::Recover ) { sessionCleanup(); } @@ -850,7 +850,7 @@ bool MainWindow::saveProjectAs() } if( this->guiSaveProjectAs( fname ) ) { - if( getSession() == Recover ) + if( getSession() == SessionState::Recover ) { sessionCleanup(); } @@ -1214,19 +1214,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 +1288,7 @@ void MainWindow::sessionCleanup() { // delete recover session files QFile::remove( ConfigManager::inst()->recoveryFile() ); - setSession( Normal ); + setSession( SessionState::Normal ); } @@ -1480,7 +1480,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 +1625,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 +1643,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..7ab4cc0b1 100644 --- a/src/gui/MicrotunerConfig.cpp +++ b/src/gui/MicrotunerConfig.cpp @@ -64,6 +64,16 @@ MicrotunerConfig::MicrotunerConfig() : 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")); 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..0edebcb8a 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 ); @@ -245,13 +255,13 @@ void MixerView::updateMaxChannelSelector() { 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/clips/AutomationClipView.cpp b/src/gui/clips/AutomationClipView.cpp index a5d415a2e..3e0e12b75 100644 --- a/src/gui/clips/AutomationClipView.cpp +++ b/src/gui/clips/AutomationClipView.cpp @@ -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 b78605906..7a7a19c11 100644 --- a/src/gui/clips/ClipView.cpp +++ b/src/gui/clips/ClipView.cpp @@ -87,7 +87,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() ), @@ -435,7 +435,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()) ) ); } } @@ -457,7 +457,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; } @@ -537,7 +537,7 @@ 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) @@ -547,7 +547,7 @@ DataFile ClipView::createClipDataFiles( int trackIndex = std::distance(tc->tracks().begin(), std::find(tc->tracks().begin(), tc->tracks().end(), clipTrack)); 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 ); @@ -645,27 +645,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); } @@ -675,22 +675,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 ); @@ -698,11 +698,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" ). @@ -710,7 +710,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)" ). @@ -727,11 +727,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), @@ -748,9 +748,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) { @@ -790,12 +790,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 = @@ -816,7 +816,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 ); @@ -827,7 +827,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 ); } } @@ -839,7 +839,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); @@ -851,7 +851,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 ); @@ -881,13 +881,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 ); @@ -990,7 +990,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) { @@ -1015,21 +1015,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; @@ -1039,7 +1039,7 @@ void ClipView::mouseReleaseEvent( QMouseEvent * me ) ); } - m_action = NoAction; + m_action = Action::None; delete m_hint; m_hint = nullptr; s_textFloat->hide(); @@ -1079,7 +1079,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(); @@ -1088,14 +1088,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); } ); } } @@ -1105,12 +1105,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(); @@ -1119,7 +1119,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(); @@ -1143,22 +1143,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; } @@ -1205,7 +1205,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() ); } 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 1289c5626..a24165332 100644 --- a/src/gui/editors/AutomationEditor.cpp +++ b/src/gui/editors/AutomationEditor.cpp @@ -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..229c90bc2 100644 --- a/src/gui/editors/PatternEditor.cpp +++ b/src/gui/editors/PatternEditor.cpp @@ -73,7 +73,7 @@ void PatternEditor::removeSteps() 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() ); } @@ -180,7 +180,7 @@ void PatternEditor::makeSteps( bool clone ) 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 753dfe77f..0cc825725 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,11 +138,11 @@ 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 } ; @@ -168,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 ), @@ -191,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), @@ -241,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 ); @@ -298,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& ) ), @@ -314,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& ) ) );*/ @@ -524,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()) @@ -533,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() ) @@ -553,7 +553,7 @@ void PianoRoll::markSemiTone(int i, bool fromMenu) } break; } - case stmaMarkAllOctaveSemiTones: + case SemiToneMarkerAction::MarkAllOctaveSemiTones: { QList aok = getAllOctavesForKey(key); @@ -578,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 ) { @@ -611,7 +611,7 @@ void PianoRoll::markSemiTone(int i, bool fromMenu) } break; } - case stmaCopyAllNotesOnKey: + case SemiToneMarkerAction::CopyAllNotesOnKey: { selectNotesOnKey(); break; @@ -858,7 +858,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 ); } @@ -1146,12 +1146,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; } @@ -1299,7 +1299,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) { @@ -1316,7 +1316,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_ @@ -1334,7 +1334,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()) @@ -1350,8 +1350,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, @@ -1370,7 +1370,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()) @@ -1378,7 +1378,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()) @@ -1409,8 +1409,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, @@ -1446,7 +1446,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(); } @@ -1501,7 +1501,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; } @@ -1512,7 +1512,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(); } @@ -1531,7 +1531,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); @@ -1544,7 +1544,7 @@ void PianoRoll::keyReleaseEvent(QKeyEvent* ke ) switch( ke->key() ) { case Qt::Key_Control: - if (m_editMode == ModeEditKnife) + if (m_editMode == EditMode::Knife) { break; } @@ -1637,7 +1637,7 @@ 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(); @@ -1656,7 +1656,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) @@ -1675,10 +1675,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(); } @@ -1694,7 +1694,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; } @@ -1764,7 +1764,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; @@ -1871,7 +1871,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 @@ -1901,7 +1901,7 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) } // otherwise move it - m_action = ActionMoveNote; + m_action = Action::MoveNote; // set move-cursor setCursor( Qt::SizeAllCursor ); @@ -1931,8 +1931,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; @@ -1944,7 +1944,7 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) } } else if( me->button() == Qt::LeftButton && - m_editMode == ModeSelect ) + m_editMode == EditMode::Select ) { // select an area of notes @@ -1952,7 +1952,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 @@ -1990,7 +1990,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; } @@ -2163,11 +2163,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(); } @@ -2176,7 +2176,7 @@ void PianoRoll::setKnifeAction() void PianoRoll::cancelKnifeAction() { m_editMode = m_knifeMode; - m_action = ActionNone; + m_action = Action::None; update(); } @@ -2281,7 +2281,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(); } @@ -2290,14 +2290,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- @@ -2306,7 +2306,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 @@ -2345,12 +2345,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 ); } @@ -2372,7 +2372,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. @@ -2382,7 +2382,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) @@ -2406,22 +2406,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 ) { @@ -2434,14 +2434,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(); } @@ -2454,13 +2454,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 ) ) ) { @@ -2501,12 +2501,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() ); @@ -2533,7 +2533,7 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) ( isUnderPosition && n->selected() && altPressed ) ) { - if( m_noteEditMode == NoteEditVolume ) + if( m_noteEditMode == NoteEditMode::Volume ) { n->setVolume( vol ); @@ -2541,7 +2541,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 ) ); @@ -2566,7 +2566,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 @@ -2619,8 +2619,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 @@ -2640,8 +2640,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 @@ -2693,7 +2693,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) @@ -2703,8 +2703,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; @@ -2823,11 +2823,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); @@ -2849,7 +2849,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) @@ -2877,7 +2877,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; @@ -2901,7 +2901,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 @@ -3002,7 +3002,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(); @@ -3099,7 +3099,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; @@ -3153,11 +3153,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 @@ -3170,15 +3170,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 @@ -3189,10 +3189,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 @@ -3212,8 +3212,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); } @@ -3224,7 +3224,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); } @@ -3238,7 +3238,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; @@ -3252,7 +3252,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); } @@ -3263,17 +3263,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); } @@ -3381,7 +3381,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... @@ -3507,7 +3507,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() ) @@ -3525,7 +3525,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() ) @@ -3559,7 +3559,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 + ( @@ -3696,12 +3696,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; } @@ -3710,10 +3710,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()) @@ -3756,7 +3756,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(); } @@ -3794,7 +3794,7 @@ void PianoRoll::wheelEvent(QWheelEvent * we ) 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 ) { @@ -3813,7 +3813,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 ) { @@ -3921,9 +3921,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; } @@ -3968,13 +3968,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; } @@ -3987,7 +3987,7 @@ void PianoRoll::play() return; } - if( Engine::getSong()->playMode() != Song::Mode_PlayMidiClip ) + if( Engine::getSong()->playMode() != Song::PlayMode::MidiClip ) { Engine::getSong()->playMidiClip( m_midiClip ); } @@ -4065,7 +4065,7 @@ bool PianoRoll::toggleStepRecording() { m_stepRecorder.start( Engine::getSong()->getPlayPos( - Song::Mode_PlayMidiClip), newNoteLen()); + Song::PlayMode::MidiClip), newNoteLen()); } } } @@ -4080,7 +4080,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 ); } @@ -4093,10 +4093,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(); } @@ -4127,7 +4127,7 @@ 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 ) @@ -4179,7 +4179,7 @@ void PianoRoll::verScrolled( int new_pos ) void PianoRoll::setEditMode(int mode) { - m_ctrlMode = m_editMode = (EditModes) mode; + m_ctrlMode = m_editMode = (EditMode) mode; } @@ -4271,7 +4271,7 @@ void PianoRoll::selectNotesOnKey() void PianoRoll::enterValue( NoteVector* nv ) { - if( m_noteEditMode == NoteEditVolume ) + if( m_noteEditMode == NoteEditMode::Volume ) { bool ok; int new_val; @@ -4290,7 +4290,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; @@ -4338,7 +4338,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 ); @@ -4495,8 +4495,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 ); @@ -4532,16 +4532,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 ); } } @@ -4596,7 +4596,7 @@ void PianoRoll::noteLengthChanged() void PianoRoll::keyChanged() { - markSemiTone(stmaMarkCurrentScale, false); + markSemiTone(SemiToneMarkerAction::MarkCurrentScale, false); } int PianoRoll::quantization() const @@ -4617,7 +4617,7 @@ int PianoRoll::quantization() const } -void PianoRoll::quantizeNotes(QuantizeActions mode) +void PianoRoll::quantizeNotes(QuantizeAction mode) { if( ! hasValidMidiClip() ) { @@ -4645,11 +4645,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()); } @@ -4737,9 +4737,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()); } @@ -4783,8 +4783,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); @@ -5189,7 +5189,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 ); } @@ -5281,7 +5281,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 939c1fdf4..518068759 100644 --- a/src/gui/editors/SongEditor.cpp +++ b/src/gui/editors/SongEditor.cpp @@ -82,7 +82,7 @@ SongEditor::SongEditor( Song * song ) : 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(), @@ -99,11 +99,11 @@ SongEditor::SongEditor( Song * song ) : 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& ) ) ); @@ -341,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 ) ); } @@ -456,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() @@ -496,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 ) @@ -504,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 ) { @@ -560,7 +560,7 @@ void SongEditor::wheelEvent( QWheelEvent * we ) m_leftRightScroll->setValue(m_leftRightScroll->value() + bar - newBar); // 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(); } @@ -788,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(); @@ -808,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 ) { @@ -872,7 +872,7 @@ void SongEditor::zoomingChanged() int ppb = calculatePixelsPerBar(); setPixelsPerBar(ppb); - m_song->m_playPos[Song::Mode_PlaySong].m_timeLine->setPixelsPerBar(ppb); + m_song->getPlayPos(Song::PlayMode::Song).m_timeLine->setPixelsPerBar(ppb); realignTracks(); updateRubberband(); m_timeLine->setSnapSize(getSnapSize()); @@ -895,7 +895,7 @@ void SongEditor::selectAllClips( bool select ) bool SongEditor::allowRubberband() const { - return m_mode == SelectMode; + return m_mode == EditMode::Select; } @@ -903,7 +903,7 @@ bool SongEditor::allowRubberband() const bool SongEditor::knifeMode() const { - return m_mode == KnifeMode; + return m_mode == EditMode::Knife; } @@ -1104,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(); } diff --git a/src/gui/editors/TimeLineWidget.cpp b/src/gui/editors/TimeLineWidget.cpp index b051fa79b..423485a25 100644 --- a/src/gui/editors/TimeLineWidget.cpp +++ b/src/gui/editors/TimeLineWidget.cpp @@ -49,7 +49,7 @@ namespace 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 ), @@ -61,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 ), @@ -74,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; @@ -157,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 ); @@ -171,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) ); } @@ -182,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" ) ) { @@ -214,7 +214,7 @@ void TimeLineWidget::updatePosition( const TimePos & ) void TimeLineWidget::toggleAutoScroll( int _n ) { - m_autoScroll = static_cast( _n ); + m_autoScroll = static_cast( _n ); } @@ -222,7 +222,7 @@ void TimeLineWidget::toggleAutoScroll( int _n ) void TimeLineWidget::toggleLoopPoints( int _n ) { - m_loopPoints = static_cast( _n ); + m_loopPoints = static_cast( _n ); update(); } @@ -231,7 +231,7 @@ void TimeLineWidget::toggleLoopPoints( int _n ) void TimeLineWidget::toggleBehaviourAtStop( int _n ) { - m_behaviourAtStop = static_cast( _n ); + m_behaviourAtStop = static_cast( _n ); } @@ -327,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; @@ -339,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 ) @@ -348,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" ), @@ -373,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 ); @@ -387,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) { @@ -409,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; @@ -431,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 83017fb1a..60a468380 100644 --- a/src/gui/editors/TrackContainerView.cpp +++ b/src/gui/editors/TrackContainerView.cpp @@ -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..43cca0dac 100644 --- a/src/gui/instrument/InstrumentTrackWindow.cpp +++ b/src/gui/instrument/InstrumentTrackWindow.cpp @@ -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 ); @@ -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,7 +374,7 @@ 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_track->m_microtuner.enabledModel()->setValue(false); @@ -425,7 +425,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 +466,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/PianoView.cpp b/src/gui/instrument/PianoView.cpp index a2df50e47..20db2e8e8 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 * @@ -398,8 +400,8 @@ int PianoView::getKeyFromMouse( const QPoint & _p ) const */ void PianoView::pianoScrolled(int new_pos) { - m_startKey = WhiteKeys[new_pos % Piano::WhiteKeysPerOctave] + - (new_pos / Piano::WhiteKeysPerOctave) * KeysPerOctave; + m_startKey = static_cast(new_pos / Piano::WhiteKeysPerOctave) + + WhiteKeys[new_pos % Piano::WhiteKeysPerOctave]; update(); } @@ -625,8 +627,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 +655,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 +913,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 +927,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 040ed9e0f..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 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..669fdaccb 100644 --- a/src/gui/tracks/InstrumentTrackView.cpp +++ b/src/gui/tracks/InstrumentTrackView.cpp @@ -87,7 +87,7 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV widgetWidth = DEFAULT_SETTINGS_WIDGET_WIDTH; } - 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 ); @@ -96,7 +96,7 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV 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:"), "%"); @@ -110,9 +110,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( diff --git a/src/gui/tracks/SampleTrackView.cpp b/src/gui/tracks/SampleTrackView.cpp index fbdd41ded..6a6a2c5fd 100644 --- a/src/gui/tracks/SampleTrackView.cpp +++ b/src/gui/tracks/SampleTrackView.cpp @@ -59,7 +59,7 @@ SampleTrackView::SampleTrackView( SampleTrack * _t, TrackContainerView* tcv ) : m_tlb->move(3, 1); m_tlb->show(); - m_volumeKnob = new Knob( knobSmall_17, getTrackSettingsWidget(), + m_volumeKnob = new Knob( KnobType::Small17, getTrackSettingsWidget(), tr( "Track volume" ) ); m_volumeKnob->setVolumeKnob( true ); m_volumeKnob->setModel( &_t->m_volumeModel ); @@ -73,7 +73,7 @@ SampleTrackView::SampleTrackView( SampleTrack * _t, TrackContainerView* tcv ) : 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:" ), "%" ); diff --git a/src/gui/tracks/TrackContentWidget.cpp b/src/gui/tracks/TrackContentWidget.cpp index ca7123bda..442d717bf 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,7 +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()))) + if (type != ("clip_" + QString::number(static_cast(t->type())))) { return false; } @@ -382,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() ) { @@ -538,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 ) @@ -655,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 ); @@ -669,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/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..d67c6dbdd 100644 --- a/src/gui/widgets/Knob.cpp +++ b/src/gui/widgets/Knob.cpp @@ -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; } diff --git a/src/gui/widgets/LedCheckBox.cpp b/src/gui/widgets/LedCheckBox.cpp index 1be072815..0c16bf391 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 ) : + const QString & _name, LedColor _color ) : AutomatableButton( _parent, _name ), m_text( _text ) { @@ -55,7 +55,7 @@ LedCheckBox::LedCheckBox( const QString & _text, QWidget * _parent, LedCheckBox::LedCheckBox( QWidget * _parent, - const QString & _name, LedColors _color ) : + const QString & _name, LedColor _color ) : LedCheckBox( QString(), _parent, _name, _color ) { } @@ -103,16 +103,12 @@ void LedCheckBox::paintEvent( QPaintEvent * ) -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" ) ); setFont( pointSize<7>( font() ) ); diff --git a/src/gui/widgets/TempoSyncKnob.cpp b/src/gui/widgets/TempoSyncKnob.cpp index 86ee6df3c..b58e61cf4 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" ) ), @@ -104,51 +104,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 +162,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 +174,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 +210,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 +305,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 a688aed9a..84b73614b 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -45,7 +45,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 ), @@ -220,7 +220,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 +230,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,7 +260,7 @@ 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 ); @@ -343,7 +343,7 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const TimePos& tim typeInfo::max() / 2, Note( TimePos(), TimePos(), 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 +363,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 +403,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 +536,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(); @@ -726,7 +726,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; } diff --git a/src/tracks/MidiClip.cpp b/src/tracks/MidiClip.cpp index 4fa2af5d8..b35979f61 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,7 +111,7 @@ 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) { @@ -144,7 +144,7 @@ void MidiClip::init() void MidiClip::updateLength() { - if( m_clipType == BeatClip ) + if( m_clipType == Type::BeatClip ) { changeLength( beatClipLength() ); updatePatternTrack(); @@ -337,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; } @@ -355,11 +355,11 @@ void MidiClip::checkType() { if (note->length() > 0) { - setType(MelodyClip); + setType(Type::MelodyClip); return; } } - setType( BeatClip ); + setType( Type::BeatClip ); } @@ -367,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() ) @@ -401,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" ) ); 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/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); From a311eed8e8c4fc4efc0683160edfe01d2b92f327 Mon Sep 17 00:00:00 2001 From: saker Date: Fri, 25 Aug 2023 14:43:09 -0400 Subject: [PATCH 100/308] Add Tap Tempo (#6375) * Add Tap Tempo Feature (#6375) Resolves #5181 * Update formatting, use namespaces, etc. * Use Qt Designer .ui file to handle the UI Thanks to irrenhaus for the idea Also added a few buttons I will add functionality for * Play metronome sound when tapped * Improve stabilization speed by comparing differences in length between intervals To improve the speed at which the BPM counter stabilizes at a certain number, we now compare the differences in length between the last two taps and the most recent two taps and reset the counter if the threshold is passed. I made it so that a difference of 500 ms resets the counter. * Remove duplicate m_ui An artifact from my battle with Git and merge conflicts.. * Format TapTempoUi header file * Add lmms namespace in UI file * Remove taptempo.ui XML file Not needed * Add LMMS_EXPORT to SamplePlayHandle * Use std::chrono::duration for intervals Co-authored-by: irrenhaus3 * Use alias for steady_clock Co-authored-by: irrenhaus3 * Speed up convergence by accounting for recent intervals This uses a combination of keeping track of a more accurate BPM, while also using a BPM difference threshold to move towards the true BPM more quickly. After three taps, a "recent interval" is calculated, which is similar to the latest interval, but less fluctuating since it accounts for three taps instead of one. This allows for comparing between the BPM on the display with the recent BPM more closely. We then compare the difference in magnitude of both BPM's with the threshold. If the threshold is passed, the counter gets reset. * Remove semicolon from "QOBJECT;" in plugins/TapTempo/TapTempo.h Co-authored-by: Hyunjin Song * Add newline between using alias and constructor * Cleanup header files * Add // namespace lmms::gui comment * Rename header guards in plugins/TapTempo/TapTempo.h Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com> * Rename header guards in plugins/TapTempo/TapTempo.h Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com> * Rename header guards in plugins/TapTempo/TapTempoUi.h Will merge this file with ``TapTempoView`` soon. Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com> * Rename header guards in plugins/TapTempo/TapTempoUi.h Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com> * Update plugins/TapTempo/TapTempo.h Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com> * Replace virtual with override in plugins/TapTempo/TapTempo.h Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com> * Merge UI file into TapTempoView * Pass TapTempo* directly into constructor in plugins/TapTempo/TapTempoView.h Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com> * Update style in plugins/TapTempo/TapTempoView.h Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com> * Add parameter name for keyPressEvent function in plugins/TapTempo/TapTempoView.h Also reorder the function declarations to match the order in the source file. Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com> * Remove dynamic_cast to TapTempo* in plugins/TapTempo/TapTempoView.cpp Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com> * Restrict C linkage to only lmms_plugin_main and plugin descriptor Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com> * Simplify algorithm * Update labels when calling closeEvent * Add reset button * Adjust layout * Format document * Only allow the tap button to gain focus * Use icon provided by LMMS * Add sync button and adjust formatting * Make the metronome downbeat the first beat Also simplify code Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com> * Round BPM values when syncing with project tempo Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com> * Change Plugin::Tool to Plugin::Type::Tool --------- Co-authored-by: Hyunjin Song Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com> --- cmake/modules/PluginList.cmake | 1 + include/SamplePlayHandle.h | 2 +- plugins/TapTempo/CMakeLists.txt | 3 + plugins/TapTempo/TapTempo.cpp | 85 +++++++++++++++ plugins/TapTempo/TapTempo.h | 61 +++++++++++ plugins/TapTempo/TapTempoView.cpp | 168 ++++++++++++++++++++++++++++++ plugins/TapTempo/TapTempoView.h | 64 ++++++++++++ plugins/TapTempo/logo.png | Bin 0 -> 510 bytes 8 files changed, 383 insertions(+), 1 deletion(-) create mode 100644 plugins/TapTempo/CMakeLists.txt create mode 100644 plugins/TapTempo/TapTempo.cpp create mode 100644 plugins/TapTempo/TapTempo.h create mode 100644 plugins/TapTempo/TapTempoView.cpp create mode 100644 plugins/TapTempo/TapTempoView.h create mode 100644 plugins/TapTempo/logo.png 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/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/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 0000000000000000000000000000000000000000..67e6a350346a826763c804621bae006580a71ef7 GIT binary patch literal 510 zcmV Date: Fri, 25 Aug 2023 21:16:34 -0400 Subject: [PATCH 101/308] fixes #6759: Tempo Sync Knob - Context menu string don't update on custom tempo (#6827) * fixed #6759: Context menu string doesn't update The TempoSyncKnobModel didn't emit any signal when the a SyncMode::Custom was recaclulated. Also it looks like someone broke the TempoSyncKnowModel bc SyncMode had been renamed to TempoSyncMode and the build was screaming. * fixed #6759: Knob custom tempo The TempoSyncKnobModel didn't emit any signal when the a SyncMode::Custom was recalculated. Also it looks like someone broke the TempoSyncKnowModel because SyncMode had been renamed to TempoSyncMode and the build was screaming. Recommit, fixed silly mistake where the signal would be emitted twice on mode change to Custom. * Update src/core/TempoSyncKnobModel.cpp Co-authored-by: saker * Update src/core/TempoSyncKnobModel.cpp Co-authored-by: saker * Use function pointers for connect TempoSyncKnob.cpp * Silly fp mistake fixed in TempoSyncKnob.cpp * Unfixed second macro call for now: TempoSyncKnob.cpp --------- Co-authored-by: saker --- src/core/TempoSyncKnobModel.cpp | 4 ++++ src/gui/widgets/TempoSyncKnob.cpp | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/core/TempoSyncKnobModel.cpp b/src/core/TempoSyncKnobModel.cpp index e89716ab2..7f707478f 100644 --- a/src/core/TempoSyncKnobModel.cpp +++ b/src/core/TempoSyncKnobModel.cpp @@ -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); + } } diff --git a/src/gui/widgets/TempoSyncKnob.cpp b/src/gui/widgets/TempoSyncKnob.cpp index b58e61cf4..473cee28c 100644 --- a/src/gui/widgets/TempoSyncKnob.cpp +++ b/src/gui/widgets/TempoSyncKnob.cpp @@ -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(); From 7000afb2eac1deab0ed76db48371613525b94986 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sat, 26 Aug 2023 04:11:03 +0200 Subject: [PATCH 102/308] Modifier keys for mouse wheel adjustments (#6769) (#6770) * Modifier keys for mouse wheel adjustments (#6769) Give the users the option to use modifier keys (Shift, Ctrl, Alt) to switch between different scales of adjustment when changing knob values using the mouse wheel. The commit implements the following behaviour: * Using the mouse wheel without any modifier keys makes coarser adjustments than the current default, i.e. the range of the parameter can be swept with 100 mouse wheel events instead of 2000. * Pressing the "Shift" key while using the mouse wheel allows making coarser adjustments than the default. The range can be swept with 10 mouse wheel events. * Pressing the "Ctrl" key allows making finer adjustments than the default. The range is swept with 1000 events. * Pressing the "Alt" key allows even finer adjustments. The range is swept with 2000 events (the current default). Most of these scales are organized in magnitudes (10, 100, 1000) which should give a very natural feeling to "zone in" on a value. * Fix indentation of comments Fix the indention of comments as Qt Creator seems to be incapable of copy-pasting code in a sensible way. * Fix comments Fix the comments by describing better the ideas instead of referencing values. * Fix format in src/gui/widgets/Knob.cpp --------- Co-authored-by: saker --- src/gui/widgets/Knob.cpp | 48 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/src/gui/widgets/Knob.cpp b/src/gui/widgets/Knob.cpp index d67c6dbdd..c2f90fb2b 100644 --- a/src/gui/widgets/Knob.cpp +++ b/src/gui/widgets/Knob.cpp @@ -689,10 +689,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 ) ); From fc2f6a0b31bdd10c47cc0c6c2c18723d208eaae0 Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Sat, 26 Aug 2023 11:53:34 +0900 Subject: [PATCH 103/308] Replace the CI status badge with GitHub Actions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) From 4cb09e2b6058155efc9920ea09a973071ce1c58e Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sun, 27 Aug 2023 18:21:38 +0200 Subject: [PATCH 104/308] Fix the base note automation fix (#6828) Towards the end of the development for the fix of #6548 (via #6725) the upgrade code was refactored into its own class. While doing so it was forgotten to actually call the `upgrade` method on the `UpgradeExtendedNoteRange` instance. As a result almost all files should currently open in a wrong state with many instruments transposed. This commit fixes this. Also explicitly check the assertion that BB tracks do not contain other BB tracks. --- src/core/DataFile.cpp | 2 ++ src/core/UpgradeExtendedNoteRange.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/src/core/DataFile.cpp b/src/core/DataFile.cpp index 6ad2f8526..5c98ec81c 100644 --- a/src/core/DataFile.cpp +++ b/src/core/DataFile.cpp @@ -1671,6 +1671,8 @@ void DataFile::upgrade_extendedNoteRange() { auto root = documentElement(); UpgradeExtendedNoteRange upgradeExtendedNoteRange(root); + + upgradeExtendedNoteRange.upgrade(); } diff --git a/src/core/UpgradeExtendedNoteRange.cpp b/src/core/UpgradeExtendedNoteRange.cpp index e61da3723..6ed98e63e 100644 --- a/src/core/UpgradeExtendedNoteRange.cpp +++ b/src/core/UpgradeExtendedNoteRange.cpp @@ -193,6 +193,7 @@ static void fixTrack(QDomElement & track, std::set & automatedBase 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); } } From e2fd288ae7413e37e078a1f1b57ba9bf45761a3a Mon Sep 17 00:00:00 2001 From: MrTopom Date: Sun, 27 Aug 2023 20:11:41 +0200 Subject: [PATCH 105/308] =?UTF-8?q?Change=20the=20title=20for=20SideBarWid?= =?UTF-8?q?gets=20to=20be=20vertically=20centered=20related=E2=80=A6=20(#6?= =?UTF-8?q?833)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Change the title for SideBarWidgets to be vertically centered related to icon and with no underlining * Update src/gui/SideBarWidget.cpp Co-authored-by: saker --------- Co-authored-by: saker --- src/gui/SideBarWidget.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 ) ) ); From 1e6a66f4ac4ecd3890d1dc66268590979cfb2b53 Mon Sep 17 00:00:00 2001 From: saker Date: Mon, 28 Aug 2023 13:14:19 -0400 Subject: [PATCH 106/308] Add mixer LCD channels for Instrument & Sample tracks (#6831) * Add mixer channel LCD to SampleTrackView * Increase sizes to compensate for LCD box The DEFAULT_SETTINGS_WIDGET_WIDTH and DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT were both increased by +32 pixels. TRACK_OP_WIDTH and TRACK_OP_WIDTH_COMPACT were then changed relative to that increase. * Use Qt layout in SampleTrackView * Add mixer channel LCD to InstrumentTrackView * Move LCD box to the right of the track label * Revert changes to TRACK_OP_WIDTH and TRACK_OP_WIDTH_COMPACT --- include/InstrumentTrackView.h | 3 +++ include/SampleTrackView.h | 2 ++ include/TrackView.h | 4 +-- src/gui/tracks/InstrumentTrackView.cpp | 36 ++++++++++++++------------ src/gui/tracks/SampleTrackView.cpp | 23 ++++++++++------ 5 files changed, 42 insertions(+), 26 deletions(-) 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/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/TrackView.h b/include/TrackView.h index 763705599..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; diff --git a/src/gui/tracks/InstrumentTrackView.cpp b/src/gui/tracks/InstrumentTrackView.cpp index 669fdaccb..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,24 +74,14 @@ 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( 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(); @@ -100,7 +89,6 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV 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(); @@ -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 6a6a2c5fd..8516eb5c2 100644 --- a/src/gui/tracks/SampleTrackView.cpp +++ b/src/gui/tracks/SampleTrackView.cpp @@ -56,20 +56,17 @@ 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_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(); @@ -77,7 +74,6 @@ SampleTrackView::SampleTrackView( SampleTrack * _t, TrackContainerView* tcv ) : 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(); } From d2a0780a6eca1fbddc7b3cd2dc050d283799883d Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Mon, 28 Aug 2023 20:12:09 +0200 Subject: [PATCH 107/308] Adjust classic style sheet Adjust the classic style sheet in the same way that the default style sheet was adjusted. The change also removes the usage of a bold font weight for selected menu items to achieve a more consistent feel. --- data/themes/classic/style.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/data/themes/classic/style.css b/data/themes/classic/style.css index 2880fe661..777dbc230 100644 --- a/data/themes/classic/style.css +++ b/data/themes/classic/style.css @@ -82,7 +82,6 @@ lmms--gui--TextFloat, lmms--gui--SimpleTextFloat { QMenu { border:1px solid #747474; background-color: #c9c9c9; - font-size:11px; } QMenu::separator { @@ -98,15 +97,12 @@ QMenu::item { QMenu::item:selected { color: white; - font-weight:bold; background-color: #747474; } QMenu::item:disabled { color: #747474; background-color: #c9c9c9; - font-size:12px; - font-weight: normal; padding: 4px 32px 4px 20px; } From fcdf4c0568407762db38c180684cea9af101a937 Mon Sep 17 00:00:00 2001 From: MrTopom Date: Tue, 29 Aug 2023 21:32:11 +0200 Subject: [PATCH 108/308] Showing Knob value on mouse over (#6835) * Showing Knob value on mouse over * Correcting minors source code issues * Correcting double QTimer include * Removing blank lines * Removing space and add one * Update src/gui/widgets/SimpleTextFloat.cpp Co-authored-by: saker * Correcting QTimer * Remove a parameter that has the default value --------- Co-authored-by: saker --- include/Knob.h | 4 ++++ include/SimpleTextFloat.h | 8 +++++++- src/gui/widgets/Knob.cpp | 26 ++++++++++++++++++------ src/gui/widgets/SimpleTextFloat.cpp | 31 +++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 7 deletions(-) diff --git a/include/Knob.h b/include/Knob.h index 85a51e363..d5739bb1c 100644 --- a/include/Knob.h +++ b/include/Knob.h @@ -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(); 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/src/gui/widgets/Knob.cpp b/src/gui/widgets/Knob.cpp index c2f90fb2b..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 { @@ -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 ) diff --git a/src/gui/widgets/SimpleTextFloat.cpp b/src/gui/widgets/SimpleTextFloat.cpp index d1f490b5e..df438423e 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(); + m_showTimer->setSingleShot(true); + QObject::connect(m_showTimer, &QTimer::timeout, this, &SimpleTextFloat::show); + + m_hideTimer = new QTimer(); + 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) { From 3263bfd555982d52735a19763eff26f4be7e0eb7 Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Thu, 31 Aug 2023 02:01:15 +0100 Subject: [PATCH 109/308] Fix generator expression in strip command (#6762) * Fix generator expression in strip command * Add TODO comment for CMake 3.19 --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a68b788d6..1ec3f992e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -605,7 +605,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() From 4804ab678501f9c746b4b2c870f0a323f7d3953b Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Thu, 31 Aug 2023 12:12:00 +0100 Subject: [PATCH 110/308] Support per-note detuning and panning with Sf2 Player (#6602) * Add `ArrayVector` class template and tests * Fix counting of failed test suites * Support detuning and panning with Sf2 Player * Restrict panning to supported FluidSynth versions * Fix data array cast type * Fix tests for Qt<5.10 and correct mistaken test * DIsplay warning for FluidSynth < 2 * Remove unnecessary clamp * Update include guard name --- CMakeLists.txt | 6 +- include/ArrayVector.h | 388 ++++++++++++++ include/NotePlayHandle.h | 3 + plugins/Sf2Player/Sf2Player.cpp | 99 +++- tests/CMakeLists.txt | 1 + tests/main.cpp | 2 +- tests/src/core/ArrayVectorTest.cpp | 831 +++++++++++++++++++++++++++++ 7 files changed, 1306 insertions(+), 24 deletions(-) create mode 100644 include/ArrayVector.h create mode 100644 tests/src/core/ArrayVectorTest.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ec3f992e..e20f13527 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -494,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") 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/NotePlayHandle.h b/include/NotePlayHandle.h index 46b14c4cd..61df5a77a 100644 --- a/include/NotePlayHandle.h +++ b/include/NotePlayHandle.h @@ -108,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; diff --git a/plugins/Sf2Player/Sf2Player.cpp b/plugins/Sf2Player/Sf2Player.cpp index 1f0cb7c59..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" @@ -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; +}; @@ -681,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; @@ -703,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); + } + } + } } @@ -715,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(); @@ -859,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 ) { 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" From 005ee47d439f0ccf023de4c73f552f8c5119ec63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s?= Date: Thu, 31 Aug 2023 12:17:00 -0300 Subject: [PATCH 111/308] pitch wheel recording in the detune pattern (#6297) --- include/Note.h | 2 +- include/NotePlayHandle.h | 2 +- src/core/NotePlayHandle.cpp | 16 +++++++++++----- src/gui/editors/PianoRoll.cpp | 4 ++-- src/tracks/InstrumentTrack.cpp | 10 +++++++--- 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/include/Note.h b/include/Note.h index 5e3a1b8a2..2df196af2 100644 --- a/include/Note.h +++ b/include/Note.h @@ -91,7 +91,7 @@ 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; diff --git a/include/NotePlayHandle.h b/include/NotePlayHandle.h index 61df5a77a..7105d6672 100644 --- a/include/NotePlayHandle.h +++ b/include/NotePlayHandle.h @@ -248,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 ); diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index 70007ebf1..eb9c7ddbf 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -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(); } } diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 0cc825725..05900bf0b 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -4134,9 +4134,9 @@ void PianoRoll::finishRecordNote(const Note & n ) { 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(); diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 84b73614b..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" @@ -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); @@ -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::Origin::MidiInput ); + NotePlayHandle::Origin::MidiInput); m_notes[event.key()] = nph; if( ! Engine::audioEngine()->addPlayHandle( nph ) ) { @@ -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 ) From 8a94fb36818b7af8eb6fa5815c4836f19e7c2210 Mon Sep 17 00:00:00 2001 From: Dalton Messmer <33463986+messmerd@users.noreply.github.com> Date: Thu, 31 Aug 2023 12:55:02 -0400 Subject: [PATCH 112/308] Fix std::vector refactor mistake (#6836) * Use std::vector const reference instead of copying * Add assertions * Simplification --- include/MidiClip.h | 2 +- include/PianoRoll.h | 4 ++-- src/core/EffectChain.cpp | 3 +++ src/core/Mixer.cpp | 4 ++-- src/core/PatternStore.cpp | 12 +++++------ src/core/RenderManager.cpp | 4 ++-- src/core/Song.cpp | 2 +- src/gui/MixerView.cpp | 4 ++-- src/gui/clips/ClipView.cpp | 4 +++- src/gui/editors/PatternEditor.cpp | 4 ++-- src/gui/editors/PianoRoll.cpp | 29 ++++++++++++--------------- src/gui/tracks/TrackContentWidget.cpp | 4 ++-- src/tracks/MidiClip.cpp | 4 ++-- 13 files changed, 41 insertions(+), 39 deletions(-) diff --git a/include/MidiClip.h b/include/MidiClip.h index 43b322f80..c2287bd00 100644 --- a/include/MidiClip.h +++ b/include/MidiClip.h @@ -79,7 +79,7 @@ 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 Type type() const diff --git a/include/PianoRoll.h b/include/PianoRoll.h index 9f3bbcd7d..38788180f 100644 --- a/include/PianoRoll.h +++ b/include/PianoRoll.h @@ -308,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 ); diff --git a/src/core/EffectChain.cpp b/src/core/EffectChain.cpp index b07a7227b..4da5c5197 100644 --- a/src/core/EffectChain.cpp +++ b/src/core/EffectChain.cpp @@ -25,6 +25,7 @@ #include +#include #include "EffectChain.h" #include "Effect.h" @@ -162,6 +163,7 @@ void EffectChain::moveDown( Effect * _effect ) if (_effect != m_effects.back()) { auto it = std::find(m_effects.begin(), m_effects.end(), _effect); + assert(it != m_effects.end()); std::swap(*std::next(it), *it); } } @@ -174,6 +176,7 @@ void EffectChain::moveUp( Effect * _effect ) if (_effect != m_effects.front()) { auto it = std::find(m_effects.begin(), m_effects.end(), _effect); + assert(it != m_effects.end()); std::swap(*std::prev(it), *it); } } diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index e14660e1f..59c2dd72e 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -394,8 +394,8 @@ 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}) { diff --git a/src/core/PatternStore.cpp b/src/core/PatternStore.cpp index c5a352139..6af434f65 100644 --- a/src/core/PatternStore.cpp +++ b/src/core/PatternStore.cpp @@ -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)) @@ -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); @@ -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) @@ -215,7 +215,7 @@ 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::Type::Pattern) @@ -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/RenderManager.cpp b/src/core/RenderManager.cpp index 969cad15b..9f6192039 100644 --- a/src/core/RenderManager.cpp +++ b/src/core/RenderManager.cpp @@ -97,7 +97,7 @@ 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) @@ -112,7 +112,7 @@ void RenderManager::renderTracks() } } - const TrackContainer::TrackList t2 = Engine::patternStore()->tracks(); + const TrackContainer::TrackList& t2 = Engine::patternStore()->tracks(); for (const auto& tk : t2) { Track::Type type = tk->type(); diff --git a/src/core/Song.cpp b/src/core/Song.cpp index e8073f225..3a735331c 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -383,7 +383,7 @@ 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) diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index 0edebcb8a..dff19ca3e 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -248,8 +248,8 @@ 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}) { diff --git a/src/gui/clips/ClipView.cpp b/src/gui/clips/ClipView.cpp index 7a7a19c11..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 @@ -545,6 +546,7 @@ DataFile ClipView::createClipDataFiles( // Insert into the dom under the "clips" element Track* clipTrack = clipView->m_trackView->getTrack(); 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", static_cast(clipTrack->type()) ); @@ -1308,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/editors/PatternEditor.cpp b/src/gui/editors/PatternEditor.cpp index 229c90bc2..5237690a7 100644 --- a/src/gui/editors/PatternEditor.cpp +++ b/src/gui/editors/PatternEditor.cpp @@ -69,7 +69,7 @@ void PatternEditor::cloneSteps() void PatternEditor::removeSteps() { - TrackContainer::TrackList tl = model()->tracks(); + const TrackContainer::TrackList& tl = model()->tracks(); for (const auto& track : tl) { @@ -176,7 +176,7 @@ void PatternEditor::updatePosition() void PatternEditor::makeSteps( bool clone ) { - TrackContainer::TrackList tl = model()->tracks(); + const TrackContainer::TrackList& tl = model()->tracks(); for (const auto& track : tl) { diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 05900bf0b..b38335995 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -741,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(); @@ -762,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 @@ -797,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) { @@ -1207,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 ); } @@ -1232,11 +1229,11 @@ 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(); diff --git a/src/gui/tracks/TrackContentWidget.cpp b/src/gui/tracks/TrackContentWidget.cpp index 442d717bf..619eff831 100644 --- a/src/gui/tracks/TrackContentWidget.cpp +++ b/src/gui/tracks/TrackContentWidget.cpp @@ -344,7 +344,7 @@ 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 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; @@ -443,7 +443,7 @@ 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 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; diff --git a/src/tracks/MidiClip.cpp b/src/tracks/MidiClip.cpp index b35979f61..490f6e6d0 100644 --- a/src/tracks/MidiClip.cpp +++ b/src/tracks/MidiClip.cpp @@ -305,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; } @@ -472,7 +472,7 @@ MidiClip * MidiClip::nextMidiClip() const MidiClip * MidiClip::adjacentMidiClipByOffset(int offset) const { - std::vector clips = m_instrumentTrack->getClips(); + auto& clips = m_instrumentTrack->getClips(); int clipNum = m_instrumentTrack->getClipNum(this); if (clipNum < 0 || clipNum > clips.size() - 1) { return nullptr; } return dynamic_cast(clips[clipNum + offset]); From e1d3ecb1843df3a4aff96ea086df3260fdd26672 Mon Sep 17 00:00:00 2001 From: Martin Pavelek Date: Thu, 31 Aug 2023 19:21:26 +0200 Subject: [PATCH 113/308] Microtuner UI update (#6206) * Replace deprecated sprintf() function * Update microtuner-related UI (add more clues explaining how to use it) * Simpler wording in the tooltips for "apply" buttons * Post-merge fix of a forward declaration * Rename Misc tab to Tuning and transposition; move Microtuner config dialog to Edit menu and make it also available from instrument tab * Enable word wrap on "MIDI unsupported" label * Remove forgotten new unnecessary includes * Rename InstrumentMiscView to InstrumentTuningView in locales --- data/locale/ar.ts | 2 +- data/locale/bs.ts | 2 +- data/locale/ca.ts | 2 +- data/locale/cs.ts | 2 +- data/locale/de.ts | 2 +- data/locale/el.ts | 2 +- data/locale/en.ts | 2 +- data/locale/eo.ts | 2 +- data/locale/es.ts | 2 +- data/locale/eu.ts | 2 +- data/locale/fa.ts | 2 +- data/locale/fr.ts | 2 +- data/locale/gl.ts | 2 +- data/locale/he.ts | 2 +- data/locale/hi_IN.ts | 2 +- data/locale/hu_HU.ts | 2 +- data/locale/id.ts | 2 +- data/locale/it.ts | 2 +- data/locale/ja.ts | 2 +- data/locale/ka.ts | 2 +- data/locale/ko.ts | 2 +- data/locale/ms_MY.ts | 2 +- data/locale/nb.ts | 2 +- data/locale/nl.ts | 2 +- data/locale/oc.ts | 2 +- data/locale/pl.ts | 2 +- data/locale/pt.ts | 2 +- data/locale/ro.ts | 2 +- data/locale/ru.ts | 2 +- data/locale/sl.ts | 2 +- data/locale/sr.ts | 2 +- data/locale/sv.ts | 2 +- data/locale/tr.ts | 2 +- data/locale/uk.ts | 2 +- data/locale/zh_CN.ts | 2 +- data/locale/zh_TW.ts | 2 +- data/themes/default/edit_draw_small.png | Bin 0 -> 5367 bytes data/themes/default/tuning_tab.png | Bin 0 -> 7016 bytes include/InstrumentTrack.h | 4 +- include/InstrumentTrackWindow.h | 4 +- ...umentMiscView.h => InstrumentTuningView.h} | 22 ++++++---- src/gui/CMakeLists.txt | 2 +- src/gui/MainWindow.cpp | 19 +++------ src/gui/MicrotunerConfig.cpp | 20 +++++---- src/gui/instrument/InstrumentTrackWindow.cpp | 38 +++++++++--------- ...tMiscView.cpp => InstrumentTuningView.cpp} | 33 ++++++++++++--- 46 files changed, 122 insertions(+), 92 deletions(-) create mode 100644 data/themes/default/edit_draw_small.png create mode 100644 data/themes/default/tuning_tab.png rename include/{InstrumentMiscView.h => InstrumentTuningView.h} (72%) rename src/gui/instrument/{InstrumentMiscView.cpp => InstrumentTuningView.cpp} (69%) 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/themes/default/edit_draw_small.png b/data/themes/default/edit_draw_small.png new file mode 100644 index 0000000000000000000000000000000000000000..9979c8223457ac27e70116b300062a3237b3272a GIT binary patch literal 5367 zcmeHLc~}$I79VY8Qv`gX7I`|vrKn6YSxM5M><}f81_azYnM}e+NaD;u0=QHQ)?HC> zsdYiIR{d;ik+v$h0*Zq2tk#OSR4sN9vBfH)=(`gT!>i9ezwh-w;Y-Lp_ji8h+}}O- z+zboVu~F`BK5h^Mxhtc?HQ=u&`*Lvt?}MA4Vi45*PF6xPqrt4Og)-|&BLOp+76K-0 zq#lB7b&adjmes?(=0Bwu4eEAj!1^1WE*f*~jR(0i8AC==-Ofkb&*r##epu=>ruVup zp0>)4diW*;muAk?4bIu$n9-PdiOa^Fxz%zi_P3CQ zBePl~Ph85xvrFGSyQ3*Cbo-EXLM_ueA|clAhZ{~Cy8n@!SY6TB*ypRZlt(3f#+*iX z&8R3}*6>jN)|Lz2vvV^0uUzm^?sC@?3R(1qK=tD4xkH!D&fhzIjA7pUGy86D(I@_} z?&RgIakt~tLkHi7j^SwY<=H83w@F*D+?J&V^6Oj92dWyc`<)n7xixzLJ|;0KJ~Fy_ z->0b~c6~T^U?}(3JxjDw?^%lb;?dDt%rWbMJaNcZ@d(&9qG z6mY6RJNX-BuWR}G!Xv{Ym@z?ZQw@!M0~n>BV6o^gI8m>QyfFT5xIT`#B9&0rG9-*p~IxTCCLjAnAA zo8N=ONYTBx`W8@*4XM%(e0qF7*lB#m^utDX$JQ@o}5M$t+u1a-?H!@|_cu&`&9599tV3Az;BG>2&W!YQJ-CyX9*qxAsu^tnAxA>PX48Ysa=joch6U%Lu`sLOKgRD)^oU-bKV%%3PJ{3Ledg$;2Bj23n zb<{J9zhrHB%&geHtM2+vdvN!+Ke&~}rDxh?`wKp&cKe+25ot-yXuy5>pHV zj2wF0MA)eCf&PuNo^|J#9{(?OlCHooQPL!;Qk>lnxE~YbU39c>80y-50 zDaP0=7@kTnu$C~8rXWt!fkPaa)CF;p#41!}2_sU-=q!qe&x%dJvr=)Hjx%Poo5Cgs z1Zf0=!L~G`iI&@fICfq+_{^Gl9M}$FQiC|jDm5HtrU+QX6>(7{!bWBYIHTQQ1*Ox= zHQ|vR6krs@Nnsd^oX4|Ttz4^+Yo-i5zDy?Lp#q*jfB*zSXPOwyhM4FfEJZsnS zX<*q6i!5B5GH1bV^E7R zopy|wP7|!jp0`n_=Ygc`ksW=alqz+n4=baAOtaWMShOQjhj-#E>6Foq(cwJ8NTh*8 zXu!F#?#rL%J3i#o3C7F#z~#r{t@Mi z2}~f8A!3PChKO(pACVFg5rPR(Ax6kBtzJMlP$^9`gPCxGr2^z!67Yz0SfD^3$VYTq zOn`_a0xh5rVn`rgD?w2`E*27j4is?|2~GlLbj*sS(g7-=kT1{*2|XghWKu*Vlc5ME zkVz1+SR#<%fdZ*SE45Rx`ydZdD}y)!F8bV}He!t4Or-^JVn|cE?fFCknMTAj7%LiI zA_?S+WFnDNEJ9I!dun#RM1rD0k+Yn9lq(R}-F3J;5-?(**vK@@K=3RkgMEVC7CBf9 z5Ef(424J?^!CK^D6oD~jD#2_v260$!n5DEIDOk~QSmZHg-0o-x6FT<1b)2|R%)qk` z6}*>$|HKrZVz!$8H=gIvPL>dgv6`vWI4Vv%oxquw^SlV$$)o|jj%KJ#h4SSn%4y$TSixf(>a*o3*p{PG$sGkyuq{chWGgQ|-C{A41l3iT zXNB@#a1Q<*Mfq3mj<9y`Fta5S9NH8n&T4vT_!j`%8DdDBFwy3hrS1r6m&M`U0XetZ zz$P03q`)hIUsu=v zO)j_RPuPSBe9^Ol=Vzx!J9>g=Zzt`zsBlQe{`%DfZUPopOY{U9{7dly`|1|zzupFn z&WutO;oRUh$m>m)xwr3x0TZqa4@r=os#$f!{V?kCM&YWwnlInFT-{crS)|U%JU?d> zk`v+54TZS>M4ER=%E=R}jiRCFPQ#UJhZGS`&=)1&Iz8o2tLQ&qXV#{(w+eH|FK=)y o|K5DbkDy~V-VPpJb^Gw35sA|d%&gsc8-#ZwkUVl5!IQX(oXL1Voym*c&2tR0cso z2LTHrpkP6;fFngw>>!FrnNjq+38?rz-@NBqZ~hZj!ae)^_HXaA%Q2HS6yE3r9v06IzHF8=iKIxYW+A_NZ$NyFO6X|G>U;`oxp(ef@ua zn*O2B#p}rXcs-d7{G>G##HUyf9!Si{k`<0c=5dzRsIe5gy&NX=4W)j zs&x`^p6#D*qVZ;Uz2US8^&bvcluR0)b0U4E{u90PJ!f*aLpB~4zj;+C*&ABXQ0@2> zndh{a5PEP@_T%|Uaq}M?zaanVp*)Azj$c8z-%s(MpL`bGvUv9k(%CJ+5FT;&>53EF z&_C3OFWaC~FD<>4J9I-Fyz1G{`x5?oFmJtH*lMSxR4CS?sd$i3ot!!MSp9UC*`~n? zPqT2dM;%Xe+?(oeM+RzyPk5_;{n8l(qgxQ(p>4E=TXkhR%+Bm>-FafAQC^h!td!&O z!ibRHVQDiiv~}Xw9z3g7`SYC(eV!30QMRp_;r(fPlvUVMcIzVzd_uF)Gb@Z0 zd(Ggq~7#T^BCO zcy)d7YG)q{wGf^3DSb7+!82wD`4XRQCf;d3VQBN)qd=&MZBlh@Cf0;=tUc7GIarF= z7GNHI^d{57u&&*+Yf*SK+}~!SU3qx1Q(m1fWuV>b>95PXF}m|D){(Dt26RMHIk~t1 zE6z@GH$P}msP>_4i+%X$ad|8WmJ=(zxBZ`$*Tamg;q-v-P)U9JF>S@+#QTDrQZ6<|2ZGsG|vKc3EIDd-yNO8o%%!T}*YvU~O7|dGc>o5xCpFQ`0h10(Vh$Y{h$07uM+BGzw(tvO_GzWoXIbys!{X-`)MM zS6z&CK9^V7Q};Hpb*J0zB5g@eb5h9V7xOkG0~5kh-@=1#76dJMP-(O7@G^j~Lo=Zh zSI}9KIb~C@$)5f34Xa8II=NG8ub$Y=Xgg*4LazqCEka4HH{9K%Hlxk+_?`kvO6|RoSWAnm

r9)cx3t;iLjUAK5X8+YNet8%gu77rk#y8G8&F~)^W-ooh5{pr!{ zO*DhsVYjbaWCT4vOEpAm9x7?k$Owt&7Pc9Ly~~Ia|FNWAFZ(>bY6)U6E^4SM;i%^I z=&%faGyS&ZNBgT622s1)hHi^8=e7;}`Q$GXTKV2=1xL03-8WgU*J{ol^Xie>TC7T% zp*>_^(5U<1SD#EucE{E>6Ufz`g0e@8Rp-P)I}ZbK$* zrFsuOFwZ!^mC_-@KVQZQXywzq$%K3UC>vk1HS;1M#e0*B-R~Q$(SqMR_W=^u%JP6{ z-Rb8wYOJ|6b3#{IwNts<8ayuC@JiWyJd%$o%a88~zq)!ayU%MN$2eBx=m zX#ZL~S{zm9v1Ch~_B5z0oY~7rPf2@fbXwCR!_f0~;s&hA3y8wTc$v|gZEJK(OP1o) zV>AvlxO$05LGzB6-S!n&>K=LX9FeSVE1Y$xhE^2W(Yck{jf*)2r##sStgC2BdeRi( zH!05WzG+T5DMEgCYSNU9Gy89lU&S`7m-t18>K$%5am+0h+ww|t;dz6{y;VX@VPuY% zRgTtn&AiPE-gOj~_8myyzC%h~URmtyxhE07&74}X!@HseCo33?m+ZUYy)vp_ur)6w zi`Rd(NqWAJJ1=(2s%Uo!O*S}pre$SV=2K33Jmq@+nSfStoj`hl@@i=Nsrtcf)c%Sx zr@mF^(w8hbT=AimI@C+!nyNK8tQ7pwiI?LZ6SJNNnYNPpMXG&E5A*XB~duWFwKhTqxQhvaZOyc7GVOP1udbMVF4YN|xb0Mi z|D-_?bXJb-riV%A*G{~qHPgyNH*v!AH0?X~*)=Z>CLM9K_JxUgtPh1wa`&Mf>K)Cs zNR2^PYHD7ml>>S9LYFY(+u?&2Y3kEoCJuJOsRJ) z<$RaE!itEdV0P;t)BEk(p2PU5YQ>)6PK* zCggZFica--%qw(eX5(|q@al5^{6>?24aU1gdc~C=7dR(pPso@RAoi;g?-SQSc!>v+ zNdfH|tNl>??HlAnGv%+6BMw&Mjz*g` z$=bZF444jOHiKv3SqvJ?Y2!}d8a)tN+0{K$t@7T*xa}V+7P!+I!Y6C5u044TC3raH z;d7t1&a-}IfaPM#`BpQr&r@nQ{1QS=>iR`Stj8YY%%S+1SsJhXxlo3(-D%oqxXim* zc4ZoevWO^J)?$NiIc>FK|HeBZ+bevf+H^anjy}yge}5K~U(0Kzmux&dlD1(*(}35b z!1{%n7Io?cO|UabuNMq=6fMloeZ4ttV$;Y&!Ym7?M*F71dDn+Zx^RBUO<3`vvXN#@ zR6jlbT+zk#$(4f6ho_6?F0Xn#74@23f4IlfJm-Ronqt90(G|6kGABhtcTwqvTUs#c zl0(AeRBFWU9(TLvzv_M2^YT8n=tB|&Wh}|+aij1d5Z!Pdc%cmS@g}iE0(%Bq#02aW z0x@{ugh0p(6k-M|8j!)50GB7Ez+as?4~OyC6nF^U2jwHC0+BqAcnJ^`?;FgDk7g0s z@CEasWCaN%5CAd;Od;S4r6dIfuHq$u&q^^84pTv7(G+;7k3Wnmk^nHAJYP zG4T0N7+J#RkOFCLV-(G1BoiW2Asmr1G23<{&|*RF=obV)57{)gzWeL=n&^9KsP`vJp5OKtwQD4mbn{k6}7E0FDd}iam~s zE|kg`LKdK;0?F-pAP*Bo#1rsn7J@@y;1Dj-ykoNQRILfV=Hjt9_F5zEQ>)297}_5;zDH9>+o8m^c8z z#Bm(K0>pA02v`S4fIw6w_%pjy#F5Dv62O@Y)&Q7iu(ecqhFPnsZ|>J7#jqVfv>S42RwiA0CdUiu%dhm2Gn5TDXT zR&Jp_KBVypB`ddB5?$FzK`~-6p9e_3PV}e3|2MdC`eRM@pVY_0MzyITaU8e_Maul- z!oM~D4d5t)H;)AfrJ}!ceLQ3|EaT2m(C1MZcs_&2J@WH;KUU^oO8&{8vG(~VO~7D3 zjC@yoe}wBtxV|d_-v$0rT|dJ0T@m;$@Q>>HpM?wh<&6O#1TU^~@O{9pE}<>>E - * 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/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 9f940c035..afed153f9 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/MainWindow.cpp b/src/gui/MainWindow.cpp index 559756169..10805fe01 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -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" ) ); @@ -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? @@ -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(); diff --git a/src/gui/MicrotunerConfig.cpp b/src/gui/MicrotunerConfig.cpp index 7ab4cc0b1..4156b9e79 100644 --- a/src/gui/MicrotunerConfig.cpp +++ b/src/gui/MicrotunerConfig.cpp @@ -56,8 +56,8 @@ 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")), @@ -75,7 +75,7 @@ MicrotunerConfig::MicrotunerConfig() : #endif setWindowIcon(embed::getIconPixmap("microtuner")); - setWindowTitle(tr("Microtuner")); + setWindowTitle(tr("Microtuner Configuration")); // Organize into 2 main columns: scales and keymaps auto microtunerLayout = new QGridLayout(); @@ -84,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++) @@ -102,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();}); @@ -112,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++) @@ -137,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();}); @@ -181,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/instrument/InstrumentTrackWindow.cpp b/src/gui/instrument/InstrumentTrackWindow.cpp index 43cca0dac..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" @@ -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 ); @@ -376,12 +376,14 @@ void InstrumentTrackWindow::modelChanged() 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(); } 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()); From 0768f5ad2febea80e4766b25547d42fa12b7bd9a Mon Sep 17 00:00:00 2001 From: Dalton Messmer <33463986+messmerd@users.noreply.github.com> Date: Sun, 3 Sep 2023 17:29:31 -0400 Subject: [PATCH 114/308] Fix a few memory issues found with ASan (#6843) * Fix LADSPA effects memory leak * Fix buffer overflow in PianoView * Avoid using invalid iterators in AutomationClip * Fix memory leaks in SimpleTextFloat * Handle potential case where QMap::lowerBound(...) returns end iterator * Implement suggestions from review --- plugins/LadspaEffect/caps/Descriptor.h | 3 +- src/core/AutomationClip.cpp | 27 +++---- src/gui/instrument/PianoView.cpp | 107 ++++++++++++------------- src/gui/widgets/SimpleTextFloat.cpp | 4 +- 4 files changed, 64 insertions(+), 77 deletions(-) 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/src/core/AutomationClip.cpp b/src/core/AutomationClip.cpp index 906cb148c..3b36f6b49 100644 --- a/src/core/AutomationClip.cpp +++ b/src/core/AutomationClip.cpp @@ -1106,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. @@ -1123,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 @@ -1159,7 +1151,6 @@ void AutomationClip::generateTangents(timeMap::iterator it, int numToGenerate) it.value().setOutTangent(outTangent); } } - it++; } } diff --git a/src/gui/instrument/PianoView.cpp b/src/gui/instrument/PianoView.cpp index 20db2e8e8..d20cbcac5 100644 --- a/src/gui/instrument/PianoView.cpp +++ b/src/gui/instrument/PianoView.cpp @@ -322,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); } @@ -396,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 = static_cast(new_pos / Piano::WhiteKeysPerOctave) - + WhiteKeys[new_pos % Piano::WhiteKeysPerOctave]; + m_startKey = static_cast(newPos / Piano::WhiteKeysPerOctave) + + WhiteKeys[newPos % Piano::WhiteKeysPerOctave]; update(); } diff --git a/src/gui/widgets/SimpleTextFloat.cpp b/src/gui/widgets/SimpleTextFloat.cpp index df438423e..e37753229 100644 --- a/src/gui/widgets/SimpleTextFloat.cpp +++ b/src/gui/widgets/SimpleTextFloat.cpp @@ -46,11 +46,11 @@ SimpleTextFloat::SimpleTextFloat() : m_textLabel = new QLabel(this); layout->addWidget(m_textLabel); - m_showTimer = new QTimer(); + m_showTimer = new QTimer(this); m_showTimer->setSingleShot(true); QObject::connect(m_showTimer, &QTimer::timeout, this, &SimpleTextFloat::show); - m_hideTimer = new QTimer(); + m_hideTimer = new QTimer(this); m_hideTimer->setSingleShot(true); QObject::connect(m_hideTimer, &QTimer::timeout, this, &SimpleTextFloat::hide); } From fa05ce20b8578b77b19fd22d8c63eb59fe7ea0e1 Mon Sep 17 00:00:00 2001 From: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com> Date: Mon, 4 Sep 2023 07:29:29 +0530 Subject: [PATCH 115/308] Replace corrupted default samples with fixed ones. (#6752) * pulled from upstream * replaced broken sample files * Revert "pulled from upstream" This reverts commit 76967b5cc4e7fbc12086830bd6a3954146bdbb9f. * fixed shortened samples * will this fix exprtk submodule? This reverts commit 76967b5cc4e7fbc12086830bd6a3954146bdbb9f. --- data/samples/drums/kick04.ogg | Bin 7126 -> 12017 bytes data/samples/effects/scratch01.ogg | Bin 5516 -> 12370 bytes data/samples/effects/wind_chimes01.ogg | Bin 22654 -> 57873 bytes data/samples/instruments/harpsichord01.ogg | Bin 38144 -> 60978 bytes data/samples/misc/hit01.ogg | Bin 16606 -> 43603 bytes 5 files changed, 0 insertions(+), 0 deletions(-) diff --git a/data/samples/drums/kick04.ogg b/data/samples/drums/kick04.ogg index 567480abd683475c1ba4325469adc111dac42b8d..8f7dce5271252405b7adfe8bc2bb606479c342ce 100644 GIT binary patch literal 12017 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 MGw>pjd%^O*0FRxTr2qf` literal 7126 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 diff --git a/data/samples/effects/scratch01.ogg b/data/samples/effects/scratch01.ogg index 9f216038dc49095c6a07a217e28ec0ab95842f32..0b05505cd3615b2d450a59b7719793c315865a38 100644 GIT binary patch literal 12370 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 literal 5516 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 HhJyb9N{p{9 diff --git a/data/samples/effects/wind_chimes01.ogg b/data/samples/effects/wind_chimes01.ogg index 35d3374a2e2465f38380d7556b5ff4c6fecb6f12..7fb3c441a24c9184ea544604b474bcf998450dd0 100644 GIT binary patch literal 57873 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 AJ^%m! literal 22654 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�N8BI=>A&+m!_r3kJq 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�Vb`AKuTSXj;ait*miRnbc)i?K3Y`y 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 QFJbgN{C~2M8UKIz7tkX;xBvhE diff --git a/data/samples/instruments/harpsichord01.ogg b/data/samples/instruments/harpsichord01.ogg index 028bbd912596ea0492dbcbb23f0cab73e8b9f371..c84ffd7df44519fc3323c22aac403ca69a25a375 100644 GIT binary patch literal 60978 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

8H#vZ7^Yax`|9Q=JWLJ*QP(UD1| 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

f6AE{sO1O8|-| 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 WXje3ae0ayF!)1--1L*#*@BabsA+zTI literal 16606 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 From de062d6c54d48cc53d080fb25ed33a6c72d6e26f Mon Sep 17 00:00:00 2001 From: Martin Pavelek Date: Tue, 5 Sep 2023 01:33:42 +0200 Subject: [PATCH 116/308] Show detailed CPU load information in a tool-tip (#5970) * Profiler rework * Workaround for GCC bug * Rollback QFile removal * Use enum instead of a plain index to describe detailed stats * Use the GCC workaround code for all compilers to avoid redundancy * Update and fix comments * Implement suggestions from review * Split AudioEngine::renderNextBuffer() into separate functions, fix old formatting * Remove QFile include * Revert formatting changes * Apply suggestion from review (remove unnecessary template parameter) * Revert more formatting changes * Convert DetailType to enum class * DetailType enum class improvements suggested in review * Use std::atomic for m_detailLoad * RAII-style profiler probes * Apply suggestions from code review Co-authored-by: Dominic Clark * Fix namespace comment * Improve CPU load widget precision and use floats for load computations * Atomic m_cpuLoad * Add custom step size support for CPULoadWidget * Apply suggestions from review (convert the profiler probe into a nested class, other small changes) * Do not limit stored load averages to 100% --------- Co-authored-by: sakertooth Co-authored-by: Dominic Clark --- data/themes/classic/style.css | 1 + data/themes/default/style.css | 1 + include/AudioEngine.h | 9 ++++++ include/AudioEngineProfiler.h | 48 +++++++++++++++++++++++++++++- include/CPULoadWidget.h | 6 ++++ src/core/AudioEngine.cpp | 49 ++++++++++++++++++++++++------- src/core/AudioEngineProfiler.cpp | 22 ++++++++++++-- src/gui/widgets/CPULoadWidget.cpp | 27 ++++++++++++----- 8 files changed, 140 insertions(+), 23 deletions(-) diff --git a/data/themes/classic/style.css b/data/themes/classic/style.css index d1f4d0588..ac22a14ec 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 */ diff --git a/data/themes/default/style.css b/data/themes/default/style.css index e88e51e5b..092332eee 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 */ diff --git a/include/AudioEngine.h b/include/AudioEngine.h index 030c5bce3..f056c22e1 100644 --- a/include/AudioEngine.h +++ b/include/AudioEngine.h @@ -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(); 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/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/src/core/AudioEngine.cpp b/src/core/AudioEngine.cpp index 21a9a3598..2d077babc 100644 --- a/src/core/AudioEngine.cpp +++ b/src/core/AudioEngine.cpp @@ -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 ) { @@ -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 @@ -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::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; } diff --git a/src/core/AudioEngineProfiler.cpp b/src/core/AudioEngineProfiler.cpp index 9e05ff80a..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 = std::clamp((newCpuLoad * 0.1f + m_cpuLoad * 0.9f), 0, 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/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 From b7196337a4fedec03566f39a220a42f154a5d806 Mon Sep 17 00:00:00 2001 From: Lost Robot <34612565+LostRobotMusic@users.noreply.github.com> Date: Thu, 7 Sep 2023 11:43:23 -0700 Subject: [PATCH 117/308] Fix Compressor arithmetic exception in Debug mode (#6854) --- plugins/Compressor/Compressor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/Compressor/Compressor.cpp b/plugins/Compressor/Compressor.cpp index 3c5ad6157..33571606e 100755 --- a/plugins/Compressor/Compressor.cpp +++ b/plugins/Compressor/Compressor.cpp @@ -320,8 +320,8 @@ bool CompressorEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames) float inputValue = feedback ? m_prevOut[i] : s[i]; // Calculate the crest factor of the audio by diving the peak by the RMS - m_crestPeakVal[i] = qMax(inputValue * inputValue, m_crestTimeConst * m_crestPeakVal[i] + (1 - m_crestTimeConst) * (inputValue * inputValue)); - m_crestRmsVal[i] = m_crestTimeConst * m_crestRmsVal[i] + ((1 - m_crestTimeConst) * (inputValue * inputValue)); + m_crestPeakVal[i] = qMax(qMax(COMP_NOISE_FLOOR, inputValue * inputValue), m_crestTimeConst * m_crestPeakVal[i] + (1 - m_crestTimeConst) * (inputValue * inputValue)); + m_crestRmsVal[i] = qMax(COMP_NOISE_FLOOR, m_crestTimeConst * m_crestRmsVal[i] + ((1 - m_crestTimeConst) * (inputValue * inputValue))); m_crestFactorVal[i] = m_crestPeakVal[i] / m_crestRmsVal[i]; m_rmsVal[i] = m_rmsTimeConst * m_rmsVal[i] + ((1 - m_rmsTimeConst) * (inputValue * inputValue)); From 10f1b21fb7ec2beeef42b43bef53e30fdb4e87eb Mon Sep 17 00:00:00 2001 From: consolegrl <5942029+consolegrl@users.noreply.github.com> Date: Thu, 7 Sep 2023 22:19:56 -0400 Subject: [PATCH 118/308] fixes #4049: Off-grid nodes not draggable (#6852) The quantPos arg of AutomationClip::setDragValue causes the node time to be quantized before its looked up in the timeMap iterator. This results in the node not being found and a new one being created inside the setDragValue function even though we had found one. Simply setting it to true causes this bug, simply setting it to false causes a new node to be created off grid/not snapped. So the fix is to quantize the position for the lookup only if we haven't found an existing node under the cursor. --- src/gui/editors/AutomationEditor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/editors/AutomationEditor.cpp b/src/gui/editors/AutomationEditor.cpp index a24165332..f98066bba 100644 --- a/src/gui/editors/AutomationEditor.cpp +++ b/src/gui/editors/AutomationEditor.cpp @@ -531,7 +531,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent ) : POS(clickedNode) ), level, - true, + clickedNode == tm.end(), mouseEvent->modifiers() & Qt::ControlModifier ); From b353cbea822b73ccef5f4f0ea7a22cf5e19162e5 Mon Sep 17 00:00:00 2001 From: saker Date: Fri, 8 Sep 2023 11:49:43 -0400 Subject: [PATCH 119/308] Add options to enable sanitizers (#6840) * Add options to enable sanitizers * Specify them as debugging options * Apply suggestions made by Dom * Fix linking issues There were linking issues, most likely because we were applying the sanitizer flags to unnecessary targets that are part of the build. Now, we only focus on adding the compiler flags to lmmsobjs as a PUBLIC dependency, and selectively choose what targets we need to apply the linker flags to as PRIVATE dependencies. * Add UBSan * Add status messages * Remove GNU as supported compiler for MSan * Revert to using add__options again * Fix sanitizer linkage within veal and cmt libraries I suspect that our sanitizer flags were removed for these two CMake targets. Instead of setting the properties directly, we call target_compile_options and target_link_options instead. * Remove TODO comment * Revert "Fix sanitizer linkage within veal and cmt libraries" This reverts commit b04dce8d8c0092353ec9fc462d237bac369a9eb6. * Use CMAKE__FLAGS_ and apply fixes * Remove quotes * Add support for additional flags * Disable vptr for UBSan * Print "Debug using" in status for clarity * Wrap ${supported_compilers} and ${status_flag} in quotes * Replace semicolons with spaces in additional_flags * Remove platform check for no-undefined flag The platform check was added as an attempt to make this branch compile with the veal and cmt libraries. However, it seems to work without it, so the problem must've been something else occuring in these files. * Undo change to FP exceptions status message * Use spaces instead of tabs * Remove -no-undefined flag for cmt and veal libraries --- CMakeLists.txt | 36 ++++++++++++++++++++++-- plugins/LadspaEffect/calf/CMakeLists.txt | 6 ++-- plugins/LadspaEffect/cmt/CMakeLists.txt | 6 ++-- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e20f13527..1b17d0e7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,6 +78,10 @@ OPTION(WANT_VST_32 "Include 32-bit VST support" ON) OPTION(WANT_VST_64 "Include 64-bit VST support" ON) OPTION(WANT_WINMM "Include WinMM MIDI support" OFF) OPTION(WANT_DEBUG_FPE "Debug floating point exceptions" OFF) +option(WANT_DEBUG_ASAN "Enable AddressSanitizer" OFF) +option(WANT_DEBUG_TSAN "Enable ThreadSanitizer" OFF) +option(WANT_DEBUG_MSAN "Enable MemorySanitizer" OFF) +option(WANT_DEBUG_UBSAN "Enable UndefinedBehaviorSanitizer" OFF) OPTION(BUNDLE_QT_TRANSLATIONS "Install Qt translation files for LMMS" OFF) @@ -649,6 +653,31 @@ IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") ENDIF(WIN32) ENDIF() +# add enabled sanitizers +function(add_sanitizer sanitizer supported_compilers want_flag status_flag) + if(${want_flag}) + if(CMAKE_CXX_COMPILER_ID MATCHES "${supported_compilers}") + set("${status_flag}" "Enabled" PARENT_SCOPE) + string(REPLACE ";" " " additional_flags "${ARGN}") + # todo CMake 3.13: use add_compile_options/add_link_options instead + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fsanitize=${sanitizer} ${additional_flags}" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=${sanitizer} ${additional_flags}" PARENT_SCOPE) + else() + set("${status_flag}" "Wanted but disabled due to unsupported compiler" PARENT_SCOPE) + endif() + else() + set("${status_flag}" "Disabled" PARENT_SCOPE) + endif() +endfunction() + +add_sanitizer(address "GNU|Clang|MSVC" WANT_DEBUG_ASAN STATUS_DEBUG_ASAN) +add_sanitizer(thread "GNU|Clang" WANT_DEBUG_TSAN STATUS_DEBUG_TSAN) +add_sanitizer(memory "Clang" WANT_DEBUG_MSAN STATUS_DEBUG_MSAN -fno-omit-frame-pointer) +# UBSan does not link with vptr enabled due to a problem with references from PeakControllerEffect +# not being found by PeakController +add_sanitizer(undefined "GNU|Clang" WANT_DEBUG_UBSAN STATUS_DEBUG_UBSAN -fno-sanitize=vptr) + + # use ccache include(CompileCache) @@ -717,7 +746,6 @@ ADD_CUSTOM_TARGET(uninstall COMMAND ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}" -P "${CMAKE_CURRENT_SOURCE_DIR}/cmake/uninstall.cmake" ) - # # display configuration information # @@ -783,7 +811,11 @@ MESSAGE( MESSAGE( "Developer options\n" "-----------------------------------------\n" -"* Debug FP exceptions : ${STATUS_DEBUG_FPE}\n" +"* Debug FP exceptions : ${STATUS_DEBUG_FPE}\n" +"* Debug using AddressSanitizer : ${STATUS_DEBUG_ASAN}\n" +"* Debug using ThreadSanitizer : ${STATUS_DEBUG_TSAN}\n" +"* Debug using MemorySanitizer : ${STATUS_DEBUG_MSAN}\n" +"* Debug using UBSanitizer : ${STATUS_DEBUG_UBSAN}\n" ) MESSAGE( diff --git a/plugins/LadspaEffect/calf/CMakeLists.txt b/plugins/LadspaEffect/calf/CMakeLists.txt index 90f506417..0c9cd8fa9 100644 --- a/plugins/LadspaEffect/calf/CMakeLists.txt +++ b/plugins/LadspaEffect/calf/CMakeLists.txt @@ -36,9 +36,9 @@ TARGET_COMPILE_DEFINITIONS(veal PRIVATE DISABLE_OSC=1) SET(INLINE_FLAGS "") IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - SET(INLINE_FLAGS "-finline-functions-called-once -finline-limit=80") + SET(INLINE_FLAGS -finline-functions-called-once -finline-limit=80) ENDIF() -SET_TARGET_PROPERTIES(veal PROPERTIES COMPILE_FLAGS "-fexceptions -O2 -finline-functions ${INLINE_FLAGS}") +target_compile_options(veal PRIVATE -fexceptions -O2 -finline-functions ${INLINE_FLAGS}) if(LMMS_BUILD_WIN32) add_custom_command( @@ -50,5 +50,5 @@ if(LMMS_BUILD_WIN32) ) endif() IF(NOT LMMS_BUILD_APPLE AND NOT LMMS_BUILD_OPENBSD) - SET_TARGET_PROPERTIES(veal PROPERTIES LINK_FLAGS "${LINK_FLAGS} -shared -Wl,-no-undefined") + target_link_libraries(veal PRIVATE -shared) ENDIF() diff --git a/plugins/LadspaEffect/cmt/CMakeLists.txt b/plugins/LadspaEffect/cmt/CMakeLists.txt index ded7b8958..75dba319d 100644 --- a/plugins/LadspaEffect/cmt/CMakeLists.txt +++ b/plugins/LadspaEffect/cmt/CMakeLists.txt @@ -5,7 +5,7 @@ ADD_LIBRARY(cmt MODULE ${SOURCES}) INSTALL(TARGETS cmt LIBRARY DESTINATION "${PLUGIN_DIR}/ladspa") SET_TARGET_PROPERTIES(cmt PROPERTIES PREFIX "") -SET_TARGET_PROPERTIES(cmt PROPERTIES COMPILE_FLAGS "-Wall -O3 -fno-strict-aliasing") +target_compile_options(cmt PRIVATE -Wall -O3 -fno-strict-aliasing) if(LMMS_BUILD_WIN32) add_custom_command( @@ -18,10 +18,10 @@ if(LMMS_BUILD_WIN32) endif() if(NOT LMMS_BUILD_WIN32) - set_target_properties(cmt PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -fPIC") + target_compile_options(cmt PRIVATE -fPIC) endif() IF(NOT LMMS_BUILD_APPLE AND NOT LMMS_BUILD_OPENBSD) - SET_TARGET_PROPERTIES(cmt PROPERTIES LINK_FLAGS "${LINK_FLAGS} -shared -Wl,-no-undefined") + target_link_libraries(cmt PRIVATE -shared) ENDIF() From a8d765f8d57075217546282a55d3bb407512f4bf Mon Sep 17 00:00:00 2001 From: MrTopom Date: Sun, 10 Sep 2023 17:52:18 +0200 Subject: [PATCH 120/308] Make files visible when searching in ``FileBrowser`` (#6845) * Change the title for SideBarWidgets to be vertically centered related to icon and with no underlining * Update src/gui/SideBarWidget.cpp Co-authored-by: saker * Updating FileBrowser display when searching : showing matching files * Correcting increment and removing duplicated calls * Correcting reload tree when filter is activated --------- Co-authored-by: saker --- include/FileBrowser.h | 9 ++- src/gui/FileBrowser.cpp | 124 ++++++++++++++++++++++++++++------------ 2 files changed, 95 insertions(+), 38 deletions(-) diff --git a/include/FileBrowser.h b/include/FileBrowser.h index 3334a73f6..eafb827da 100644 --- a/include/FileBrowser.h +++ b/include/FileBrowser.h @@ -75,8 +75,7 @@ public: private slots: void reloadTree(); void expandItems( QTreeWidgetItem * item=nullptr, QList expandedDirs = QList() ); - // call with item=NULL to filter the entire tree - bool filterItems( const QString & filter, QTreeWidgetItem * item=nullptr ); + bool filterAndExpandItems(const QString & filter, QTreeWidgetItem * item = nullptr); void giveFocusToFilter(); private: @@ -84,6 +83,9 @@ private: void addItems( const QString & path ); + void saveDirectoriesStates(); + void restoreDirectoriesStates(); + FileBrowserTreeWidget * m_fileBrowserTreeWidget; QLineEdit * m_filterEdit; @@ -99,6 +101,8 @@ private: QCheckBox* m_showFactoryContent = nullptr; QString m_userDir; QString m_factoryDir; + QList m_savedExpandedDirs; + QString m_previousFilterValue; } ; @@ -115,7 +119,6 @@ public: //! that are expanded in the tree. QList expandedDirs( QTreeWidgetItem * item = nullptr ) const; - protected: void contextMenuEvent( QContextMenuEvent * e ) override; void mousePressEvent( QMouseEvent * me ) override; diff --git a/src/gui/FileBrowser.cpp b/src/gui/FileBrowser.cpp index c0763d542..181e67cd7 100644 --- a/src/gui/FileBrowser.cpp +++ b/src/gui/FileBrowser.cpp @@ -23,7 +23,6 @@ * */ - #include #include #include @@ -126,7 +125,7 @@ FileBrowser::FileBrowser(const QString & directories, const QString & filter, m_filterEdit->setPlaceholderText( tr("Search") ); m_filterEdit->setClearButtonEnabled( true ); connect( m_filterEdit, SIGNAL( textEdited( const QString& ) ), - this, SLOT( filterItems( const QString& ) ) ); + this, SLOT( filterAndExpandItems( const QString& ) ) ); auto reload_btn = new QPushButton(embed::getIconPixmap("reload"), QString(), searchWidget); reload_btn->setToolTip( tr( "Refresh list" ) ); @@ -145,53 +144,95 @@ FileBrowser::FileBrowser(const QString & directories, const QString & filter, auto filterFocusShortcut = new QShortcut(QKeySequence(QKeySequence::Find), this, SLOT(giveFocusToFilter())); filterFocusShortcut->setContext(Qt::WidgetWithChildrenShortcut); + m_previousFilterValue = ""; + reloadTree(); show(); } -bool FileBrowser::filterItems( const QString & filter, QTreeWidgetItem * item ) +void FileBrowser::saveDirectoriesStates() +{ + m_savedExpandedDirs = m_fileBrowserTreeWidget->expandedDirs(); +} + +void FileBrowser::restoreDirectoriesStates() { - // call with item=NULL to filter the entire tree + expandItems(nullptr, m_savedExpandedDirs); +} + +bool FileBrowser::filterAndExpandItems(const QString & filter, QTreeWidgetItem * item) +{ + // Call with item = nullptr to filter the entire tree + + if (item == nullptr) + { + // First search character so need to save current expanded directories + if (m_previousFilterValue.isEmpty()) + { + saveDirectoriesStates(); + } + + m_previousFilterValue = filter; + } + + if (filter.isEmpty()) + { + // Restore previous expanded directories + if (item == nullptr) + { + restoreDirectoriesStates(); + } + + return false; + } + bool anyMatched = false; int numChildren = item ? item->childCount() : m_fileBrowserTreeWidget->topLevelItemCount(); - for( int i = 0; i < numChildren; ++i ) + + for (int i = 0; i < numChildren; ++i) { QTreeWidgetItem * it = item ? item->child( i ) : m_fileBrowserTreeWidget->topLevelItem(i); - // is directory? - if( it->childCount() ) + auto d = dynamic_cast(it); + if (d) { - // matches filter? - if( it->text( 0 ). - contains( filter, Qt::CaseInsensitive ) ) + if (it->text(0).contains(filter, Qt::CaseInsensitive)) { - // yes, then show everything below - it->setHidden( false ); - filterItems( QString(), it ); + it->setHidden(false); + it->setExpanded(true); + filterAndExpandItems(QString(), it); anyMatched = true; } else { - // only show if item below matches filter - bool didMatch = filterItems( filter, it ); - it->setHidden( !didMatch ); + // Expanding is required when recursive to load in its contents, even if it's collapsed right afterward + it->setExpanded(true); + + bool didMatch = filterAndExpandItems(filter, it); + it->setHidden(!didMatch); + it->setExpanded(didMatch); anyMatched = anyMatched || didMatch; } } - // a standard item (i.e. no file or directory item?) - else if( it->type() == QTreeWidgetItem::Type ) - { - // hide if there's any filter - it->setHidden( !filter.isEmpty() ); - } + else { - // file matches filter? - bool didMatch = it->text( 0 ). - contains( filter, Qt::CaseInsensitive ); - it->setHidden( !didMatch ); - anyMatched = anyMatched || didMatch; + auto f = dynamic_cast(it); + if (f) + { + // File + bool didMatch = it->text(0).contains(filter, Qt::CaseInsensitive); + it->setHidden(!didMatch); + anyMatched = anyMatched || didMatch; + } + + // A standard item (i.e. no file or directory item?) + else + { + // Hide if there's any filter + it->setHidden(!filter.isEmpty()); + } } } @@ -201,15 +242,20 @@ bool FileBrowser::filterItems( const QString & filter, QTreeWidgetItem * item ) void FileBrowser::reloadTree() { - QList expandedDirs = m_fileBrowserTreeWidget->expandedDirs(); - const QString text = m_filterEdit->text(); - m_filterEdit->clear(); + if (m_filterEdit->text().isEmpty()) + { + saveDirectoriesStates(); + } + m_fileBrowserTreeWidget->clear(); + QStringList paths = m_directories.split('*'); + if (m_showUserContent && !m_showUserContent->isChecked()) { paths.removeAll(m_userDir); } + if (m_showFactoryContent && !m_showFactoryContent->isChecked()) { paths.removeAll(m_factoryDir); @@ -222,9 +268,15 @@ void FileBrowser::reloadTree() addItems(path); } } - expandItems(nullptr, expandedDirs); - m_filterEdit->setText( text ); - filterItems( text ); + + if (m_filterEdit->text().isEmpty()) + { + restoreDirectoriesStates(); + } + else + { + filterAndExpandItems(m_filterEdit->text()); + } } @@ -240,12 +292,16 @@ void FileBrowser::expandItems(QTreeWidgetItem* item, QList expandedDirs { // Expanding is required when recursive to load in its contents, even if it's collapsed right afterward if (m_recurse) { d->setExpanded(true); } + d->setExpanded(expandedDirs.contains(d->fullName())); + if (m_recurse && it->childCount()) { expandItems(it, expandedDirs); } } + + it->setHidden(false); } } @@ -416,8 +472,6 @@ QList FileBrowserTreeWidget::expandedDirs( QTreeWidgetItem * item ) con } - - void FileBrowserTreeWidget::keyPressEvent(QKeyEvent * ke ) { // Shorter names for some commonly used properties of the event From 296d5736c8371e365a877f14de8bd45f57ff720f Mon Sep 17 00:00:00 2001 From: Babakinha <59146844+Babakinha@users.noreply.github.com> Date: Mon, 11 Sep 2023 11:57:36 -0300 Subject: [PATCH 121/308] Remember to check for Linux VST Effects (#6751) Remember to also check .so files and not only .dll --- plugins/VstEffect/VstSubPluginFeatures.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/VstEffect/VstSubPluginFeatures.cpp b/plugins/VstEffect/VstSubPluginFeatures.cpp index f929b5526..7eab7a9bf 100644 --- a/plugins/VstEffect/VstSubPluginFeatures.cpp +++ b/plugins/VstEffect/VstSubPluginFeatures.cpp @@ -82,7 +82,11 @@ void VstSubPluginFeatures::addPluginsFromDir( QStringList* filenames, QString pa } } QStringList dlls = QDir( ConfigManager::inst()->vstDir() + path ). - entryList( QStringList() << "*.dll", + entryList( QStringList() << "*.dll" +#ifdef LMMS_BUILD_LINUX + << "*.so" +#endif + , QDir::Files, QDir::Name ); for( int i = 0; i < dlls.size(); i++ ) { From b64912cd57db7bfa2692be42bfa904adc1e72b65 Mon Sep 17 00:00:00 2001 From: consolegrl <5942029+consolegrl@users.noreply.github.com> Date: Tue, 12 Sep 2023 14:35:54 -0400 Subject: [PATCH 122/308] fixes #6354: Sample and Hold for LFO Controller (#6850) * fixes #6354: Sample and Hold for LFO Controller LFO controller's "white noise" wave shape didn't respect the frequency knob at all, so Sample-and-Hold was added to extend the functionality of the LFO Controller with this random waveshape. The original functionallity can still be accessed by setting the FREQ knob to minimum (0.01) --------- Co-authored-by: Kevin Zander Co-authored-by: saker --- include/DataFile.h | 1 + include/LfoController.h | 1 + src/core/DataFile.cpp | 18 ++++++++++++++++++ src/core/LfoController.cpp | 34 ++++++++++++++++++++++++++++++---- 4 files changed, 50 insertions(+), 4 deletions(-) diff --git a/include/DataFile.h b/include/DataFile.h index 137f0156f..c19a00f7f 100644 --- a/include/DataFile.h +++ b/include/DataFile.h @@ -126,6 +126,7 @@ private: void upgrade_defaultTripleOscillatorHQ(); void upgrade_mixerRename(); void upgrade_bbTcoRename(); + void upgrade_sampleAndHold(); // List of all upgrade methods static const std::vector UPGRADE_METHODS; diff --git a/include/LfoController.h b/include/LfoController.h index 1c63ba698..109edbd3f 100644 --- a/include/LfoController.h +++ b/include/LfoController.h @@ -86,6 +86,7 @@ protected: sample_t (*m_sampleFunction)( const float ); private: + float m_heldSample; SampleBuffer * m_userDefSampleBuffer; protected slots: diff --git a/src/core/DataFile.cpp b/src/core/DataFile.cpp index 5c98ec81c..d237d13ae 100644 --- a/src/core/DataFile.cpp +++ b/src/core/DataFile.cpp @@ -79,6 +79,7 @@ const std::vector DataFile::UPGRADE_METHODS = { &DataFile::upgrade_automationNodes , &DataFile::upgrade_extendedNoteRange, &DataFile::upgrade_defaultTripleOscillatorHQ, &DataFile::upgrade_mixerRename , &DataFile::upgrade_bbTcoRename, + &DataFile::upgrade_sampleAndHold , }; // Vector of all versions that have upgrade routines. @@ -1762,6 +1763,23 @@ void DataFile::upgrade_bbTcoRename() } +// Set LFO speed to 0.01 on projects made before sample-and-hold PR +void DataFile::upgrade_sampleAndHold() +{ + QDomNodeList elements = elementsByTagName("lfocontroller"); + for (int i = 0; i < elements.length(); ++i) + { + if (elements.item(i).isNull()) { continue; } + auto e = elements.item(i).toElement(); + // Correct old random wave LFO speeds + if (e.attribute("wave").toInt() == 6) + { + e.setAttribute("speed",0.01f); + } + } +} + + void DataFile::upgrade() { // Runs all necessary upgrade methods diff --git a/src/core/LfoController.cpp b/src/core/LfoController.cpp index 23621b847..88f64803c 100644 --- a/src/core/LfoController.cpp +++ b/src/core/LfoController.cpp @@ -88,6 +88,7 @@ void LfoController::updateValueBuffer() { m_phaseOffset = m_phaseModel.value() / 360.0; float phase = m_currentPhase + m_phaseOffset; + float phasePrev = 0.0f; // roll phase up until we're in sync with period counter m_bufferLastUpdated++; @@ -102,20 +103,45 @@ void LfoController::updateValueBuffer() ValueBuffer *amountBuffer = m_amountModel.valueBuffer(); int amountInc = amountBuffer ? 1 : 0; float *amountPtr = amountBuffer ? &(amountBuffer->values()[ 0 ] ) : &amount; + Oscillator::WaveShape waveshape = static_cast(m_waveModel.value()); for( float& f : m_valueBuffer ) { - const float currentSample = m_sampleFunction != nullptr - ? m_sampleFunction( phase ) - : m_userDefSampleBuffer->userWaveSample( phase ); + float currentSample = 0; + switch (waveshape) + { + case Oscillator::WaveShape::WhiteNoise: + { + if (absFraction(phase) < absFraction(phasePrev)) + { + // Resample when phase period has completed + m_heldSample = m_sampleFunction(phase); + } + currentSample = m_heldSample; + break; + } + case Oscillator::WaveShape::UserDefined: + { + currentSample = m_userDefSampleBuffer->userWaveSample(phase); + break; + } + default: + { + if (m_sampleFunction != nullptr) + { + currentSample = m_sampleFunction(phase); + } + } + } f = std::clamp(m_baseModel.value() + (*amountPtr * currentSample / 2.0f), 0.0f, 1.0f); + phasePrev = phase; phase += 1.0 / m_duration; amountPtr += amountInc; } - m_currentPhase = absFraction( phase - m_phaseOffset ); + m_currentPhase = absFraction(phase - m_phaseOffset); m_bufferLastUpdated = s_periods; } From 89baab6b87df8401cea43118a067573c1e99d303 Mon Sep 17 00:00:00 2001 From: MrTopom Date: Tue, 12 Sep 2023 23:30:31 +0200 Subject: [PATCH 123/308] FileDialog : Adding mounted volumes on Linux (#6834) * FileDialog : Adding mounted volumes on Linux * Adding some file systems types and collapsing 2 'if' statements in one * Removing the foreach * Correcting PREPROCESSOR directive --- src/gui/modals/FileDialog.cpp | 58 ++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/src/gui/modals/FileDialog.cpp b/src/gui/modals/FileDialog.cpp index 512d7179f..a6cf4827a 100644 --- a/src/gui/modals/FileDialog.cpp +++ b/src/gui/modals/FileDialog.cpp @@ -26,11 +26,12 @@ #include #include #include +#include +#include #include "ConfigManager.h" #include "FileDialog.h" - namespace lmms::gui { @@ -45,19 +46,38 @@ FileDialog::FileDialog( QWidget *parent, const QString &caption, setOption( QFileDialog::DontUseNativeDialog ); - // Add additional locations to the sidebar +#ifdef LMMS_BUILD_LINUX + QList urls; +#else QList urls = sidebarUrls(); - urls << QUrl::fromLocalFile( QStandardPaths::writableLocation( QStandardPaths::DesktopLocation ) ); - // Find downloads directory - QDir downloadDir( QDir::homePath() + "/Downloads" ); - if ( ! downloadDir.exists() ) - downloadDir.setPath(QStandardPaths::writableLocation( QStandardPaths::DownloadLocation )); - if ( downloadDir.exists() ) - urls << QUrl::fromLocalFile( downloadDir.absolutePath() ); +#endif - urls << QUrl::fromLocalFile( QStandardPaths::writableLocation( QStandardPaths::MusicLocation ) ); - urls << QUrl::fromLocalFile( ConfigManager::inst()->workingDir() ); + QDir desktopDir; + desktopDir.setPath(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); + if (desktopDir.exists()) + { + urls << QUrl::fromLocalFile(desktopDir.absolutePath()); + } + + QDir downloadDir(QDir::homePath() + "/Downloads"); + if (!downloadDir.exists()) + { + downloadDir.setPath(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)); + } + if (downloadDir.exists()) + { + urls << QUrl::fromLocalFile(downloadDir.absolutePath()); + } + QDir musicDir; + musicDir.setPath(QStandardPaths::writableLocation(QStandardPaths::MusicLocation)); + if (musicDir.exists()) + { + urls << QUrl::fromLocalFile(musicDir.absolutePath()); + } + + urls << QUrl::fromLocalFile(ConfigManager::inst()->workingDir()); + // Add `/Volumes` directory on OS X systems, this allows the user to browse // external disk drives. #ifdef LMMS_BUILD_APPLE @@ -66,6 +86,22 @@ FileDialog::FileDialog( QWidget *parent, const QString &caption, urls << QUrl::fromLocalFile( volumesDir.absolutePath() ); #endif +#ifdef LMMS_BUILD_LINUX + + // FileSystem types : https://www.javatpoint.com/linux-file-system + QStringList usableFileSystems = {"ext", "ext2", "ext3", "ext4", "jfs", "reiserfs", "ntfs3", "fuse.sshfs", "fuseblk"}; + + for(QStorageInfo storage : QStorageInfo::mountedVolumes()) + { + storage.refresh(); + + if (usableFileSystems.contains(QString(storage.fileSystemType()), Qt::CaseInsensitive) && storage.isValid() && storage.isReady()) + { + urls << QUrl::fromLocalFile(storage.rootPath()); + } + } +#endif + setSidebarUrls(urls); } From 3a0e68c0ac93a743cedca379c66de00d13647d69 Mon Sep 17 00:00:00 2001 From: consolegrl <5942029+consolegrl@users.noreply.github.com> Date: Tue, 12 Sep 2023 18:08:06 -0400 Subject: [PATCH 124/308] fixes #6736: Sample tracks lose FX Channel (#6851) * fixes #6736: Sample tracks lose FX Channel * Styling fixes * Restyled remaining blocks of upgrade routine * Fixed hang due to sleepy typo * Update src/core/DataFile.cpp Co-authored-by: saker --------- Co-authored-by: saker --- src/core/DataFile.cpp | 46 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/src/core/DataFile.cpp b/src/core/DataFile.cpp index d237d13ae..5915b25ef 100644 --- a/src/core/DataFile.cpp +++ b/src/core/DataFile.cpp @@ -1704,26 +1704,56 @@ void DataFile::upgrade_mixerRename() { // Change nodename to QDomNodeList fxmixer = elementsByTagName("fxmixer"); - for (int i = 0; !fxmixer.item(i).isNull(); ++i) + for (int i = 0; i < fxmixer.length(); ++i) { - fxmixer.item(i).toElement().setTagName("mixer"); + auto item = fxmixer.item(i).toElement(); + if (item.isNull()) + { + continue; + } + item.setTagName("mixer"); } // Change nodename to QDomNodeList fxchannel = elementsByTagName("fxchannel"); - for (int i = 0; !fxchannel.item(i).isNull(); ++i) + for (int i = 0; i < fxchannel.length(); ++i) { - fxchannel.item(i).toElement().setTagName("mixerchannel"); + auto item = fxchannel.item(i).toElement(); + if (item.isNull()) + { + continue; + } + item.setTagName("mixerchannel"); } // Change the attribute fxch of element to mixch QDomNodeList fxch = elementsByTagName("instrumenttrack"); - for(int i = 0; !fxch.item(i).isNull(); ++i) + for (int i = 0; i < fxch.length(); ++i) { - if(fxch.item(i).toElement().hasAttribute("fxch")) + auto item = fxch.item(i).toElement(); + if (item.isNull()) { - fxch.item(i).toElement().setAttribute("mixch", fxch.item(i).toElement().attribute("fxch")); - fxch.item(i).toElement().removeAttribute("fxch"); + continue; + } + if (item.hasAttribute("fxch")) + { + item.setAttribute("mixch", item.attribute("fxch")); + item.removeAttribute("fxch"); + } + } + // Change the attribute fxch of element to mixch + fxch = elementsByTagName("sampletrack"); + for (int i = 0; i < fxch.length(); ++i) + { + auto item = fxch.item(i).toElement(); + if (item.isNull()) + { + continue; + } + if (item.hasAttribute("fxch")) + { + item.setAttribute("mixch", item.attribute("fxch")); + item.removeAttribute("fxch"); } } } From 9b1933e544697bfa67d337ed12e0501d66a66ec0 Mon Sep 17 00:00:00 2001 From: Maxwell Voorhes <100326501+mvoorhes@users.noreply.github.com> Date: Thu, 14 Sep 2023 08:17:36 -0700 Subject: [PATCH 125/308] Added flats to array of keys (#6865) --- src/gui/editors/PianoRoll.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index b38335995..751fb9d2a 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -130,7 +130,7 @@ QPixmap* PianoRoll::s_toolKnife = nullptr; SimpleTextFloat * PianoRoll::s_textFloat = nullptr; -static std::array s_noteStrings {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"}; +static std::array s_noteStrings {"C", "C# / D\u266D", "D", "D# / E\u266D", "E", "F", "F# / G\u266D", "G", "G# / A\u266D", "A", "A# / B\u266D", "B"}; static QString getNoteString(int key) { From d3d710e0adac3798ae65f1e2b34fd582e4c02bc6 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Thu, 14 Sep 2023 23:12:22 +0200 Subject: [PATCH 126/308] Remove identical calls to `InstrumentTrack::processAudioBuffer` Remove identical calls to `InstrumentTrack::processAudioBuffer` which appear in the overridden implementations of `Instrument::play` and `Instrument::playNotes`. Instead the call to `processAudioBuffer` has been moved into `InstrumentPlayHandle::play` and `InstrumentTrack::playNote`. These two methods call the aforementioned methods of `Instrument`. Especially in the case of `InstrumentTrack::playNote` the previous implementation resulted in some unncessary "ping pong" where `InstrumentTrack` called a method on an `Instrument` which then in turn called a method on `InstrumentTrack`. And this was done in almost every instrument. In `InstrumentTrack::playNote` an additional check was added which only calls `processAudioBuffer` if the buffer is not `nullptr`. The reason is that under certain circumstances `PlayHandle::doProcessing` calls the `play` method by explicitly passing a `nullptr` as the buffer. This behavior was added with commit 7bc97f5d5bd. Because it is unknown if this was done for some side effects the code was adjusted so that it behaves identical in this case. Move the complex implementation for `InstrumentPlayHandle::play` and `InstrumentPlayHandle::isFromTrack` into the cpp file and optimize the includes. --- include/InstrumentPlayHandle.h | 38 +++--------------- .../AudioFileProcessor/AudioFileProcessor.cpp | 3 -- plugins/BitInvader/BitInvader.cpp | 2 - plugins/CarlaBase/Carla.cpp | 3 -- plugins/FreeBoy/FreeBoy.cpp | 1 - plugins/GigPlayer/GigPlayer.cpp | 2 - plugins/Kicker/Kicker.cpp | 2 - plugins/Lb302/Lb302.cpp | 1 - plugins/Lv2Instrument/Lv2Instrument.cpp | 2 - plugins/Monstro/Monstro.cpp | 2 - plugins/Nes/Nes.cpp | 2 - plugins/OpulenZ/OpulenZ.cpp | 4 -- plugins/Organic/Organic.cpp | 2 - plugins/Patman/Patman.cpp | 2 - plugins/Sf2Player/Sf2Player.cpp | 2 - plugins/Sfxr/Sfxr.cpp | 3 -- plugins/Sid/SidInstrument.cpp | 2 - plugins/Stk/Mallets/Mallets.cpp | 2 - plugins/TripleOscillator/TripleOscillator.cpp | 2 - plugins/Vestige/Vestige.cpp | 2 - plugins/Vibed/Vibed.cpp | 2 - plugins/Watsyn/Watsyn.cpp | 2 - plugins/Xpressive/Xpressive.cpp | 2 - plugins/ZynAddSubFx/ZynAddSubFx.cpp | 1 - src/core/InstrumentPlayHandle.cpp | 39 +++++++++++++++++++ src/tracks/InstrumentTrack.cpp | 7 ++++ 26 files changed, 51 insertions(+), 81 deletions(-) diff --git a/include/InstrumentPlayHandle.h b/include/InstrumentPlayHandle.h index bbf53d16c..1455134e6 100644 --- a/include/InstrumentPlayHandle.h +++ b/include/InstrumentPlayHandle.h @@ -26,13 +26,14 @@ #define LMMS_INSTRUMENT_PLAY_HANDLE_H #include "PlayHandle.h" -#include "Instrument.h" -#include "NotePlayHandle.h" #include "lmms_export.h" namespace lmms { +class Instrument; +class InstrumentTrack; + class LMMS_EXPORT InstrumentPlayHandle : public PlayHandle { public: @@ -40,46 +41,17 @@ public: ~InstrumentPlayHandle() override = default; - - void play( sampleFrame * _working_buffer ) override - { - // ensure that all our nph's have been processed first - ConstNotePlayHandleList nphv = NotePlayHandle::nphsOfInstrumentTrack( m_instrument->instrumentTrack(), true ); - - bool nphsLeft; - do - { - nphsLeft = false; - for( const NotePlayHandle * constNotePlayHandle : nphv ) - { - NotePlayHandle * notePlayHandle = const_cast( constNotePlayHandle ); - if( notePlayHandle->state() != ThreadableJob::ProcessingState::Done && - !notePlayHandle->isFinished()) - { - nphsLeft = true; - notePlayHandle->process(); - } - } - } - while( nphsLeft ); - - m_instrument->play( _working_buffer ); - } + void play( sampleFrame * _working_buffer ) override; bool isFinished() const override { return false; } - bool isFromTrack( const Track* _track ) const override - { - return m_instrument->isFromTrack( _track ); - } - + bool isFromTrack( const Track* _track ) const override; private: Instrument* m_instrument; - } ; diff --git a/plugins/AudioFileProcessor/AudioFileProcessor.cpp b/plugins/AudioFileProcessor/AudioFileProcessor.cpp index a941e773f..667102207 100644 --- a/plugins/AudioFileProcessor/AudioFileProcessor.cpp +++ b/plugins/AudioFileProcessor/AudioFileProcessor.cpp @@ -171,9 +171,6 @@ void AudioFileProcessor::playNote( NotePlayHandle * _n, static_cast( m_loopModel.value() ) ) ) { applyRelease( _working_buffer, _n ); - instrumentTrack()->processAudioBuffer( _working_buffer, - frames + offset, _n ); - emit isPlaying( ((handleState *)_n->m_pluginData)->frameIndex() ); } else diff --git a/plugins/BitInvader/BitInvader.cpp b/plugins/BitInvader/BitInvader.cpp index 98ef1e97c..4ea73dc71 100644 --- a/plugins/BitInvader/BitInvader.cpp +++ b/plugins/BitInvader/BitInvader.cpp @@ -307,8 +307,6 @@ void BitInvader::playNote( NotePlayHandle * _n, } applyRelease( _working_buffer, _n ); - - instrumentTrack()->processAudioBuffer( _working_buffer, frames + offset, _n ); } diff --git a/plugins/CarlaBase/Carla.cpp b/plugins/CarlaBase/Carla.cpp index faff94b57..819736e92 100644 --- a/plugins/CarlaBase/Carla.cpp +++ b/plugins/CarlaBase/Carla.cpp @@ -508,7 +508,6 @@ void CarlaInstrument::play(sampleFrame* workingBuffer) if (fHandle == nullptr) { - instrumentTrack()->processAudioBuffer(workingBuffer, bufsize, nullptr); return; } @@ -556,8 +555,6 @@ void CarlaInstrument::play(sampleFrame* workingBuffer) workingBuffer[i][0] = buf1[i]; workingBuffer[i][1] = buf2[i]; } - - instrumentTrack()->processAudioBuffer(workingBuffer, bufsize, nullptr); } bool CarlaInstrument::handleMidiEvent(const MidiEvent& event, const TimePos&, f_cnt_t offset) diff --git a/plugins/FreeBoy/FreeBoy.cpp b/plugins/FreeBoy/FreeBoy.cpp index 6450253ee..f2dc95699 100644 --- a/plugins/FreeBoy/FreeBoy.cpp +++ b/plugins/FreeBoy/FreeBoy.cpp @@ -419,7 +419,6 @@ void FreeBoyInstrument::playNote(NotePlayHandle* nph, sampleFrame* workingBuffer } framesLeft -= count; } - instrumentTrack()->processAudioBuffer(workingBuffer, frames + offset, nph); } diff --git a/plugins/GigPlayer/GigPlayer.cpp b/plugins/GigPlayer/GigPlayer.cpp index c2e155a20..0713d3100 100644 --- a/plugins/GigPlayer/GigPlayer.cpp +++ b/plugins/GigPlayer/GigPlayer.cpp @@ -494,8 +494,6 @@ void GigInstrument::play( sampleFrame * _working_buffer ) _working_buffer[i][0] *= m_gain.value(); _working_buffer[i][1] *= m_gain.value(); } - - instrumentTrack()->processAudioBuffer( _working_buffer, frames, nullptr ); } diff --git a/plugins/Kicker/Kicker.cpp b/plugins/Kicker/Kicker.cpp index ef1d623c1..e6418e2da 100644 --- a/plugins/Kicker/Kicker.cpp +++ b/plugins/Kicker/Kicker.cpp @@ -197,8 +197,6 @@ void KickerInstrument::playNote( NotePlayHandle * _n, _working_buffer[f+offset][1] *= fac; } } - - instrumentTrack()->processAudioBuffer( _working_buffer, frames + offset, _n ); } diff --git a/plugins/Lb302/Lb302.cpp b/plugins/Lb302/Lb302.cpp index b8fff2c0b..ee49442d5 100644 --- a/plugins/Lb302/Lb302.cpp +++ b/plugins/Lb302/Lb302.cpp @@ -790,7 +790,6 @@ void Lb302Synth::play( sampleFrame * _working_buffer ) const fpp_t frames = Engine::audioEngine()->framesPerPeriod(); process( _working_buffer, frames ); - instrumentTrack()->processAudioBuffer( _working_buffer, frames, nullptr ); // release_frame = 0; //removed for issue # 1432 } diff --git a/plugins/Lv2Instrument/Lv2Instrument.cpp b/plugins/Lv2Instrument/Lv2Instrument.cpp index 1e45f4e91..32f81d23c 100644 --- a/plugins/Lv2Instrument/Lv2Instrument.cpp +++ b/plugins/Lv2Instrument/Lv2Instrument.cpp @@ -197,8 +197,6 @@ void Lv2Instrument::play(sampleFrame *buf) copyModelsToLmms(); copyBuffersToLmms(buf, fpp); - - instrumentTrack()->processAudioBuffer(buf, fpp, nullptr); } diff --git a/plugins/Monstro/Monstro.cpp b/plugins/Monstro/Monstro.cpp index f588d6b78..2201e4ed9 100644 --- a/plugins/Monstro/Monstro.cpp +++ b/plugins/Monstro/Monstro.cpp @@ -1040,8 +1040,6 @@ void MonstroInstrument::playNote( NotePlayHandle * _n, ms->renderOutput( frames, _working_buffer + offset ); //applyRelease( _working_buffer, _n ); // we have our own release - - instrumentTrack()->processAudioBuffer( _working_buffer, frames + offset, _n ); } void MonstroInstrument::deleteNotePluginData( NotePlayHandle * _n ) diff --git a/plugins/Nes/Nes.cpp b/plugins/Nes/Nes.cpp index a530ac19b..47122a0c6 100644 --- a/plugins/Nes/Nes.cpp +++ b/plugins/Nes/Nes.cpp @@ -561,8 +561,6 @@ void NesInstrument::playNote( NotePlayHandle * n, sampleFrame * workingBuffer ) nes->renderOutput( workingBuffer + offset, frames ); applyRelease( workingBuffer, n ); - - instrumentTrack()->processAudioBuffer( workingBuffer, frames + offset, n ); } diff --git a/plugins/OpulenZ/OpulenZ.cpp b/plugins/OpulenZ/OpulenZ.cpp index 64f609995..d90d5f343 100644 --- a/plugins/OpulenZ/OpulenZ.cpp +++ b/plugins/OpulenZ/OpulenZ.cpp @@ -412,10 +412,6 @@ void OpulenzInstrument::play( sampleFrame * _working_buffer ) } } emulatorMutex.unlock(); - - // Throw the data to the track... - instrumentTrack()->processAudioBuffer( _working_buffer, frameCount, nullptr ); - } diff --git a/plugins/Organic/Organic.cpp b/plugins/Organic/Organic.cpp index f8a2b0d13..a70da6421 100644 --- a/plugins/Organic/Organic.cpp +++ b/plugins/Organic/Organic.cpp @@ -312,8 +312,6 @@ void OrganicInstrument::playNote( NotePlayHandle * _n, } // -- -- - - instrumentTrack()->processAudioBuffer( _working_buffer, frames + offset, _n ); } diff --git a/plugins/Patman/Patman.cpp b/plugins/Patman/Patman.cpp index a2b829940..668c7f461 100644 --- a/plugins/Patman/Patman.cpp +++ b/plugins/Patman/Patman.cpp @@ -157,8 +157,6 @@ void PatmanInstrument::playNote( NotePlayHandle * _n, play_freq, m_loopedModel.value() ? SampleBuffer::LoopMode::On : SampleBuffer::LoopMode::Off ) ) { applyRelease( _working_buffer, _n ); - instrumentTrack()->processAudioBuffer( _working_buffer, - frames + offset, _n ); } else { diff --git a/plugins/Sf2Player/Sf2Player.cpp b/plugins/Sf2Player/Sf2Player.cpp index d46af5e4f..79bd4b976 100644 --- a/plugins/Sf2Player/Sf2Player.cpp +++ b/plugins/Sf2Player/Sf2Player.cpp @@ -848,7 +848,6 @@ void Sf2Instrument::play( sampleFrame * _working_buffer ) if( m_playingNotes.isEmpty() ) { renderFrames( frames, _working_buffer ); - instrumentTrack()->processAudioBuffer( _working_buffer, frames, nullptr ); return; } @@ -906,7 +905,6 @@ void Sf2Instrument::play( sampleFrame * _working_buffer ) { renderFrames( frames - currentFrame, _working_buffer + currentFrame ); } - instrumentTrack()->processAudioBuffer( _working_buffer, frames, nullptr ); } diff --git a/plugins/Sfxr/Sfxr.cpp b/plugins/Sfxr/Sfxr.cpp index fc39ea0fa..e79b8e2ad 100644 --- a/plugins/Sfxr/Sfxr.cpp +++ b/plugins/Sfxr/Sfxr.cpp @@ -480,9 +480,6 @@ void SfxrInstrument::playNote( NotePlayHandle * _n, sampleFrame * _working_buffe delete[] pitchedBuffer; applyRelease( _working_buffer, _n ); - - instrumentTrack()->processAudioBuffer( _working_buffer, frameNum + offset, _n ); - } diff --git a/plugins/Sid/SidInstrument.cpp b/plugins/Sid/SidInstrument.cpp index f663c3b69..143003f98 100644 --- a/plugins/Sid/SidInstrument.cpp +++ b/plugins/Sid/SidInstrument.cpp @@ -429,8 +429,6 @@ void SidInstrument::playNote( NotePlayHandle * _n, _working_buffer[frame+offset][ch] = s; } } - - instrumentTrack()->processAudioBuffer( _working_buffer, frames + offset, _n ); } diff --git a/plugins/Stk/Mallets/Mallets.cpp b/plugins/Stk/Mallets/Mallets.cpp index 4fb077de5..b746e9491 100644 --- a/plugins/Stk/Mallets/Mallets.cpp +++ b/plugins/Stk/Mallets/Mallets.cpp @@ -359,8 +359,6 @@ void MalletsInstrument::playNote( NotePlayHandle * _n, _working_buffer[frame][1] = ps->nextSampleRight() * ( m_scalers[p] + add_scale ); } - - instrumentTrack()->processAudioBuffer( _working_buffer, frames + offset, _n ); } diff --git a/plugins/TripleOscillator/TripleOscillator.cpp b/plugins/TripleOscillator/TripleOscillator.cpp index f2340d3d6..5b8f6e8ad 100644 --- a/plugins/TripleOscillator/TripleOscillator.cpp +++ b/plugins/TripleOscillator/TripleOscillator.cpp @@ -380,8 +380,6 @@ void TripleOscillator::playNote( NotePlayHandle * _n, applyFadeIn(_working_buffer, _n); applyRelease( _working_buffer, _n ); - - instrumentTrack()->processAudioBuffer( _working_buffer, frames + offset, _n ); } diff --git a/plugins/Vestige/Vestige.cpp b/plugins/Vestige/Vestige.cpp index dd8e9cbef..aff5b7fdc 100644 --- a/plugins/Vestige/Vestige.cpp +++ b/plugins/Vestige/Vestige.cpp @@ -409,8 +409,6 @@ void VestigeInstrument::play( sampleFrame * _buf ) m_plugin->process( nullptr, _buf ); - instrumentTrack()->processAudioBuffer( _buf, frames, nullptr ); - m_pluginMutex.unlock(); } diff --git a/plugins/Vibed/Vibed.cpp b/plugins/Vibed/Vibed.cpp index 3ed51fe79..ad6a3942a 100644 --- a/plugins/Vibed/Vibed.cpp +++ b/plugins/Vibed/Vibed.cpp @@ -251,8 +251,6 @@ void Vibed::playNote(NotePlayHandle* n, sampleFrame* workingBuffer) } } } - - instrumentTrack()->processAudioBuffer(workingBuffer, frames + offset, n); } void Vibed::deleteNotePluginData(NotePlayHandle* n) diff --git a/plugins/Watsyn/Watsyn.cpp b/plugins/Watsyn/Watsyn.cpp index 7603a9c1b..8e49942e1 100644 --- a/plugins/Watsyn/Watsyn.cpp +++ b/plugins/Watsyn/Watsyn.cpp @@ -445,8 +445,6 @@ void WatsynInstrument::playNote( NotePlayHandle * _n, } applyRelease( _working_buffer, _n ); - - instrumentTrack()->processAudioBuffer( _working_buffer, frames + offset, _n ); } diff --git a/plugins/Xpressive/Xpressive.cpp b/plugins/Xpressive/Xpressive.cpp index b1a17a1ce..babc37231 100644 --- a/plugins/Xpressive/Xpressive.cpp +++ b/plugins/Xpressive/Xpressive.cpp @@ -233,8 +233,6 @@ void Xpressive::playNote(NotePlayHandle* nph, sampleFrame* working_buffer) { const f_cnt_t offset = nph->noteOffset(); ps->renderOutput(frames, working_buffer + offset); - - instrumentTrack()->processAudioBuffer(working_buffer, frames + offset, nph); } void Xpressive::deleteNotePluginData(NotePlayHandle* nph) { diff --git a/plugins/ZynAddSubFx/ZynAddSubFx.cpp b/plugins/ZynAddSubFx/ZynAddSubFx.cpp index 2ec864592..be38bcb79 100644 --- a/plugins/ZynAddSubFx/ZynAddSubFx.cpp +++ b/plugins/ZynAddSubFx/ZynAddSubFx.cpp @@ -341,7 +341,6 @@ void ZynAddSubFxInstrument::play( sampleFrame * _buf ) m_plugin->processAudio( _buf ); } m_pluginMutex.unlock(); - instrumentTrack()->processAudioBuffer( _buf, Engine::audioEngine()->framesPerPeriod(), nullptr ); } diff --git a/src/core/InstrumentPlayHandle.cpp b/src/core/InstrumentPlayHandle.cpp index e1a9d9d65..30f5fde38 100644 --- a/src/core/InstrumentPlayHandle.cpp +++ b/src/core/InstrumentPlayHandle.cpp @@ -24,7 +24,10 @@ #include "InstrumentPlayHandle.h" +#include "Instrument.h" #include "InstrumentTrack.h" +#include "Engine.h" +#include "AudioEngine.h" namespace lmms { @@ -37,5 +40,41 @@ InstrumentPlayHandle::InstrumentPlayHandle( Instrument * instrument, InstrumentT setAudioPort( instrumentTrack->audioPort() ); } +void InstrumentPlayHandle::play( sampleFrame * _working_buffer ) +{ + InstrumentTrack * instrumentTrack = m_instrument->instrumentTrack(); + + // ensure that all our nph's have been processed first + ConstNotePlayHandleList nphv = NotePlayHandle::nphsOfInstrumentTrack(instrumentTrack, true ); + + bool nphsLeft; + do + { + nphsLeft = false; + for( const NotePlayHandle * constNotePlayHandle : nphv ) + { + NotePlayHandle * notePlayHandle = const_cast( constNotePlayHandle ); + if( notePlayHandle->state() != ThreadableJob::ProcessingState::Done && + !notePlayHandle->isFinished()) + { + nphsLeft = true; + notePlayHandle->process(); + } + } + } + while( nphsLeft ); + + m_instrument->play( _working_buffer ); + + // Process the audio buffer that the instrument has just worked on... + const fpp_t frames = Engine::audioEngine()->framesPerPeriod(); + instrumentTrack->processAudioBuffer(_working_buffer, frames, nullptr); +} + +bool InstrumentPlayHandle::isFromTrack( const Track* _track ) const +{ + return m_instrument->isFromTrack( _track ); +} + } // namespace lmms \ No newline at end of file diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index a4de188a5..c9b87a4f2 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -579,6 +579,13 @@ void InstrumentTrack::playNote( NotePlayHandle* n, sampleFrame* workingBuffer ) { // all is done, so now lets play the note! m_instrument->playNote( n, workingBuffer ); + + if (workingBuffer != nullptr) + { + const fpp_t frames = n->framesLeftForCurrentPeriod(); + const f_cnt_t offset = n->noteOffset(); + this->processAudioBuffer(workingBuffer, frames + offset, n); + } } } From a6b6565687d658350fe84b448676ace5a1c466c7 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Thu, 14 Sep 2023 23:35:16 +0200 Subject: [PATCH 127/308] Remove unused variable Remove the unused variable `frames` in `VestigeInstrument::play` to fix the stricter GitHub build. --- plugins/Vestige/Vestige.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/Vestige/Vestige.cpp b/plugins/Vestige/Vestige.cpp index aff5b7fdc..a696a4b2d 100644 --- a/plugins/Vestige/Vestige.cpp +++ b/plugins/Vestige/Vestige.cpp @@ -399,8 +399,6 @@ void VestigeInstrument::play( sampleFrame * _buf ) { if (!m_pluginMutex.tryLock(Engine::getSong()->isExporting() ? -1 : 0)) {return;} - const fpp_t frames = Engine::audioEngine()->framesPerPeriod(); - if( m_plugin == nullptr ) { m_pluginMutex.unlock(); From d25723cead8dbf46e9b4983e90813ab36325f5dc Mon Sep 17 00:00:00 2001 From: saker Date: Fri, 15 Sep 2023 22:25:54 -0400 Subject: [PATCH 128/308] Update display file name when opening ``PatmanView`` (#6870) * Update display file name when loading Patman * Conditionally update file name --- plugins/Patman/Patman.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/plugins/Patman/Patman.cpp b/plugins/Patman/Patman.cpp index a2b829940..e96431e3a 100644 --- a/plugins/Patman/Patman.cpp +++ b/plugins/Patman/Patman.cpp @@ -446,7 +446,7 @@ namespace gui PatmanView::PatmanView( Instrument * _instrument, QWidget * _parent ) : InstrumentViewFixedSize( _instrument, _parent ), - m_pi( nullptr ) + m_pi(castModel()) { setAutoFillBackground( true ); QPalette pal; @@ -487,7 +487,15 @@ PatmanView::PatmanView( Instrument * _instrument, QWidget * _parent ) : "tune_off" ) ); m_tuneButton->setToolTip(tr("Tune mode")); - m_displayFilename = tr( "No file selected" ); + + if (m_pi->m_patchFile.isEmpty()) + { + m_displayFilename = tr("No file selected"); + } + else + { + updateFilename(); + } setAcceptDrops( true ); } From 73f9f36c9afcf65150ae8b1f47d359f2472d3eae Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sat, 16 Sep 2023 13:35:15 +0200 Subject: [PATCH 129/308] Code review changes Remove whitespace in methods and add it to the parenthesis of some statements. Remove underscores from parameter names. Remove usage of `this` pointer. Add `auto` keyword to shorten line length in `InstrumentPlayHandle::play`. Move `const_cast` of `NotePlayHandle` closer to the `process` method as this method is the reason that the cast is needed in the first place. One might also add a version of `nphsOfInstrumentTrack` that returns a non-const result but it seems to be a general problem of a missing clear responsibility so I keep it as is. --- include/InstrumentPlayHandle.h | 9 ++++----- src/core/InstrumentPlayHandle.cpp | 32 +++++++++++++++---------------- src/tracks/InstrumentTrack.cpp | 2 +- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/include/InstrumentPlayHandle.h b/include/InstrumentPlayHandle.h index 1455134e6..dc744b4ff 100644 --- a/include/InstrumentPlayHandle.h +++ b/include/InstrumentPlayHandle.h @@ -37,23 +37,22 @@ class InstrumentTrack; class LMMS_EXPORT InstrumentPlayHandle : public PlayHandle { public: - InstrumentPlayHandle( Instrument * instrument, InstrumentTrack* instrumentTrack ); + InstrumentPlayHandle(Instrument * instrument, InstrumentTrack* instrumentTrack); ~InstrumentPlayHandle() override = default; - void play( sampleFrame * _working_buffer ) override; + void play(sampleFrame * working_buffer) override; bool isFinished() const override { return false; } - bool isFromTrack( const Track* _track ) const override; + bool isFromTrack(const Track* track) const override; private: Instrument* m_instrument; -} ; - +}; } // namespace lmms diff --git a/src/core/InstrumentPlayHandle.cpp b/src/core/InstrumentPlayHandle.cpp index 30f5fde38..097719ad8 100644 --- a/src/core/InstrumentPlayHandle.cpp +++ b/src/core/InstrumentPlayHandle.cpp @@ -33,48 +33,48 @@ namespace lmms { -InstrumentPlayHandle::InstrumentPlayHandle( Instrument * instrument, InstrumentTrack* instrumentTrack ) : - PlayHandle( Type::InstrumentPlayHandle ), - m_instrument( instrument ) +InstrumentPlayHandle::InstrumentPlayHandle(Instrument * instrument, InstrumentTrack* instrumentTrack) : + PlayHandle(Type::InstrumentPlayHandle), + m_instrument(instrument) { - setAudioPort( instrumentTrack->audioPort() ); + setAudioPort(instrumentTrack->audioPort()); } -void InstrumentPlayHandle::play( sampleFrame * _working_buffer ) +void InstrumentPlayHandle::play(sampleFrame * working_buffer) { InstrumentTrack * instrumentTrack = m_instrument->instrumentTrack(); // ensure that all our nph's have been processed first - ConstNotePlayHandleList nphv = NotePlayHandle::nphsOfInstrumentTrack(instrumentTrack, true ); + auto nphv = NotePlayHandle::nphsOfInstrumentTrack(instrumentTrack, true); bool nphsLeft; do { nphsLeft = false; - for( const NotePlayHandle * constNotePlayHandle : nphv ) + for (const NotePlayHandle * constNotePlayHandle : nphv) { - NotePlayHandle * notePlayHandle = const_cast( constNotePlayHandle ); - if( notePlayHandle->state() != ThreadableJob::ProcessingState::Done && - !notePlayHandle->isFinished()) + if (constNotePlayHandle->state() != ThreadableJob::ProcessingState::Done && + !constNotePlayHandle->isFinished()) { nphsLeft = true; + NotePlayHandle * notePlayHandle = const_cast(constNotePlayHandle); notePlayHandle->process(); } } } - while( nphsLeft ); + while (nphsLeft); - m_instrument->play( _working_buffer ); + m_instrument->play(working_buffer); // Process the audio buffer that the instrument has just worked on... const fpp_t frames = Engine::audioEngine()->framesPerPeriod(); - instrumentTrack->processAudioBuffer(_working_buffer, frames, nullptr); + instrumentTrack->processAudioBuffer(working_buffer, frames, nullptr); } -bool InstrumentPlayHandle::isFromTrack( const Track* _track ) const +bool InstrumentPlayHandle::isFromTrack(const Track* track) const { - return m_instrument->isFromTrack( _track ); + return m_instrument->isFromTrack(track); } -} // namespace lmms \ No newline at end of file +} // namespace lmms diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index c9b87a4f2..0ffde61bc 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -584,7 +584,7 @@ void InstrumentTrack::playNote( NotePlayHandle* n, sampleFrame* workingBuffer ) { const fpp_t frames = n->framesLeftForCurrentPeriod(); const f_cnt_t offset = n->noteOffset(); - this->processAudioBuffer(workingBuffer, frames + offset, n); + processAudioBuffer(workingBuffer, frames + offset, n); } } } From 6c3ae30c8937173bd69ec3f12ccd5996189c3342 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sat, 16 Sep 2023 19:19:37 +0200 Subject: [PATCH 130/308] Add comments about nullptr guard Add some comments which describe why we need to guard agains nullptr. --- src/tracks/InstrumentTrack.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 0ffde61bc..5dee1f3a5 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -570,6 +570,10 @@ f_cnt_t InstrumentTrack::beatLen( NotePlayHandle * _n ) const void InstrumentTrack::playNote( NotePlayHandle* n, sampleFrame* workingBuffer ) { + // Note: under certain circumstances the working buffer is a nullptr. + // These cases are triggered in PlayHandle::doProcessing when the play method is called with a nullptr. + // TODO: Find out if we can skip processing at a higher level if the buffer is nullptr. + // arpeggio- and chord-widget has to do its work -> adding sub-notes // for chords/arpeggios m_noteStacking.processNote( n ); @@ -580,6 +584,8 @@ void InstrumentTrack::playNote( NotePlayHandle* n, sampleFrame* workingBuffer ) // all is done, so now lets play the note! m_instrument->playNote( n, workingBuffer ); + // Calling processAudioBuffer with a nullptr leads to crashes when checking if the buffer represents silence. + // Therefore we must guard against a nullptr here. if (workingBuffer != nullptr) { const fpp_t frames = n->framesLeftForCurrentPeriod(); From 4348038b0ff2f334f85a37a1caf124213f6d3439 Mon Sep 17 00:00:00 2001 From: Austin <61636545+aakers24@users.noreply.github.com> Date: Sun, 17 Sep 2023 08:34:42 -0700 Subject: [PATCH 131/308] Added automatic dark note on light background for midi clips. (#6539) --- src/gui/clips/MidiClipView.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/clips/MidiClipView.cpp b/src/gui/clips/MidiClipView.cpp index 79c4cd73d..151df8d3c 100644 --- a/src/gui/clips/MidiClipView.cpp +++ b/src/gui/clips/MidiClipView.cpp @@ -523,7 +523,8 @@ void MidiClipView::paintEvent( QPaintEvent * ) p.scale(width(), height() - distanceToTop - 2 * notesBorder); // set colour based on mute status - QColor noteFillColor = muted ? getMutedNoteFillColor() : getNoteFillColor(); + QColor noteFillColor = muted ? getMutedNoteFillColor().lighter(200) + : (c.lightness() > 175 ? getNoteFillColor().darker(400) : getNoteFillColor()); QColor noteBorderColor = muted ? getMutedNoteBorderColor() : ( m_clip->hasColor() ? c.lighter( 200 ) : getNoteBorderColor() ); From e9125d3ad3c8d6da568ea64641896a0f71671534 Mon Sep 17 00:00:00 2001 From: Martin Pavelek Date: Sun, 17 Sep 2023 17:55:04 +0200 Subject: [PATCH 132/308] Fix LcdFloatSpinBox constructor and label alignment (#6686) --- src/gui/widgets/LcdFloatSpinBox.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/gui/widgets/LcdFloatSpinBox.cpp b/src/gui/widgets/LcdFloatSpinBox.cpp index 6391f314a..96f2b27e1 100644 --- a/src/gui/widgets/LcdFloatSpinBox.cpp +++ b/src/gui/widgets/LcdFloatSpinBox.cpp @@ -49,6 +49,7 @@ namespace lmms::gui LcdFloatSpinBox::LcdFloatSpinBox(int numWhole, int numFrac, const QString& name, QWidget* parent) : + QWidget(parent), FloatModelView(new FloatModel(0, 0, 0, 0, nullptr, name, true), this), m_wholeDisplay(numWhole, parent, name, false), m_fractionDisplay(numFrac, parent, name, true), @@ -62,6 +63,7 @@ LcdFloatSpinBox::LcdFloatSpinBox(int numWhole, int numFrac, const QString& name, LcdFloatSpinBox::LcdFloatSpinBox(int numWhole, int numFrac, const QString& style, const QString& name, QWidget* parent) : + QWidget(parent), FloatModelView(new FloatModel(0, 0, 0, 0, nullptr, name, true), this), m_wholeDisplay(numWhole, style, parent, name, false), m_fractionDisplay(numFrac, style, parent, name, true), @@ -101,6 +103,7 @@ void LcdFloatSpinBox::layoutSetup(const QString &style) outerLayout->setContentsMargins(0, 0, 0, 0); outerLayout->setSizeConstraint(QLayout::SetFixedSize); this->setLayout(outerLayout); + this->setFixedHeight(32); } @@ -240,9 +243,9 @@ void LcdFloatSpinBox::paintEvent(QPaintEvent*) { p.setFont(pointSizeF(p.font(), 6.5)); p.setPen(m_wholeDisplay.textShadowColor()); - p.drawText(width() / 2 - horizontalAdvance(p.fontMetrics(), m_label) / 2 + 1, height(), m_label); + p.drawText(width() / 2 - p.fontMetrics().boundingRect(m_label).width() / 2 + 1, height(), m_label); p.setPen(m_wholeDisplay.textColor()); - p.drawText(width() / 2 - horizontalAdvance(p.fontMetrics(), m_label) / 2, height() - 1, m_label); + p.drawText(width() / 2 - p.fontMetrics().boundingRect(m_label).width() / 2, height() - 1, m_label); } } From 733e0a1e542dec42325d1110688848d4fecf4f56 Mon Sep 17 00:00:00 2001 From: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com> Date: Mon, 18 Sep 2023 22:14:08 +0530 Subject: [PATCH 133/308] Fix invalid use of iterators in piano roll (#6869) --- src/gui/editors/PianoRoll.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 751fb9d2a..1da6aa3df 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -1719,10 +1719,10 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) const NoteVector & notes = m_midiClip->notes(); // will be our iterator in the following loop - auto it = notes.begin() + notes.size() - 1; + auto it = notes.rbegin(); // loop through whole note-vector... - for( int i = 0; i < notes.size(); ++i ) + while (it != notes.rend()) { Note *note = *it; TimePos len = note->length(); @@ -1747,7 +1747,7 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) { break; } - --it; + ++it; } // first check whether the user clicked in note-edit- @@ -1769,7 +1769,7 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) Note * created_new_note = nullptr; // did it reach end of vector because // there's no note?? - if( it == notes.begin()-1 ) + if (it == notes.rend()) { is_new_note = true; m_midiClip->addJournalCheckPoint(); @@ -1816,8 +1816,8 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) // reset it so that it can be used for // ops (move, resize) after this // code-block - it = notes.begin(); - while( it != notes.end() && *it != created_new_note ) + it = notes.rbegin(); + while (it != notes.rend() && *it != created_new_note) { ++it; } @@ -1933,7 +1933,7 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) { // erase single note m_mouseDownRight = true; - if( it != notes.begin()-1 ) + if (it != notes.rend()) { m_midiClip->addJournalCheckPoint(); m_midiClip->removeNote( *it ); @@ -2513,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 - auto it = notes.begin() + notes.size() - 1; + auto it = notes.rbegin(); for( int i = 0; i < notes.size(); ++i ) { Note* n = *it; @@ -2556,7 +2556,7 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) } - --it; + ++it; } // Emit MIDI clip has changed @@ -2575,10 +2575,10 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) const NoteVector & notes = m_midiClip->notes(); // will be our iterator in the following loop - auto it = notes.begin() + notes.size() - 1; + auto it = notes.rbegin(); // loop through whole note-vector... - for( int i = 0; i < notes.size(); ++i ) + while (it != notes.rend()) { Note *note = *it; // and check whether the cursor is over an @@ -2591,12 +2591,12 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me ) { break; } - --it; + ++it; } // did it reach end of vector because there's // no note?? - if( it != notes.begin()-1 ) + if (it != notes.rend()) { Note *note = *it; // x coordinate of the right edge of the note From dc88040fbe59222620535a347fc209a020133c71 Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Tue, 19 Sep 2023 00:18:28 +0100 Subject: [PATCH 134/308] Add instrument play handles unconditionally (#6875) --- src/core/AudioEngine.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/core/AudioEngine.cpp b/src/core/AudioEngine.cpp index 2d077babc..29c54647c 100644 --- a/src/core/AudioEngine.cpp +++ b/src/core/AudioEngine.cpp @@ -701,7 +701,10 @@ void AudioEngine::removeAudioPort(AudioPort * port) bool AudioEngine::addPlayHandle( PlayHandle* handle ) { - if( criticalXRuns() == false ) + // Only add play handles if we have the CPU capacity to process them. + // Instrument play handles are not added during playback, but when the + // associated instrument is created, so add those unconditionally. + if (handle->type() == PlayHandle::Type::InstrumentPlayHandle || !criticalXRuns()) { m_newPlayHandles.push( handle ); handle->audioPort()->addPlayHandle( handle ); From 94d0b9111b24687e44f65cdf1e5c691e249ee50d Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Wed, 20 Sep 2023 00:56:55 +0100 Subject: [PATCH 135/308] Use UTF-8 for MSVC source and execution charset (#6876) --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b17d0e7c..c1cf3406b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -651,6 +651,9 @@ IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") ELSE(WIN32) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -DPIC") ENDIF(WIN32) +elseif(MSVC) + # Use UTF-8 as the source and execution character set + add_compile_options("/utf-8") ENDIF() # add enabled sanitizers From 7e8c79a191e2dbb8ac5a2a85fd758b0782d37662 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Wed, 20 Sep 2023 19:52:59 +0200 Subject: [PATCH 136/308] Enable build under NixOS (#6855) Explicitly call the perl interpreter when building the SWH LADSPA plugins --- CMakeLists.txt | 20 ++++++++++++++++++-- plugins/LadspaEffect/swh/CMakeLists.txt | 3 ++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c1cf3406b..7c3770f31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,13 @@ SET(LMMS_BINARY_DIR ${CMAKE_BINARY_DIR}) SET(LMMS_SOURCE_DIR ${CMAKE_SOURCE_DIR}) # CMAKE_POLICY Section +IF(COMMAND CMAKE_POLICY) + # TODO: Keep CMP0074 but remove this condition when cmake 3.12+ is guaranteed + IF(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.12) + # Needed for the SWH Ladspa plugins. See below. + CMAKE_POLICY(SET CMP0074 NEW) # find_package() uses _ROOT variables + ENDIF() +ENDIF(COMMAND CMAKE_POLICY) # Import of windows.h breaks min()/max() ADD_DEFINITIONS(-DNOMINMAX) @@ -266,8 +273,17 @@ ELSE(WANT_CMT) ENDIF(WANT_CMT) IF(WANT_SWH) - SET(LMMS_HAVE_SWH TRUE) - SET(STATUS_SWH "OK") + IF(LMMS_BUILD_APPLE) + # Prefer system perl over Homebrew, MacPorts, etc + SET(Perl_ROOT "/usr/bin") + ENDIF() + FIND_PACKAGE(Perl) + IF(PERL_FOUND) + SET(LMMS_HAVE_SWH TRUE) + SET(STATUS_SWH "OK") + ELSE() + SET(STATUS_SWH "Skipping, perl is missing") + ENDIF() ELSE(WANT_SWH) SET(STATUS_SWH "not built as requested") ENDIF(WANT_SWH) diff --git a/plugins/LadspaEffect/swh/CMakeLists.txt b/plugins/LadspaEffect/swh/CMakeLists.txt index aec01c22f..a83001177 100644 --- a/plugins/LadspaEffect/swh/CMakeLists.txt +++ b/plugins/LadspaEffect/swh/CMakeLists.txt @@ -16,6 +16,7 @@ SET(COMPILE_FLAGS "${COMPILE_FLAGS} ${PIC_FLAGS}") # Loop over every XML file FILE(GLOB XML_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/ladspa/*.xml") LIST(SORT XML_SOURCES) + FOREACH(_item ${XML_SOURCES}) # Get library name and (soon to be) C file GET_FILENAME_COMPONENT(_plugin "${_item}" NAME_WE) @@ -24,7 +25,7 @@ FOREACH(_item ${XML_SOURCES}) # Coerce XML source file to C ADD_CUSTOM_COMMAND( OUTPUT "${_out_file}" - COMMAND ./makestub.pl "${_item}" > "${_out_file}" + COMMAND "${PERL_EXECUTABLE}" ./makestub.pl "${_item}" > "${_out_file}" DEPENDS "${_item}" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/ladspa" VERBATIM From 3df28e30b68db4d696b50315577bf7a04cd391f7 Mon Sep 17 00:00:00 2001 From: Maxwell Voorhes <100326501+mvoorhes@users.noreply.github.com> Date: Wed, 20 Sep 2023 15:32:21 -0700 Subject: [PATCH 137/308] Changed sharps to music sharps unicode (#6873) --- src/gui/editors/PianoRoll.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 1da6aa3df..cef2205d2 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -130,7 +130,10 @@ QPixmap* PianoRoll::s_toolKnife = nullptr; SimpleTextFloat * PianoRoll::s_textFloat = nullptr; -static std::array s_noteStrings {"C", "C# / D\u266D", "D", "D# / E\u266D", "E", "F", "F# / G\u266D", "G", "G# / A\u266D", "A", "A# / B\u266D", "B"}; +static std::array s_noteStrings { + "C", "C\u266F / D\u266D", "D", "D\u266F / E\u266D", "E", "F", "F\u266F / G\u266D", + "G", "G\u266F / A\u266D", "A", "A\u266F / B\u266D", "B" +}; static QString getNoteString(int key) { From b6c80bd7366a789cab3f5a6a017636faf80a95ee Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Thu, 21 Sep 2023 19:24:06 +0200 Subject: [PATCH 138/308] Replace check for nullptr Replace the check for a `nullptr` buffer with a check that checks if the NotePlayHandle uses a buffer. This is effectively the same condition that's used by `PlayHandle::doProcessing` to decide if it should call play with a `nullptr` in the first place. Hence it should be the most fitting check. --- src/tracks/InstrumentTrack.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 5dee1f3a5..29fda075e 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -584,9 +584,9 @@ void InstrumentTrack::playNote( NotePlayHandle* n, sampleFrame* workingBuffer ) // all is done, so now lets play the note! m_instrument->playNote( n, workingBuffer ); - // Calling processAudioBuffer with a nullptr leads to crashes when checking if the buffer represents silence. - // Therefore we must guard against a nullptr here. - if (workingBuffer != nullptr) + // This is effectively the same as checking if workingBuffer is not a nullptr. + // Calling processAudioBuffer with a nullptr leads to crashes. Hence the check. + if (n->usesBuffer()) { const fpp_t frames = n->framesLeftForCurrentPeriod(); const f_cnt_t offset = n->noteOffset(); From 07229b64048c118bd8a25904c2cbc1a603fad838 Mon Sep 17 00:00:00 2001 From: Alexandre Almeida Date: Thu, 21 Sep 2023 20:18:23 -0300 Subject: [PATCH 139/308] Show error message when loading an invalid sample file (#6286) --- include/SampleClip.h | 2 +- src/core/SampleBuffer.cpp | 62 +++++++++++++++++++++++++++++++-------- src/core/SampleClip.cpp | 29 ++++++++++-------- 3 files changed, 66 insertions(+), 27 deletions(-) diff --git a/include/SampleClip.h b/include/SampleClip.h index c9e247328..5246787bd 100644 --- a/include/SampleClip.h +++ b/include/SampleClip.h @@ -77,7 +77,7 @@ public: public slots: void setSampleBuffer( lmms::SampleBuffer* sb ); - void setSampleFile( const QString & _sf ); + void setSampleFile( const QString & sf ); void updateLength(); void toggleRecord(); void playbackPositionChanged(); diff --git a/src/core/SampleBuffer.cpp b/src/core/SampleBuffer.cpp index 775db125b..5e2d09c57 100644 --- a/src/core/SampleBuffer.cpp +++ b/src/core/SampleBuffer.cpp @@ -247,7 +247,15 @@ void SampleBuffer::update(bool keepSettings) const int fileSizeMax = 300; // MB const int sampleLengthMax = 90; // Minutes - bool fileLoadError = false; + enum class FileLoadError + { + None, + ReadPermissionDenied, + TooLarge, + Invalid + }; + FileLoadError fileLoadError = FileLoadError::None; + if (m_audioFile.isEmpty() && m_origData != nullptr && m_origFrames > 0) { // TODO: reverse- and amplification-property is not covered @@ -271,31 +279,40 @@ void SampleBuffer::update(bool keepSettings) m_frames = 0; const QFileInfo fileInfo(file); - if (fileInfo.size() > fileSizeMax * 1024 * 1024) + if (!fileInfo.isReadable()) { - fileLoadError = true; + fileLoadError = FileLoadError::ReadPermissionDenied; + } + else if (fileInfo.size() > fileSizeMax * 1024 * 1024) + { + fileLoadError = FileLoadError::TooLarge; } else { // Use QFile to handle unicode file names on Windows QFile f(file); - SNDFILE * sndFile; + SNDFILE * sndFile = nullptr; SF_INFO sfInfo; sfInfo.format = 0; + if (f.open(QIODevice::ReadOnly) && (sndFile = sf_open_fd(f.handle(), SFM_READ, &sfInfo, false))) { f_cnt_t frames = sfInfo.frames; int rate = sfInfo.samplerate; if (frames / rate > sampleLengthMax * 60) { - fileLoadError = true; + fileLoadError = FileLoadError::TooLarge; } sf_close(sndFile); } + else + { + fileLoadError = FileLoadError::Invalid; + } f.close(); } - if (!fileLoadError) + if (fileLoadError == FileLoadError::None) { #ifdef LMMS_HAVE_OGGVORBIS // workaround for a bug in libsndfile or our libsndfile decoder @@ -322,7 +339,7 @@ void SampleBuffer::update(bool keepSettings) } } - if (m_frames == 0 || fileLoadError) // if still no frames, bail + if (m_frames == 0 || fileLoadError != FileLoadError::None) // if still no frames, bail { // sample couldn't be decoded, create buffer containing // one sample-frame @@ -363,16 +380,35 @@ void SampleBuffer::update(bool keepSettings) } Oscillator::generateAntiAliasUserWaveTable(this); - if (fileLoadError) + if (fileLoadError != FileLoadError::None) { QString title = tr("Fail to open file"); - QString message = tr("Audio files are limited to %1 MB " - "in size and %2 minutes of playing time" - ).arg(fileSizeMax).arg(sampleLengthMax); + QString message; + + switch (fileLoadError) + { + case FileLoadError::None: + // present just to avoid a compiler warning + break; + + case FileLoadError::ReadPermissionDenied: + message = tr("Read permission denied"); + break; + + case FileLoadError::TooLarge: + message = tr("Audio files are limited to %1 MB " + "in size and %2 minutes of playing time" + ).arg(fileSizeMax).arg(sampleLengthMax); + break; + + case FileLoadError::Invalid: + message = tr("Invalid audio file"); + break; + } + if (gui::getGUI() != nullptr) { - QMessageBox::information(nullptr, - title, message, QMessageBox::Ok); + QMessageBox::information(nullptr, title, message, QMessageBox::Ok); } else { diff --git a/src/core/SampleClip.cpp b/src/core/SampleClip.cpp index 592a63827..b09d7b3bb 100644 --- a/src/core/SampleClip.cpp +++ b/src/core/SampleClip.cpp @@ -143,23 +143,26 @@ void SampleClip::setSampleBuffer( SampleBuffer* sb ) -void SampleClip::setSampleFile( const QString & _sf ) +void SampleClip::setSampleFile(const QString & sf) { - int length; - if ( _sf.isEmpty() ) - { //When creating an empty sample clip make it a bar long - float nom = Engine::getSong()->getTimeSigModel().getNumerator(); - float den = Engine::getSong()->getTimeSigModel().getDenominator(); - length = DefaultTicksPerBar * ( nom / den ); - } - else - { //Otherwise set it to the sample's length - m_sampleBuffer->setAudioFile( _sf ); + int length = 0; + + if (!sf.isEmpty()) + { + m_sampleBuffer->setAudioFile(sf); length = sampleLength(); } - changeLength(length); - setStartTimeOffset( 0 ); + if (length == 0) + { + //If there is no sample, make the clip a bar long + float nom = Engine::getSong()->getTimeSigModel().getNumerator(); + float den = Engine::getSong()->getTimeSigModel().getDenominator(); + length = DefaultTicksPerBar * (nom / den); + } + + changeLength(length); + setStartTimeOffset(0); emit sampleChanged(); emit playbackPositionChanged(); From 93d3e8c82c4b2968c5949dde0fb8bb4a952bb54f Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Fri, 22 Sep 2023 18:16:45 +0200 Subject: [PATCH 140/308] Adjust the classic theme Adjust the classic theme so that it is consistent with the changes made to the default theme. It was only necessary to change the font-size of the check boxes in the file browser to points because the QTreeView already does not contain any font settings. --- data/themes/classic/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/themes/classic/style.css b/data/themes/classic/style.css index 2880fe661..4c266e064 100644 --- a/data/themes/classic/style.css +++ b/data/themes/classic/style.css @@ -132,7 +132,7 @@ QMenu::indicator:selected { lmms--gui--FileBrowser QCheckBox { - font-size: 10px; + font-size: 8pt; color: white; } From f0aa2862d7efe06a483f6056ba20de315d065597 Mon Sep 17 00:00:00 2001 From: Artur-Twardowski-Mobica <139768112+Artur-Twardowski-Mobica@users.noreply.github.com> Date: Fri, 22 Sep 2023 21:07:25 +0200 Subject: [PATCH 141/308] Updated MIDI CC handling not to count from 1 (#6774) --- include/DataFile.h | 1 + include/MidiController.h | 1 + src/core/DataFile.cpp | 23 ++++++++++++++++++- src/core/midi/MidiController.cpp | 11 ++++----- src/core/midi/MidiPort.cpp | 7 +++--- src/gui/modals/ControllerConnectionDialog.cpp | 6 ++--- 6 files changed, 36 insertions(+), 13 deletions(-) diff --git a/include/DataFile.h b/include/DataFile.h index c19a00f7f..dc82315ad 100644 --- a/include/DataFile.h +++ b/include/DataFile.h @@ -127,6 +127,7 @@ private: void upgrade_mixerRename(); void upgrade_bbTcoRename(); void upgrade_sampleAndHold(); + void upgrade_midiCCIndexing(); // List of all upgrade methods static const std::vector UPGRADE_METHODS; diff --git a/include/MidiController.h b/include/MidiController.h index c4ef49590..9f49627ac 100644 --- a/include/MidiController.h +++ b/include/MidiController.h @@ -48,6 +48,7 @@ class MidiController : public Controller, public MidiEventProcessor { Q_OBJECT public: + static constexpr int NONE = -1; MidiController( Model * _parent ); ~MidiController() override = default; diff --git a/src/core/DataFile.cpp b/src/core/DataFile.cpp index 5915b25ef..8d0a8dca4 100644 --- a/src/core/DataFile.cpp +++ b/src/core/DataFile.cpp @@ -79,7 +79,7 @@ const std::vector DataFile::UPGRADE_METHODS = { &DataFile::upgrade_automationNodes , &DataFile::upgrade_extendedNoteRange, &DataFile::upgrade_defaultTripleOscillatorHQ, &DataFile::upgrade_mixerRename , &DataFile::upgrade_bbTcoRename, - &DataFile::upgrade_sampleAndHold , + &DataFile::upgrade_sampleAndHold , &DataFile::upgrade_midiCCIndexing }; // Vector of all versions that have upgrade routines. @@ -1809,6 +1809,27 @@ void DataFile::upgrade_sampleAndHold() } } +//! Update MIDI CC indexes, so that they are counted from 0. Older releases of LMMS +//! count the CCs from 1. +void DataFile::upgrade_midiCCIndexing() +{ + static constexpr std::array attributesToUpdate{"inputcontroller", "outputcontroller"}; + + QDomNodeList elements = elementsByTagName("Midicontroller"); + for(int i = 0; i < elements.length(); i++) + { + if (elements.item(i).isNull()) { continue; } + auto element = elements.item(i).toElement(); + for (const char* attrName : attributesToUpdate) + { + if (element.hasAttribute(attrName)) + { + int cc = element.attribute(attrName).toInt(); + element.setAttribute(attrName, cc - 1); + } + } + } +} void DataFile::upgrade() { diff --git a/src/core/midi/MidiController.cpp b/src/core/midi/MidiController.cpp index d7c89e940..0ae76d352 100644 --- a/src/core/midi/MidiController.cpp +++ b/src/core/midi/MidiController.cpp @@ -72,21 +72,20 @@ void MidiController::updateName() -void MidiController::processInEvent( const MidiEvent& event, const TimePos& time, f_cnt_t offset ) +void MidiController::processInEvent(const MidiEvent& event, const TimePos& time, f_cnt_t offset) { unsigned char controllerNum; - switch( event.type() ) + switch(event.type()) { case MidiControlChange: controllerNum = event.controllerNumber(); - if( m_midiPort.inputController() == controllerNum + 1 && - ( m_midiPort.inputChannel() == event.channel() + 1 || - m_midiPort.inputChannel() == 0 ) ) + if (m_midiPort.inputController() == controllerNum && + (m_midiPort.inputChannel() == event.channel() + 1 || m_midiPort.inputChannel() == 0)) { unsigned char val = event.controllerValue(); m_previousValue = m_lastValue; - m_lastValue = (float)( val ) / 127.0f; + m_lastValue = static_cast(val) / 127.0f; emit valueChanged(); } break; diff --git a/src/core/midi/MidiPort.cpp b/src/core/midi/MidiPort.cpp index c7c947e8e..24263f913 100644 --- a/src/core/midi/MidiPort.cpp +++ b/src/core/midi/MidiPort.cpp @@ -31,6 +31,7 @@ #include "MidiEventProcessor.h" #include "Note.h" #include "Song.h" +#include "MidiController.h" namespace lmms @@ -54,8 +55,8 @@ MidiPort::MidiPort( const QString& name, m_mode( mode ), m_inputChannelModel( 0, 0, MidiChannelCount, this, tr( "Input channel" ) ), m_outputChannelModel( 1, 0, MidiChannelCount, this, tr( "Output channel" ) ), - m_inputControllerModel( 0, 0, MidiControllerCount, this, tr( "Input controller" ) ), - m_outputControllerModel( 0, 0, MidiControllerCount, this, tr( "Output controller" ) ), + m_inputControllerModel(MidiController::NONE, MidiController::NONE, MidiControllerCount - 1, this, tr( "Input controller" )), + m_outputControllerModel(MidiController::NONE, MidiController::NONE, MidiControllerCount - 1, this, tr( "Output controller" )), m_fixedInputVelocityModel( -1, -1, MidiMaxVelocity, this, tr( "Fixed input velocity" ) ), m_fixedOutputVelocityModel( -1, -1, MidiMaxVelocity, this, tr( "Fixed output velocity" ) ), m_fixedOutputNoteModel( -1, -1, MidiMaxKey, this, tr( "Fixed output note" ) ), @@ -436,4 +437,4 @@ void MidiPort::invalidateCilent() } -} // namespace lmms \ No newline at end of file +} // namespace lmms diff --git a/src/gui/modals/ControllerConnectionDialog.cpp b/src/gui/modals/ControllerConnectionDialog.cpp index 79daa25b5..4d1090d5c 100644 --- a/src/gui/modals/ControllerConnectionDialog.cpp +++ b/src/gui/modals/ControllerConnectionDialog.cpp @@ -54,7 +54,7 @@ public: AutoDetectMidiController( Model* parent ) : MidiController( parent ), m_detectedMidiChannel( 0 ), - m_detectedMidiController( 0 ) + m_detectedMidiController(NONE) { updateName(); } @@ -69,7 +69,7 @@ public: ( m_midiPort.inputChannel() == 0 || m_midiPort.inputChannel() == event.channel() + 1 ) ) { m_detectedMidiChannel = event.channel() + 1; - m_detectedMidiController = event.controllerNumber() + 1; + m_detectedMidiController = event.controllerNumber(); m_detectedMidiPort = Engine::audioEngine()->midiClient()->sourcePortName( event ); emit valueChanged(); @@ -152,7 +152,7 @@ ControllerConnectionDialog::ControllerConnectionDialog( QWidget * _parent, m_midiControllerSpinBox = new LcdSpinBox( 3, m_midiGroupBox, tr( "Input controller" ) ); - m_midiControllerSpinBox->addTextForValue( 0, "---" ); + m_midiControllerSpinBox->addTextForValue(MidiController::NONE, "---" ); m_midiControllerSpinBox->setLabel( tr( "CONTROLLER" ) ); m_midiControllerSpinBox->move( 68, 24 ); From 49c713df5bad0c7285dd04d236ea3f5e9f3c34ef Mon Sep 17 00:00:00 2001 From: saker Date: Sat, 23 Sep 2023 19:33:20 -0400 Subject: [PATCH 142/308] Use resid submodule from libsidplayfp (#6883) --- .gitmodules | 6 +-- CMakeLists.txt | 24 ++++++++--- plugins/Sid/CMakeLists.txt | 47 +++------------------- plugins/Sid/SidInstrument.cpp | 24 +++++------ plugins/Sid/resid | 1 - plugins/Sid/resid/CMakeLists.txt | 68 ++++++++++++++++++++++++++++++++ plugins/Sid/resid/resid | 1 + 7 files changed, 108 insertions(+), 63 deletions(-) delete mode 160000 plugins/Sid/resid create mode 100644 plugins/Sid/resid/CMakeLists.txt create mode 160000 plugins/Sid/resid/resid diff --git a/.gitmodules b/.gitmodules index ee6e7eac9..fa6980ac5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -40,9 +40,9 @@ [submodule "plugins/CarlaBase/carla"] path = plugins/CarlaBase/carla url = https://github.com/falktx/carla -[submodule "plugins/Sid/resid"] - path = plugins/Sid/resid - url = https://github.com/simonowen/resid +[submodule "plugins/Sid/resid/resid"] + path = plugins/Sid/resid/resid + url = https://github.com/libsidplayfp/resid [submodule "src/3rdparty/jack2"] path = src/3rdparty/jack2 url = https://github.com/jackaudio/jack2 diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c3770f31..4163ca5cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,6 +77,7 @@ OPTION(WANT_SOUNDIO "Include libsoundio support" ON) OPTION(WANT_SDL "Include SDL (Simple DirectMedia Layer) support" ON) OPTION(WANT_SF2 "Include SoundFont2 player plugin" ON) OPTION(WANT_GIG "Include GIG player plugin" ON) +option(WANT_SID "Include Sid instrument" ON) OPTION(WANT_STK "Include Stk (Synthesis Toolkit) support" ON) OPTION(WANT_SWH "Include Steve Harris's LADSPA plugins" ON) OPTION(WANT_TAP "Include Tom's Audio Processing LADSPA plugins" ON) @@ -211,6 +212,13 @@ CHECK_CXX_SOURCE_COMPILES( LMMS_HAVE_SF_COMPLEVEL ) +# check for perl +if(LMMS_BUILD_APPLE) + # Prefer system perl over Homebrew, MacPorts, etc + set(Perl_ROOT "/usr/bin") +endif() +find_package(Perl) + IF(WANT_LV2) IF(PKG_CONFIG_FOUND) PKG_CHECK_MODULES(LV2 lv2) @@ -273,11 +281,6 @@ ELSE(WANT_CMT) ENDIF(WANT_CMT) IF(WANT_SWH) - IF(LMMS_BUILD_APPLE) - # Prefer system perl over Homebrew, MacPorts, etc - SET(Perl_ROOT "/usr/bin") - ENDIF() - FIND_PACKAGE(Perl) IF(PERL_FOUND) SET(LMMS_HAVE_SWH TRUE) SET(STATUS_SWH "OK") @@ -349,6 +352,16 @@ IF(WANT_SDL AND NOT LMMS_HAVE_SDL2) ENDIF() ENDIF() +# check for Sid +if(WANT_SID) + if(PERL_FOUND) + set(LMMS_HAVE_SID TRUE) + set(STATUS_SID "OK") + else() + set(STATUS_SID "not found, please install perl if you require the Sid instrument") + endif() +endif() + # check for Stk IF(WANT_STK) FIND_PACKAGE(STK) @@ -816,6 +829,7 @@ MESSAGE( "* ZynAddSubFX instrument : ${STATUS_ZYN}\n" "* Carla Patchbay & Rack : ${STATUS_CARLA}\n" "* SoundFont2 player : ${STATUS_FLUIDSYNTH}\n" +"* Sid instrument : ${STATUS_SID}\n" "* Stk Mallets : ${STATUS_STK}\n" "* VST-instrument hoster : ${STATUS_VST}\n" "* VST-effect hoster : ${STATUS_VST}\n" diff --git a/plugins/Sid/CMakeLists.txt b/plugins/Sid/CMakeLists.txt index c9fce7bb7..c771fc66d 100644 --- a/plugins/Sid/CMakeLists.txt +++ b/plugins/Sid/CMakeLists.txt @@ -1,51 +1,14 @@ INCLUDE(BuildPlugin) -INCLUDE_DIRECTORIES(resid) +if(NOT LMMS_HAVE_SID) + return() +endif() BUILD_PLUGIN(sid SidInstrument.cpp SidInstrument.h - resid/envelope.h - resid/extfilt.h - resid/filter.h - resid/pot.h - resid/siddefs.h - resid/sid.h - resid/spline.h - resid/voice.h - resid/wave.h - resid/envelope.cc - resid/extfilt.cc - resid/filter.cc - resid/pot.cc - resid/sid.cc - resid/version.cc - resid/voice.cc - resid/wave6581_PS_.cc - resid/wave6581_PST.cc - resid/wave6581_P_T.cc - resid/wave6581__ST.cc - resid/wave8580_PS_.cc - resid/wave8580_PST.cc - resid/wave8580_P_T.cc - resid/wave8580__ST.cc - resid/wave.cc MOCFILES SidInstrument.h EMBEDDED_RESOURCES *.png) -# Parse VERSION -FILE(READ "resid/CMakeLists.txt" lines) -STRING(REGEX MATCH "set\\(MAJOR_VER [A-Za-z0-9_]*\\)" MAJOR_RAW ${lines}) -STRING(REGEX MATCH "set\\(MINOR_VER [A-Za-z0-9_]*\\)" MINOR_RAW ${lines}) -STRING(REGEX MATCH "set\\(PATCH_VER [A-Za-z0-9_]*\\)" PATCH_RAW ${lines}) -SEPARATE_ARGUMENTS(MAJOR_RAW) -SEPARATE_ARGUMENTS(MINOR_RAW) -SEPARATE_ARGUMENTS(PATCH_RAW) -LIST(GET MAJOR_RAW 1 MAJOR_RAW) -LIST(GET MINOR_RAW 1 MINOR_RAW) -LIST(GET PATCH_RAW 1 PATCH_RAW) -STRING(REPLACE ")" "" MAJOR_VER "${MAJOR_RAW}") -STRING(REPLACE ")" "" MINOR_VER "${MINOR_RAW}") -STRING(REPLACE ")" "" PATCH_VER "${PATCH_RAW}") - -TARGET_COMPILE_DEFINITIONS(sid PRIVATE VERSION="${MAJOR_VER}.${MINOR_VER}.${PATCH_VER}") +add_subdirectory(resid) +target_link_libraries(sid resid) diff --git a/plugins/Sid/SidInstrument.cpp b/plugins/Sid/SidInstrument.cpp index 143003f98..7f9edf13f 100644 --- a/plugins/Sid/SidInstrument.cpp +++ b/plugins/Sid/SidInstrument.cpp @@ -239,7 +239,7 @@ f_cnt_t SidInstrument::desiredReleaseFrames() const -static int sid_fillbuffer(unsigned char* sidreg, SID *sid, int tdelta, short *ptr, int samples) +static int sid_fillbuffer(unsigned char* sidreg, reSID::SID *sid, int tdelta, short *ptr, int samples) { int tdelta2; int result; @@ -302,9 +302,9 @@ void SidInstrument::playNote( NotePlayHandle * _n, if (!_n->m_pluginData) { - SID *sid = new SID(); - sid->set_sampling_parameters( clockrate, SAMPLE_FAST, samplerate ); - sid->set_chip_model( MOS8580 ); + auto sid = new reSID::SID(); + sid->set_sampling_parameters(clockrate, reSID::SAMPLE_FAST, samplerate); + sid->set_chip_model(reSID::MOS8580); sid->enable_filter( true ); sid->reset(); _n->m_pluginData = sid; @@ -312,7 +312,7 @@ void SidInstrument::playNote( NotePlayHandle * _n, const fpp_t frames = _n->framesLeftForCurrentPeriod(); const f_cnt_t offset = _n->noteOffset(); - SID *sid = static_cast( _n->m_pluginData ); + auto sid = static_cast(_n->m_pluginData); int delta_t = clockrate * frames / samplerate + 4; // avoid variable length array for msvc compat auto buf = reinterpret_cast(_working_buffer + offset); @@ -325,20 +325,20 @@ void SidInstrument::playNote( NotePlayHandle * _n, if( (ChipModel)m_chipModel.value() == ChipModel::MOS6581 ) { - sid->set_chip_model( MOS6581 ); + sid->set_chip_model(reSID::MOS6581); } else { - sid->set_chip_model( MOS8580 ); + sid->set_chip_model(reSID::MOS8580); } // voices - reg8 data8 = 0; - reg8 data16 = 0; - reg8 base = 0; + reSID::reg8 data8 = 0; + reSID::reg16 data16 = 0; + size_t base = 0; float freq = 0.0; float note = 0.0; - for( reg8 i = 0 ; i < 3 ; ++i ) + for (size_t i = 0; i < 3; ++i) { base = i*7; // freq ( Fn = Fout / Fclk * 16777216 ) + coarse detuning @@ -436,7 +436,7 @@ void SidInstrument::playNote( NotePlayHandle * _n, void SidInstrument::deleteNotePluginData( NotePlayHandle * _n ) { - delete static_cast( _n->m_pluginData ); + delete static_cast(_n->m_pluginData); } diff --git a/plugins/Sid/resid b/plugins/Sid/resid deleted file mode 160000 index 02afcc5ce..000000000 --- a/plugins/Sid/resid +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 02afcc5cefac34bd0c665dc0fa6b748d238c1831 diff --git a/plugins/Sid/resid/CMakeLists.txt b/plugins/Sid/resid/CMakeLists.txt new file mode 100644 index 000000000..bb39e3d16 --- /dev/null +++ b/plugins/Sid/resid/CMakeLists.txt @@ -0,0 +1,68 @@ +# These are the defaults +set(RESID_INLINING 1) +set(RESID_INLINE inline) +set(RESID_BRANCH_HINTS 1) +set(NEW_8580_FILTER 0) + +set(HAVE_BOOL 1) +set(HAVE_LOG1P 1) + +if(CMAKE_CXX_COMPILER_ID MATCHES "GCC|Clang") + set(HAVE_BUILTIN_EXPECT 1) +else() + set(HAVE_BUILTIN_EXPECT 0) +endif() + +configure_file(resid/siddefs.h.in resid/siddefs.h @ONLY) + +add_library(resid_objects OBJECT + resid/sid.cc + resid/voice.cc + resid/wave.cc + resid/envelope.cc + resid/filter.cc + resid/dac.cc + resid/extfilt.cc + resid/pot.cc + resid/version.cc +) + +target_include_directories(resid_objects PUBLIC + "${CMAKE_CURRENT_SOURCE_DIR}/resid" + "${CMAKE_CURRENT_BINARY_DIR}/resid" +) +target_compile_definitions(resid_objects PUBLIC VERSION="1.0") + +set(RESID_WAVES + wave6581_PST + wave6581_PS_ + wave6581_P_T + wave6581__ST + wave8580_PST + wave8580_PS_ + wave8580_P_T + wave8580__ST +) + +set(RESID_SAMP2SRC_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/resid/samp2src.pl) +foreach(WAVE_DATA IN LISTS RESID_WAVES) + set(WAVE_DATA_IN ${CMAKE_CURRENT_SOURCE_DIR}/resid/${WAVE_DATA}.dat) + set(WAVE_SRC_OUT ${CMAKE_CURRENT_BINARY_DIR}/resid/${WAVE_DATA}.h) + set(WAVE_COMMAND + "${PERL_EXECUTABLE}" + "${RESID_SAMP2SRC_SCRIPT}" + "${WAVE_DATA}" + "${WAVE_DATA_IN}" + "${WAVE_SRC_OUT}" + ) + add_custom_command(OUTPUT ${WAVE_SRC_OUT} COMMAND ${WAVE_COMMAND} VERBATIM) + target_sources(resid_objects PUBLIC ${WAVE_SRC_OUT}) +endforeach() + +# TODO CMake 3.12: Use target_link_libraries() to propagate usage requirements directly to sid plugin +add_library(resid INTERFACE) + +target_sources(resid INTERFACE $) + +get_target_property(resid_includes resid_objects INCLUDE_DIRECTORIES) +target_include_directories(resid INTERFACE ${resid_includes}) diff --git a/plugins/Sid/resid/resid b/plugins/Sid/resid/resid new file mode 160000 index 000000000..ef72462f5 --- /dev/null +++ b/plugins/Sid/resid/resid @@ -0,0 +1 @@ +Subproject commit ef72462f5fa0682d099413512b764ae479e77f9b From 006c43820bfb7867c84abffc96bf178bf12437a0 Mon Sep 17 00:00:00 2001 From: Lost Robot <34612565+LostRobotMusic@users.noreply.github.com> Date: Sun, 24 Sep 2023 04:19:19 -0700 Subject: [PATCH 143/308] Fix Compressor zero divisions (#6887) * Fix threshold zero division * Fix RMS zero division --- plugins/Compressor/Compressor.cpp | 3 ++- plugins/Compressor/CompressorControlDialog.cpp | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/plugins/Compressor/Compressor.cpp b/plugins/Compressor/Compressor.cpp index 33571606e..0fe139420 100755 --- a/plugins/Compressor/Compressor.cpp +++ b/plugins/Compressor/Compressor.cpp @@ -177,7 +177,8 @@ void CompressorEffect::calcRange() void CompressorEffect::resizeRMS() { - m_rmsTimeConst = exp(-1.f / (m_compressorControls.m_rmsModel.value() * 0.001f * m_sampleRate)); + const float rmsValue = m_compressorControls.m_rmsModel.value(); + m_rmsTimeConst = (rmsValue > 0) ? exp(-1.f / (rmsValue * 0.001f * m_sampleRate)) : 0; } void CompressorEffect::calcLookaheadLength() diff --git a/plugins/Compressor/CompressorControlDialog.cpp b/plugins/Compressor/CompressorControlDialog.cpp index 114980a7d..1516456a2 100755 --- a/plugins/Compressor/CompressorControlDialog.cpp +++ b/plugins/Compressor/CompressorControlDialog.cpp @@ -497,10 +497,12 @@ void CompressorControlDialog::redrawKnee() float actualRatio = m_controls->m_limiterModel.value() ? 0 : m_controls->m_effect->m_ratioVal; // Calculate endpoints for the two straight lines - float kneePoint1 = m_controls->m_effect->m_thresholdVal - m_controls->m_effect->m_kneeVal; - float kneePoint2X = m_controls->m_effect->m_thresholdVal + m_controls->m_effect->m_kneeVal; - float kneePoint2Y = (m_controls->m_effect->m_thresholdVal + (-m_controls->m_effect->m_thresholdVal * (actualRatio * (m_controls->m_effect->m_kneeVal / -m_controls->m_effect->m_thresholdVal)))); - float ratioPoint = m_controls->m_effect->m_thresholdVal + (-m_controls->m_effect->m_thresholdVal * actualRatio); + const float thresholdVal = m_controls->m_effect->m_thresholdVal; + const float kneeVal = m_controls->m_effect->m_kneeVal; + float kneePoint1 = thresholdVal - kneeVal; + float kneePoint2X = thresholdVal + kneeVal; + float kneePoint2Y = thresholdVal + kneeVal * actualRatio; + float ratioPoint = thresholdVal + (-thresholdVal * actualRatio); // Draw two straight lines m_p.drawLine(0, m_kneeWindowSizeY, dbfsToXPoint(kneePoint1), dbfsToYPoint(kneePoint1)); @@ -510,7 +512,7 @@ void CompressorControlDialog::redrawKnee() } // Draw knee section - if (m_controls->m_effect->m_kneeVal) + if (kneeVal) { m_p.setPen(QPen(m_kneeColor2, 3)); @@ -522,8 +524,8 @@ void CompressorControlDialog::redrawKnee() { newPoint[0] = linearInterpolate(kneePoint1, kneePoint2X, (i + 1) / (float)COMP_KNEE_LINES); - const float temp = newPoint[0] - m_controls->m_effect->m_thresholdVal + m_controls->m_effect->m_kneeVal; - newPoint[1] = (newPoint[0] + (actualRatio - 1) * temp * temp / (4 * m_controls->m_effect->m_kneeVal)); + const float temp = newPoint[0] - thresholdVal + kneeVal; + newPoint[1] = (newPoint[0] + (actualRatio - 1) * temp * temp / (4 * kneeVal)); m_p.drawLine(dbfsToXPoint(prevPoint[0]), dbfsToYPoint(prevPoint[1]), dbfsToXPoint(newPoint[0]), dbfsToYPoint(newPoint[1])); @@ -768,4 +770,4 @@ void CompressorControlDialog::resetCompressorView() } -} // namespace lmms::gui \ No newline at end of file +} // namespace lmms::gui From c309d8bd11659a3f14557960a5e83366374d0ec2 Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Fri, 22 Sep 2023 23:54:07 +0200 Subject: [PATCH 144/308] Lv2ViewProc: Improve variable names --- include/Lv2ViewBase.h | 2 +- src/gui/Lv2ViewBase.cpp | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/Lv2ViewBase.h b/include/Lv2ViewBase.h index f7d0e9bcb..3c8f1bc3f 100644 --- a/include/Lv2ViewBase.h +++ b/include/Lv2ViewBase.h @@ -56,7 +56,7 @@ class Lv2ViewProc : public LinkedModelGroupView { public: //! @param colNum numbers of columns for the controls - Lv2ViewProc(QWidget *parent, Lv2Proc *ctrlBase, int colNum); + Lv2ViewProc(QWidget *parent, Lv2Proc *proc, int colNum); ~Lv2ViewProc() override = default; private: diff --git a/src/gui/Lv2ViewBase.cpp b/src/gui/Lv2ViewBase.cpp index 3fd1d44b1..12be5e069 100644 --- a/src/gui/Lv2ViewBase.cpp +++ b/src/gui/Lv2ViewBase.cpp @@ -51,13 +51,13 @@ namespace lmms::gui { -Lv2ViewProc::Lv2ViewProc(QWidget* parent, Lv2Proc* ctrlBase, int colNum) : - LinkedModelGroupView (parent, ctrlBase, colNum) +Lv2ViewProc::Lv2ViewProc(QWidget* parent, Lv2Proc* proc, int colNum) : + LinkedModelGroupView (parent, proc, colNum) { - class SetupWidget : public Lv2Ports::ConstVisitor + class SetupTheWidget : public Lv2Ports::ConstVisitor { public: - QWidget* m_par; // input + QWidget* m_parent; // input const LilvNode* m_commentUri; // input Control* m_control = nullptr; // output void visit(const Lv2Ports::Control& port) override @@ -69,20 +69,20 @@ Lv2ViewProc::Lv2ViewProc(QWidget* parent, Lv2Proc* ctrlBase, int colNum) : switch (port.m_vis) { case PortVis::Generic: - m_control = new KnobControl(m_par); + m_control = new KnobControl(m_parent); break; case PortVis::Integer: { sample_rate_t sr = Engine::audioEngine()->processingSampleRate(); m_control = new LcdControl((port.max(sr) <= 9.0f) ? 1 : 2, - m_par); + m_parent); break; } case PortVis::Enumeration: - m_control = new ComboControl(m_par); + m_control = new ComboControl(m_parent); break; case PortVis::Toggled: - m_control = new CheckControl(m_par); + m_control = new CheckControl(m_parent); break; } m_control->setText(port.name()); @@ -100,14 +100,14 @@ Lv2ViewProc::Lv2ViewProc(QWidget* parent, Lv2Proc* ctrlBase, int colNum) : }; AutoLilvNode commentUri = uri(LILV_NS_RDFS "comment"); - ctrlBase->foreach_port( + proc->foreach_port( [this, &commentUri](const Lv2Ports::PortBase* port) { if(!lilv_port_has_property(port->m_plugin, port->m_port, uri(LV2_PORT_PROPS__notOnGUI).get())) { - SetupWidget setup; - setup.m_par = this; + SetupTheWidget setup; + setup.m_parent = this; setup.m_commentUri = commentUri.get(); port->accept(setup); From d97377b640c3f288ed68860a3ffcf60ad7b5c7d9 Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Fri, 22 Sep 2023 23:58:52 +0200 Subject: [PATCH 145/308] Lv2: Improve LED widget's digit calculation This improves the way digits are calculated for display in `Lv2ViewProc`: - More than 2 digits are now recognized - Minus signs are now recognized - Tests have been added --- include/lmms_math.h | 26 ++++++++++++++++++ src/gui/Lv2ViewBase.cpp | 7 +++-- tests/CMakeLists.txt | 1 + tests/src/core/MathTest.cpp | 53 +++++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 tests/src/core/MathTest.cpp diff --git a/include/lmms_math.h b/include/lmms_math.h index b62da81c2..ea0a75581 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -325,6 +325,32 @@ static inline T absMin( T a, T b ) return std::abs(a) < std::abs(b) ? a : b; } +// @brief Calculate number of digits which LcdSpinBox would show for a given number +// @note Once we upgrade to C++20, we could probably use std::formatted_size +static inline int numDigitsAsInt(float f) +{ + // use rounding: + // LcdSpinBox sometimes uses roundf(), sometimes cast rounding + // we use rounding to be on the "safe side" + const float rounded = roundf(f); + int asInt = static_cast(rounded); + int digits = 1; // always at least 1 + if(asInt < 0) + { + ++digits; + asInt = -asInt; + } + // "asInt" is positive from now + int32_t power = 1; + for(int32_t i = 1; i<10; ++i) + { + power *= 10; + if(static_cast(asInt) >= power) { ++digits; } // 2 digits for >=10, 3 for >=100 + else { break; } + } + return digits; +} + } // namespace lmms diff --git a/src/gui/Lv2ViewBase.cpp b/src/gui/Lv2ViewBase.cpp index 12be5e069..830a994c8 100644 --- a/src/gui/Lv2ViewBase.cpp +++ b/src/gui/Lv2ViewBase.cpp @@ -39,6 +39,7 @@ #include "GuiApplication.h" #include "embed.h" #include "gui_templates.h" +#include "lmms_math.h" #include "Lv2ControlBase.h" #include "Lv2Manager.h" #include "Lv2Proc.h" @@ -74,8 +75,10 @@ Lv2ViewProc::Lv2ViewProc(QWidget* parent, Lv2Proc* proc, int colNum) : case PortVis::Integer: { sample_rate_t sr = Engine::audioEngine()->processingSampleRate(); - m_control = new LcdControl((port.max(sr) <= 9.0f) ? 1 : 2, - m_parent); + auto pMin = port.min(sr); + auto pMax = port.max(sr); + int numDigits = std::max(numDigitsAsInt(pMin), numDigitsAsInt(pMax)); + m_control = new LcdControl(numDigits, m_parent); break; } case PortVis::Enumeration: diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 514bf7815..ddf9e2962 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -21,6 +21,7 @@ ADD_EXECUTABLE(tests src/core/ArrayVectorTest.cpp src/core/AutomatableModelTest.cpp + src/core/MathTest.cpp src/core/ProjectVersionTest.cpp src/core/RelativePathsTest.cpp diff --git a/tests/src/core/MathTest.cpp b/tests/src/core/MathTest.cpp new file mode 100644 index 000000000..2b6404cfd --- /dev/null +++ b/tests/src/core/MathTest.cpp @@ -0,0 +1,53 @@ +/* + * MathTest.cpp + * + * Copyright (c) 2023 Johannes Lorenz + * + * 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 "QTestSuite.h" + +#include "lmms_math.h" + +#include + +class MathTest : QTestSuite +{ + Q_OBJECT +private slots: + void NumDigitsTest() + { + using namespace lmms; + QCOMPARE(numDigitsAsInt(1.f), 1); + QCOMPARE(numDigitsAsInt(9.9f), 2); + QCOMPARE(numDigitsAsInt(10.f), 2); + QCOMPARE(numDigitsAsInt(0.f), 1); + QCOMPARE(numDigitsAsInt(-100.f), 4); + QCOMPARE(numDigitsAsInt(-99.f), 3); + QCOMPARE(numDigitsAsInt(-0.4f), 1); // there is no "-0" for LED spinbox + QCOMPARE(numDigitsAsInt(-0.99f), 2); + QCOMPARE(numDigitsAsInt(1000000000), 10); + QCOMPARE(numDigitsAsInt(-1000000000), 11); + QCOMPARE(numDigitsAsInt(900000000), 9); + QCOMPARE(numDigitsAsInt(-900000000), 10); + } +} MathTests; + +#include "MathTest.moc" From 9c46370234fe45437f0f64fab963a232cb3e9a46 Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Sat, 23 Sep 2023 00:00:02 +0200 Subject: [PATCH 146/308] Support LV2_BUF_SIZE__powerOf2BlockLength --- src/core/lv2/Lv2Manager.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/lv2/Lv2Manager.cpp b/src/core/lv2/Lv2Manager.cpp index 9c62703e0..df6e5a7c1 100644 --- a/src/core/lv2/Lv2Manager.cpp +++ b/src/core/lv2/Lv2Manager.cpp @@ -35,6 +35,7 @@ #include #include +#include "AudioEngine.h" #include "Engine.h" #include "Plugin.h" #include "Lv2ControlBase.h" @@ -156,6 +157,10 @@ Lv2Manager::Lv2Manager() : m_supportedFeatureURIs.insert(LV2_BUF_SIZE__boundedBlockLength); // block length is only changed initially in AudioEngine CTOR m_supportedFeatureURIs.insert(LV2_BUF_SIZE__fixedBlockLength); + if (const auto fpp = Engine::audioEngine()->framesPerPeriod(); (fpp & (fpp - 1)) == 0) // <=> ffp is power of 2 (for ffp > 0) + { + m_supportedFeatureURIs.insert(LV2_BUF_SIZE__powerOf2BlockLength); + } auto supportOpt = [this](Lv2UridCache::Id id) { From 61b612634d1690ba5ac21c4a9fea455e8a9e6f64 Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Fri, 22 Sep 2023 23:38:57 +0200 Subject: [PATCH 147/308] Add plugin blacklist for buffersize<=32 --- include/Lv2Features.h | 3 ++- include/Lv2Manager.h | 20 ++++++++++---------- src/core/lv2/Lv2Features.cpp | 6 +++--- src/core/lv2/Lv2Manager.cpp | 31 +++++++++++++++++++++---------- src/core/lv2/Lv2Proc.cpp | 16 ++++++++++++---- 5 files changed, 48 insertions(+), 28 deletions(-) diff --git a/include/Lv2Features.h b/include/Lv2Features.h index b5bc284c8..69a456bbd 100644 --- a/include/Lv2Features.h +++ b/include/Lv2Features.h @@ -30,6 +30,7 @@ #ifdef LMMS_HAVE_LV2 #include +#include #include #include "Lv2Manager.h" @@ -78,7 +79,7 @@ private: //! pointers to m_features, required for lilv_plugin_instantiate std::vector m_featurePointers; //! features + data, ordered by URI - std::map m_featureByUri; + std::map m_featureByUri; }; diff --git a/include/Lv2Manager.h b/include/Lv2Manager.h index 909dba560..58126a0a4 100644 --- a/include/Lv2Manager.h +++ b/include/Lv2Manager.h @@ -31,6 +31,7 @@ #include #include +#include #include #include "Lv2Basics.h" @@ -120,15 +121,9 @@ public: Iterator begin() { return m_lv2InfoMap.begin(); } Iterator end() { return m_lv2InfoMap.end(); } - //! strcmp based key comparator for std::set and std::map - struct CmpStr - { - bool operator()(char const *a, char const *b) const; - }; - UridMap& uridMap() { return m_uridMap; } const Lv2UridCache& uridCache() const { return m_uridCache; } - const std::set& supportedFeatureURIs() const + const std::set& supportedFeatureURIs() const { return m_supportedFeatureURIs; } @@ -136,17 +131,21 @@ public: AutoLilvNodes findNodes(const LilvNode *subject, const LilvNode *predicate, const LilvNode *object); - static const std::set& getPluginBlacklist() + static const std::set& getPluginBlacklist() { return pluginBlacklist; } + static const std::set& getPluginBlacklistBuffersizeLessThan32() + { + return pluginBlacklistBuffersizeLessThan32; + } private: // general data bool m_debug; //!< if set, debug output will be printed LilvWorld* m_world; Lv2InfoMap m_lv2InfoMap; - std::set m_supportedFeatureURIs; + std::set m_supportedFeatureURIs; // feature data that are common for all Lv2Proc UridMap m_uridMap; @@ -155,7 +154,8 @@ private: Lv2UridCache m_uridCache; // static - static const std::set pluginBlacklist; + static const std::set + pluginBlacklist, pluginBlacklistBuffersizeLessThan32; // functions bool isSubclassOf(const LilvPluginClass *clvss, const char *uriStr); diff --git a/src/core/lv2/Lv2Features.cpp b/src/core/lv2/Lv2Features.cpp index 6e74a8936..c8fc05465 100644 --- a/src/core/lv2/Lv2Features.cpp +++ b/src/core/lv2/Lv2Features.cpp @@ -48,7 +48,7 @@ Lv2Features::Lv2Features() { const Lv2Manager* man = Engine::getLv2Manager(); // create (yet empty) map feature URI -> feature - for(const char* uri : man->supportedFeatureURIs()) + for(auto uri : man->supportedFeatureURIs()) { m_featureByUri.emplace(uri, nullptr); } @@ -71,7 +71,7 @@ void Lv2Features::initCommon() void Lv2Features::createFeatureVectors() { // create vector of features - for(std::pair& pr : m_featureByUri) + for(const auto& [uri, feature] : m_featureByUri) { /* If pr.second is nullptr here, this means that the LV2_feature @@ -82,7 +82,7 @@ void Lv2Features::createFeatureVectors() vector creation (This can be done in Lv2Proc::initPluginSpecificFeatures or in Lv2Features::initCommon) */ - m_features.push_back(LV2_Feature { pr.first, pr.second }); + m_features.push_back(LV2_Feature{(const char*)uri.data(), (void*)feature}); } // create pointer vector (for lilv_plugin_instantiate) diff --git a/src/core/lv2/Lv2Manager.cpp b/src/core/lv2/Lv2Manager.cpp index df6e5a7c1..489e613b7 100644 --- a/src/core/lv2/Lv2Manager.cpp +++ b/src/core/lv2/Lv2Manager.cpp @@ -28,7 +28,6 @@ #include #include -#include #include #include #include @@ -47,7 +46,7 @@ namespace lmms { -const std::set Lv2Manager::pluginBlacklist = +const std::set Lv2Manager::pluginBlacklist = { // github.com/calf-studio-gear/calf, #278 "http://calf.sourceforge.net/plugins/Analyzer", @@ -138,6 +137,26 @@ const std::set Lv2Manager::pluginBlacklist = "urn:juced:DrumSynth" }; +const std::set Lv2Manager::pluginBlacklistBuffersizeLessThan32 = +{ + "http://moddevices.com/plugins/mod-devel/2Voices", + "http://moddevices.com/plugins/mod-devel/Capo", + "http://moddevices.com/plugins/mod-devel/Drop", + "http://moddevices.com/plugins/mod-devel/Harmonizer", + "http://moddevices.com/plugins/mod-devel/Harmonizer2", + "http://moddevices.com/plugins/mod-devel/HarmonizerCS", + "http://moddevices.com/plugins/mod-devel/SuperCapo", + "http://moddevices.com/plugins/mod-devel/SuperWhammy", + "http://moddevices.com/plugins/mod-devel/Gx2Voices", + "http://moddevices.com/plugins/mod-devel/GxCapo", + "http://moddevices.com/plugins/mod-devel/GxDrop", + "http://moddevices.com/plugins/mod-devel/GxHarmonizer", + "http://moddevices.com/plugins/mod-devel/GxHarmonizer2", + "http://moddevices.com/plugins/mod-devel/GxHarmonizerCS", + "http://moddevices.com/plugins/mod-devel/GxSuperCapo", + "http://moddevices.com/plugins/mod-devel/GxSuperWhammy" +}; + @@ -293,14 +312,6 @@ void Lv2Manager::initPlugins() -bool Lv2Manager::CmpStr::operator()(const char *a, const char *b) const -{ - return std::strcmp(a, b) < 0; -} - - - - bool Lv2Manager::isFeatureSupported(const char *featName) const { return m_supportedFeatureURIs.find(featName) != m_supportedFeatureURIs.end(); diff --git a/src/core/lv2/Lv2Proc.cpp b/src/core/lv2/Lv2Proc.cpp index e0541b948..6776a26ed 100644 --- a/src/core/lv2/Lv2Proc.cpp +++ b/src/core/lv2/Lv2Proc.cpp @@ -75,11 +75,19 @@ Plugin::Type Lv2Proc::check(const LilvPlugin *plugin, // TODO: manage a global blacklist outside of the code // for now, this will help // this is only a fix for the meantime - const auto& pluginBlacklist = Lv2Manager::getPluginBlacklist(); - if (!Engine::ignorePluginBlacklist() && - pluginBlacklist.find(pluginUri) != pluginBlacklist.end()) + if (!Engine::ignorePluginBlacklist()) { - issues.emplace_back(PluginIssueType::Blacklisted); + const auto& pluginBlacklist = Lv2Manager::getPluginBlacklist(); + const auto& pluginBlacklist32 = Lv2Manager::getPluginBlacklistBuffersizeLessThan32(); + if(pluginBlacklist.find(pluginUri) != pluginBlacklist.end()) + { + issues.emplace_back(PluginIssueType::Blacklisted); + } + else if(Engine::audioEngine()->framesPerPeriod() <= 32 && + pluginBlacklist32.find(pluginUri) != pluginBlacklist32.end()) + { + issues.emplace_back(PluginIssueType::Blacklisted); // currently no special blacklist category + } } for (unsigned portNum = 0; portNum < maxPorts; ++portNum) From 7aca8ae726ab425b47802721703fb5589fe8289a Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Fri, 22 Sep 2023 23:56:45 +0200 Subject: [PATCH 148/308] SetupDialog: Warn of unusual buffersizes This displays a warning dialog if the users requests unusual buffersizes: - buffersizes less than 32 - buffersizes which are not a (natural number) power of 2 This commit also replaces some `setGeometry` stuff by `QBoxLayout`. --- include/SetupDialog.h | 2 ++ src/gui/modals/SetupDialog.cpp | 38 ++++++++++++++++++++++++++++------ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/include/SetupDialog.h b/include/SetupDialog.h index de4cdd9dd..fa41325db 100644 --- a/include/SetupDialog.h +++ b/include/SetupDialog.h @@ -102,6 +102,7 @@ private slots: // Audio settings widget. void audioInterfaceChanged(const QString & driver); void toggleHQAudioDev(bool enabled); + void updateBufferSizeWarning(int value); void setBufferSize(int value); void resetBufferSize(); @@ -179,6 +180,7 @@ private: int m_bufferSize; QSlider * m_bufferSizeSlider; QLabel * m_bufferSizeLbl; + QLabel * m_bufferSizeWarnLbl; // MIDI settings widgets. QComboBox * m_midiInterfaces; diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index 63b84506e..0266285a7 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -579,32 +579,39 @@ SetupDialog::SetupDialog(ConfigTab tab_to_open) : // Buffer size tab. auto bufferSize_tw = new TabWidget(tr("Buffer size"), audio_w); - bufferSize_tw->setFixedHeight(76); + auto bufferSize_layout = new QVBoxLayout(bufferSize_tw); + bufferSize_layout->setSpacing(10); + bufferSize_layout->setContentsMargins(10, 18, 10, 10); m_bufferSizeSlider = new QSlider(Qt::Horizontal, bufferSize_tw); m_bufferSizeSlider->setRange(1, 128); m_bufferSizeSlider->setTickInterval(8); m_bufferSizeSlider->setPageStep(8); m_bufferSizeSlider->setValue(m_bufferSize / BUFFERSIZE_RESOLUTION); - m_bufferSizeSlider->setGeometry(10, 18, 340, 18); m_bufferSizeSlider->setTickPosition(QSlider::TicksBelow); + m_bufferSizeLbl = new QLabel(bufferSize_tw); + + m_bufferSizeWarnLbl = new QLabel(bufferSize_tw); + m_bufferSizeWarnLbl->setWordWrap(true); + connect(m_bufferSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(setBufferSize(int))); connect(m_bufferSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(showRestartWarning())); - - m_bufferSizeLbl = new QLabel(bufferSize_tw); - m_bufferSizeLbl->setGeometry(10, 40, 200, 24); setBufferSize(m_bufferSizeSlider->value()); auto bufferSize_reset_btn = new QPushButton(embed::getIconPixmap("reload"), "", bufferSize_tw); - bufferSize_reset_btn->setGeometry(320, 40, 28, 28); connect(bufferSize_reset_btn, SIGNAL(clicked()), this, SLOT(resetBufferSize())); bufferSize_reset_btn->setToolTip( tr("Reset to default value")); + bufferSize_layout->addWidget(m_bufferSizeSlider); + bufferSize_layout->addWidget(m_bufferSizeLbl); + bufferSize_layout->addWidget(m_bufferSizeWarnLbl); + bufferSize_layout->addWidget(bufferSize_reset_btn); + // Audio layout ordering. audio_layout->addWidget(audioiface_tw); @@ -1172,6 +1179,24 @@ void SetupDialog::audioInterfaceChanged(const QString & iface) } +void SetupDialog::updateBufferSizeWarning(int value) +{ + QString text = "
    "; + if((value & (value - 1)) != 0) // <=> value is not a power of 2 (for value > 0) + { + text += "
  • " + tr("The currently selected value is not a power of 2 " + "(32, 64, 128, 256, 512, 1024, ...). Some plugins may not be available.") + "
  • "; + } + if(value <= 32) + { + text += "
  • " + tr("The currently selected value is less than or equal to 32. " + "Some plugins may not be available.") + "
  • "; + } + text += "
"; + m_bufferSizeWarnLbl->setText(text); +} + + void SetupDialog::setBufferSize(int value) { const int step = DEFAULT_BUFFER_SIZE / BUFFERSIZE_RESOLUTION; @@ -1197,6 +1222,7 @@ void SetupDialog::setBufferSize(int value) m_bufferSize = value * BUFFERSIZE_RESOLUTION; m_bufferSizeLbl->setText(tr("Frames: %1\nLatency: %2 ms").arg(m_bufferSize).arg( 1000.0f * m_bufferSize / Engine::audioEngine()->processingSampleRate(), 0, 'f', 1)); + updateBufferSizeWarning(m_bufferSize); } From 94608eaad1da0622a5eb1fa6d169f8e92d06a6aa Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Fri, 22 Sep 2023 23:42:45 +0200 Subject: [PATCH 149/308] Lv2Proc: Sort scale point maps (#6859) lilv can return the scale points in randomized order, and so the linked models (of stereo effects wit 2 `Lv2Proc`) may have different scale points. This would mean that the same combo enumeration value would have different float values in linked models. This problem is fixed by sorting the scale values. Also, it is more natural for users if scale points are enumerated in a numerical order. --- include/Lv2Basics.h | 6 ++++++ src/core/lv2/Lv2Proc.cpp | 28 +++++++++++++++++----------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/include/Lv2Basics.h b/include/Lv2Basics.h index 9a958d973..53489e30d 100644 --- a/include/Lv2Basics.h +++ b/include/Lv2Basics.h @@ -47,8 +47,14 @@ struct LilvNodesDeleter void operator()(LilvNodes* n) { lilv_nodes_free(n); } }; +struct LilvScalePointsDeleter +{ + void operator()(LilvScalePoints* s) { lilv_scale_points_free(s); } +}; + using AutoLilvNode = std::unique_ptr; using AutoLilvNodes = std::unique_ptr; +using AutoLilvScalePoints = std::unique_ptr; /** Return QString from a plugin's node, everything will be freed automatically diff --git a/src/core/lv2/Lv2Proc.cpp b/src/core/lv2/Lv2Proc.cpp index 6776a26ed..a5fdf4041 100644 --- a/src/core/lv2/Lv2Proc.cpp +++ b/src/core/lv2/Lv2Proc.cpp @@ -574,19 +574,25 @@ void Lv2Proc::createPort(std::size_t portNum) break; case Lv2Ports::Vis::Enumeration: { - auto comboModel = new ComboBoxModel(nullptr, dispName); - LilvScalePoints* sps = - lilv_port_get_scale_points(m_plugin, lilvPort); - LILV_FOREACH(scale_points, i, sps) + ComboBoxModel* comboModel = new ComboBoxModel(nullptr, dispName); + { - const LilvScalePoint* sp = lilv_scale_points_get(sps, i); - ctrl->m_scalePointMap.push_back(lilv_node_as_float( - lilv_scale_point_get_value(sp))); - comboModel->addItem( - lilv_node_as_string( - lilv_scale_point_get_label(sp))); + AutoLilvScalePoints sps (static_cast(lilv_port_get_scale_points(m_plugin, lilvPort))); + // temporary map, since lilv may return scale points in random order + std::map scalePointMap; + LILV_FOREACH(scale_points, i, sps.get()) + { + const LilvScalePoint* sp = lilv_scale_points_get(sps.get(), i); + const float f = lilv_node_as_float(lilv_scale_point_get_value(sp)); + const char* s = lilv_node_as_string(lilv_scale_point_get_label(sp)); + scalePointMap[f] = s; + } + for (const auto& [f,s] : scalePointMap) + { + ctrl->m_scalePointMap.push_back(f); + comboModel->addItem(s); + } } - lilv_scale_points_free(sps); ctrl->m_connectedModel.reset(comboModel); // TODO: use default value on comboModel, too? break; From 83777dc1f73736ec58376590f09cba92331cd901 Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Fri, 22 Sep 2023 23:42:45 +0200 Subject: [PATCH 150/308] Lv2Proc: Set def val for ComboModel, too --- src/core/lv2/Lv2Proc.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/core/lv2/Lv2Proc.cpp b/src/core/lv2/Lv2Proc.cpp index a5fdf4041..242f3d92b 100644 --- a/src/core/lv2/Lv2Proc.cpp +++ b/src/core/lv2/Lv2Proc.cpp @@ -593,8 +593,16 @@ void Lv2Proc::createPort(std::size_t portNum) comboModel->addItem(s); } } + for(std::size_t i = 0; i < ctrl->m_scalePointMap.size(); ++i) + { + if(meta.def() == ctrl->m_scalePointMap[i]) + { + comboModel->setValue(i); + comboModel->setInitValue(i); + break; + } + } ctrl->m_connectedModel.reset(comboModel); - // TODO: use default value on comboModel, too? break; } case Lv2Ports::Vis::Toggled: From 33d1baddc0284bd68df752a08ff9c673a706c4d7 Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Fri, 22 Sep 2023 23:27:02 +0200 Subject: [PATCH 151/308] Implement Lv2 Worker (#6484) --- include/AudioEngine.h | 1 + include/LmmsSemaphore.h | 93 ++++++++++++++++ include/LocklessRingBuffer.h | 3 +- include/Lv2Proc.h | 13 ++- include/Lv2Worker.h | 93 ++++++++++++++++ src/core/CMakeLists.txt | 2 + src/core/LmmsSemaphore.cpp | 143 ++++++++++++++++++++++++ src/core/lv2/Lv2Manager.cpp | 2 + src/core/lv2/Lv2Proc.cpp | 31 +++++- src/core/lv2/Lv2Worker.cpp | 203 +++++++++++++++++++++++++++++++++++ 10 files changed, 580 insertions(+), 4 deletions(-) create mode 100644 include/LmmsSemaphore.h create mode 100644 include/Lv2Worker.h create mode 100644 src/core/LmmsSemaphore.cpp create mode 100644 src/core/lv2/Lv2Worker.cpp diff --git a/include/AudioEngine.h b/include/AudioEngine.h index f056c22e1..d3d0d025f 100644 --- a/include/AudioEngine.h +++ b/include/AudioEngine.h @@ -197,6 +197,7 @@ public: // audio-device-stuff + bool renderOnly() const { return m_renderOnly; } // Returns the current audio device's name. This is not necessarily // the user's preferred audio device, in case you were thinking that. inline const QString & audioDevName() const diff --git a/include/LmmsSemaphore.h b/include/LmmsSemaphore.h new file mode 100644 index 000000000..4170eef6c --- /dev/null +++ b/include/LmmsSemaphore.h @@ -0,0 +1,93 @@ +/* + * Semaphore.h - Semaphore declaration + * + * Copyright (c) 2022-2022 Johannes Lorenz + * + * 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. + * + */ + +/* + * This code has been copied and adapted from https://github.com/drobilla/jalv + * File src/zix/sem.h + */ + +#ifndef LMMS_SEMAPHORE_H +#define LMMS_SEMAPHORE_H + +#include "lmmsconfig.h" + +#ifdef LMMS_BUILD_APPLE +# include +#elif defined(LMMS_BUILD_WIN32) +# include +#else +# include +#endif + +#include + +namespace lmms { + +/** + A counting semaphore. + + This is an integer that is always positive, and has two main operations: + increment (post) and decrement (wait). If a decrement can not be performed + (i.e. the value is 0) the caller will be blocked until another thread posts + and the operation can succeed. + + Semaphores can be created with any starting value, but typically this will + be 0 so the semaphore can be used as a simple signal where each post + corresponds to one wait. + + Semaphores are very efficient (much moreso than a mutex/cond pair). In + particular, at least on Linux, post is async-signal-safe, which means it + does not block and will not be interrupted. If you need to signal from + a realtime thread, this is the most appropriate primitive to use. + + @note Likely outdated with C++20's std::counting_semaphore + (though we have to check that this will be RT conforming on all platforms) +*/ +class Semaphore +{ +public: + Semaphore(unsigned initial); + Semaphore(const Semaphore&) = delete; + Semaphore& operator=(const Semaphore&) = delete; + Semaphore(Semaphore&&) = delete; + Semaphore& operator=(Semaphore&&) = delete; + ~Semaphore(); + + void post(); + void wait(); + bool tryWait(); + +private: +#ifdef LMMS_BUILD_APPLE + semaphore_t m_sem; +#elif defined(LMMS_BUILD_WIN32) + HANDLE m_sem; +#else + sem_t m_sem; +#endif +}; + +} // namespace lmms + +#endif // LMMS_SEMAPHORE_H diff --git a/include/LocklessRingBuffer.h b/include/LocklessRingBuffer.h index 99c48cc90..2d65badfe 100644 --- a/include/LocklessRingBuffer.h +++ b/include/LocklessRingBuffer.h @@ -51,13 +51,14 @@ public: std::size_t capacity() const {return m_buffer.maximum_eventual_write_space();} std::size_t free() const {return m_buffer.write_space();} void wakeAll() {m_notifier.wakeAll();} - std::size_t write(const sampleFrame *src, std::size_t cnt, bool notify = false) + std::size_t write(const T *src, std::size_t cnt, bool notify = false) { std::size_t written = LocklessRingBuffer::m_buffer.write(src, cnt); // Let all waiting readers know new data are available. if (notify) {LocklessRingBuffer::m_notifier.wakeAll();} return written; } + void mlock() { m_buffer.mlock(); } protected: ringbuffer_t m_buffer; diff --git a/include/Lv2Proc.h b/include/Lv2Proc.h index 62070def7..76fa5eec2 100644 --- a/include/Lv2Proc.h +++ b/include/Lv2Proc.h @@ -1,7 +1,7 @@ /* * Lv2Proc.h - Lv2 processor class * - * Copyright (c) 2019-2020 Johannes Lorenz + * Copyright (c) 2019-2022 Johannes Lorenz * * This file is part of LMMS - https://lmms.io * @@ -31,11 +31,14 @@ #include #include +#include +#include "LinkedModelGroups.h" +#include "LmmsSemaphore.h" #include "Lv2Basics.h" #include "Lv2Features.h" #include "Lv2Options.h" -#include "LinkedModelGroups.h" +#include "Lv2Worker.h" #include "Plugin.h" #include "../src/3rdparty/ringbuffer/include/ringbuffer/ringbuffer.h" #include "TimePos.h" @@ -174,8 +177,14 @@ private: const LilvPlugin* m_plugin; LilvInstance* m_instance; Lv2Features m_features; + + // options Lv2Options m_options; + // worker + std::optional m_worker; + Semaphore m_workLock; // this must be shared by different workers + // full list of ports std::vector> m_ports; // quick reference to specific, unique ports diff --git a/include/Lv2Worker.h b/include/Lv2Worker.h new file mode 100644 index 000000000..7931f8e7c --- /dev/null +++ b/include/Lv2Worker.h @@ -0,0 +1,93 @@ +/* + * Lv2Worker.h - Lv2Worker class + * + * Copyright (c) 2022-2022 Johannes Lorenz + * + * 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 LV2WORKER_H +#define LV2WORKER_H + +#include "lmmsconfig.h" + +#ifdef LMMS_HAVE_LV2 + +#include +#include +#include +#include + +#include "LocklessRingBuffer.h" +#include "LmmsSemaphore.h" + +namespace lmms +{ + +/** + Worker container +*/ +class Lv2Worker +{ +public: + // CTOR/DTOR/feature access + Lv2Worker(const LV2_Worker_Interface* iface, Semaphore* common_work_lock, bool threaded); + ~Lv2Worker(); + void setHandle(LV2_Handle handle) { m_handle = handle; } + LV2_Worker_Schedule* feature() { return &m_scheduleFeature; } + + // public API + void emitResponses(); + void notifyPluginThatRunFinished() + { + if(m_iface->end_run) { m_iface->end_run(m_scheduleFeature.handle); } + } + + // to be called only by static functions + LV2_Worker_Status scheduleWork(uint32_t size, const void* data); + LV2_Worker_Status respond(uint32_t size, const void* data); + +private: + // functions + void workerFunc(); + std::size_t bufferSize() const; //!< size of internal buffers + + // parameters + const LV2_Worker_Interface* m_iface; + bool m_threaded; + LV2_Handle m_handle; + LV2_Worker_Schedule m_scheduleFeature; + + // threading/synchronization + std::thread m_thread; + std::vector m_response; //!< buffer where single requests from m_requests are unpacked + LocklessRingBuffer m_requests, m_responses; //!< ringbuffer to queue multiple requests + LocklessRingBufferReader m_requestsReader, m_responsesReader; + std::atomic m_exit = false; //!< Whether the worker function should keep looping + Semaphore m_sem; + Semaphore* m_workLock; +}; + + +} // namespace lmms + +#endif // LMMS_HAVE_LV2 + +#endif // LV2WORKER_H + diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 319882af2..1155f5e0d 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -70,6 +70,7 @@ set(LMMS_SRCS core/SamplePlayHandle.cpp core/SampleRecordHandle.cpp core/Scale.cpp + core/LmmsSemaphore.cpp core/SerializingObject.cpp core/Song.cpp core/TempoSyncKnobModel.cpp @@ -112,6 +113,7 @@ set(LMMS_SRCS core/lv2/Lv2SubPluginFeatures.cpp core/lv2/Lv2UridCache.cpp core/lv2/Lv2UridMap.cpp + core/lv2/Lv2Worker.cpp core/midi/MidiAlsaRaw.cpp core/midi/MidiAlsaSeq.cpp diff --git a/src/core/LmmsSemaphore.cpp b/src/core/LmmsSemaphore.cpp new file mode 100644 index 000000000..daa70a45b --- /dev/null +++ b/src/core/LmmsSemaphore.cpp @@ -0,0 +1,143 @@ +/* + * Semaphore.cpp - Semaphore implementation + * + * Copyright (c) 2022-2022 Johannes Lorenz + * + * 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. + * + */ + +/* + * This code has been copied and adapted from https://github.com/drobilla/jalv + * File src/zix/sem.h + */ + +#include "LmmsSemaphore.h" + +#if defined(LMMS_BUILD_WIN32) +# include +#else +# include +#endif + +#include + +namespace lmms { + +#ifdef LMMS_BUILD_APPLE +Semaphore::Semaphore(unsigned val) +{ + kern_return_t rval = semaphore_create(mach_task_self(), &m_sem, SYNC_POLICY_FIFO, val); + if(rval != 0) { + throw std::system_error(rval, std::system_category(), "Could not create semaphore"); + } +} + +Semaphore::~Semaphore() +{ + semaphore_destroy(mach_task_self(), m_sem); +} + +void Semaphore::post() +{ + semaphore_signal(m_sem); +} + +void Semaphore::wait() +{ + kern_return_t rval = semaphore_wait(m_sem); + if (rval != KERN_SUCCESS) { + throw std::system_error(rval, std::system_category(), "Waiting for semaphore failed"); + } +} + +bool Semaphore::tryWait() +{ + const mach_timespec_t zero = { 0, 0 }; + return semaphore_timedwait(m_sem, zero) == KERN_SUCCESS; +} + +#elif defined(LMMS_BUILD_WIN32) + +Semaphore::Semaphore(unsigned initial) +{ + if(CreateSemaphore(nullptr, initial, LONG_MAX, nullptr) == nullptr) { + throw std::system_error(GetLastError(), std::system_category(), "Could not create semaphore"); + } +} + +Semaphore::~Semaphore() +{ + CloseHandle(m_sem); +} + +void Semaphore::post() +{ + ReleaseSemaphore(m_sem, 1, nullptr); +} + +void Semaphore::wait() +{ + if (WaitForSingleObject(m_sem, INFINITE) != WAIT_OBJECT_0) { + throw std::system_error(GetLastError(), std::system_category(), "Waiting for semaphore failed"); + } +} + +bool Semaphore::tryWait() +{ + return WaitForSingleObject(m_sem, 0) == WAIT_OBJECT_0; +} + +#else /* !defined(LMMS_BUILD_APPLE) && !defined(LMMS_BUILD_WIN32) */ + +Semaphore::Semaphore(unsigned initial) +{ + if(sem_init(&m_sem, 0, initial) != 0) { + throw std::system_error(errno, std::generic_category(), "Could not create semaphore"); + } +} + +Semaphore::~Semaphore() +{ + sem_destroy(&m_sem); +} + +void Semaphore::post() +{ + sem_post(&m_sem); +} + +void Semaphore::wait() +{ + while (sem_wait(&m_sem) != 0) { + if (errno != EINTR) { + throw std::system_error(errno, std::generic_category(), "Waiting for semaphore failed"); + } + /* Otherwise, interrupted, so try again. */ + } +} + +bool Semaphore::tryWait() +{ + return (sem_trywait(&m_sem) == 0); +} + +#endif + +} // namespace lmms + diff --git a/src/core/lv2/Lv2Manager.cpp b/src/core/lv2/Lv2Manager.cpp index 489e613b7..6a1b2a8af 100644 --- a/src/core/lv2/Lv2Manager.cpp +++ b/src/core/lv2/Lv2Manager.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -172,6 +173,7 @@ Lv2Manager::Lv2Manager() : m_supportedFeatureURIs.insert(LV2_URID__map); m_supportedFeatureURIs.insert(LV2_URID__unmap); m_supportedFeatureURIs.insert(LV2_OPTIONS__options); + m_supportedFeatureURIs.insert(LV2_WORKER__schedule); // min/max is always passed in the options m_supportedFeatureURIs.insert(LV2_BUF_SIZE__boundedBlockLength); // block length is only changed initially in AudioEngine CTOR diff --git a/src/core/lv2/Lv2Proc.cpp b/src/core/lv2/Lv2Proc.cpp index 242f3d92b..11290013e 100644 --- a/src/core/lv2/Lv2Proc.cpp +++ b/src/core/lv2/Lv2Proc.cpp @@ -1,7 +1,7 @@ /* * Lv2Proc.cpp - Lv2 processor class * - * Copyright (c) 2019-2020 Johannes Lorenz + * Copyright (c) 2019-2022 Johannes Lorenz * * This file is part of LMMS - https://lmms.io * @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -170,6 +171,7 @@ Plugin::Type Lv2Proc::check(const LilvPlugin *plugin, Lv2Proc::Lv2Proc(const LilvPlugin *plugin, Model* parent) : LinkedModelGroup(parent), m_plugin(plugin), + m_workLock(1), m_midiInputBuf(m_maxMidiInputEvents), m_midiInputReader(m_midiInputBuf) { @@ -360,7 +362,19 @@ void Lv2Proc::copyBuffersToCore(sampleFrame* buf, void Lv2Proc::run(fpp_t frames) { + if (m_worker) + { + // Process any worker replies + m_worker->emitResponses(); + } + lilv_instance_run(m_instance, static_cast(frames)); + + if (m_worker) + { + // Notify the plugin the run() cycle is finished + m_worker->notifyPluginThatRunFinished(); + } } @@ -428,6 +442,9 @@ void Lv2Proc::initPlugin() if (m_instance) { + if(m_worker) { + m_worker->setHandle(lilv_instance_get_handle(m_instance)); + } for (std::size_t portNum = 0; portNum < m_ports.size(); ++portNum) connectPort(portNum); lilv_instance_activate(m_instance); @@ -504,8 +521,20 @@ void Lv2Proc::initMOptions() void Lv2Proc::initPluginSpecificFeatures() { + // options initMOptions(); m_features[LV2_OPTIONS__options] = const_cast(m_options.feature()); + + // worker (if plugin has worker extension) + Lv2Manager* mgr = Engine::getLv2Manager(); + if (lilv_plugin_has_extension_data(m_plugin, mgr->uri(LV2_WORKER__interface).get())) { + const auto iface = static_cast( + lilv_instance_get_extension_data(m_instance, LV2_WORKER__interface)); + bool threaded = !Engine::audioEngine()->renderOnly(); + m_worker.emplace(iface, &m_workLock, threaded); + m_features[LV2_WORKER__schedule] = m_worker->feature(); + // Note: m_worker::setHandle will still need to be called later + } } diff --git a/src/core/lv2/Lv2Worker.cpp b/src/core/lv2/Lv2Worker.cpp new file mode 100644 index 000000000..5af955ff7 --- /dev/null +++ b/src/core/lv2/Lv2Worker.cpp @@ -0,0 +1,203 @@ +/* + * Lv2Worker.cpp - Lv2Worker implementation + * + * Copyright (c) 2022-2022 Johannes Lorenz + * + * 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 "Lv2Worker.h" + +#include +#include + +#ifdef LMMS_HAVE_LV2 + +#include "Engine.h" + + +namespace lmms +{ + + +// static wrappers + +static LV2_Worker_Status +staticWorkerRespond(LV2_Worker_Respond_Handle handle, + uint32_t size, const void* data) +{ + Lv2Worker* worker = static_cast(handle); + return worker->respond(size, data); +} + + + + +std::size_t Lv2Worker::bufferSize() const +{ + // ardour uses this fixed size for ALSA: + return 8192 * 4; + // for jack, they use 4 * jack_port_type_get_buffer_size (..., JACK_DEFAULT_MIDI_TYPE) + // (possible extension for AudioDevice) +} + + + + +Lv2Worker::Lv2Worker(const LV2_Worker_Interface* iface, + Semaphore* common_work_lock, + bool threaded) : + m_iface(iface), + m_threaded(threaded), + m_response(bufferSize()), + m_requests(bufferSize()), + m_responses(bufferSize()), + m_requestsReader(m_requests), + m_responsesReader(m_responses), + m_sem(0), + m_workLock(common_work_lock) +{ + assert(iface); + m_scheduleFeature.handle = static_cast(this); + m_scheduleFeature.schedule_work = [](LV2_Worker_Schedule_Handle handle, + uint32_t size, const void* data) -> LV2_Worker_Status + { + Lv2Worker* worker = static_cast(handle); + return worker->scheduleWork(size, data); + }; + + if (threaded) { m_thread = std::thread(&Lv2Worker::workerFunc, this); } + + m_requests.mlock(); + m_responses.mlock(); +} + + + + +Lv2Worker::~Lv2Worker() +{ + m_exit = true; + if(m_threaded) { + m_sem.post(); + m_thread.join(); + } +} + + + + +// Let the worker send responses to the audio thread +LV2_Worker_Status Lv2Worker::respond(uint32_t size, const void* data) +{ + if(m_threaded) + { + if(m_responses.free() < sizeof(size) + size) + { + return LV2_WORKER_ERR_NO_SPACE; + } + else + { + m_responses.write((const char*)&size, sizeof(size)); + if(size && data) { m_responses.write((const char*)data, size); } + } + } + else + { + m_iface->work_response(m_handle, size, data); + } + return LV2_WORKER_SUCCESS; +} + + + + +// Let the worker receive work from the audio thread and "work" on it +void Lv2Worker::workerFunc() +{ + std::vector buf; + uint32_t size; + while (true) { + m_sem.wait(); + if (m_exit) { break; } + const std::size_t readSpace = m_requestsReader.read_space(); + if (readSpace <= sizeof(size)) { continue; } // (should not happen) + + m_requestsReader.read(sizeof(size)).copy((char*)&size, sizeof(size)); + assert(size <= readSpace - sizeof(size)); + if(size > buf.size()) { buf.resize(size); } + if(size) { m_requestsReader.read(size).copy(buf.data(), size); } + + m_workLock->wait(); + m_iface->work(m_handle, staticWorkerRespond, this, size, buf.data()); + m_workLock->post(); + } +} + + + + +// Let the audio thread schedule work for the worker +LV2_Worker_Status Lv2Worker::scheduleWork(uint32_t size, const void *data) +{ + if (m_threaded) + { + if(m_requests.free() < sizeof(size) + size) + { + return LV2_WORKER_ERR_NO_SPACE; + } + else + { + // Schedule a request to be executed by the worker thread + m_requests.write((const char*)&size, sizeof(size)); + if(size && data) { m_requests.write((const char*)data, size); } + m_sem.post(); + } + } + else + { + // Execute work immediately in this thread + m_workLock->wait(); + m_iface->work(m_handle, staticWorkerRespond, this, size, data); + m_workLock->post(); + } + + return LV2_WORKER_SUCCESS; +} + + + + +// Let the audio thread read incoming worker responses, and process it +void Lv2Worker::emitResponses() +{ + std::size_t read_space = m_responsesReader.read_space(); + uint32_t size; + while (read_space > sizeof(size)) { + m_responsesReader.read(sizeof(size)).copy((char*)&size, sizeof(size)); + if(size) { m_responsesReader.read(size).copy(m_response.data(), size); } + m_iface->work_response(m_handle, size, m_response.data()); + read_space -= sizeof(size) + size; + } +} + + +} // namespace lmms + +#endif // LMMS_HAVE_LV2 From f664698c80f8bf55992071a409cff4b24da84739 Mon Sep 17 00:00:00 2001 From: Bimal Poudel Date: Sun, 24 Sep 2023 16:58:56 -0600 Subject: [PATCH 152/308] Update copyright year (#6888) --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4163ca5cc..0b6d3b4ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,7 @@ INCLUDE(GenerateExportHeader) STRING(TOUPPER "${CMAKE_PROJECT_NAME}" PROJECT_NAME_UCASE) -SET(PROJECT_YEAR 2020) +SET(PROJECT_YEAR 2023) SET(PROJECT_AUTHOR "LMMS Developers") SET(PROJECT_URL "https://lmms.io") From 23ef89b4a15b6c7cccd7eae89f5fd512a460688a Mon Sep 17 00:00:00 2001 From: Bimal Poudel Date: Sun, 24 Sep 2023 19:03:29 -0600 Subject: [PATCH 153/308] Update SampleBuffer.cpp (#6892) File information corrected. --- src/core/SampleBuffer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/SampleBuffer.cpp b/src/core/SampleBuffer.cpp index 5e2d09c57..c96111bba 100644 --- a/src/core/SampleBuffer.cpp +++ b/src/core/SampleBuffer.cpp @@ -1389,7 +1389,7 @@ SampleBuffer * SampleBuffer::resample(const sample_rate_t srcSR, const sample_ra } else { - printf("Error: src_new() failed in sample_buffer.cpp!\n"); + printf("Error: src_new() failed in SampleBuffer.cpp!\n"); } dstSB->update(); return dstSB; @@ -1612,7 +1612,7 @@ SampleBuffer::handleState::handleState(bool varyingPitch, int interpolationMode) if ((m_resamplingData = src_new(interpolationMode, DEFAULT_CHANNELS, &error)) == nullptr) { - qDebug("Error: src_new() failed in sample_buffer.cpp!\n"); + qDebug("Error: src_new() failed in SampleBuffer.cpp!\n"); } } From 8fb9c3e6a26fa7a212bfe9f7dfd4f069001babab Mon Sep 17 00:00:00 2001 From: Dalton Messmer <33463986+messmerd@users.noreply.github.com> Date: Thu, 28 Sep 2023 20:23:35 -0400 Subject: [PATCH 154/308] Fix warnings in Clang build (#6893) * Fix unused variable warning * Fix implicit conversion warning * Fix unused lambda capture in DataFile.cpp * Fix implicit conversions in InstrumentFunctions.cpp * Fix operator precedence bug in Flags.h * Fix unused variable warning in Lv2UridMap.h * Fix unused lambda capture in MixerView.cpp * Fix unused lambda captures in SetupDialog.cpp * Fix unused lambda capture in TrackOperationsWidget.cpp * Fix MSVC build * Fix style * Remove unused member variable in Lv2UridMap.h --- include/Flags.h | 4 ++-- include/Lv2UridMap.h | 2 -- include/MidiEvent.h | 2 +- src/core/DataFile.cpp | 2 +- src/core/DrumSynth.cpp | 7 ++++--- src/core/InstrumentFunctions.cpp | 4 ++-- src/gui/MixerView.cpp | 2 +- src/gui/modals/SetupDialog.cpp | 6 +++--- src/gui/tracks/TrackOperationsWidget.cpp | 2 +- 9 files changed, 15 insertions(+), 16 deletions(-) diff --git a/include/Flags.h b/include/Flags.h index 76106dde6..62a5f8af8 100644 --- a/include/Flags.h +++ b/include/Flags.h @@ -48,8 +48,8 @@ public: 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 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}; } diff --git a/include/Lv2UridMap.h b/include/Lv2UridMap.h index b8733023e..6c22aca3e 100644 --- a/include/Lv2UridMap.h +++ b/include/Lv2UridMap.h @@ -55,8 +55,6 @@ class UridMap LV2_URID_Map m_mapFeature; LV2_URID_Unmap m_unmapFeature; - LV2_URID m_lastUrid = 0; - public: //! constructor; will set up the features UridMap(); diff --git a/include/MidiEvent.h b/include/MidiEvent.h index 956c33fb3..9a14e427c 100644 --- a/include/MidiEvent.h +++ b/include/MidiEvent.h @@ -212,7 +212,7 @@ private: int32_t m_sysExDataLen; // len of m_sysExData } m_data; - const char* m_sysExData; + [[maybe_unused]] const char* m_sysExData; const void* m_sourcePort; // Stores the source of the MidiEvent: Internal or External (hardware controllers). diff --git a/src/core/DataFile.cpp b/src/core/DataFile.cpp index 8d0a8dca4..90e819077 100644 --- a/src/core/DataFile.cpp +++ b/src/core/DataFile.cpp @@ -302,7 +302,7 @@ void DataFile::write( QTextStream & _strm ) bool DataFile::writeFile(const QString& filename, bool withResources) { // Small lambda function for displaying errors - auto showError = [this](QString title, QString body){ + auto showError = [](QString title, QString body){ if (gui::getGUI() != nullptr) { QMessageBox mb; diff --git a/src/core/DrumSynth.cpp b/src/core/DrumSynth.cpp index bc5455c96..decc6bfa2 100644 --- a/src/core/DrumSynth.cpp +++ b/src/core/DrumSynth.cpp @@ -273,7 +273,9 @@ int DrumSynth::GetDSFileSamples(QString dsfile, int16_t *&wave, int channels, sa //generation long Length, tpos=0, tplus, totmp, t, i, j; float x[3] = {0.f, 0.f, 0.f}; - float MasterTune, randmax, randmax2; + float MasterTune; + constexpr float randmax = 1.f / static_cast(RAND_MAX); + constexpr float randmax2 = 2.f / static_cast(RAND_MAX); int MainFilter, HighPass; long NON, NT, TON, DiON, TDroop=0, DStep; @@ -454,7 +456,6 @@ int DrumSynth::GetDSFileSamples(QString dsfile, int16_t *&wave, int channels, sa } //prepare envelopes - randmax = 1.f / RAND_MAX; randmax2 = 2.f * randmax; for (i=1;i<8;i++) { envData[i][NEXTT]=0; envData[i][PNT]=0; } Length = LongestEnv(); @@ -745,4 +746,4 @@ int DrumSynth::GetDSFileSamples(QString dsfile, int16_t *&wave, int channels, sa } -} // namespace lmms \ No newline at end of file +} // namespace lmms diff --git a/src/core/InstrumentFunctions.cpp b/src/core/InstrumentFunctions.cpp index 431afd2fe..976363d3d 100644 --- a/src/core/InstrumentFunctions.cpp +++ b/src/core/InstrumentFunctions.cpp @@ -409,7 +409,7 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) // Skip notes randomly if( m_arpSkipModel.value() ) { - if( 100 * ( (float) rand() / (float)( RAND_MAX + 1.0f ) ) < m_arpSkipModel.value() ) + if (100 * static_cast(rand()) / (static_cast(RAND_MAX) + 1.0f) < m_arpSkipModel.value()) { // update counters frames_processed += arp_frames; @@ -425,7 +425,7 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) if( m_arpMissModel.value() ) { - if( 100 * ( (float) rand() / (float)( RAND_MAX + 1.0f ) ) < m_arpMissModel.value() ) + if (100 * static_cast(rand()) / (static_cast(RAND_MAX) + 1.0f) < m_arpMissModel.value()) { dir = ArpDirection::Random; } diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index dff19ca3e..018e72c2b 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -464,7 +464,7 @@ bool MixerView::confirmRemoval(int index) QString messageTitleRemoveTrack = tr("Confirm removal"); QString askAgainText = tr("Don't ask again"); auto askAgainCheckBox = new QCheckBox(askAgainText, nullptr); - connect(askAgainCheckBox, &QCheckBox::stateChanged, [this](int state) { + connect(askAgainCheckBox, &QCheckBox::stateChanged, [](int state) { // Invert button state, if it's checked we *shouldn't* ask again ConfigManager::inst()->setValue("ui", "mixerchanneldeletionwarning", state ? "0" : "1"); }); diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index 0266285a7..09d6ab92c 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -168,8 +168,8 @@ SetupDialog::SetupDialog(ConfigTab tab_to_open) : // Constants for positioning LED check boxes. - const int XDelta = 10; - const int YDelta = 18; + constexpr int XDelta = 10; + constexpr int YDelta = 18; // Main widget. auto main_w = new QWidget(this); @@ -212,7 +212,7 @@ SetupDialog::SetupDialog(ConfigTab tab_to_open) : auto generalControlsLayout = new QVBoxLayout; generalControlsLayout->setSpacing(10); - auto addLedCheckBox = [&XDelta, &YDelta, this](const QString& ledText, TabWidget* tw, int& counter, + auto addLedCheckBox = [&](const QString& ledText, TabWidget* tw, int& counter, bool initialState, const char* toggledSlot, bool showRestartWarning) { auto checkBox = new LedCheckBox(ledText, tw); counter++; diff --git a/src/gui/tracks/TrackOperationsWidget.cpp b/src/gui/tracks/TrackOperationsWidget.cpp index fa1a651f6..31edc4949 100644 --- a/src/gui/tracks/TrackOperationsWidget.cpp +++ b/src/gui/tracks/TrackOperationsWidget.cpp @@ -195,7 +195,7 @@ bool TrackOperationsWidget::confirmRemoval() QString messageTitleRemoveTrack = tr("Confirm removal"); QString askAgainText = tr("Don't ask again"); auto askAgainCheckBox = new QCheckBox(askAgainText, nullptr); - connect(askAgainCheckBox, &QCheckBox::stateChanged, [this](int state){ + connect(askAgainCheckBox, &QCheckBox::stateChanged, [](int state){ // Invert button state, if it's checked we *shouldn't* ask again ConfigManager::inst()->setValue("ui", "trackdeletionwarning", state ? "0" : "1"); }); From 7dc00524fa263a6aebef088f8ad9eb26a4884982 Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Fri, 29 Sep 2023 20:39:01 +0200 Subject: [PATCH 155/308] Mallets - Add random knob function (#6466) * Mallets - Add random knob function Implement randomness for the instrument. When Random is applied, Hardness and Position of instrument 1 - 9, or Modulator and Crossfade on instrument 10 (Tubular Bells), are nudged on every note to liven up the sound. With the modulated knobs placed at their center values, Random at max will select from the full range of possible values. Co-authored-by: saker Co-authored-by: Dominic Clark --- plugins/Stk/Mallets/Mallets.cpp | 44 ++++++++++++++++++++++++++++----- plugins/Stk/Mallets/Mallets.h | 2 ++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/plugins/Stk/Mallets/Mallets.cpp b/plugins/Stk/Mallets/Mallets.cpp index b746e9491..1bca0d40f 100644 --- a/plugins/Stk/Mallets/Mallets.cpp +++ b/plugins/Stk/Mallets/Mallets.cpp @@ -87,6 +87,7 @@ MalletsInstrument::MalletsInstrument( InstrumentTrack * _instrument_track ): m_strikeModel( true, this, tr( "Bowed" ) ), m_presetsModel(this), m_spreadModel(0, 0, 255, 1, this, tr( "Spread" )), + m_randomModel(0.0f, 0.0f, 1.0f, 0.01f, this, tr("Randomness")), m_versionModel( MALLETS_PRESET_VERSION, 0, MALLETS_PRESET_VERSION, this, "" ), m_isOldVersionModel( false, this, "" ), m_filesMissing( !QDir( ConfigManager::inst()->stkDir() ).exists() || @@ -155,6 +156,7 @@ void MalletsInstrument::saveSettings( QDomDocument & _doc, QDomElement & _this ) m_presetsModel.saveSettings( _doc, _this, "preset" ); m_spreadModel.saveSettings( _doc, _this, "spread" ); + m_randomModel.saveSettings(_doc, _this, "randomness"); m_versionModel.saveSettings( _doc, _this, "version" ); m_isOldVersionModel.saveSettings( _doc, _this, "oldversion" ); } @@ -189,6 +191,7 @@ void MalletsInstrument::loadSettings( const QDomElement & _this ) m_presetsModel.loadSettings( _this, "preset" ); m_spreadModel.loadSettings( _this, "spread" ); + m_randomModel.loadSettings(_this, "randomness"); m_isOldVersionModel.loadSettings( _this, "oldversion" ); // To maintain backward compatibility @@ -284,7 +287,7 @@ void MalletsInstrument::playNote( NotePlayHandle * _n, } int p = m_presetsModel.value(); - + const float freq = _n->frequency(); if (!_n->m_pluginData) { @@ -293,6 +296,29 @@ void MalletsInstrument::playNote( NotePlayHandle * _n, m_isOldVersionModel.value() ? 100.0 : 200.0; const float vel = _n->getVolume() / velocityAdjust; + const float random = m_randomModel.value(); + float hardness = m_hardnessModel.value(); + float position = m_positionModel.value(); + float modulator = m_modulatorModel.value(); + float crossfade = m_crossfadeModel.value(); + + if (p < 9) + { + hardness += random * static_cast(fast_rand() % 128) - 64.0; + hardness = std::clamp(hardness, 0.0f, 128.0f); + + position += random * static_cast(fast_rand() % 64) - 32.0; + position = std::clamp(position, 0.0f, 64.0f); + } + else if (p == 9) + { + modulator += random * static_cast(fast_rand() % 128) - 64.0; + modulator = std::clamp(modulator, 0.0f, 128.0f); + + crossfade += random * static_cast(fast_rand() % 128) - 64.0; + crossfade = std::clamp(crossfade, 0.0f, 128.0f); + } + // critical section as STK is not thread-safe static QMutex m; m.lock(); @@ -301,8 +327,8 @@ void MalletsInstrument::playNote( NotePlayHandle * _n, _n->m_pluginData = new MalletsSynth( freq, vel, m_stickModel.value(), - m_hardnessModel.value(), - m_positionModel.value(), + hardness, + position, m_vibratoGainModel.value(), m_vibratoFreqModel.value(), p, @@ -315,8 +341,8 @@ void MalletsInstrument::playNote( NotePlayHandle * _n, vel, p, m_lfoDepthModel.value(), - m_modulatorModel.value(), - m_crossfadeModel.value(), + modulator, + crossfade, m_lfoSpeedModel.value(), m_adsrModel.value(), (uint8_t) m_spreadModel.value(), @@ -412,6 +438,11 @@ MalletsInstrumentView::MalletsInstrumentView( MalletsInstrument * _instrument, m_spreadKnob->move( 190, 140 ); m_spreadKnob->setHintText( tr( "Spread:" ), "" ); + m_randomKnob = new Knob(KnobType::Vintage32, this); + m_randomKnob->setLabel(tr("Random")); + m_randomKnob->move(190, 190); + m_randomKnob->setHintText(tr("Random:"), ""); + // try to inform user about missing Stk-installation if( _instrument->m_filesMissing && getGUI() != nullptr ) { @@ -467,7 +498,7 @@ QWidget * MalletsInstrumentView::setupModalBarControls( QWidget * _parent ) m_stickKnob->setLabel( tr( "Stick mix" ) ); m_stickKnob->move( 190, 90 ); m_stickKnob->setHintText( tr( "Stick mix:" ), "" ); - + return( widget ); } @@ -565,6 +596,7 @@ void MalletsInstrumentView::modelChanged() // m_strikeLED->setModel( &inst->m_strikeModel ); m_presetsCombo->setModel( &inst->m_presetsModel ); m_spreadKnob->setModel( &inst->m_spreadModel ); + m_randomKnob->setModel(&inst->m_randomModel); } diff --git a/plugins/Stk/Mallets/Mallets.h b/plugins/Stk/Mallets/Mallets.h index f66ac25d0..657d1538a 100644 --- a/plugins/Stk/Mallets/Mallets.h +++ b/plugins/Stk/Mallets/Mallets.h @@ -197,6 +197,7 @@ private: ComboBoxModel m_presetsModel; FloatModel m_spreadModel; + FloatModel m_randomModel; IntModel m_versionModel; BoolModel m_isOldVersionModel; @@ -255,6 +256,7 @@ private: ComboBox * m_presetsCombo; Knob * m_spreadKnob; + Knob * m_randomKnob; }; From d962070d7c84a1c1b0fa3877b41fe5d6365fdf69 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Sat, 30 Sep 2023 00:01:10 +0200 Subject: [PATCH 156/308] Fix release fade-out not being applied This fixes to bugs leading to clicks on instrument note-off in most instruments. The first bug was introduced as part of a refactoring done by Vesa [1] and caused each note play handle's last buffer being dropped because the play handles were deleted before being processed in AudioPort. Thanks to @lleroy for pointing this out. [2] The second bug / typo has always been there [3] and was a misplaced parenthesis in Instrument::applyRelease breaking the calculation of the note-off envelope's start frame, sometimes putting it outside of the buffer. Fixes #3086 [1] 857de8d2c829dc688745f41ba8eddbe148a63a20 and related commits [1] https://github.com/LMMS/lmms/issues/3086#issuecomment-519087089 [2] 02433380c629457ad021a1f9c91b8148769c33dc --- src/core/AudioEngine.cpp | 22 +++++++++++----------- src/core/Instrument.cpp | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/core/AudioEngine.cpp b/src/core/AudioEngine.cpp index 29c54647c..df274c188 100644 --- a/src/core/AudioEngine.cpp +++ b/src/core/AudioEngine.cpp @@ -394,6 +394,17 @@ void AudioEngine::renderStageInstruments() AudioEngineWorkerThread::fillJobQueue(m_playHandles); AudioEngineWorkerThread::startAndWaitForJobs(); +} + + + +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::startAndWaitForJobs(); // removed all play handles which are done for( PlayHandleList::Iterator it = m_playHandles.begin(); @@ -424,17 +435,6 @@ void AudioEngine::renderStageInstruments() -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::startAndWaitForJobs(); -} - - - void AudioEngine::renderStageMix() { AudioEngineProfiler::Probe profilerProbe(m_profiler, AudioEngineProfiler::DetailType::Mixing); diff --git a/src/core/Instrument.cpp b/src/core/Instrument.cpp index b715bcac0..fd729e3ab 100644 --- a/src/core/Instrument.cpp +++ b/src/core/Instrument.cpp @@ -186,7 +186,7 @@ void Instrument::applyRelease( sampleFrame * buf, const NotePlayHandle * _n ) { for( fpp_t f = (fpp_t)( ( fl > desiredReleaseFrames() ) ? (std::max(fpp - desiredReleaseFrames(), 0) + - fl % fpp) : 0); f < frames; ++f) + fl) % fpp : 0); f < frames; ++f) { const float fac = (float)( fl-f-1 ) / desiredReleaseFrames(); From b29a46edf8d27106d7e43b0b3c27d7edce5554b3 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sat, 30 Sep 2023 12:12:04 +0200 Subject: [PATCH 157/308] Ensure minimum width for setup dialog Ensure that the dialog has a minimum width so that everything is shown. --- src/gui/modals/SetupDialog.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index 892155280..effece1ba 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -870,6 +870,9 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : vlayout->addWidget(extras_w); vlayout->addSpacing(10); + // Ensure that we cannot make the dialog smaller than it wants to be + setMinimumWidth(width()); + show(); } From 4f94c3b13cec0b5c2326bc9ce08402f72fb0b2ac Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sat, 30 Sep 2023 21:15:10 +0200 Subject: [PATCH 158/308] Review change - Rectangular buttons Give the reset buttons for auto save and buffer size a rectangular shape. The size is fixed but the button and the pixmap scale with different scaling factors so that should be ok. --- src/gui/modals/SetupDialog.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index effece1ba..7faa9c934 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -372,6 +372,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : this, SLOT(setAutoSaveInterval(int))); auto autoSaveResetBtn = new QPushButton(embed::getIconPixmap("reload"), "", autoSaveBox); + autoSaveResetBtn->setFixedSize(32, 32); connect(autoSaveResetBtn, SIGNAL(clicked()), this, SLOT(resetAutoSave())); @@ -575,6 +576,7 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : bufferSizeSubLayout->addWidget(m_bufferSizeSlider, 1); auto bufferSize_reset_btn = new QPushButton(embed::getIconPixmap("reload"), "", bufferSizeBox); + bufferSize_reset_btn->setFixedSize(32, 32); connect(bufferSize_reset_btn, SIGNAL(clicked()), this, SLOT(resetBufferSize())); bufferSize_reset_btn->setToolTip( From 85310e75d3d6e658d3f7c101de884dd5194eb910 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sun, 1 Oct 2023 09:57:13 +0200 Subject: [PATCH 159/308] Order of includes and forward declarations Fix the alphabetical order of all includes and forward declarations. --- include/SetupDialog.h | 2 +- src/core/audio/AudioJack.cpp | 2 +- src/core/audio/AudioPulseAudio.cpp | 2 +- src/gui/modals/SetupDialog.cpp | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/SetupDialog.h b/include/SetupDialog.h index f45b09dab..882ca2bed 100644 --- a/include/SetupDialog.h +++ b/include/SetupDialog.h @@ -35,11 +35,11 @@ #include "MidiSetupWidget.h" +class QCheckBox; class QComboBox; class QLabel; class QLineEdit; class QSlider; -class QCheckBox; namespace lmms::gui diff --git a/src/core/audio/AudioJack.cpp b/src/core/audio/AudioJack.cpp index f5c3c160f..83fa3c177 100644 --- a/src/core/audio/AudioJack.cpp +++ b/src/core/audio/AudioJack.cpp @@ -26,9 +26,9 @@ #ifdef LMMS_HAVE_JACK +#include #include #include -#include #include "Engine.h" #include "GuiApplication.h" diff --git a/src/core/audio/AudioPulseAudio.cpp b/src/core/audio/AudioPulseAudio.cpp index 2164a99f2..3ca8764cc 100644 --- a/src/core/audio/AudioPulseAudio.cpp +++ b/src/core/audio/AudioPulseAudio.cpp @@ -22,8 +22,8 @@ * */ -#include #include +#include #include "AudioPulseAudio.h" diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index 00344b1a1..c27992fa1 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -23,14 +23,14 @@ */ +#include #include +#include #include #include #include #include #include -#include -#include #include "AudioEngine.h" #include "debug.h" From d12675af2f19dd999bfe8f9ab249f21b7171cbd2 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sun, 1 Oct 2023 10:00:52 +0200 Subject: [PATCH 160/308] Remove unnecessary addStretch Remove an unnecessary call to `addStretch` and with that a TODO. --- src/gui/modals/SetupDialog.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index c27992fa1..06231d382 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -341,10 +341,6 @@ SetupDialog::SetupDialog(ConfigTab tab_to_open) : generalScroll->setWidgetResizable(true); general_layout->addWidget(generalScroll, 1); - // TODO Does not really seem to be needed - general_layout->addStretch(); - - // Performance widget. From cc6a0e86b5942c90b4b5c538cbcd8227faaec60a Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sun, 1 Oct 2023 10:17:08 +0200 Subject: [PATCH 161/308] Remove border/shadows from scroll area Remove the border/shadows from the QScrollAreas used in the context of the setup dialog via the style sheet. --- data/themes/default/style.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index a49618b0a..344aa0519 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -464,6 +464,10 @@ lmms--gui--EffectSelectDialog QScrollArea { background: #262b30; } +lmms--gui--SetupDialog QScrollArea { + border: 0px; +} + /* the inner boxes in LADSPA effect windows */ lmms--gui--EffectControlDialog QGroupBox { From 1399d5906f06d2f384e873abb1f5b0716f64ef02 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sun, 1 Oct 2023 10:21:34 +0200 Subject: [PATCH 162/308] Left align "General" and "Paths" Left align the scroll area content for "General" and "Paths" so that they look like the content on the other tabs. --- src/gui/modals/SetupDialog.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index 06231d382..212ef92f0 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -208,6 +208,7 @@ SetupDialog::SetupDialog(ConfigTab tab_to_open) : // Path selectors layout. auto generalControlsLayout = new QVBoxLayout; generalControlsLayout->setSpacing(10); + generalControlsLayout->setContentsMargins(0, 0, 0, 0); auto addCheckBox = [&](const QString& ledText, QWidget* parent, QBoxLayout * layout, bool initialState, const char* toggledSlot, bool showRestartWarning) -> QCheckBox * { @@ -734,6 +735,7 @@ SetupDialog::SetupDialog(ConfigTab tab_to_open) : // Path selectors layout. auto pathSelectorsLayout = new QVBoxLayout; pathSelectorsLayout->setSpacing(10); + pathSelectorsLayout->setContentsMargins(0, 0, 0, 0); auto addPathEntry = [&](const QString& caption, const QString& content, const char* setSlot, const char* openSlot, QLineEdit*& lineEdit, const char* pixmap = "project_open") { From a54dc9a05f2ff73ea6c4f83012e9ec8a980a6979 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sun, 1 Oct 2023 10:34:21 +0200 Subject: [PATCH 163/308] Remove LedCheckBox include Enable the removal of the `LedCheckBox` include by commenting out code instead of using an `if(false)` statement. The commented out code was adjusted so that it would work with the current usage of layouts. --- src/gui/modals/SetupDialog.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index 212ef92f0..e64d1c572 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -38,7 +38,6 @@ #include "Engine.h" #include "FileDialog.h" #include "gui_templates.h" -#include "LedCheckBox.h" #include "MainWindow.h" #include "MidiSetupWidget.h" #include "ProjectJournal.h" @@ -542,12 +541,10 @@ SetupDialog::SetupDialog(ConfigTab tab_to_open) : this, SLOT(audioInterfaceChanged(const QString&))); // Advanced setting, hidden for now - if(false) - { - // TODO Handle or remove. - auto useNaNHandler = new LedCheckBox(tr("Use built-in NaN handler"), audio_w); - useNaNHandler->setChecked(m_NaNHandler); - } + // // TODO Handle or remove. + // auto useNaNHandler = new LedCheckBox(tr("Use built-in NaN handler"), audio_w); + // audio_layout->addWidget(useNaNHandler); + // useNaNHandler->setChecked(m_NaNHandler); // HQ mode checkbox auto hqaudio = addCheckBox(tr("HQ mode for output audio device"), audioInterfaceBox, nullptr, From e1cc63bb971825a9be38f7a235a401eb807ad314 Mon Sep 17 00:00:00 2001 From: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com> Date: Sun, 1 Oct 2023 19:25:25 +0530 Subject: [PATCH 164/308] Switched ladspaeffect/Cmakelists.txt to use `LMMS_HAVE_*` instead of `WANT_*` (#6903) * fixed cmakelists conditions * Fixed the order messup. Co-authored-by: Dominic Clark --------- Co-authored-by: Dominic Clark --- plugins/LadspaEffect/CMakeLists.txt | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/plugins/LadspaEffect/CMakeLists.txt b/plugins/LadspaEffect/CMakeLists.txt index 951615ad4..a01eb950f 100644 --- a/plugins/LadspaEffect/CMakeLists.txt +++ b/plugins/LadspaEffect/CMakeLists.txt @@ -4,22 +4,22 @@ BUILD_PLUGIN(ladspaeffect LadspaEffect.cpp LadspaControls.cpp LadspaControlDialo SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/ladspa") -IF(WANT_CAPS) +IF(LMMS_HAVE_CAPS) ADD_SUBDIRECTORY(caps) -ENDIF(WANT_CAPS) +ENDIF() -IF(WANT_TAP) +IF(LMMS_HAVE_TAP) ADD_SUBDIRECTORY(tap) -ENDIF(WANT_TAP) +ENDIF() -IF(WANT_SWH) +IF(LMMS_HAVE_SWH) ADD_SUBDIRECTORY(swh) -ENDIF(WANT_SWH) +ENDIF() -IF(WANT_CMT) +IF(LMMS_HAVE_CMT) ADD_SUBDIRECTORY(cmt) -ENDIF(WANT_CMT) +ENDIF() -IF(WANT_CALF) +IF(LMMS_HAVE_CALF) ADD_SUBDIRECTORY(calf) -ENDIF(WANT_CALF) +ENDIF() From 579d132b8a3978c5a0e08534bbbce30b167bd129 Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Thu, 5 Oct 2023 16:51:52 +0200 Subject: [PATCH 165/308] SetupDialog - message on buffer size larger than 256 (#6906) LMMS supports the Lv2 feature powerOf2BlockLength. Plugins that need to be a power of two (32, 64, 128...) are not loaded if the buffer size setting is set to something else. However this logic breaks down on buffer sizes larger than 256. On larger sizes, LMMS works with chunks of 256 and plugins are still presented with a value of 256. So anything larger than 256 is a valid size as powerOf2BlockLength is concerned. LMMS supported powerOf2BlockLength correctly since 9c46370 but setup manager messages and comments are wrong in too strictly demanding an actual power of two value. 768 is not a power of two, but three chunks of 256 which are power of two values. Co-authored-by: Johannes Lorenz <1042576+JohannesLorenz@users.noreply.github.com> --- src/core/AudioEngine.cpp | 3 +++ src/gui/modals/SetupDialog.cpp | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/core/AudioEngine.cpp b/src/core/AudioEngine.cpp index 29c54647c..2f4459748 100644 --- a/src/core/AudioEngine.cpp +++ b/src/core/AudioEngine.cpp @@ -126,6 +126,9 @@ AudioEngine::AudioEngine( bool renderOnly ) : m_framesPerPeriod = DEFAULT_BUFFER_SIZE; } + // lmms works with chunks of size DEFAULT_BUFFER_SIZE (256) and only the final mix will use the actual + // buffer size. Plugins don't see a larger buffer size than 256. If m_framesPerPeriod is larger than + // DEFAULT_BUFFER_SIZE, it's set to DEFAULT_BUFFER_SIZE and the rest is handled by an increased fifoSize. else if( m_framesPerPeriod > DEFAULT_BUFFER_SIZE ) { fifoSize = m_framesPerPeriod / DEFAULT_BUFFER_SIZE; diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index e64d1c572..209422563 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -1166,10 +1166,14 @@ void SetupDialog::audioInterfaceChanged(const QString & iface) void SetupDialog::updateBufferSizeWarning(int value) { QString text = "