diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 9c812fd9b..f6560a23e 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -339,7 +339,7 @@ jobs:
CCACHE_MAXSIZE: 500M
msvc:
name: msvc-x64
- runs-on: windows-2019
+ runs-on: windows-2022
env:
CCACHE_MAXSIZE: 0
CCACHE_NOCOMPRESS: 1
@@ -421,3 +421,68 @@ jobs:
ccache --show-stats --verbose
env:
CCACHE_MAXSIZE: 500MB
+ msys2:
+ name: windows-arm64
+ runs-on: windows-11-arm
+ defaults:
+ run:
+ shell: msys2 {0}
+ env:
+ CMAKE_OPTS: >-
+ -DCMAKE_BUILD_TYPE=RelWithDebInfo
+ -DUSE_COMPILE_CACHE=ON
+ -DCPACK_NSIS_EXECUTABLE=/clang64/bin/makensis.exe
+ CCACHE_MAXSIZE: 0
+ CCACHE_NOCOMPRESS: 1
+ MAKEFLAGS: -j2
+ steps:
+ - name: Check out
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ submodules: recursive
+ - name: Cache msys2 dependencies
+ id: cache-deps
+ uses: actions/cache@v3
+ with:
+ key: windows-arm64-${{ hashFiles('.github/workflows/deps-msys2-clangarm64.txt') }}
+ restore-keys: |
+ windows-arm64-
+ path: \msys64\var\cache\pacman\pkg
+ - name: Install msys2
+ uses: msys2/setup-msys2@v2
+ with:
+ msystem: CLANGARM64
+ update: true
+ - name: Install dependencies
+ run: pacman --needed --noconfirm -S - < .github/workflows/deps-msys2-clangarm64.txt
+ - name: Cache ccache data
+ uses: actions/cache@v3
+ with:
+ key: ccache-${{ github.job }}-${{ github.ref }}-${{ github.run_id }}
+ restore-keys: |
+ ccache-${{ github.job }}-${{ github.ref }}-
+ ccache-${{ github.job }}-
+ path: ~\AppData\Local\ccache
+ - name: Configure
+ run: |
+ /clang64/bin/ccache.exe --zero-stats
+ cmake -B build $CMAKE_OPTS
+ - name: Build
+ run: cmake --build build
+ - name: Package
+ run: cmake --build build --target package
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: windows-arm64
+ path: build\lmms-*.exe
+ - name: Trim ccache and print statistics
+ run: |
+ /clang64/bin/ccache.exe --cleanup
+ echo "[ccache config]"
+ /clang64/bin/ccache.exe --show-config
+ echo "[ccache stats]"
+ /clang64/bin/ccache.exe --show-stats --verbose
+ env:
+ CCACHE_MAXSIZE: 500MB
diff --git a/.github/workflows/deps-msys2-clangarm64.txt b/.github/workflows/deps-msys2-clangarm64.txt
new file mode 100644
index 000000000..c3feb0264
--- /dev/null
+++ b/.github/workflows/deps-msys2-clangarm64.txt
@@ -0,0 +1,25 @@
+base
+base-devel
+filesystem
+git
+mingw-w64-clang-aarch64-SDL2
+mingw-w64-clang-aarch64-ccache
+mingw-w64-clang-aarch64-clang
+mingw-w64-clang-aarch64-cmake
+mingw-w64-clang-aarch64-fftw
+mingw-w64-clang-aarch64-fltk
+mingw-w64-clang-aarch64-fluidsynth
+mingw-w64-clang-aarch64-libgig
+mingw-w64-clang-aarch64-libsamplerate
+mingw-w64-clang-aarch64-libsndfile
+mingw-w64-clang-aarch64-lilv
+mingw-w64-clang-aarch64-lv2
+mingw-w64-clang-aarch64-qt5-base
+mingw-w64-clang-aarch64-qt5-svg
+mingw-w64-clang-aarch64-suil
+mingw-w64-clang-aarch64-stk
+mingw-w64-clang-x86_64-nsis
+mingw-w64-clang-x86_64-ccache
+msys2-runtime
+perl-List-MoreUtils
+perl-XML-Parser
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index cc2823ba0..5afe75307 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,5 @@
/plugins/ZynAddSubFx/zynaddsubfx/doc/gen/Makefile
/data/locale/*.qm
Brewfile.lock.json
+/.cache/
+compile_commands.json
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3c01bebf0..f439815cb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,5 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.13)
+SET(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Set the given policy to NEW. If it does not exist, it will not be set. If it
# is already set to NEW (most likely due to predating the minimum required CMake
@@ -633,11 +634,20 @@ ENDIF()
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DLMMS_DEBUG")
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DLMMS_DEBUG")
+if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
+ add_compile_definitions(NDEBUG)
+ SET(STATUS_ASSERTIONS "Disabled")
+else()
+ remove_definitions(-DNDEBUG)
+ SET(STATUS_ASSERTIONS "Enabled")
+endif()
+
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.16")
set(NOOP_COMMAND "${CMAKE_COMMAND}" "-E" "true")
else()
set(NOOP_COMMAND "${CMAKE_COMMAND}" "-E" "echo")
endif()
+
if(STRIP)
# TODO CMake 3.19: Now that CONFIG generator expressions support testing for
# multiple configurations, combine the OR into a single CONFIG expression.
@@ -864,6 +874,7 @@ MESSAGE(
"* Debug using UBSanitizer : ${STATUS_DEBUG_UBSAN}\n"
"* Debug packaging commands : ${STATUS_DEBUG_CPACK}\n"
"* Profile using GNU profiler : ${STATUS_GPROF}\n"
+"* Debug assertions : ${STATUS_ASSERTIONS}\n"
)
MESSAGE(
diff --git a/data/themes/classic/auto_resize.png b/data/themes/classic/auto_resize.png
new file mode 100644
index 000000000..491966a8e
Binary files /dev/null and b/data/themes/classic/auto_resize.png differ
diff --git a/data/themes/classic/auto_resize_disable.png b/data/themes/classic/auto_resize_disable.png
new file mode 100644
index 000000000..e7c6c2c83
Binary files /dev/null and b/data/themes/classic/auto_resize_disable.png differ
diff --git a/data/themes/classic/automation_ghost_note.png b/data/themes/classic/automation_ghost_note.png
index d4b1416f5..4b06b4073 100644
Binary files a/data/themes/classic/automation_ghost_note.png and b/data/themes/classic/automation_ghost_note.png differ
diff --git a/data/themes/classic/clear_ghost_note.png b/data/themes/classic/clear_ghost_note.png
index a005b6034..fb5fe089c 100644
Binary files a/data/themes/classic/clear_ghost_note.png and b/data/themes/classic/clear_ghost_note.png differ
diff --git a/data/themes/classic/clear_notes_out_of_bounds.png b/data/themes/classic/clear_notes_out_of_bounds.png
new file mode 100644
index 000000000..d3f27a0f5
Binary files /dev/null and b/data/themes/classic/clear_notes_out_of_bounds.png differ
diff --git a/data/themes/classic/cursor_knife.png b/data/themes/classic/cursor_knife.png
index 591df2d62..8ddbd3ac4 100644
Binary files a/data/themes/classic/cursor_knife.png and b/data/themes/classic/cursor_knife.png differ
diff --git a/data/themes/classic/cut_overlaps.png b/data/themes/classic/cut_overlaps.png
new file mode 100644
index 000000000..e79e4950a
Binary files /dev/null and b/data/themes/classic/cut_overlaps.png differ
diff --git a/data/themes/classic/edit_knife.png b/data/themes/classic/edit_knife.png
index b6b6bf934..0afdae5b7 100644
Binary files a/data/themes/classic/edit_knife.png and b/data/themes/classic/edit_knife.png differ
diff --git a/data/themes/classic/file.png b/data/themes/classic/file.png
new file mode 100644
index 000000000..e74f14df6
Binary files /dev/null and b/data/themes/classic/file.png differ
diff --git a/data/themes/classic/fill.png b/data/themes/classic/fill.png
new file mode 100644
index 000000000..6bc07d1e8
Binary files /dev/null and b/data/themes/classic/fill.png differ
diff --git a/data/themes/classic/ghost_note.png b/data/themes/classic/ghost_note.png
index 2c3ace519..9d3b31632 100644
Binary files a/data/themes/classic/ghost_note.png and b/data/themes/classic/ghost_note.png differ
diff --git a/data/themes/classic/glue.png b/data/themes/classic/glue.png
new file mode 100644
index 000000000..c5d059a09
Binary files /dev/null and b/data/themes/classic/glue.png differ
diff --git a/data/themes/classic/gridmode.png b/data/themes/classic/gridmode.png
new file mode 100644
index 000000000..20b65fa47
Binary files /dev/null and b/data/themes/classic/gridmode.png differ
diff --git a/data/themes/classic/insert_bar.png b/data/themes/classic/insert_bar.png
new file mode 100644
index 000000000..fbc9f4775
Binary files /dev/null and b/data/themes/classic/insert_bar.png differ
diff --git a/data/themes/classic/max_length.png b/data/themes/classic/max_length.png
new file mode 100644
index 000000000..00162eb06
Binary files /dev/null and b/data/themes/classic/max_length.png differ
diff --git a/data/themes/classic/min_length.png b/data/themes/classic/min_length.png
new file mode 100644
index 000000000..be1c6e94f
Binary files /dev/null and b/data/themes/classic/min_length.png differ
diff --git a/data/themes/classic/proportional_snap.png b/data/themes/classic/proportional_snap.png
index 485ced02b..be687c9df 100644
Binary files a/data/themes/classic/proportional_snap.png and b/data/themes/classic/proportional_snap.png differ
diff --git a/data/themes/classic/receive_bg_arrow.png b/data/themes/classic/receive_bg_arrow.png
index 8aaeae606..8e01e9df8 100644
Binary files a/data/themes/classic/receive_bg_arrow.png and b/data/themes/classic/receive_bg_arrow.png differ
diff --git a/data/themes/classic/remove_bar.png b/data/themes/classic/remove_bar.png
new file mode 100644
index 000000000..143766a37
Binary files /dev/null and b/data/themes/classic/remove_bar.png differ
diff --git a/data/themes/classic/send_bg_arrow.png b/data/themes/classic/send_bg_arrow.png
index cc29b8649..2cbde2603 100644
Binary files a/data/themes/classic/send_bg_arrow.png and b/data/themes/classic/send_bg_arrow.png differ
diff --git a/data/themes/classic/hq_mode.png b/data/themes/classic/star.png
similarity index 100%
rename from data/themes/classic/hq_mode.png
rename to data/themes/classic/star.png
diff --git a/data/themes/classic/style.css b/data/themes/classic/style.css
index 13047dc5d..a0fb48209 100644
--- a/data/themes/classic/style.css
+++ b/data/themes/classic/style.css
@@ -30,9 +30,8 @@ lmms--gui--AutomationEditor {
qproperty-barLineColor: #808080;
qproperty-graphColor: rgba(153, 175, 255, 200);
- qproperty-scaleColor: qlineargradient(spread:reflect,
- x1:0, y1:0.5, x2:1, y2:0.5,
- stop:0 #333, stop:1 #202020);
+ qproperty-scaleColor: qlineargradient(spread:reflect, x1:0, y1:0.5, x2:1, y2:0.5,
+ stop:0 #333, stop:1 #202020);
qproperty-ghostNoteColor: rgba(248, 248, 255, 125);
qproperty-detuningNoteColor: rgba(248, 11, 11, 125);
@@ -69,7 +68,8 @@ QTextEdit, QLineEdit:focus, QComboBox:focus, QSpinBox:focus, QDoubleSpinBox:focu
QToolTip {
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));
+ 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;
border: 1.0px solid rgba(0,0,0,255);
color: #4afd85;
@@ -77,7 +77,8 @@ QToolTip {
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));
+ 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;
border: 1.0px solid rgba(0,0,0,255);
color: #4afd85;
@@ -248,45 +249,39 @@ QScrollBar::add-page:vertical:pressed, QScrollBar::sub-page:vertical:pressed {
/* scrollbar: handles (sliders) */
QScrollBar::handle:horizontal {
- background: qlineargradient(spread:reflect,
- x1:0.5, y1:0, x2:0.5, y2:1,
- stop:0 #969696, stop:0.5 #c9c9c9, stop:1 #aaa);
+ background: qlineargradient(spread:reflect, x1:0.5, y1:0, x2:0.5, y2:1,
+ stop:0 #969696, stop:0.5 #c9c9c9, stop:1 #aaa);
border: 1px outset #888;
border-radius: 2px;
min-width: 24px;
}
QScrollBar::handle:horizontal:hover {
- background: qlineargradient(spread:reflect,
- x1:0.5, y1:0, x2:0.5, y2:1,
- stop:0 #969696, stop:0.5 #f0f0f0, stop:1 #aaa);
+ background: qlineargradient(spread:reflect, x1:0.5, y1:0, x2:0.5, y2:1,
+ stop:0 #969696, stop:0.5 #f0f0f0, stop:1 #aaa);
}
QScrollBar::handle:horizontal:pressed {
- background: qlineargradient(spread:reflect,
- x1:0.5, y1:0, x2:0.5, y2:1,
- stop:0 #747474, stop:1 #c9c9c9);
+ background: qlineargradient(spread:reflect, x1:0.5, y1:0, x2:0.5, y2:1,
+ stop:0 #747474, stop:1 #c9c9c9);
}
QScrollBar::handle:vertical {
- background: qlineargradient(spread:reflect,
- x1:0, y1:0.5, x2:1, y2:0.5,
- stop:0 #969696, stop:0.5 #c9c9c9, stop:1 #aaa);
+ background: qlineargradient(spread:reflect, x1:0, y1:0.5, x2:1, y2:0.5,
+ stop:0 #969696, stop:0.5 #c9c9c9, stop:1 #aaa);
border: 1px outset #888;
border-radius: 2px;
min-height: 24px;
}
QScrollBar::handle:vertical:hover {
- background: qlineargradient(spread:reflect,
- x1:0, y1:0.5, x2:1, y2:0.5,
- stop:0 #969696, stop:0.5 #f0f0f0, stop:1 #aaa);
+ background: qlineargradient(spread:reflect, x1:0, y1:0.5, x2:1, y2:0.5,
+ stop:0 #969696, stop:0.5 #f0f0f0, stop:1 #aaa);
}
QScrollBar::handle:vertical:pressed {
- background: qlineargradient(spread:reflect,
- x1:0, y1:0.5, x2:1, y2:0.5,
- stop:0 #747474, stop:1 #c9c9c9);
+ background: qlineargradient(spread:reflect, x1:0, y1:0.5, x2:1, y2:0.5,
+ stop:0 #747474, stop:1 #c9c9c9);
}
QScrollBar::handle:horizontal:disabled, QScrollBar::handle:vertical:disabled {
@@ -298,7 +293,8 @@ QScrollBar::handle:horizontal:disabled, QScrollBar::handle:vertical:disabled {
/* arrow buttons */
QScrollBar::add-line, QScrollBar::sub-line {
- background: qradialgradient(cx:0.3, cy:0.3, radius:0.8, fx:0.3, fy:0.3, stop:0 #c9c9c9, stop:1 #969696 );
+ background: qradialgradient(cx:0.3, cy:0.3, radius:0.8, fx:0.3, fy:0.3,
+ stop:0 #c9c9c9, stop:1 #969696 );
border-radius: 1px;
border: 1px solid #131313;
subcontrol-origin: margin;
@@ -310,11 +306,13 @@ QScrollBar::add-line:vertical { subcontrol-position: bottom; height: 12px;}
QScrollBar::sub-line:vertical { subcontrol-position: top; height: 12px;}
QScrollBar::add-line:hover, QScrollBar::sub-line:hover {
- background: qradialgradient(cx:0.3, cy:0.3, radius:0.8, fx:0.3, fy:0.3, stop:0 #e0e0e0, stop:0.5 #c9c9c9, stop:1 #969696 );
+ background: qradialgradient(cx:0.3, cy:0.3, radius:0.8, fx:0.3, fy:0.3,
+ stop:0 #e0e0e0, stop:0.5 #c9c9c9, stop:1 #969696 );
}
QScrollBar::add-line:pressed, QScrollBar::sub-line:pressed {
- background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #969696, stop:0.5 #c9c9c9, stop:1 #969696 );
+ background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #969696,
+ stop:0.5 #c9c9c9, stop:1 #969696 );
}
QScrollBar::add-line:disabled, QScrollBar::sub-line:disabled {
@@ -356,8 +354,10 @@ lmms--gui--TrackView > QWidget {
/* track background config */
lmms--gui--TrackContentWidget {
/* colors */
- qproperty-darkerColor: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(50, 50, 50), stop:0.33 rgb(20, 20, 20), stop:1 rgb(15, 15, 15));
- qproperty-lighterColor: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(50, 50, 50), stop:0.33 rgb(40, 40, 40), stop:1 rgb(30, 30, 30));
+ qproperty-darkerColor: qlineargradient(x1:0, y1:0, x2:0, y2:1,
+ stop:0 rgb(50, 50, 50), stop:0.33 rgb(20, 20, 20), stop:1 rgb(15, 15, 15));
+ qproperty-lighterColor: qlineargradient(x1:0, y1:0, x2:0, y2:1,
+ stop:0 rgb(50, 50, 50), stop:0.33 rgb(40, 40, 40), stop:1 rgb(30, 30, 30));
qproperty-coarseGridColor: rgba(0, 0, 0, 160);
qproperty-fineGridColor: rgba(0, 0, 0, 80);
qproperty-horizontalColor: rgba(0, 0, 0, 160);
@@ -376,32 +376,61 @@ lmms--gui--TrackContentWidget {
/* gear button in tracks */
+
+/* 20px = 1px border + 2px padding + 14px icon + 2px padding + 1px border */
+QPushButton#btn-mute,
+QPushButton#btn-mute-inv:checked,
+QPushButton#btn-solo,
lmms--gui--TrackOperationsWidget QPushButton {
- max-height: 26px;
- max-width: 26px;
- min-height: 26px;
- min-width: 26px;
- background: none;
- border: none;
+ min-height: 14;
+ max-height: 14;
+ min-width: 14;
+ max-width: 14;
+ padding: 2;
+ border: 1 solid #0f1621;
+ border-top: 1 solid #18202b;
+ border-bottom: 1 solid #02060f;
+ border-radius: 4;
+ background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255, 255, 255, 20%), stop:0.1 rgba(255, 255, 255, 2%), stop:0.9 rgba(0, 0, 0, 2%), stop:1 rgba(0, 0, 0, 40%));
}
lmms--gui--TrackOperationsWidget QPushButton::menu-indicator {
- image: url("resources:trackop.png");
- subcontrol-origin: padding;
- subcontrol-position: center;
- position: relative;
- top: 1px;
+ image: none;
}
-lmms--gui--TrackOperationsWidget QPushButton::menu-indicator:hover {
- image: url("resources:trackop_h.png");
+lmms--gui--TrackOperationsWidget QPushButton {
+ image: url("resources:gear.svg");
}
-lmms--gui--TrackOperationsWidget QPushButton::menu-indicator:pressed,
-lmms--gui--TrackOperationsWidget QPushButton::menu-indicator:checked {
- image: url("resources:trackop_c.png");
- position: relative;
- top: 2px;
+QPushButton#btn-mute,
+QPushButton#btn-mute-inv:checked {
+ image: url("resources:speaker.svg");
+}
+
+QPushButton#btn-solo {
+ image: url("resources:headphones.svg");
+}
+
+QPushButton#btn-mute:hover,
+QPushButton#btn-solo:hover,
+lmms--gui--TrackOperationsWidget QPushButton:hover {
+ background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255, 255, 255, 25%), stop:0.1 rgba(255, 255, 255, 7%), stop:0.9 transparent, stop:1 rgba(0, 0, 0, 35%));
+}
+
+lmms--gui--TrackOperationsWidget QPushButton:pressed {
+ background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(0, 0, 0, 25%), stop:0.1 transparent, stop:0.8 rgba(0, 0, 0, 15%), stop:1 rgba(0, 0, 0, 35%));
+}
+
+QPushButton#btn-mute-inv,
+QPushButton#btn-mute:checked {
+ image: url("resources:speaker_slash.svg");
+ border: 1 solid #890120;
+ background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #e2515b, stop:0.1 #d40237, stop:0.9 #d40237, stop:1 #900122);
+}
+
+QPushButton#btn-solo:checked {
+ border: 1 solid #055f89;
+ background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #5aa8d9, stop:0.1 #2696d1, stop:0.9 #2696d1, stop:1 #16638c);
}
/* actually has no effect yet so disabled */
@@ -544,7 +573,8 @@ QToolButton:pressed {
}
QToolButton:checked {
- background: qradialgradient(cx:0.3, cy:0.3, radius:0.8, fx:0.3, fy:0.3, stop:0 #e0e0e0, stop:0.8 #c9c9c9, stop:1 #c0c0c0 );
+ background: qradialgradient(cx:0.3, cy:0.3, radius:0.8, fx:0.3, fy:0.3,
+ stop:0 #e0e0e0, stop:0.8 #c9c9c9, stop:1 #c0c0c0 );
padding: 2px 1px 0px 1px;
color: black;
}
@@ -578,7 +608,8 @@ lmms--gui--TrackLabelButton {
}
lmms--gui--TrackLabelButton:hover {
- background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:0.5, stop:0 #5b6571, stop:0.75 #7b838d, stop:1 #7b838d );
+ background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:0.5,
+ stop:0 #5b6571, stop:0.75 #7b838d, stop:1 #7b838d );
color: white;
border: 1px solid rgba(0,0,0,64);
padding: 1px 0px;
@@ -586,7 +617,8 @@ lmms--gui--TrackLabelButton:hover {
}
lmms--gui--TrackLabelButton:pressed {
- background: qlineargradient(spread:reflect, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 #49515b, stop:0.3 #5b6571, stop:1 #6b7581 );
+ background: qlineargradient(spread:reflect, x1:0.5, y1:0, x2:0.5, y2:1,
+ stop:0 #49515b, stop:0.3 #5b6571, stop:1 #6b7581 );
color: white;
border: 1px solid rgba(0,0,0,64);
padding: 2px 0px 0px;
@@ -594,7 +626,8 @@ lmms--gui--TrackLabelButton:pressed {
}
lmms--gui--TrackLabelButton:checked {
- background: qlineargradient(spread:reflect, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 #49515b, stop:0.3 #5b6571, stop:1 #6b7581 );
+ background: qlineargradient(spread:reflect, x1:0.5, y1:0, x2:0.5, y2:1,
+ stop:0 #49515b, stop:0.3 #5b6571, stop:1 #6b7581 );
color: white;
border: 1px solid rgba(0,0,0,128);
padding: 2px 0px 0px;
@@ -602,17 +635,19 @@ lmms--gui--TrackLabelButton:checked {
}
lmms--gui--TrackLabelButton:checked:hover {
- background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:0.5, stop:0 #5b6571, stop:0.75 #7b838d, stop:1 #7b838d );
+ background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:0.5,
+ stop:0 #5b6571, stop:0.75 #7b838d, stop:1 #7b838d );
}
lmms--gui--TrackLabelButton:checked:pressed {
- background: qlineargradient(spread:reflect, x1:0.5, y1:0, x2:0.5, y2:1, stop:0 #49515b, stop:0.3 #5b6571, stop:1 #6b7581 );
+ background: qlineargradient(spread:reflect, x1:0.5, y1:0, x2:0.5, y2:1,
+ stop:0 #49515b, stop:0.3 #5b6571, stop:1 #6b7581 );
}
/* sidebar, sidebar buttons */
lmms--gui--SideBar {
- background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop: 0 #98a2a7, stop: 1.0 #5b646f);
+ background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #98a2a7, stop:1 #5b646f);
}
lmms--gui--SideBar QToolButton {
@@ -649,8 +684,7 @@ lmms--gui--ControllerRackView QPushButton {
lmms--gui--MixerChannelView {
background: #5b6571;
color: #e0e0e0;
- qproperty-backgroundActive: qlineargradient(spread:reflect, x1:0, y1:0, x2:1, y2:0,
- stop:0 #7b838d, stop:1 #6b7581 );
+ qproperty-backgroundActive: #7d8691;
qproperty-strokeOuterActive: rgb( 0, 0, 0 );
qproperty-strokeOuterInactive: rgba( 0, 0, 0, 50 );
qproperty-strokeInnerActive: rgba( 255, 255, 255, 100 );
@@ -684,16 +718,14 @@ lmms--gui--TimeLineWidget {
min-height: 1.5em;
max-height: 1.5em;
- background-color: qlineargradient( x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #8796a7, stop: 1.0 #3e454e );
+ background-color: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop:0 #8796a7, stop:1 #3e454e );
qproperty-inactiveLoopColor: rgba( 52, 63, 53, 64 );
qproperty-inactiveLoopBrush: rgba( 255, 255, 255, 32 );
qproperty-inactiveLoopInnerColor: rgba( 255, 255, 255, 32 );
qproperty-inactiveLoopHandleColor: rgba( 192, 192, 192, 100 );
qproperty-activeLoopColor: rgba( 52, 63, 53, 255 );
- qproperty-activeLoopBrush: qlineargradient( x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #378d59, stop: 1.0 #297e36 );
+ qproperty-activeLoopBrush: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop:0 #378d59, stop:1 #297e36 );
qproperty-activeLoopInnerColor: rgba( 74, 155, 100, 255 );
qproperty-activeLoopHandleColor: rgba( 192, 192, 192, 200 );
@@ -729,6 +761,7 @@ lmms--gui--ClipView {
qproperty-textBackgroundColor: rgba(0, 0, 0, 75);
qproperty-textShadowColor: rgb( 0, 0, 0 );
qproperty-gradient: true; /* boolean property, set true to have a gradient */
+ qproperty-markerColor: rgb(0, 0, 0);
/* finger tip offset of cursor */
qproperty-mouseHotspotHand: 3px 3px;
qproperty-mouseHotspotKnife: 0px 0px;
@@ -766,10 +799,8 @@ lmms--gui--PatternClipView {
/* Subwindows in MDI-Area */
lmms--gui--SubWindow {
- color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #4b525c, stop: 1.0 #31363d);
- qproperty-activeColor: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 #33383e, stop: 1.0 #1a1c20);
+ color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #4b525c, stop:1 #31363d);
+ qproperty-activeColor: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #33383e, stop:1 #1a1c20);
qproperty-textShadowColor: rgb( 0, 0, 0 );
qproperty-borderColor: rgb( 0, 0, 0 );
}
diff --git a/data/themes/classic/tool.png b/data/themes/classic/tool.png
new file mode 100644
index 000000000..183470438
Binary files /dev/null and b/data/themes/classic/tool.png differ
diff --git a/data/themes/default/auto_resize.png b/data/themes/default/auto_resize.png
new file mode 100644
index 000000000..52b65742d
Binary files /dev/null and b/data/themes/default/auto_resize.png differ
diff --git a/data/themes/default/auto_resize_disable.png b/data/themes/default/auto_resize_disable.png
new file mode 100644
index 000000000..a997c81b6
Binary files /dev/null and b/data/themes/default/auto_resize_disable.png differ
diff --git a/data/themes/default/clear_notes_out_of_bounds.png b/data/themes/default/clear_notes_out_of_bounds.png
new file mode 100644
index 000000000..8387db843
Binary files /dev/null and b/data/themes/default/clear_notes_out_of_bounds.png differ
diff --git a/data/themes/default/fader_knob.png b/data/themes/default/fader_knob.png
deleted file mode 100644
index 2190451d8..000000000
Binary files a/data/themes/default/fader_knob.png and /dev/null differ
diff --git a/data/themes/default/fader_knob.svg b/data/themes/default/fader_knob.svg
new file mode 100644
index 000000000..8a5d9e908
--- /dev/null
+++ b/data/themes/default/fader_knob.svg
@@ -0,0 +1,18 @@
+
diff --git a/data/themes/default/gear.svg b/data/themes/default/gear.svg
new file mode 100644
index 000000000..dfcd7d4d9
--- /dev/null
+++ b/data/themes/default/gear.svg
@@ -0,0 +1,26 @@
+
+
diff --git a/data/themes/default/headphones.svg b/data/themes/default/headphones.svg
new file mode 100644
index 000000000..ecdc5a18e
--- /dev/null
+++ b/data/themes/default/headphones.svg
@@ -0,0 +1,44 @@
+
+
diff --git a/data/themes/default/mute_active.svg b/data/themes/default/mute_active.svg
deleted file mode 100644
index 600144697..000000000
--- a/data/themes/default/mute_active.svg
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
diff --git a/data/themes/default/mute_inactive.svg b/data/themes/default/mute_inactive.svg
deleted file mode 100644
index 6042cc767..000000000
--- a/data/themes/default/mute_inactive.svg
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
diff --git a/data/themes/default/solo_active.svg b/data/themes/default/solo_active.svg
deleted file mode 100644
index d5c151be3..000000000
--- a/data/themes/default/solo_active.svg
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
diff --git a/data/themes/default/solo_inactive.svg b/data/themes/default/solo_inactive.svg
deleted file mode 100644
index 57788c607..000000000
--- a/data/themes/default/solo_inactive.svg
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
diff --git a/data/themes/default/speaker.svg b/data/themes/default/speaker.svg
new file mode 100644
index 000000000..1f43f5517
--- /dev/null
+++ b/data/themes/default/speaker.svg
@@ -0,0 +1,42 @@
+
+
diff --git a/data/themes/default/speaker_slash.svg b/data/themes/default/speaker_slash.svg
new file mode 100644
index 000000000..9b42db7ac
--- /dev/null
+++ b/data/themes/default/speaker_slash.svg
@@ -0,0 +1,44 @@
+
+
diff --git a/data/themes/default/hq_mode.png b/data/themes/default/star.png
similarity index 100%
rename from data/themes/default/hq_mode.png
rename to data/themes/default/star.png
diff --git a/data/themes/default/style.css b/data/themes/default/style.css
index 184bc9b56..f78df0982 100644
--- a/data/themes/default/style.css
+++ b/data/themes/default/style.css
@@ -387,6 +387,24 @@ lmms--gui--TrackView > QWidget {
}
+QPushButton#btn {
+ color: #d1d8e4;
+ padding: 2 4;
+ border: 1 solid #000;
+ border-radius: 3;
+ background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255, 255, 255, 20%), stop:0.1 rgba(255, 255, 255, 4%), stop:0.9 rgba(0, 0, 0, 4%), stop:1 rgba(0, 0, 0, 40%));
+}
+
+QPushButton#btn:hover {
+ background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255, 255, 255, 25%), stop:0.1 rgba(255, 255, 255, 7%), stop:0.9 rgba(255, 255, 255, 4%), stop:1 rgba(0, 0, 0, 35%));
+}
+
+QPushButton#btn:pressed,
+QPushButton#btn:checked {
+ color: #02ee89;
+ background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(0, 0, 0, 25%), stop:0.1 transparent, stop:0.9 rgba(0, 0, 0, 15%), stop:1 rgba(0, 0, 0, 35%));
+}
+
/* autoscroll, loop, stop behaviour toggle buttons */
/* track background config */
@@ -412,30 +430,64 @@ lmms--gui--TrackContentWidget {
/* gear button in tracks */
+
+/* 20px = 1px border + 2px padding + 14px icon + 2px padding + 1px border */
+QPushButton#btn-mute,
+QPushButton#btn-mute-inv:checked,
+QPushButton#btn-solo,
lmms--gui--TrackOperationsWidget QPushButton {
- max-height: 26px;
- max-width: 26px;
- min-height: 26px;
- min-width: 26px;
- background: none;
- border: none;
+ min-height: 14;
+ max-height: 14;
+ min-width: 14;
+ max-width: 14;
+ padding: 2;
+ border: 1 solid #0f1621;
+ border-top: 1 solid #18202b;
+ border-bottom: 1 solid #02060f;
+ border-radius: 2;
+ background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255, 255, 255, 20%), stop:0.1 rgba(255, 255, 255, 2%), stop:0.9 rgba(0, 0, 0, 2%), stop:1 rgba(0, 0, 0, 40%));
}
lmms--gui--TrackOperationsWidget QPushButton::menu-indicator {
- image: url("resources:trackop.png");
- subcontrol-origin: padding;
- subcontrol-position: center;
- position: relative;
- top: 1px;
+ image: none;
}
-lmms--gui--TrackOperationsWidget QPushButton::menu-indicator:pressed,
-lmms--gui--TrackOperationsWidget QPushButton::menu-indicator:checked {
- image: url("resources:trackop.png");
- position: relative;
- top: 2px;
+lmms--gui--TrackOperationsWidget QPushButton {
+ image: url("resources:gear.svg");
}
+QPushButton#btn-mute,
+QPushButton#btn-mute-inv:checked {
+ image: url("resources:speaker.svg");
+}
+
+QPushButton#btn-solo {
+ image: url("resources:headphones.svg");
+}
+
+QPushButton#btn-mute:hover,
+QPushButton#btn-solo:hover,
+lmms--gui--TrackOperationsWidget QPushButton:hover {
+ background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255, 255, 255, 25%), stop:0.1 rgba(255, 255, 255, 7%), stop:0.9 transparent, stop:1 rgba(0, 0, 0, 35%));
+}
+
+lmms--gui--TrackOperationsWidget QPushButton:pressed {
+ background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(0, 0, 0, 25%), stop:0.1 transparent, stop:0.8 rgba(0, 0, 0, 15%), stop:1 rgba(0, 0, 0, 35%));
+}
+
+QPushButton#btn-mute-inv,
+QPushButton#btn-mute:checked {
+ image: url("resources:speaker_slash.svg");
+ border: 1 solid #890120;
+ background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #e2515b, stop:0.1 #d40237, stop:0.9 #d40237, stop:1 #900122);
+}
+
+QPushButton#btn-solo:checked {
+ border: 1 solid #055f89;
+ background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #5aa8d9, stop:0.1 #2696d1, stop:0.9 #2696d1, stop:1 #16638c);
+}
+
+
/* font sizes */
lmms--gui--Sf2InstrumentView > QLabel {
@@ -770,6 +822,7 @@ lmms--gui--ClipView {
qproperty-textBackgroundColor: rgba(0, 0, 0, 75);
qproperty-textShadowColor: rgba(0,0,0,200);
qproperty-gradient: false; /* boolean property, set true to have a gradient */
+ qproperty-markerColor: rgb(0, 0, 0);
/* finger tip offset of cursor */
qproperty-mouseHotspotHand: 7px 2px;
qproperty-mouseHotspotKnife: 0px 0px;
diff --git a/data/themes/default/trackop.png b/data/themes/default/trackop.png
deleted file mode 100644
index a4f90e35c..000000000
Binary files a/data/themes/default/trackop.png and /dev/null differ
diff --git a/include/AudioBufferView.h b/include/AudioBufferView.h
new file mode 100644
index 000000000..56fff10fa
--- /dev/null
+++ b/include/AudioBufferView.h
@@ -0,0 +1,276 @@
+/*
+ * AudioBufferView.h - Non-owning views for interleaved and
+ * non-interleaved (planar) buffers
+ *
+ * Copyright (c) 2025 Dalton Messmer
+ *
+ * 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_AUDIO_BUFFER_VIEW_H
+#define LMMS_AUDIO_BUFFER_VIEW_H
+
+#include
+#include
+#include
+
+#include "LmmsTypes.h"
+
+namespace lmms
+{
+
+//! Use when the number of channels is not known at compile time
+inline constexpr auto DynamicChannelCount = static_cast(-1);
+
+
+namespace detail {
+
+// For static channel count
+template
+class BufferViewData
+{
+public:
+ constexpr BufferViewData() = default;
+ constexpr BufferViewData(const BufferViewData&) = default;
+
+ constexpr BufferViewData(SampleT* data, proc_ch_t channels, f_cnt_t frames) noexcept
+ : m_data{data}
+ , m_frames{frames}
+ {
+ assert(channels == channelCount);
+ }
+
+ constexpr BufferViewData(SampleT* data, f_cnt_t frames) noexcept
+ : m_data{data}
+ , m_frames{frames}
+ {
+ }
+
+ constexpr auto data() const noexcept -> SampleT* { return m_data; }
+ constexpr auto channels() const noexcept -> proc_ch_t { return channelCount; }
+ constexpr auto frames() const noexcept -> f_cnt_t { return m_frames; }
+
+protected:
+ SampleT* m_data = nullptr;
+ f_cnt_t m_frames = 0;
+};
+
+// For dynamic channel count
+template
+class BufferViewData
+{
+public:
+ constexpr BufferViewData() = default;
+ constexpr BufferViewData(const BufferViewData&) = default;
+
+ constexpr BufferViewData(SampleT* data, proc_ch_t channels, f_cnt_t frames) noexcept
+ : m_data{data}
+ , m_channels{channels}
+ , m_frames{frames}
+ {
+ assert(channels != DynamicChannelCount);
+ }
+
+ constexpr auto data() const noexcept -> SampleT* { return m_data; }
+ constexpr auto channels() const noexcept -> proc_ch_t { return m_channels; }
+ constexpr auto frames() const noexcept -> f_cnt_t { return m_frames; }
+
+protected:
+ SampleT* m_data = nullptr;
+ proc_ch_t m_channels = 0;
+ f_cnt_t m_frames = 0;
+};
+
+} // namespace detail
+
+
+/**
+ * Non-owning view for multi-channel interleaved audio data
+ *
+ * TODO C++23: Use std::mdspan?
+ */
+template
+class InterleavedBufferView : public detail::BufferViewData
+{
+ using Base = detail::BufferViewData;
+
+public:
+ using Base::Base;
+
+ //! Contruct const from mutable (static channel count)
+ template requires (std::is_const_v && channelCount != DynamicChannelCount)
+ constexpr InterleavedBufferView(InterleavedBufferView, channelCount> other) noexcept
+ : Base{other.data(), other.frames()}
+ {
+ }
+
+ //! Contruct const from mutable (dynamic channel count)
+ template requires (std::is_const_v && channelCount == DynamicChannelCount)
+ constexpr InterleavedBufferView(InterleavedBufferView, channelCount> other) noexcept
+ : Base{other.data(), other.channels(), other.frames()}
+ {
+ }
+
+ //! Construct dynamic channel count from static
+ template
+ requires (channelCount == DynamicChannelCount && otherChannels != DynamicChannelCount)
+ constexpr InterleavedBufferView(InterleavedBufferView other) noexcept
+ : Base{other.data(), otherChannels, other.frames()}
+ {
+ }
+
+ constexpr auto empty() const noexcept -> bool
+ {
+ return !this->m_data || this->channels() == 0 || this->m_frames == 0;
+ }
+
+ //! @return the frame at the given index
+ constexpr auto frame(f_cnt_t index) const noexcept
+ {
+ if constexpr (channelCount == DynamicChannelCount)
+ {
+ return std::span{framePtr(index), this->channels()};
+ }
+ else
+ {
+ return std::span{framePtr(index), this->channels()};
+ }
+ }
+
+ /**
+ * @return pointer to the frame at the given index.
+ * The size of the frame is `channels()`.
+ */
+ constexpr auto framePtr(f_cnt_t index) const noexcept -> SampleT*
+ {
+ assert(index < this->m_frames);
+ return this->m_data + index * this->channels();
+ }
+
+ /**
+ * @return pointer to the frame at the given index.
+ * The size of the frame is `channels()`.
+ */
+ constexpr auto operator[](f_cnt_t index) const noexcept -> SampleT*
+ {
+ return framePtr(index);
+ }
+};
+
+// Check that the std::span-like space optimization works
+static_assert(sizeof(InterleavedBufferView) > sizeof(InterleavedBufferView));
+static_assert(sizeof(InterleavedBufferView) == sizeof(void*) + sizeof(f_cnt_t));
+
+
+/**
+ * Non-owning view for multi-channel non-interleaved audio data
+ *
+ * The data type is `SampleT* const*` which is a 2D array accessed as data[channel][frame index]
+ * where each channel's buffer contains `frames()` frames.
+ *
+ * TODO C++23: Use std::mdspan?
+ */
+template
+class PlanarBufferView : public detail::BufferViewData
+{
+ using Base = detail::BufferViewData;
+
+public:
+ using Base::Base;
+
+ //! Contruct const from mutable (static channel count)
+ template requires (std::is_const_v && channelCount != DynamicChannelCount)
+ constexpr PlanarBufferView(PlanarBufferView, channelCount> other) noexcept
+ : Base{other.data(), other.frames()}
+ {
+ }
+
+ //! Contruct const from mutable (dynamic channel count)
+ template requires (std::is_const_v && channelCount == DynamicChannelCount)
+ constexpr PlanarBufferView(PlanarBufferView, channelCount> other) noexcept
+ : Base{other.data(), other.channels(), other.frames()}
+ {
+ }
+
+ //! Construct dynamic channel count from static
+ template
+ requires (channelCount == DynamicChannelCount && otherChannels != DynamicChannelCount)
+ constexpr PlanarBufferView(PlanarBufferView other) noexcept
+ : Base{other.data(), otherChannels, other.frames()}
+ {
+ }
+
+ constexpr auto empty() const noexcept -> bool
+ {
+ return !this->m_data || this->channels() == 0 || this->m_frames == 0;
+ }
+
+ //! @return the buffer of the given channel
+ constexpr auto buffer(proc_ch_t channel) const noexcept -> std::span
+ {
+ return {bufferPtr(channel), this->m_frames};
+ }
+
+ //! @return the buffer of the given channel
+ template requires (channelCount != DynamicChannelCount)
+ constexpr auto buffer() const noexcept -> std::span
+ {
+ return {bufferPtr(), this->m_frames};
+ }
+
+ /**
+ * @return pointer to the buffer of the given channel.
+ * The size of the buffer is `frames()`.
+ */
+ constexpr auto bufferPtr(proc_ch_t channel) const noexcept -> SampleT*
+ {
+ assert(channel < this->channels());
+ assert(this->m_data != nullptr);
+ return this->m_data[channel];
+ }
+
+ /**
+ * @return pointer to the buffer of the given channel.
+ * The size of the buffer is `frames()`.
+ */
+ template requires (channelCount != DynamicChannelCount)
+ constexpr auto bufferPtr() const noexcept -> SampleT*
+ {
+ static_assert(channel < channelCount);
+ assert(this->m_data != nullptr);
+ return this->m_data[channel];
+ }
+
+ /**
+ * @return pointer to the buffer of a given channel.
+ * The size of the buffer is `frames()`.
+ */
+ constexpr auto operator[](proc_ch_t channel) const noexcept -> SampleT*
+ {
+ return bufferPtr(channel);
+ }
+};
+
+// Check that the std::span-like space optimization works
+static_assert(sizeof(PlanarBufferView) > sizeof(PlanarBufferView));
+static_assert(sizeof(PlanarBufferView) == sizeof(void**) + sizeof(f_cnt_t));
+
+} // namespace lmms
+
+#endif // LMMS_AUDIO_BUFFER_VIEW_H
diff --git a/include/AudioDevice.h b/include/AudioDevice.h
index 228b1c1aa..0a649bbe0 100644
--- a/include/AudioDevice.h
+++ b/include/AudioDevice.h
@@ -28,7 +28,7 @@
#include
#include
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
class QThread;
diff --git a/include/AudioEngine.h b/include/AudioEngine.h
index 921fa1b34..04f08bb08 100644
--- a/include/AudioEngine.h
+++ b/include/AudioEngine.h
@@ -34,7 +34,7 @@
#include
#include "AudioDevice.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#include "SampleFrame.h"
#include "LocklessList.h"
#include "FifoBuffer.h"
@@ -50,7 +50,6 @@ class MidiClient;
class AudioBusHandle;
class AudioEngineWorkerThread;
-
constexpr fpp_t MINIMUM_BUFFER_SIZE = 32;
constexpr fpp_t DEFAULT_BUFFER_SIZE = 256;
constexpr fpp_t MAXIMUM_BUFFER_SIZE = 4096;
@@ -61,6 +60,8 @@ constexpr int BYTES_PER_FRAME = sizeof(SampleFrame);
constexpr float OUTPUT_SAMPLE_MULTIPLIER = 32767.0f;
+constexpr auto SUPPORTED_SAMPLERATES = std::array{44100, 48000, 88200, 96000, 192000};
+
class LMMS_EXPORT AudioEngine : public QObject
{
Q_OBJECT
diff --git a/include/AudioEngineProfiler.h b/include/AudioEngineProfiler.h
index b0d62a1dc..cee1ea0dd 100644
--- a/include/AudioEngineProfiler.h
+++ b/include/AudioEngineProfiler.h
@@ -29,7 +29,7 @@
#include
#include
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#include "MicroTimer.h"
namespace lmms
diff --git a/include/AudioJack.h b/include/AudioJack.h
index e13b4a5ef..84d85a649 100644
--- a/include/AudioJack.h
+++ b/include/AudioJack.h
@@ -53,11 +53,6 @@ namespace lmms
class MidiJack;
-namespace gui
-{
-class LcdSpinBox;
-}
-
class AudioJack : public QObject, public AudioDevice
{
@@ -82,13 +77,10 @@ public:
{
public:
setupWidget(QWidget* parent);
- ~setupWidget() override;
-
void saveSettings() override;
private:
QLineEdit* m_clientName;
- gui::LcdSpinBox* m_channels;
};
private slots:
@@ -96,6 +88,7 @@ private slots:
private:
bool initJackClient();
+ void resizeInputBuffer(jack_nframes_t nframes);
void startProcessing() override;
void stopProcessing() override;
@@ -116,7 +109,9 @@ private:
std::atomic m_midiClient;
std::vector m_outputPorts;
+ std::vector m_inputPorts;
jack_default_audio_sample_t** m_tempOutBufs;
+ std::vector m_inputFrameBuffer;
SampleFrame* m_outBuf;
f_cnt_t m_framesDoneInCurBuf;
diff --git a/include/AutomationClip.h b/include/AutomationClip.h
index 0b49978c7..abc713869 100644
--- a/include/AutomationClip.h
+++ b/include/AutomationClip.h
@@ -68,7 +68,6 @@ public:
using TimemapIterator = timeMap::const_iterator;
AutomationClip( AutomationTrack * _auto_track );
- AutomationClip( const AutomationClip & _clip_to_copy );
~AutomationClip() override = default;
bool addObject( AutomatableModel * _obj, bool _search_dup = true );
@@ -90,7 +89,7 @@ public:
void setTension( QString _new_tension );
TimePos timeMapLength() const;
- void updateLength();
+ void updateLength() override;
TimePos putValue(
const TimePos & time,
@@ -196,12 +195,22 @@ public:
static int quantization() { return s_quantization; }
static void setQuantization(int q) { s_quantization = q; }
+ AutomationClip* clone() override
+ {
+ return new AutomationClip(*this);
+ }
+
+ void clearObjects() { m_objects.clear(); }
+
public slots:
void clear();
void objectDestroyed( lmms::jo_id_t );
void flipY( int min, int max );
void flipY();
- void flipX( int length = -1 );
+ void flipX(int start = -1, int end = -1);
+
+protected:
+ AutomationClip( const AutomationClip & _clip_to_copy );
private:
void cleanObjects();
diff --git a/include/AutomationClipView.h b/include/AutomationClipView.h
index bdd2f0568..e55c44228 100644
--- a/include/AutomationClipView.h
+++ b/include/AutomationClipView.h
@@ -75,6 +75,8 @@ private:
QStaticText m_staticTextName;
void scaleTimemapToFit( float oldMin, float oldMax );
+
+ bool isResizableBeforeStart() override { return false; }
} ;
diff --git a/include/AutomationEditor.h b/include/AutomationEditor.h
index eb3d229a3..c7eaca8aa 100644
--- a/include/AutomationEditor.h
+++ b/include/AutomationEditor.h
@@ -37,7 +37,7 @@
#include "MidiClip.h"
#include "SampleClip.h"
#include "TimePos.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#include "SampleThumbnail.h"
class QPainter;
@@ -74,6 +74,7 @@ class AutomationEditor : public QWidget, public JournallingObject
Q_PROPERTY(QColor ghostNoteColor MEMBER m_ghostNoteColor)
Q_PROPERTY(QColor detuningNoteColor MEMBER m_detuningNoteColor)
Q_PROPERTY(QColor ghostSampleColor MEMBER m_ghostSampleColor)
+ Q_PROPERTY(QColor outOfBoundsShade MEMBER m_outOfBoundsShade)
public:
void setCurrentClip(AutomationClip * new_clip);
void setGhostMidiClip(MidiClip* newMidiClip);
@@ -291,6 +292,7 @@ private:
QColor m_ghostNoteColor;
QColor m_detuningNoteColor;
QColor m_ghostSampleColor;
+ QColor m_outOfBoundsShade;
SampleThumbnail m_sampleThumbnail;
diff --git a/include/BandLimitedWave.h b/include/BandLimitedWave.h
index c70b8f6eb..0c38413ef 100644
--- a/include/BandLimitedWave.h
+++ b/include/BandLimitedWave.h
@@ -31,7 +31,7 @@ class QString;
#include "lmms_export.h"
#include "interpolation.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#include "lmms_math.h"
#include "Engine.h"
#include "AudioEngine.h"
diff --git a/include/BasicFilters.h b/include/BasicFilters.h
index 51d617480..a0ab32871 100644
--- a/include/BasicFilters.h
+++ b/include/BasicFilters.h
@@ -36,7 +36,9 @@
#include
#include
-#include "lmms_basics.h"
+#include "lmms_constants.h"
+#include "LmmsTypes.h"
+
namespace lmms
{
@@ -207,7 +209,7 @@ public:
inline float update( float s, ch_cnt_t ch )
{
- if (std::abs(s) < 1.0e-10f && std::abs(m_z1[ch]) < 1.0e-10f) { return 0.0f; }
+ if (std::abs(s) < F_EPSILON && std::abs(m_z1[ch]) < F_EPSILON) { return 0.0f; }
return m_z1[ch] = s * m_a0 + m_z1[ch] * m_b1;
}
@@ -593,7 +595,7 @@ public:
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
+ if (std::abs(_in0) < F_EPSILON && std::abs(m_vflast[0][_chnl]) < F_EPSILON) { return 0.0f; } // performance hack - skip processing when the numbers get too small
const int os = m_type == FilterType::FastFormant ? 1 : 4; // no oversampling for fast formant
for( int o = 0; o < os; ++o )
diff --git a/include/BufferManager.h b/include/BufferManager.h
index 84602f121..0a39114ca 100644
--- a/include/BufferManager.h
+++ b/include/BufferManager.h
@@ -27,7 +27,7 @@
#define LMMS_BUFFER_MANAGER_H
#include "lmms_export.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms
{
diff --git a/include/CPULoadWidget.h b/include/CPULoadWidget.h
index bed10b05e..17a046e37 100644
--- a/include/CPULoadWidget.h
+++ b/include/CPULoadWidget.h
@@ -31,7 +31,7 @@
#include
#include
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms::gui
diff --git a/include/Clip.h b/include/Clip.h
index a520ad4e4..706b982c8 100644
--- a/include/Clip.h
+++ b/include/Clip.h
@@ -100,12 +100,28 @@ public:
* resized by clicking and dragging its edge.
*
*/
- inline void setAutoResize( const bool r )
+ inline void setResizable( const bool r )
+ {
+ m_resizable = r;
+ }
+
+ inline const bool getResizable() const
+ {
+ return m_resizable;
+ }
+
+ /*! \brief Set whether a clip has been resized yet by the user or the knife tool.
+ *
+ * If a clip has been resized previously, it will not automatically
+ * resize when editing it.
+ *
+ */
+ void setAutoResize(const bool r)
{
m_autoResize = r;
}
- inline const bool getAutoResize() const
+ bool getAutoResize() const
{
return m_autoResize;
}
@@ -115,6 +131,7 @@ public:
virtual void movePosition( const TimePos & pos );
virtual void changeLength( const TimePos & length );
+ virtual void updateLength() {};
virtual gui::ClipView * createView( gui::TrackView * tv ) = 0;
@@ -137,6 +154,12 @@ public:
// Will copy the state of a clip to another clip
static void copyStateTo( Clip *src, Clip *dst );
+ /**
+ * Creates a copy of this clip
+ * @return pointer to the new clip object
+ */
+ virtual Clip* clone() = 0;
+
public slots:
void toggleMute();
@@ -147,6 +170,8 @@ signals:
void destroyedClip();
void colorChanged();
+protected:
+ Clip(const Clip& other);
private:
Track * m_track;
@@ -158,7 +183,8 @@ private:
BoolModel m_mutedModel;
BoolModel m_soloModel;
- bool m_autoResize;
+ bool m_resizable = true;
+ bool m_autoResize = true;
bool m_selectViewOnCreate;
diff --git a/include/ClipView.h b/include/ClipView.h
index 14898db65..6e904b856 100644
--- a/include/ClipView.h
+++ b/include/ClipView.h
@@ -63,6 +63,7 @@ class ClipView : public selectableObject, public ModelView
Q_PROPERTY( QColor textShadowColor READ textShadowColor WRITE setTextShadowColor )
Q_PROPERTY( QColor patternClipBackground READ patternClipBackground WRITE setPatternClipBackground )
Q_PROPERTY( bool gradient READ gradient WRITE setGradient )
+ Q_PROPERTY(QColor markerColor READ markerColor WRITE setMarkerColor)
// We have to use a QSize here because using QPoint isn't supported.
// width -> x, height -> y
Q_PROPERTY( QSize mouseHotspotHand MEMBER m_mouseHotspotHand )
@@ -94,6 +95,7 @@ public:
QColor textBackgroundColor() const;
QColor textShadowColor() const;
QColor patternClipBackground() const;
+ QColor markerColor() const;
bool gradient() const;
void setMutedColor( const QColor & c );
void setMutedBackgroundColor( const QColor & c );
@@ -103,6 +105,7 @@ public:
void setTextShadowColor( const QColor & c );
void setPatternClipBackground(const QColor& c);
void setGradient( const bool & b );
+ void setMarkerColor(const QColor& c);
// access needsUpdate member variable
bool needsUpdate();
@@ -121,10 +124,8 @@ public:
// some metadata to be written to the clipboard.
static void remove( QVector clipvs );
static void toggleMute( QVector clipvs );
- static void mergeClips(QVector clipvs);
- // Returns true if selection can be merged and false if not
- static bool canMergeSelection(QVector clipvs);
+ void toggleSelectedAutoResize();
QColor getColorForDisplay( QColor );
@@ -147,8 +148,7 @@ protected:
Cut,
Copy,
Paste,
- Mute,
- Merge
+ Mute
};
TrackView * m_trackView;
@@ -176,7 +176,7 @@ protected:
}
bool unquantizedModHeld( QMouseEvent * me );
- TimePos quantizeSplitPos( TimePos, bool shiftMode );
+ TimePos quantizeSplitPos(TimePos);
float pixelsPerBar();
@@ -224,6 +224,7 @@ private:
QColor m_textShadowColor;
QColor m_patternClipBackground;
bool m_gradient;
+ QColor m_markerColor;
QSize m_mouseHotspotHand; // QSize must be used because QPoint
QSize m_mouseHotspotKnife; // isn't supported by property system
QCursor m_cursorHand;
@@ -244,8 +245,24 @@ private:
TimePos draggedClipPos( QMouseEvent * me );
int knifeMarkerPos( QMouseEvent * me );
void setColor(const std::optional& color);
- //! Return true iff the clip could be split. Currently only implemented for samples
- virtual bool splitClip( const TimePos pos ){ return false; };
+
+ //! Returns whether the user can left-resize this clip so that the start of the clip bounds is before the start of the clip content.
+ virtual bool isResizableBeforeStart() { return true; };
+ /**
+ * Split this Clip into two clips
+ * @param pos the position of the split, relative to the start of the clip
+ * @return true if the clip could be split
+ */
+ bool splitClip(const TimePos pos);
+ /**
+ * Destructively split this Clip into two clips. If the clip type does not implement this feature, it will default to normal splitting.
+ * @param pos the position of the split, relative to the start of the clip
+ * @return true if the clip could be split
+ */
+ virtual bool destructiveSplitClip(const TimePos pos)
+ {
+ return splitClip(pos);
+ }
void updateCursor(QMouseEvent * me);
} ;
diff --git a/include/ComboBoxModel.h b/include/ComboBoxModel.h
index 7037495ea..904629ee2 100644
--- a/include/ComboBoxModel.h
+++ b/include/ComboBoxModel.h
@@ -45,6 +45,7 @@ public:
bool isDefaultConstructed = false ) :
IntModel( 0, 0, 0, parent, displayName, isDefaultConstructed )
{
+ setJournalling(false);
}
void addItem( QString item, std::unique_ptr loader = nullptr );
diff --git a/include/ConfigManager.h b/include/ConfigManager.h
index 3cba834e1..bf98f5999 100644
--- a/include/ConfigManager.h
+++ b/include/ConfigManager.h
@@ -214,6 +214,8 @@ public:
return m_recentlyOpenedProjects;
}
+ const QStringList& favoriteItems() { return m_favoriteItems; }
+
QString localeDir() const
{
return m_dataDir + LOCALE_PATH;
@@ -240,6 +242,10 @@ public:
void addRecentlyOpenedProject(const QString & _file);
+ void addFavoriteItem(const QString& item);
+ void removeFavoriteItem(const QString& item);
+ bool isFavoriteItem(const QString& item);
+
QString value(const QString& cls, const QString& attribute, const QString& defaultVal = "") const;
void setValue(const QString & cls, const QString & attribute,
@@ -265,6 +271,7 @@ public:
signals:
void valueChanged( QString cls, QString attribute, QString value );
+ void favoritesChanged();
private:
static ConfigManager * s_instanceOfMe;
@@ -299,6 +306,7 @@ private:
QString m_version;
unsigned int m_configVersion;
QStringList m_recentlyOpenedProjects;
+ QStringList m_favoriteItems;
using stringPairVector = std::vector>;
using settingsMap = QMap;
diff --git a/include/ControllerRackView.h b/include/ControllerRackView.h
index 93d1e8438..436618303 100644
--- a/include/ControllerRackView.h
+++ b/include/ControllerRackView.h
@@ -29,7 +29,6 @@
#include
#include "SerializingObject.h"
-#include "lmms_basics.h"
class QPushButton;
diff --git a/include/Controls.h b/include/Controls.h
index 5ed19027e..243f77690 100644
--- a/include/Controls.h
+++ b/include/Controls.h
@@ -80,7 +80,7 @@ public:
FloatModel* model() override;
AutomatableModelView* modelView() override;
- KnobControl(QWidget* parent = nullptr);
+ KnobControl(const QString& text, QWidget* parent = nullptr);
~KnobControl() override = default;
};
diff --git a/include/CustomTextKnob.h b/include/CustomTextKnob.h
index 31a58415e..34434f3ae 100644
--- a/include/CustomTextKnob.h
+++ b/include/CustomTextKnob.h
@@ -36,9 +36,7 @@ class LMMS_EXPORT CustomTextKnob : public Knob
protected:
inline void setHintText( const QString & _txt_before, const QString & _txt_after ) {} // inaccessible
public:
- 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
+ CustomTextKnob( KnobType _knob_num, const QString& label, QWidget * _parent = nullptr, const QString & _name = QString(), const QString & _value_text = QString() );
CustomTextKnob( const Knob& other ) = delete;
diff --git a/include/Delay.h b/include/Delay.h
index 8ead1c37b..199c592ce 100644
--- a/include/Delay.h
+++ b/include/Delay.h
@@ -28,7 +28,7 @@
#include
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms
{
diff --git a/include/DetuningHelper.h b/include/DetuningHelper.h
index da8eb5983..b76708082 100644
--- a/include/DetuningHelper.h
+++ b/include/DetuningHelper.h
@@ -39,6 +39,10 @@ public:
InlineAutomation()
{
}
+ DetuningHelper(const DetuningHelper& _copy) :
+ InlineAutomation(_copy)
+ {
+ }
~DetuningHelper() override = default;
diff --git a/include/DrumSynth.h b/include/DrumSynth.h
index 3b418abd6..2894817fe 100644
--- a/include/DrumSynth.h
+++ b/include/DrumSynth.h
@@ -28,7 +28,7 @@
#include
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
class QString;
diff --git a/include/DspEffectLibrary.h b/include/DspEffectLibrary.h
index 656d5b1dd..8b3060334 100644
--- a/include/DspEffectLibrary.h
+++ b/include/DspEffectLibrary.h
@@ -28,7 +28,7 @@
#include
#include "lmms_math.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#include "SampleFrame.h"
namespace lmms::DspEffectLibrary
diff --git a/include/Editor.h b/include/Editor.h
index a5b667166..46caab538 100644
--- a/include/Editor.h
+++ b/include/Editor.h
@@ -57,6 +57,13 @@ protected:
DropToolBar * addDropToolBar(QWidget * parent, Qt::ToolBarArea whereToAdd, QString const & windowTitle);
void closeEvent(QCloseEvent * event) override;
+ void keyPressEvent(QKeyEvent *ke) override;
+public slots:
+ //! Called by pressing the space key. Plays or stops.
+ void togglePlayStop();
+ //! Called by pressing shift+space. Toggles pause state.
+ void togglePause();
+
protected slots:
virtual void play() {}
virtual void record() {}
@@ -65,12 +72,6 @@ protected slots:
virtual void stop() {}
private slots:
- /// Called by pressing the space key. Plays or stops.
- void togglePlayStop();
-
- /// Called by pressing shift+space. Toggles pause state.
- void togglePause();
-
void toggleMaximize();
signals:
diff --git a/include/EffectRackView.h b/include/EffectRackView.h
index fec627a56..f166612e2 100644
--- a/include/EffectRackView.h
+++ b/include/EffectRackView.h
@@ -30,7 +30,6 @@
#include "EffectChain.h"
#include "ModelView.h"
-#include "lmms_basics.h"
class QScrollArea;
class QVBoxLayout;
diff --git a/include/Engine.h b/include/Engine.h
index 7e19e2e84..cc37ecee8 100644
--- a/include/Engine.h
+++ b/include/Engine.h
@@ -30,7 +30,7 @@
#include "lmmsconfig.h"
#include "lmms_export.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms
{
diff --git a/include/EnvelopeAndLfoParameters.h b/include/EnvelopeAndLfoParameters.h
index 50bfdf787..34cbae5ec 100644
--- a/include/EnvelopeAndLfoParameters.h
+++ b/include/EnvelopeAndLfoParameters.h
@@ -32,7 +32,7 @@
#include "AutomatableModel.h"
#include "SampleBuffer.h"
#include "TempoSyncKnobModel.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms
{
diff --git a/include/Fader.h b/include/Fader.h
index 9d6e21590..27e5e07a1 100644
--- a/include/Fader.h
+++ b/include/Fader.h
@@ -171,6 +171,7 @@ private:
QElapsedTimer m_lastPeakTimer_R;
QPixmap m_knob {embed::getIconPixmap("fader_knob")};
+ QSize m_knobSize;
/**
* @brief Stores the offset to the knob center when the user drags the fader knob
diff --git a/include/FileBrowser.h b/include/FileBrowser.h
index 6c10ee763..71a878fc1 100644
--- a/include/FileBrowser.h
+++ b/include/FileBrowser.h
@@ -61,19 +61,22 @@ class FileBrowser : public SideBarWidget
{
Q_OBJECT
public:
+ enum class Type
+ {
+ Normal,
+ Favorites
+ };
+
/**
- Create a file browser side bar widget
- @param directories '*'-separated list of directories to search for.
- If a directory of factory files should be in the list it
- must be the last one (for the factory files delimiter to work)
- @param filter Filter as used in QDir::match
- @param recurse *to be documented*
- */
- FileBrowser( const QString & directories, const QString & filter,
- const QString & title, const QPixmap & pm,
- QWidget * parent, bool dirs_as_items = false,
- const QString& userDir = "",
- const QString& factoryDir = "");
+ Create a file browser side bar widget
+ @param directories '*'-separated list of directories to search for.
+ If a directory of factory files should be in the list it
+ must be the last one (for the factory files delimiter to work)
+ @param filter Filter as used in QDir::match
+ @param recurse *to be documented*
+ */
+ FileBrowser(Type type, const QString& directories, const QString& filter, const QString& title, const QPixmap& pm,
+ QWidget* parent, bool dirs_as_items = false, const QString& userDir = "", const QString& factoryDir = "");
~FileBrowser() override = default;
@@ -90,6 +93,7 @@ public:
};
return s_excludedPaths;
}
+
static QDir::Filters dirFilters() { return QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden; }
static QDir::SortFlags sortFlags() { return QDir::LocaleAware | QDir::DirsFirst | QDir::Name | QDir::IgnoreCase; }
@@ -101,7 +105,7 @@ private slots:
private:
void keyPressEvent( QKeyEvent * ke ) override;
- void addItems( const QString & path );
+ void addItems(const QString & path);
void saveDirectoriesStates();
void restoreDirectoriesStates();
@@ -117,6 +121,7 @@ private:
FileBrowserTreeWidget * m_searchTreeWidget;
QLineEdit * m_filterEdit;
+ Type m_type;
std::shared_ptr m_currentSearch;
QProgressBar* m_searchIndicator = nullptr;
@@ -216,8 +221,7 @@ public:
{
path += QDir::separator();
}
- return( QDir::cleanPath( path + text( 0 ) ) +
- QDir::separator() );
+ return QDir::cleanPath(path + text(0));
}
inline void addDirectory( const QString & dir )
diff --git a/include/FileRevealer.h b/include/FileRevealer.h
index feb6d1223..46c52cd8c 100644
--- a/include/FileRevealer.h
+++ b/include/FileRevealer.h
@@ -22,12 +22,12 @@
*
*/
-#ifndef LMMS_FILE_REVEALER_H
-#define LMMS_FILE_REVEALER_H
+#ifndef LMMS_GUI_FILE_REVEALER_H
+#define LMMS_GUI_FILE_REVEALER_H
#include
-namespace lmms {
+namespace lmms::gui {
/**
* @class FileRevealer
@@ -73,5 +73,6 @@ protected:
static bool supportsArg(const QString& command, const QString& arg);
};
-} // namespace lmms
-#endif // LMMS_FILE_REVEALER_H
+} // namespace lmms::gui
+
+#endif // LMMS_GUI_FILE_REVEALER_H
diff --git a/include/FontHelper.h b/include/FontHelper.h
index ccef24775..c1c0ee665 100644
--- a/include/FontHelper.h
+++ b/include/FontHelper.h
@@ -22,8 +22,8 @@
*
*/
-#ifndef LMMS_FONT_HELPER_H
-#define LMMS_FONT_HELPER_H
+#ifndef LMMS_GUI_FONT_HELPER_H
+#define LMMS_GUI_FONT_HELPER_H
#include
#include
@@ -44,4 +44,4 @@ inline QFont adjustedToPixelSize(QFont font, int size)
} // namespace lmms::gui
-#endif // LMMS_FONT_HELPER_H
+#endif // LMMS_GUI_FONT_HELPER_H
diff --git a/include/Graph.h b/include/Graph.h
index cc87b913e..4cb3af512 100644
--- a/include/Graph.h
+++ b/include/Graph.h
@@ -32,7 +32,7 @@
#include "Model.h"
#include "ModelView.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms
{
diff --git a/include/GuiApplication.h b/include/GuiApplication.h
index 3a0851499..02fb6ed67 100644
--- a/include/GuiApplication.h
+++ b/include/GuiApplication.h
@@ -26,6 +26,7 @@
#define LMMS_GUI_GUI_APPLICATION_H
#include
+#include
#include "lmms_export.h"
#include "lmmsconfig.h"
@@ -53,10 +54,14 @@ public:
~GuiApplication() override;
static GuiApplication* instance();
+ static void sigintHandler(int);
+ static bool isWayland();
#ifdef LMMS_BUILD_WIN32
static QFont getWin32SystemFont();
#endif
+ void createSocketNotifier();
+
MainWindow* mainWindow() { return m_mainWindow; }
MixerView* mixerView() { return m_mixerView; }
SongEditorWindow* songEditor() { return m_songEditor; }
@@ -67,11 +72,15 @@ public:
AutomationEditorWindow* automationEditor() { return m_automationEditor; }
ControllerRackView* getControllerRackView() { return m_controllerRackView; }
+ //! File descriptors for unix socketpair, used to receive SIGINT
+ static inline int s_sigintFd[2];
+
public slots:
void displayInitProgress(const QString &msg);
private slots:
void childDestroyed(QObject *obj);
+ void sigintOccurred();
private:
static GuiApplication* s_instance;
@@ -86,6 +95,7 @@ private:
MicrotunerConfig* m_microtunerConfig;
ControllerRackView* m_controllerRackView;
QLabel* m_loadingProgressLabel;
+ QSocketNotifier* m_sigintNotifier;
};
// Short-hand function
diff --git a/include/InlineAutomation.h b/include/InlineAutomation.h
index 3e27e137b..32241d451 100644
--- a/include/InlineAutomation.h
+++ b/include/InlineAutomation.h
@@ -27,27 +27,28 @@
#include "AutomationNode.h"
#include "AutomationClip.h"
-#include "shared_object.h"
namespace lmms
{
-class InlineAutomation : public FloatModel, public sharedObject
+class InlineAutomation : public FloatModel
{
public:
InlineAutomation() :
- FloatModel(),
- sharedObject(),
- m_autoClip( nullptr )
+ FloatModel()
{
}
+ InlineAutomation(const InlineAutomation& _copy) :
+ FloatModel(_copy.value(), _copy.minValue(), _copy.maxValue(), _copy.step()),
+ m_autoClip(_copy.m_autoClip->clone())
+ {
+ m_autoClip->clearObjects();
+ m_autoClip->addObject(this);
+ }
+
~InlineAutomation() override
{
- if( m_autoClip )
- {
- delete m_autoClip;
- }
}
virtual float defaultValue() const = 0;
@@ -81,10 +82,10 @@ public:
{
if( m_autoClip == nullptr )
{
- m_autoClip = new AutomationClip( nullptr );
+ m_autoClip = std::make_unique(nullptr);
m_autoClip->addObject( this );
}
- return m_autoClip;
+ return m_autoClip.get();
}
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
@@ -92,7 +93,7 @@ public:
private:
- AutomationClip * m_autoClip;
+ std::unique_ptr m_autoClip;
} ;
diff --git a/include/Instrument.h b/include/Instrument.h
index 3f701f12e..21353f725 100644
--- a/include/Instrument.h
+++ b/include/Instrument.h
@@ -30,7 +30,7 @@
#include "Flags.h"
#include "lmms_export.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#include "Plugin.h"
#include "TimePos.h"
diff --git a/include/InstrumentTrackWindow.h b/include/InstrumentTrackWindow.h
index 5d26ba9a2..6f0245875 100644
--- a/include/InstrumentTrackWindow.h
+++ b/include/InstrumentTrackWindow.h
@@ -27,8 +27,8 @@
#include
+#include "AutomatableButton.h"
#include "ModelView.h"
-#include "PixmapButton.h"
#include "SerializingObject.h"
#include "PluginView.h"
@@ -148,8 +148,8 @@ private:
Knob * m_volumeKnob;
Knob * m_panningKnob;
Knob * m_pitchKnob;
- PixmapButton *m_muteBtn;
- PixmapButton *m_soloBtn;
+ AutomatableButton* m_muteBtn;
+ AutomatableButton* m_soloBtn;
QLabel * m_pitchLabel;
LcdSpinBox* m_pitchRangeSpinBox;
QLabel * m_pitchRangeLabel;
diff --git a/include/JournallingObject.h b/include/JournallingObject.h
index f3e134f34..bc6a89076 100644
--- a/include/JournallingObject.h
+++ b/include/JournallingObject.h
@@ -27,7 +27,7 @@
#include
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#include "SerializingObject.h"
namespace lmms
diff --git a/include/Knob.h b/include/Knob.h
index 3c3339a6f..5ec8fd70f 100644
--- a/include/Knob.h
+++ b/include/Knob.h
@@ -77,11 +77,65 @@ class LMMS_EXPORT Knob : public FloatModelEditorBase
void onKnobNumUpdated(); //!< to be called when you updated @a m_knobNum
public:
+ /**
+ * @brief Determines how the label of the knob is rendered.
+ *
+ * Labels can be rendered using the font that is set for the knob or using a
+ * font with a fixed size which is determined by SMALL_FONT_SIZE.
+ */
+ enum class LabelRendering
+ {
+ /**
+ * @brief Renders the label using the font that is set for the widget.
+ *
+ * The space that's needed for the label is determined using the font metrics of the knob's font.
+ */
+ WidgetFont,
+
+ /**
+ * @brief Renders the labels in legacy mode. This uses a fixed font size and does not adhere
+ * to the font size that's set for the widget's font.
+ *
+ * @deprecated Do not use this mode in new code as it is considered deprecated and might be removed in the future.
+ */
+ LegacyFixedFontSize
+ };
+
+ /**
+ * @brief Construct a Knob with the given style and no label.
+ *
+ * @param _knob_num Style of the knob
+ * @param _parent Parent widget
+ * @param _name Object name of the widget
+ */
Knob( KnobType _knob_num, QWidget * _parent = nullptr, const QString & _name = QString() );
+
+ /**
+ * @brief Construct a Knob with the given style and label text.
+ *
+ * @param knobNum Style of the knob
+ * @param labelText Text for the label
+ * @param parent Parent widget
+ * @param labelRendering Determines if the label uses the widget font or a font with a fixed size of 12 pixels (LegacyFixedFontSize). The default is to use the widget font.
+ * @param name Object name of the widget
+ */
+ Knob(KnobType knobNum, const QString& labelText, QWidget* parent = nullptr, LabelRendering labelRendering = LabelRendering::WidgetFont, const QString& name = QString());
+
+ /**
+ * @brief Constructs a knob with a label font in the pixel size.
+ *
+ * @param knobNum Style of the knob
+ * @param labelText Text for the label
+ * @param labelPixelSize Pixel size for the label
+ * @param parent Parent widget
+ * @param name Object name of the widget
+ */
+ Knob(KnobType knobNum, const QString& labelText, int labelPixelSize, QWidget* parent, const QString& name = QString());
+
Knob( QWidget * _parent = nullptr, const QString & _name = QString() ); //!< default ctor
+
Knob( const Knob& other ) = delete;
- void setLabel( const QString & txt );
void setHtmlLabel( const QString &htmltxt );
void setTotalAngle( float angle );
@@ -113,15 +167,44 @@ public:
protected:
- void paintEvent( QPaintEvent * _me ) override;
+ void setLabel(const QString& txt);
+
+ void paintEvent(QPaintEvent*) override;
void changeEvent(QEvent * ev) override;
+ /*!
+ * Affects how the label of the knob is rendered.
+ *
+ * The default mode returns false. The height of the label text is taken into account when a new fixed
+ * size is computed for the Knob. When the label text is painted the descent of the font is used to
+ * compute the base line. The default mode returns false.
+ *
+ * Enabling fixed font size rendering mode leads to the following behavior:
+ * * The height of the label is not taken into account when the new fixed height of the Knob is computed.
+ * Instead a fixed size of 10 is added for the label.
+ * * When the knob is painted the baseline of the font is always set to 2 pixels away from the lower side
+ * of the Knob's rectangle.
+ * * The label is always rendered with a size of SMALL_FONT_SIZE.
+ */
+ bool fixedFontSizeLabelRendering() const { return m_fixedFontSizeLabelRendering; }
+
+ /*!
+ * Set the button to legacy rendering mode which uses a fixed font size and that does not take the size
+ * of the widget's font into account.
+ *
+ * This can be thought of as a legacy mode which reinstates the old behavior of the knob.
+ *
+ * @see fixedFontSizeLabelRendering().
+ */
+ void setFixedFontSizeLabelRendering();
+
private:
QLineF calculateLine( const QPointF & _mid, float _radius,
float _innerRadius = 1) const;
void drawKnob( QPainter * _p );
+ void drawLabel(QPainter& p);
bool updateAngle();
int angleFromValue( float value, float minValue, float maxValue, float totalAngle ) const
@@ -129,7 +212,10 @@ private:
return static_cast( ( value - 0.5 * ( minValue + maxValue ) ) / ( maxValue - minValue ) * m_totalAngle ) % 360;
}
+ void updateFixedSize();
+
QString m_label;
+ bool m_fixedFontSizeLabelRendering = false;
bool m_isHtmlLabel;
QTextDocument* m_tdRenderer;
diff --git a/include/LadspaManager.h b/include/LadspaManager.h
index 1a3360231..0d2defafd 100644
--- a/include/LadspaManager.h
+++ b/include/LadspaManager.h
@@ -36,7 +36,7 @@
#include "lmms_export.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms
diff --git a/include/LfoController.h b/include/LfoController.h
index 01b4b1862..e884cd5e4 100644
--- a/include/LfoController.h
+++ b/include/LfoController.h
@@ -31,8 +31,8 @@
#include "AutomatableModel.h"
#include "Controller.h"
#include "ControllerDialog.h"
+#include "SampleBuffer.h"
#include "TempoSyncKnobModel.h"
-#include "Oscillator.h"
namespace lmms
{
diff --git a/include/debug.h b/include/LmmsCommonMacros.h
similarity index 64%
rename from include/debug.h
rename to include/LmmsCommonMacros.h
index 7cf51acaa..9840240f9 100644
--- a/include/debug.h
+++ b/include/LmmsCommonMacros.h
@@ -1,8 +1,8 @@
/*
- * debug.h - header file to be included for debugging purposes
- *
- * Copyright (c) 2004-2008 Tobias Doerffel
+ * LmmsCommonMacros.h - defines some common macros used in the codebase
*
+ * Copyright (c) 2025 Roshan M R (Ross Maxx)
+ *
* This file is part of LMMS - https://lmms.io
*
* This program is free software; you can redistribute it and/or
@@ -22,20 +22,15 @@
*
*/
-#ifndef LMMS_DEBUG_H
-#define LMMS_DEBUG_H
+#ifndef LMMS_COMMON_MACROS_H
+#define LMMS_COMMON_MACROS_H
-#include "lmmsconfig.h"
+namespace lmms
+{
-// Define standard macro NDEBUG when building without debug flag to make sure asserts become no-ops.
-#ifndef LMMS_DEBUG
-#ifndef NDEBUG
- #define NDEBUG
-#endif
-#endif // LMMS_DEBUG
+#define LMMS_STRINGIFY(s) LMMS_STR(s) // a macro used to stringify the plugin name
+#define LMMS_STR(PN) #PN
-#include
-#include
+} // namespace lmms
-
-#endif // LMMS_DEBUG_H
+#endif // LMMS_COMMON_MACROS_H
diff --git a/include/lmms_basics.h b/include/LmmsTypes.h
similarity index 50%
rename from include/lmms_basics.h
rename to include/LmmsTypes.h
index ea9371603..c348a85bf 100644
--- a/include/lmms_basics.h
+++ b/include/LmmsTypes.h
@@ -1,5 +1,5 @@
/*
- * lmms_basics.h - typedefs for common types that are used in the whole app
+ * LmmsTypes.h - typedefs for common types that are used in the whole app
*
* Copyright (c) 2004-2009 Tobias Doerffel
*
@@ -26,48 +26,31 @@
#define LMMS_TYPES_H
#include
-
-#include "lmmsconfig.h"
-
#include
-
namespace lmms
{
-using bar_t = int32_t;
-using tick_t = int32_t;
-using volume_t = uint8_t;
-using panning_t = int8_t;
+using bar_t = std::int32_t;
+using tick_t = std::int32_t;
+using volume_t = std::uint8_t;
+using panning_t = std::int8_t;
-using sample_t = float; // standard sample-type
-using int_sample_t = int16_t; // 16-bit-int-sample
+using sample_t = float; // standard sample-type
+using int_sample_t = std::int16_t; // 16-bit-int-sample
-using sample_rate_t = uint32_t; // sample-rate
-using fpp_t = size_t; // frames per period (0-16384)
-using f_cnt_t = size_t; // standard frame-count
-using ch_cnt_t = uint8_t; // channel-count (0-DEFAULT_CHANNELS)
-using bpm_t = uint16_t; // tempo (MIN_BPM to MAX_BPM)
-using bitrate_t = uint16_t; // bitrate in kbps
-using mix_ch_t = uint16_t; // Mixer-channel (0 to MAX_CHANNEL)
+using sample_rate_t = std::uint32_t; // sample-rate
+using fpp_t = std::size_t; // frames per period (0-16384)
+using f_cnt_t = std::size_t; // standard frame-count
+using ch_cnt_t = std::uint8_t; // channel-count (0-DEFAULT_CHANNELS)
+using bpm_t = std::uint16_t; // tempo (MIN_BPM to MAX_BPM)
+using bitrate_t = std::uint16_t; // bitrate in kbps
+using mix_ch_t = std::uint16_t; // Mixer-channel (0 to MAX_CHANNEL)
+using track_ch_t = std::uint16_t; // track channel index/count (0-256)
+using proc_ch_t = std::uint16_t; // audio processor channel index/count
-using jo_id_t = uint32_t; // (unique) ID of a journalling object
-
-
-constexpr ch_cnt_t DEFAULT_CHANNELS = 2;
-
-constexpr char LADSPA_PATH_SEPERATOR =
-#ifdef LMMS_BUILD_WIN32
-';';
-#else
-':';
-#endif
-
-
-
-#define LMMS_STRINGIFY(s) LMMS_STR(s)
-#define LMMS_STR(PN) #PN
+using jo_id_t = std::uint32_t; // (unique) ID of a journalling object
} // namespace lmms
diff --git a/include/LocklessRingBuffer.h b/include/LocklessRingBuffer.h
index ec3f4fc52..45dab858f 100644
--- a/include/LocklessRingBuffer.h
+++ b/include/LocklessRingBuffer.h
@@ -30,7 +30,7 @@
#include
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms
{
diff --git a/include/Lv2Ports.h b/include/Lv2Ports.h
index 1b2986938..8bbf7b4d2 100644
--- a/include/Lv2Ports.h
+++ b/include/Lv2Ports.h
@@ -34,7 +34,7 @@
#include
#include "Flags.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#include "PluginIssue.h"
diff --git a/include/MainWindow.h b/include/MainWindow.h
index 1330de8c5..d2efd4ac0 100644
--- a/include/MainWindow.h
+++ b/include/MainWindow.h
@@ -46,6 +46,7 @@ class ConfigManager;
namespace gui
{
+class FileBrowser;
class PluginView;
class SubWindow;
class ToolButton;
diff --git a/include/Midi.h b/include/Midi.h
index 21db021b3..d68dda318 100644
--- a/include/Midi.h
+++ b/include/Midi.h
@@ -25,8 +25,6 @@
#ifndef LMMS_MIDI_H
#define LMMS_MIDI_H
-#include "lmms_basics.h"
-
namespace lmms
{
diff --git a/include/MidiClip.h b/include/MidiClip.h
index f3150ba6f..076ec93b0 100644
--- a/include/MidiClip.h
+++ b/include/MidiClip.h
@@ -53,12 +53,11 @@ public:
} ;
MidiClip( InstrumentTrack* instrumentTrack );
- MidiClip( const MidiClip& other );
~MidiClip() override;
void init();
- void updateLength();
+ void updateLength() override;
// note management
Note * addNote( const Note & _new_note, const bool _quant_pos = true );
@@ -79,6 +78,9 @@ public:
Note * addStepNote( int step );
void setStep( int step, bool enabled );
+ //! Horizontally flip the positions of the given notes.
+ void reverseNotes(const NoteVector& notes);
+
// Split the list of notes on the given position
void splitNotes(const NoteVector& notes, TimePos pos);
@@ -114,6 +116,11 @@ public:
gui::ClipView * createView( gui::TrackView * _tv ) override;
+ MidiClip* clone() override
+ {
+ return new MidiClip(*this);
+ }
+
using Model::dataChanged;
@@ -124,6 +131,7 @@ public slots:
void clear();
protected:
+ MidiClip( const MidiClip& other );
void updatePatternTrack();
protected slots:
diff --git a/include/MidiClipView.h b/include/MidiClipView.h
index 4285bf9da..9f1894755 100644
--- a/include/MidiClipView.h
+++ b/include/MidiClipView.h
@@ -63,6 +63,11 @@ public:
QColor const & getMutedNoteBorderColor() const { return m_mutedNoteBorderColor; }
void setMutedNoteBorderColor(QColor const & color) { m_mutedNoteBorderColor = color; }
+ // Returns true if selection can be merged and false if not
+ static bool canMergeSelection(QVector clipvs);
+ static void mergeClips(QVector clipvs);
+ static void bulkClearNotesOutOfBounds(QVector clipvs);
+
public slots:
lmms::MidiClip* getMidiClip();
void update() override;
@@ -76,6 +81,7 @@ protected slots:
void resetName();
void changeName();
void transposeSelection();
+ void clearNotesOutOfBounds();
protected:
@@ -103,6 +109,10 @@ private:
QStaticText m_staticTextName;
bool m_legacySEPattern;
+
+ bool isResizableBeforeStart() override { return false; }
+
+ bool destructiveSplitClip(const TimePos pos) override;
} ;
diff --git a/include/MixHelpers.h b/include/MixHelpers.h
index a55ad6058..3b0ecf968 100644
--- a/include/MixHelpers.h
+++ b/include/MixHelpers.h
@@ -25,7 +25,7 @@
#ifndef LMMS_MIX_HELPERS_H
#define LMMS_MIX_HELPERS_H
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms
{
diff --git a/include/MixerChannelView.h b/include/MixerChannelView.h
index 3d5f4ffb6..ed0d4f1ff 100644
--- a/include/MixerChannelView.h
+++ b/include/MixerChannelView.h
@@ -61,7 +61,7 @@ public:
void contextMenuEvent(QContextMenuEvent*) override;
void mousePressEvent(QMouseEvent*) override;
void mouseDoubleClickEvent(QMouseEvent*) override;
- bool eventFilter(QObject* dist, QEvent* event) override;
+ void keyPressEvent(QKeyEvent* ke) override;
void reset();
int channelIndex() const { return m_channelIndex; }
@@ -115,8 +115,8 @@ private:
QLineEdit* m_renameLineEdit;
QGraphicsView* m_renameLineEditView;
QLabel* m_sendArrow;
- PixmapButton* m_muteButton;
- PixmapButton* m_soloButton;
+ AutomatableButton* m_muteButton;
+ AutomatableButton* m_soloButton;
PeakIndicator* m_peakIndicator = nullptr;
Fader* m_fader;
EffectRackView* m_effectRackView;
diff --git a/include/Note.h b/include/Note.h
index 08cbce3db..7f81f7d13 100644
--- a/include/Note.h
+++ b/include/Note.h
@@ -26,6 +26,7 @@
#ifndef LMMS_NOTE_H
#define LMMS_NOTE_H
+#include
#include
#include
@@ -103,10 +104,15 @@ public:
int key = DefaultKey,
volume_t volume = DefaultVolume,
panning_t panning = DefaultPanning,
- DetuningHelper * detuning = nullptr );
+ std::shared_ptr detuning = nullptr);
Note( const Note & note );
~Note() override;
+ Note& operator=(const Note& note);
+
+ //! Performs a deep copy and returns an owning raw pointer
+ Note* clone() const;
+
// Note types
enum class Type
{
@@ -234,10 +240,8 @@ public:
static TimePos quantized( const TimePos & m, const int qGrid );
- DetuningHelper * detuning() const
- {
- return m_detuning;
- }
+ const std::shared_ptr& detuning() const { return m_detuning; }
+
bool hasDetuningInfo() const;
bool withinRange(int tickStart, int tickEnd) const;
@@ -262,7 +266,7 @@ private:
panning_t m_panning;
TimePos m_length;
TimePos m_pos;
- DetuningHelper * m_detuning;
+ std::shared_ptr m_detuning;
Type m_type = Type::Regular;
};
diff --git a/include/Oscillator.h b/include/Oscillator.h
index 13d8264be..84e9264c9 100644
--- a/include/Oscillator.h
+++ b/include/Oscillator.h
@@ -34,7 +34,6 @@
#include "Engine.h"
#include "lmms_math.h"
-#include "lmmsconfig.h"
#include "AudioEngine.h"
#include "OscillatorConstants.h"
#include "SampleBuffer.h"
diff --git a/include/OscillatorConstants.h b/include/OscillatorConstants.h
index 85ae38fe8..5aaab6f7a 100644
--- a/include/OscillatorConstants.h
+++ b/include/OscillatorConstants.h
@@ -28,7 +28,7 @@
#include
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms::OscillatorConstants
{
diff --git a/include/Oscilloscope.h b/include/Oscilloscope.h
index 1e3c52b1e..8675cea33 100644
--- a/include/Oscilloscope.h
+++ b/include/Oscilloscope.h
@@ -28,7 +28,7 @@
#include
#include
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms
{
diff --git a/include/OutputSettings.h b/include/OutputSettings.h
index 8a7ebc993..283826543 100644
--- a/include/OutputSettings.h
+++ b/include/OutputSettings.h
@@ -26,7 +26,7 @@
#ifndef LMMS_OUTPUT_SETTINGS_H
#define LMMS_OUTPUT_SETTINGS_H
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms
{
diff --git a/include/PathUtil.h b/include/PathUtil.h
index 9b410d014..9bc71c1a1 100644
--- a/include/PathUtil.h
+++ b/include/PathUtil.h
@@ -31,8 +31,8 @@
namespace lmms::PathUtil
{
- enum class Base { Absolute, ProjectDir, FactorySample, UserSample, UserVST, Preset,
- UserLADSPA, DefaultLADSPA, UserSoundfont, DefaultSoundfont, UserGIG, DefaultGIG,
+ enum class Base { Absolute, ProjectDir, FactoryProjects, FactorySample, UserSample, UserVST, Preset,
+ FactoryPresets, UserLADSPA, DefaultLADSPA, UserSoundfont, DefaultSoundfont, UserGIG, DefaultGIG,
LocalDir };
//! Return the directory associated with a given base as a QString
diff --git a/include/PatternClip.h b/include/PatternClip.h
index 968a0b198..0be217407 100644
--- a/include/PatternClip.h
+++ b/include/PatternClip.h
@@ -51,6 +51,11 @@ public:
gui::ClipView * createView( gui::TrackView * _tv ) override;
+ PatternClip* clone() override
+ {
+ return new PatternClip(*this);
+ }
+
private:
friend class PatternClipView;
} ;
diff --git a/include/PeakController.h b/include/PeakController.h
index a22257374..de9da3b1c 100644
--- a/include/PeakController.h
+++ b/include/PeakController.h
@@ -78,7 +78,8 @@ private:
static int m_loadCount;
static bool m_buggedFile;
- float m_coeff;
+ float m_attackCoeff;
+ float m_decayCoeff;
bool m_coeffNeedsUpdate;
} ;
diff --git a/include/PianoRoll.h b/include/PianoRoll.h
index a1d045ff4..96557f33d 100644
--- a/include/PianoRoll.h
+++ b/include/PianoRoll.h
@@ -35,7 +35,7 @@
#include "ComboBoxModel.h"
#include "SerializingObject.h"
#include "Note.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#include "Song.h"
#include "StepRecorder.h"
#include "StepRecorderWidget.h"
@@ -90,6 +90,7 @@ class PianoRoll : public QWidget
Q_PROPERTY(int ghostNoteOpacity MEMBER m_ghostNoteOpacity)
Q_PROPERTY(bool ghostNoteBorders MEMBER m_ghostNoteBorders)
Q_PROPERTY(QColor backgroundShade MEMBER m_backgroundShade)
+ Q_PROPERTY(QColor outOfBoundsShade MEMBER m_outOfBoundsShade)
/* white key properties */
Q_PROPERTY(int whiteKeyWidth MEMBER m_whiteKeyWidth)
@@ -112,7 +113,8 @@ public:
Erase,
Select,
Detuning,
- Knife
+ Knife,
+ Strum
};
/*! \brief Resets settings to default when e.g. creating a new project */
@@ -247,6 +249,7 @@ protected slots:
void clearGhostClip();
void glueNotes();
void fitNoteLengths(bool fill);
+ void reverseNotes();
void constrainNoteLengths(bool constrainMax);
void changeSnapMode();
@@ -268,7 +271,8 @@ private:
SelectNotes,
ChangeNoteProperty,
ResizeNoteEditArea,
- Knife
+ Knife,
+ Strum
};
enum class NoteEditMode
@@ -324,6 +328,9 @@ private:
void setKnifeAction();
void cancelKnifeAction();
+ void setStrumAction();
+ void cancelStrumAction();
+
void updateScrollbars();
void updatePositionLineHeight();
@@ -347,6 +354,7 @@ private:
QPixmap m_toolMove = embed::getIconPixmap("edit_move");
QPixmap m_toolOpen = embed::getIconPixmap("automation");
QPixmap m_toolKnife = embed::getIconPixmap("edit_knife");
+ QPixmap m_toolStrum = embed::getIconPixmap("arp_free");
static std::array prKeyOrder;
@@ -437,6 +445,7 @@ private:
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
+ EditMode m_strumMode; //< mode they where in before entering strum mode
bool m_mouseDownRight; //true if right click is being held down
@@ -465,6 +474,21 @@ private:
void updateKnifePos(QMouseEvent* me, bool initial);
+ //! Stores the chords for the strum tool
+ std::vector m_selectedChords;
+ //! Computes which notes belong to which chords from the selection
+ void setupSelectedChords();
+
+ TimePos m_strumStartTime;
+ TimePos m_strumCurrentTime;
+ int m_strumStartVertical = 0;
+ int m_strumCurrentVertical = 0;
+ float m_strumHeightRatio = 0.0f;
+ bool m_strumEnabled = false;
+ //! Handles updating all of the note positions when performing a strum
+ void updateStrumPos(QMouseEvent* me, bool initial, bool warp);
+
+
friend class PianoRollWindow;
StepRecorderWidget m_stepRecorderWidget;
@@ -493,6 +517,7 @@ private:
bool m_noteBorders;
bool m_ghostNoteBorders;
QColor m_backgroundShade;
+ QColor m_outOfBoundsShade;
/* white key properties */
int m_whiteKeyWidth;
QColor m_whiteKeyActiveTextColor;
diff --git a/include/PlayHandle.h b/include/PlayHandle.h
index 5f0256a1a..fbe45471b 100644
--- a/include/PlayHandle.h
+++ b/include/PlayHandle.h
@@ -32,7 +32,7 @@
#include "Flags.h"
#include "ThreadableJob.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
class QThread;
diff --git a/include/PositionLine.h b/include/PositionLine.h
index 3e798948f..7a619c450 100644
--- a/include/PositionLine.h
+++ b/include/PositionLine.h
@@ -28,6 +28,8 @@
#include
+#include "Song.h"
+
namespace lmms::gui
{
@@ -37,7 +39,7 @@ class PositionLine : public QWidget
Q_PROPERTY(bool tailGradient MEMBER m_hasTailGradient)
Q_PROPERTY(QColor lineColor MEMBER m_lineColor)
public:
- PositionLine(QWidget* parent);
+ PositionLine(QWidget* parent, Song::PlayMode playMode);
public slots:
void zoomChange(float zoom);
@@ -45,6 +47,8 @@ public slots:
private:
void paintEvent(QPaintEvent* pe) override;
+ Song::PlayMode m_playMode;
+
bool m_hasTailGradient;
QColor m_lineColor;
};
diff --git a/include/ProjectJournal.h b/include/ProjectJournal.h
index 841bbf094..b5b8fc138 100644
--- a/include/ProjectJournal.h
+++ b/include/ProjectJournal.h
@@ -28,7 +28,7 @@
#include
#include
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#include "DataFile.h"
diff --git a/include/ProjectRenderer.h b/include/ProjectRenderer.h
index 14c584a2e..3183fc478 100644
--- a/include/ProjectRenderer.h
+++ b/include/ProjectRenderer.h
@@ -26,7 +26,6 @@
#define LMMS_PROJECT_RENDERER_H
#include "AudioFileDevice.h"
-#include "lmmsconfig.h"
#include "AudioEngine.h"
#include "OutputSettings.h"
diff --git a/include/RemotePluginBase.h b/include/RemotePluginBase.h
index 787742fc0..53ccce1c7 100644
--- a/include/RemotePluginBase.h
+++ b/include/RemotePluginBase.h
@@ -27,6 +27,8 @@
#include "MidiEvent.h"
+#include "lmmsconfig.h"
+
#include
#include
#include
diff --git a/include/RingBuffer.h b/include/RingBuffer.h
index 41595be19..0a7bb550a 100644
--- a/include/RingBuffer.h
+++ b/include/RingBuffer.h
@@ -28,7 +28,7 @@
#include
#include
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#include "lmms_export.h"
diff --git a/include/SampleBuffer.h b/include/SampleBuffer.h
index 8ec6c5886..d21bacf84 100644
--- a/include/SampleBuffer.h
+++ b/include/SampleBuffer.h
@@ -34,7 +34,7 @@
#include "AudioEngine.h"
#include "Engine.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#include "lmms_export.h"
namespace lmms {
diff --git a/include/SampleClip.h b/include/SampleClip.h
index 3beca338b..ea7853386 100644
--- a/include/SampleClip.h
+++ b/include/SampleClip.h
@@ -49,13 +49,11 @@ class SampleClip : public Clip
public:
SampleClip(Track* track, Sample sample, bool isPlaying);
SampleClip(Track* track);
- SampleClip( const SampleClip& orig );
~SampleClip() override;
SampleClip& operator=( const SampleClip& that ) = delete;
void changeLength( const TimePos & _length ) override;
- void changeLengthToSampleLength();
const QString& sampleFile() const;
bool hasSampleFileLoaded(const QString & filename) const;
@@ -81,6 +79,11 @@ public:
void setIsPlaying(bool isPlaying);
void setSampleBuffer(std::shared_ptr sb);
+ SampleClip* clone() override
+ {
+ return new SampleClip(*this);
+ }
+
public slots:
void setSampleFile(const QString& sf);
void updateLength();
@@ -88,6 +91,8 @@ public slots:
void playbackPositionChanged();
void updateTrackClips();
+protected:
+ SampleClip( const SampleClip& orig );
private:
Sample m_sample;
diff --git a/include/SampleClipView.h b/include/SampleClipView.h
index 07d04d9d0..b0304fd06 100644
--- a/include/SampleClipView.h
+++ b/include/SampleClipView.h
@@ -68,7 +68,7 @@ private:
SampleClip * m_clip;
SampleThumbnail m_sampleThumbnail;
QPixmap m_paintPixmap;
- bool splitClip( const TimePos pos ) override;
+ long m_paintPixmapXPosition;
} ;
diff --git a/include/SampleDecoder.h b/include/SampleDecoder.h
index 2cfd00977..9109d4121 100644
--- a/include/SampleDecoder.h
+++ b/include/SampleDecoder.h
@@ -31,7 +31,6 @@
#include
#include
-#include "lmms_basics.h"
#include "SampleFrame.h"
namespace lmms {
diff --git a/include/SampleFrame.h b/include/SampleFrame.h
index 238a85dea..43db2f6e6 100644
--- a/include/SampleFrame.h
+++ b/include/SampleFrame.h
@@ -26,7 +26,8 @@
#ifndef LMMS_SAMPLEFRAME_H
#define LMMS_SAMPLEFRAME_H
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
+#include "lmms_constants.h"
#include
#include
diff --git a/include/SampleThumbnail.h b/include/SampleThumbnail.h
index b8e1e85af..7d1082437 100644
--- a/include/SampleThumbnail.h
+++ b/include/SampleThumbnail.h
@@ -54,10 +54,8 @@ public:
{
QRect sampleRect; //!< A rectangle that covers the entire range of samples.
- QRect drawRect; //!< Specifies the location in `sampleRect` where the waveform will be drawn. Equals
- //!< `sampleRect` when null.
-
- QRect viewportRect; //!< Clips `drawRect`. Equals `drawRect` when null.
+ QRect viewportRect; //!< Specifies the location in `sampleRect` where the waveform will be drawn. Equals
+ //!< `sampleRect` when null.
float amplification = 1.0f; //!< The amount of amplification to apply to the waveform.
@@ -95,8 +93,8 @@ private:
Peak operator+(const Peak& other) const { return Peak(std::min(min, other.min), std::max(max, other.max)); }
Peak operator+(const SampleFrame& frame) const { return *this + Peak{frame}; }
- float min = std::numeric_limits::max();
- float max = std::numeric_limits::min();
+ float min = std::numeric_limits::infinity();
+ float max = -std::numeric_limits::infinity();
};
Thumbnail() = default;
@@ -105,6 +103,7 @@ private:
Thumbnail zoomOut(float factor) const;
+ Peak* data() { return m_peaks.data(); }
Peak& operator[](size_t index) { return m_peaks[index]; }
const Peak& operator[](size_t index) const { return m_peaks[index]; }
@@ -134,7 +133,7 @@ private:
using ThumbnailCache = std::vector;
std::shared_ptr m_thumbnailCache = std::make_shared();
-
+ std::shared_ptr m_buffer = SampleBuffer::emptyBuffer();
inline static std::unordered_map, Hash> s_sampleThumbnailCacheMap;
};
diff --git a/include/SampleTrackWindow.h b/include/SampleTrackWindow.h
index 01adb0080..f9aa0f71c 100644
--- a/include/SampleTrackWindow.h
+++ b/include/SampleTrackWindow.h
@@ -28,9 +28,9 @@
#include
#include "ModelView.h"
-#include "PixmapButton.h"
#include "SampleTrack.h"
#include "SerializingObject.h"
+#include "AutomatableButton.h"
class QLineEdit;
@@ -91,8 +91,8 @@ private:
QLineEdit * m_nameLineEdit;
Knob * m_volumeKnob;
Knob * m_panningKnob;
- PixmapButton *m_muteBtn;
- PixmapButton *m_soloBtn;
+ AutomatableButton* m_muteBtn;
+ AutomatableButton* m_soloBtn;
MixerChannelLcdSpinBox * m_mixerChannelNumber;
EffectRackView * m_effectRack;
diff --git a/include/SetupDialog.h b/include/SetupDialog.h
index 23589f91a..c314ff42d 100644
--- a/include/SetupDialog.h
+++ b/include/SetupDialog.h
@@ -30,7 +30,6 @@
#include "AudioDevice.h"
#include "AudioDeviceSetupWidget.h"
-#include "lmmsconfig.h"
#include "MidiClient.h"
#include "MidiSetupWidget.h"
@@ -183,6 +182,8 @@ private:
QSlider * m_bufferSizeSlider;
QLabel * m_bufferSizeLbl;
QLabel * m_bufferSizeWarnLbl;
+ int m_sampleRate;
+ QSlider* m_sampleRateSlider;
// MIDI settings widgets.
QComboBox * m_midiInterfaces;
diff --git a/include/SimpleTextFloat.h b/include/SimpleTextFloat.h
index bde6c84fa..2821ca411 100644
--- a/include/SimpleTextFloat.h
+++ b/include/SimpleTextFloat.h
@@ -23,8 +23,8 @@
*/
-#ifndef SIMPLE_TEXT_FLOAT_H
-#define SIMPLE_TEXT_FLOAT_H
+#ifndef LMMS_GUI_SIMPLE_TEXT_FLOAT_H
+#define LMMS_GUI_SIMPLE_TEXT_FLOAT_H
#include
@@ -47,7 +47,10 @@ public:
void showWithDelay(int msecBeforeDisplay, int msecDisplayTime);
- void setVisibilityTimeOut(int msecs);
+ void showWithTimeout(int msec)
+ {
+ showWithDelay(0, msec);
+ }
void moveGlobal(QWidget * w, const QPoint & offset)
{
@@ -64,4 +67,4 @@ private:
} // namespace lmms::gui
-#endif
+#endif // LMMS_GUI_SIMPLE_TEXT_FLOAT_H
diff --git a/include/Song.h b/include/Song.h
index f08edfff6..7fedaa44d 100644
--- a/include/Song.h
+++ b/include/Song.h
@@ -257,6 +257,7 @@ public:
return m_playMode;
}
+ PlayMode lastPlayMode() const { return m_lastPlayMode; }
inline PlayPos & getPlayPos( PlayMode pm )
{
return m_playPos[static_cast(pm)];
@@ -492,6 +493,7 @@ private:
std::array m_timelines;
PlayMode m_playMode;
+ PlayMode m_lastPlayMode;
PlayPos m_playPos[PlayModeCount];
bar_t m_length;
diff --git a/include/SweepOscillator.h b/include/SweepOscillator.h
deleted file mode 100644
index c7c7938d1..000000000
--- a/include/SweepOscillator.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * SweepOscillator.h - sweeping oscillator
- *
- * Copyright (c) 2006-2014 Tobias Doerffel
- *
- * 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_SWEEP_OSCILLATOR_H
-#define LMMS_SWEEP_OSCILLATOR_H
-
-#include "Oscillator.h"
-#include "DspEffectLibrary.h"
-
-namespace lmms
-{
-
-template
-class SweepOscillator
-{
-public:
- SweepOscillator( const FX & _fx = FX() ) :
- m_phase( 0.0f ),
- m_FX( _fx )
- {
- }
-
- virtual ~SweepOscillator() = default;
-
- void update( SampleFrame* buf, const fpp_t frames, const float freq1, const float freq2, const float sampleRate )
- {
- const float df = freq2 - freq1;
- for( fpp_t frame = 0; frame < frames; ++frame )
- {
- const sample_t s = Oscillator::sinSample( m_phase );
- buf[frame][0] = s;
- buf[frame][1] = s;
- m_FX.nextSample( buf[frame][0], buf[frame][1] );
- m_phase += ( freq1 + ( frame * df / frames ) ) / sampleRate;
- }
- }
-
-
-private:
- float m_phase;
- FX m_FX;
-
-// inline sample_t getSample( const float _sample );
-// inline void recalcPhase();
-
-} ;
-
-
-} // namespace lmms
-
-#endif // LMMS_SWEEP_OSCILLATOR_H
diff --git a/include/TempoSyncKnob.h b/include/TempoSyncKnob.h
index b86320d13..656f145ab 100644
--- a/include/TempoSyncKnob.h
+++ b/include/TempoSyncKnob.h
@@ -42,6 +42,29 @@ class LMMS_EXPORT TempoSyncKnob : public Knob
Q_OBJECT
public:
TempoSyncKnob( KnobType knobNum, QWidget* parent = nullptr, const QString& name = QString() );
+
+ /**
+ * @brief Construct a TempoSyncKnob with the given style and label text.
+ *
+ * @param knobNum Style of the knob
+ * @param labelText Text for the label
+ * @param parent Parent widget
+ * @param labelRendering Determines if the label uses the widget font or a font with a fixed size of 12 pixels (LegacyFixedFontSize). The default is to use the widget font.
+ * @param name Object name of the widget
+ */
+ TempoSyncKnob(KnobType knobNum, const QString& labelText, QWidget* parent = nullptr, LabelRendering labelRendering = LabelRendering::WidgetFont, const QString& name = QString());
+
+ /**
+ * @brief Constructs a tempo sync knob with a label font in the pixel size.
+ *
+ * @param knobNum Style of the knob
+ * @param labelText Text for the label
+ * @param labelPixelSize Pixel size for the label
+ * @param parent Parent widget
+ * @param name Object name of the widget
+ */
+ TempoSyncKnob(KnobType knobNum, const QString& labelText, int labelPixelSize, QWidget* parent, const QString& name = QString());
+
~TempoSyncKnob() override;
const QString & syncDescription();
diff --git a/include/ThreadableJob.h b/include/ThreadableJob.h
index 9d5a0beee..2f65ed5d9 100644
--- a/include/ThreadableJob.h
+++ b/include/ThreadableJob.h
@@ -25,7 +25,7 @@
#ifndef LMMS_THREADABLE_JOB_H
#define LMMS_THREADABLE_JOB_H
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#include
diff --git a/include/TimePos.h b/include/TimePos.h
index 68f3bd01b..02338c6e7 100644
--- a/include/TimePos.h
+++ b/include/TimePos.h
@@ -29,7 +29,7 @@
#include
#include
#include "lmms_export.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms
{
@@ -70,7 +70,7 @@ public:
TimePos( const bar_t bar, const tick_t ticks );
TimePos( const tick_t ticks = 0 );
- TimePos quantize(float) const;
+ TimePos quantize(float bars, bool forceRoundDown = false) const;
TimePos toAbsoluteBar() const { return getBar() * s_ticksPerBar; }
TimePos& operator+=(const TimePos& time)
diff --git a/include/Track.h b/include/Track.h
index a152640e1..274e7a1fc 100644
--- a/include/Track.h
+++ b/include/Track.h
@@ -31,7 +31,7 @@
#include "AutomatableModel.h"
#include "JournallingObject.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#include
diff --git a/include/TrackOperationsWidget.h b/include/TrackOperationsWidget.h
index 8417298b4..3eb9215b9 100644
--- a/include/TrackOperationsWidget.h
+++ b/include/TrackOperationsWidget.h
@@ -26,6 +26,7 @@
#define LMMS_GUI_TRACK_OPERATIONS_WIDGET_H
#include
+#include "AutomatableButton.h"
class QPushButton;
@@ -69,8 +70,8 @@ private:
TrackGrip* m_trackGrip;
QPushButton * m_trackOps;
- PixmapButton * m_muteBtn;
- PixmapButton * m_soloBtn;
+ AutomatableButton* m_muteBtn;
+ AutomatableButton* m_soloBtn;
friend class TrackView;
diff --git a/include/embed.h b/include/embed.h
index 40a3622c6..489a06270 100644
--- a/include/embed.h
+++ b/include/embed.h
@@ -32,7 +32,8 @@
#include
#include "lmms_export.h"
-#include "lmms_basics.h"
+#include "LmmsCommonMacros.h"
+
namespace lmms {
@@ -51,6 +52,24 @@ auto LMMS_EXPORT getIconPixmap(std::string_view name,
int width = -1, int height = -1, const char* const* xpm = nullptr) -> QPixmap;
auto LMMS_EXPORT getText(std::string_view name) -> QString;
+/**
+ * @brief Temporary shim for QPixmap::deviceIndependentSize.
+ * @param pixmap The pixmap to get the size of.
+ * @return The device-independent size of the pixmap.
+ */
+#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
+[[deprecated("Use QPixmap::deviceIndependentSize() instead; See "
+ "https://doc.qt.io/qt-6/qpixmap.html#deviceIndependentSize")]]
+#endif
+inline auto logicalSize(const QPixmap &pixmap) noexcept
+{
+#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
+ return pixmap.deviceIndependentSize().toSize();
+#else
+ return pixmap.isNull() ? QSize() : pixmap.size() / pixmap.devicePixelRatio();
+#endif
+}
+
} // namespace embed
class PixmapLoader
diff --git a/include/endian_handling.h b/include/endian_handling.h
index 7ddb22f22..793b22e46 100644
--- a/include/endian_handling.h
+++ b/include/endian_handling.h
@@ -25,10 +25,9 @@
#ifndef LMMS_ENDIAN_HANDLING_H
#define LMMS_ENDIAN_HANDLING_H
+#include
#include
-#include "lmms_basics.h"
-
namespace lmms
{
diff --git a/include/lmms_constants.h b/include/lmms_constants.h
index 782e6849d..8be44a404 100644
--- a/include/lmms_constants.h
+++ b/include/lmms_constants.h
@@ -25,17 +25,23 @@
#ifndef LMMS_CONSTANTS_H
#define LMMS_CONSTANTS_H
+#include "lmmsconfig.h"
+#include "LmmsTypes.h"
+
namespace lmms
{
-
// Prefer using `approximatelyEqual()` from lmms_math.h rather than
// using this directly
inline constexpr float F_EPSILON = 1.0e-10f; // 10^-10
+inline constexpr ch_cnt_t DEFAULT_CHANNELS = 2;
+
// Microtuner
inline constexpr unsigned MaxScaleCount = 10; //!< number of scales per project
inline constexpr unsigned MaxKeymapCount = 10; //!< number of keyboard mappings per project
+
+// Note: All constants below are used only in spectrum analyser
// Frequency ranges (in Hz).
// Arbitrary low limit for logarithmic frequency scale; >1 Hz.
inline constexpr auto LOWEST_LOG_FREQ = 5;
@@ -79,6 +85,15 @@ inline constexpr auto ARANGE_LOUD_END = 0;
inline constexpr auto ARANGE_SILENT_START = -60;
inline constexpr auto ARANGE_SILENT_END = -10;
+
+// This macro is used to handle path seperation properly in windows
+constexpr char LADSPA_PATH_SEPERATOR =
+#ifdef LMMS_BUILD_WIN32
+';';
+#else
+':';
+#endif
+
} // namespace lmms
#endif // LMMS_CONSTANTS_H
diff --git a/include/lmms_math.h b/include/lmms_math.h
index 1d3de249d..5129743de 100644
--- a/include/lmms_math.h
+++ b/include/lmms_math.h
@@ -34,7 +34,6 @@
#include
#include
-#include "lmmsconfig.h"
#include "lmms_constants.h"
namespace lmms
diff --git a/include/panning.h b/include/panning.h
index 2945988ba..fa9cde9ee 100644
--- a/include/panning.h
+++ b/include/panning.h
@@ -26,7 +26,7 @@
#ifndef LMMS_PANNING_H
#define LMMS_PANNING_H
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#include "Midi.h"
#include "volume.h"
diff --git a/include/shared_object.h b/include/shared_object.h
deleted file mode 100644
index e9fdb57a3..000000000
--- a/include/shared_object.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * shared_object.h - class sharedObject for use among other objects
- *
- * Copyright (c) 2006-2007 Javier Serrano Polo
- * Copyright (c) 2008-2014 Tobias Doerffel
- *
- * 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_SHARED_OBJECT_H
-#define LMMS_SHARED_OBJECT_H
-
-#include
-
-namespace lmms
-{
-
-class sharedObject
-{
-public:
- sharedObject() :
- m_referenceCount(1)
- {
- }
-
- virtual ~sharedObject() = default;
-
- template
- static T* ref( T* object )
- {
- // Incrementing an atomic reference count can be relaxed since no action
- // is ever taken as a result of increasing the count.
- // Other loads and stores can be reordered around this without consequence.
- object->m_referenceCount.fetch_add(1, std::memory_order_relaxed);
- return object;
- }
-
- template
- static void unref( T* object )
- {
- // When decrementing an atomic reference count, we need to provide
- // two ordering guarantees:
- // 1. All reads and writes to the referenced object occur before
- // the count reaches zero.
- // 2. Deletion occurs after the count reaches zero.
- //
- // To accomplish this, each decrement must be store-released,
- // and the final thread (which is deleting the referenced data)
- // must load-acquire those stores.
- // The simplest way to do this to give the decrement acquire-release
- // semantics.
- //
- // See https://www.boost.org/doc/libs/1_67_0/doc/html/atomic/usage_examples.html
- // for further discussion, along with a slightly more complicated
- // (but possibly more performant on weakly-ordered hardware like ARM)
- // approach.
- const bool deleteObject =
- object->m_referenceCount.fetch_sub(1, std::memory_order_acq_rel) == 1;
-
- if ( deleteObject )
- {
- object->deleteLater();
- }
- }
-
-private:
- std::atomic_int m_referenceCount;
-} ;
-
-
-} // namespace lmms
-
-#endif // LMMS_SHARED_OBJECT_H
diff --git a/include/versioninfo.h b/include/versioninfo.h
index 7495299c2..f2a535313 100644
--- a/include/versioninfo.h
+++ b/include/versioninfo.h
@@ -1,7 +1,7 @@
#ifndef LMMS_VERSION_INFO_H
#define LMMS_VERSION_INFO_H
-#include "lmms_basics.h"
+#include "LmmsCommonMacros.h"
#if defined(__GNUC__)
constexpr const char* LMMS_BUILDCONF_COMPILER_VERSION = "GCC " __VERSION__;
diff --git a/include/volume.h b/include/volume.h
index 382f76780..76c6c37de 100644
--- a/include/volume.h
+++ b/include/volume.h
@@ -26,7 +26,7 @@
#ifndef LMMS_VOLUME_H
#define LMMS_VOLUME_H
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms
{
diff --git a/plugins/Amplifier/AmplifierControlDialog.cpp b/plugins/Amplifier/AmplifierControlDialog.cpp
index 1fbc3729a..9bf0bb649 100644
--- a/plugins/Amplifier/AmplifierControlDialog.cpp
+++ b/plugins/Amplifier/AmplifierControlDialog.cpp
@@ -28,6 +28,9 @@
#include "embed.h"
#include "Knob.h"
+#include
+
+
namespace lmms::gui
{
@@ -38,23 +41,22 @@ AmplifierControlDialog::AmplifierControlDialog(AmplifierControls* controls) :
QPalette pal;
pal.setBrush(backgroundRole(), PLUGIN_NAME::getIconPixmap("artwork"));
setPalette(pal);
- setFixedSize(100, 110);
-
- auto makeKnob = [this](int x, int y, const QString& label, const QString& hintText, const QString& unit, FloatModel* model, bool isVolume)
- {
- Knob* newKnob = new Knob(KnobType::Bright26, this);
- newKnob->move(x, y);
- newKnob->setModel(model);
- newKnob->setLabel(label);
- newKnob->setHintText(hintText, unit);
- newKnob->setVolumeKnob(isVolume);
- return newKnob;
- };
- makeKnob(16, 10, tr("VOL"), tr("Volume:"), "%", &controls->m_volumeModel, true);
- makeKnob(57, 10, tr("PAN"), tr("Panning:"), "%", &controls->m_panModel, false);
- makeKnob(16, 65, tr("LEFT"), tr("Left gain:"), "%", &controls->m_leftModel, true);
- makeKnob(57, 65, tr("RIGHT"), tr("Right gain:"), "%", &controls->m_rightModel, true);
+ QGridLayout* gridLayout = new QGridLayout(this);
+
+ auto makeKnob = [this](const QString& label, const QString& hintText, const QString& unit, FloatModel* model, bool isVolume)
+ {
+ Knob* newKnob = new Knob(KnobType::Bright26, label, this);
+ newKnob->setModel(model);
+ newKnob->setHintText(hintText, unit);
+ newKnob->setVolumeKnob(isVolume);
+ return newKnob;
+ };
+
+ gridLayout->addWidget(makeKnob(tr("VOL"), tr("Volume:"), "%", &controls->m_volumeModel, true), 0, 0, Qt::AlignHCenter);
+ gridLayout->addWidget(makeKnob(tr("PAN"), tr("Panning:"), "%", &controls->m_panModel, false), 0, 1, Qt::AlignHCenter);
+ gridLayout->addWidget(makeKnob(tr("LEFT"), tr("Left gain:"), "%", &controls->m_leftModel, true), 1, 0, Qt::AlignHCenter);
+ gridLayout->addWidget(makeKnob(tr("RIGHT"), tr("Right gain:"), "%", &controls->m_rightModel, true), 1, 1, Qt::AlignHCenter);
}
} // namespace lmms::gui
diff --git a/plugins/Amplifier/CMakeLists.txt b/plugins/Amplifier/CMakeLists.txt
index 3e57ba5ef..2d465fc55 100644
--- a/plugins/Amplifier/CMakeLists.txt
+++ b/plugins/Amplifier/CMakeLists.txt
@@ -1,3 +1,3 @@
INCLUDE(BuildPlugin)
-BUILD_PLUGIN(amplifier Amplifier.cpp AmplifierControls.cpp AmplifierControlDialog.cpp MOCFILES AmplifierControls.h AmplifierControlDialog.h EMBEDDED_RESOURCES artwork.png logo.png)
+BUILD_PLUGIN(amplifier Amplifier.cpp AmplifierControls.cpp AmplifierControlDialog.cpp MOCFILES AmplifierControls.h AmplifierControlDialog.h EMBEDDED_RESOURCES artwork.svg logo.svg)
diff --git a/plugins/Amplifier/artwork.png b/plugins/Amplifier/artwork.png
deleted file mode 100644
index 5598b32db..000000000
Binary files a/plugins/Amplifier/artwork.png and /dev/null differ
diff --git a/plugins/Amplifier/artwork.svg b/plugins/Amplifier/artwork.svg
new file mode 100644
index 000000000..df574cfda
--- /dev/null
+++ b/plugins/Amplifier/artwork.svg
@@ -0,0 +1,13 @@
+
diff --git a/plugins/Amplifier/logo.png b/plugins/Amplifier/logo.png
deleted file mode 100644
index 9340da708..000000000
Binary files a/plugins/Amplifier/logo.png and /dev/null differ
diff --git a/plugins/Amplifier/logo.svg b/plugins/Amplifier/logo.svg
new file mode 100644
index 000000000..7920fa6b0
--- /dev/null
+++ b/plugins/Amplifier/logo.svg
@@ -0,0 +1,3 @@
+
diff --git a/plugins/AudioFileProcessor/AudioFileProcessor.cpp b/plugins/AudioFileProcessor/AudioFileProcessor.cpp
index 4cc14ba9c..6754624df 100644
--- a/plugins/AudioFileProcessor/AudioFileProcessor.cpp
+++ b/plugins/AudioFileProcessor/AudioFileProcessor.cpp
@@ -30,7 +30,7 @@
#include "SampleLoader.h"
#include "Song.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#include "plugin_export.h"
#include
diff --git a/plugins/AudioFileProcessor/AudioFileProcessor.h b/plugins/AudioFileProcessor/AudioFileProcessor.h
index acdbc45f7..0548d5b45 100644
--- a/plugins/AudioFileProcessor/AudioFileProcessor.h
+++ b/plugins/AudioFileProcessor/AudioFileProcessor.h
@@ -32,7 +32,7 @@
#include "Instrument.h"
#include "Sample.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms
diff --git a/plugins/AudioFileProcessor/AudioFileProcessorView.cpp b/plugins/AudioFileProcessor/AudioFileProcessorView.cpp
index 298e79c5e..02098c540 100644
--- a/plugins/AudioFileProcessor/AudioFileProcessorView.cpp
+++ b/plugins/AudioFileProcessor/AudioFileProcessorView.cpp
@@ -120,15 +120,15 @@ AudioFileProcessorView::AudioFileProcessorView(Instrument* instrument,
m_ampKnob->setHintText(tr("Amplify:"), "%");
m_startKnob = new AudioFileProcessorWaveView::knob(this);
- m_startKnob->move(45, 108);
+ m_startKnob->move(50, 108);
m_startKnob->setHintText(tr("Start point:"), "");
m_endKnob = new AudioFileProcessorWaveView::knob(this);
- m_endKnob->move(125, 108);
+ m_endKnob->move(130, 108);
m_endKnob->setHintText(tr("End point:"), "");
m_loopKnob = new AudioFileProcessorWaveView::knob(this);
- m_loopKnob->move(85, 108);
+ m_loopKnob->move(90, 108);
m_loopKnob->setHintText(tr("Loopback point:"), "");
// interpolation selector
diff --git a/plugins/AudioFileProcessor/AudioFileProcessorWaveView.h b/plugins/AudioFileProcessor/AudioFileProcessorWaveView.h
index 6440570e6..69dea0b1b 100644
--- a/plugins/AudioFileProcessor/AudioFileProcessorWaveView.h
+++ b/plugins/AudioFileProcessor/AudioFileProcessorWaveView.h
@@ -73,7 +73,6 @@ public:
m_waveView(0),
m_relatedKnob(0)
{
- setFixedSize(37, 47);
}
void setWaveView(const AudioFileProcessorWaveView* wv)
diff --git a/plugins/BassBooster/BassBoosterControlDialog.cpp b/plugins/BassBooster/BassBoosterControlDialog.cpp
index 9efa07c0d..fcdf10cc2 100644
--- a/plugins/BassBooster/BassBoosterControlDialog.cpp
+++ b/plugins/BassBooster/BassBoosterControlDialog.cpp
@@ -43,26 +43,22 @@ BassBoosterControlDialog::BassBoosterControlDialog( BassBoosterControls* control
QPalette pal;
pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) );
setPalette( pal );
- setFixedSize( 120, 60 );
auto tl = new QVBoxLayout(this);
tl->addSpacing( 4 );
auto l = new QHBoxLayout;
- auto freqKnob = new Knob(KnobType::Bright26, this);
+ auto freqKnob = new Knob(KnobType::Bright26, tr("FREQ"), this);
freqKnob->setModel( &controls->m_freqModel );
- freqKnob->setLabel( tr( "FREQ" ) );
freqKnob->setHintText( tr( "Frequency:" ) , "Hz" );
- auto gainKnob = new Knob(KnobType::Bright26, this);
+ auto gainKnob = new Knob(KnobType::Bright26, tr("GAIN"), this);
gainKnob->setModel( &controls->m_gainModel );
- gainKnob->setLabel( tr( "GAIN" ) );
gainKnob->setHintText( tr( "Gain:" ) , "" );
- auto ratioKnob = new Knob(KnobType::Bright26, this);
+ auto ratioKnob = new Knob(KnobType::Bright26, tr("RATIO"), this);
ratioKnob->setModel( &controls->m_ratioModel );
- ratioKnob->setLabel( tr( "RATIO" ) );
ratioKnob->setHintText( tr( "Ratio:" ) , "" );
l->addWidget( freqKnob );
diff --git a/plugins/BassBooster/CMakeLists.txt b/plugins/BassBooster/CMakeLists.txt
index 35bfb5049..955a6584c 100644
--- a/plugins/BassBooster/CMakeLists.txt
+++ b/plugins/BassBooster/CMakeLists.txt
@@ -1,3 +1,3 @@
INCLUDE(BuildPlugin)
-BUILD_PLUGIN(bassbooster BassBooster.cpp BassBoosterControls.cpp BassBoosterControlDialog.cpp MOCFILES BassBoosterControls.h BassBoosterControlDialog.h EMBEDDED_RESOURCES artwork.png logo.png)
+BUILD_PLUGIN(bassbooster BassBooster.cpp BassBoosterControls.cpp BassBoosterControlDialog.cpp MOCFILES BassBoosterControls.h BassBoosterControlDialog.h EMBEDDED_RESOURCES artwork.svg logo.svg)
diff --git a/plugins/BassBooster/artwork.png b/plugins/BassBooster/artwork.png
deleted file mode 100644
index c16b8ca2b..000000000
Binary files a/plugins/BassBooster/artwork.png and /dev/null differ
diff --git a/plugins/BassBooster/artwork.svg b/plugins/BassBooster/artwork.svg
new file mode 100644
index 000000000..f98447e18
--- /dev/null
+++ b/plugins/BassBooster/artwork.svg
@@ -0,0 +1,10 @@
+
diff --git a/plugins/BassBooster/logo.png b/plugins/BassBooster/logo.png
deleted file mode 100644
index 9340da708..000000000
Binary files a/plugins/BassBooster/logo.png and /dev/null differ
diff --git a/plugins/BassBooster/logo.svg b/plugins/BassBooster/logo.svg
new file mode 100644
index 000000000..7920fa6b0
--- /dev/null
+++ b/plugins/BassBooster/logo.svg
@@ -0,0 +1,3 @@
+
diff --git a/plugins/Bitcrush/BitcrushControlDialog.cpp b/plugins/Bitcrush/BitcrushControlDialog.cpp
index 64c9b6361..3036c802a 100644
--- a/plugins/Bitcrush/BitcrushControlDialog.cpp
+++ b/plugins/Bitcrush/BitcrushControlDialog.cpp
@@ -29,6 +29,7 @@
#include "embed.h"
#include "BitcrushControlDialog.h"
#include "BitcrushControls.h"
+#include "FontHelper.h"
#include "LedCheckBox.h"
#include "Knob.h"
@@ -46,37 +47,37 @@ BitcrushControlDialog::BitcrushControlDialog( BitcrushControls * controls ) :
setFixedSize( 181, 128 );
// labels
+ const auto labelFont = adjustedToPixelSize(font(), DEFAULT_FONT_SIZE);
+
auto inLabel = new QLabel(tr("IN"), this);
+ inLabel->setFont(labelFont);
inLabel->move( 24, 15 );
auto outLabel = new QLabel(tr("OUT"), this);
+ outLabel->setFont(labelFont);
outLabel->move( 139, 15 );
// input knobs
- auto inGain = new Knob(KnobType::Bright26, this);
+ auto inGain = new Knob(KnobType::Bright26, tr("GAIN"), SMALL_FONT_SIZE, this);
inGain->move( 16, 32 );
inGain->setModel( & controls->m_inGain );
- inGain->setLabel( tr( "GAIN" ) );
inGain->setHintText( tr( "Input gain:" ) , " dBFS" );
- auto inNoise = new Knob(KnobType::Bright26, this);
+ auto inNoise = new Knob(KnobType::Bright26, tr("NOISE"), SMALL_FONT_SIZE, this);
inNoise->move( 14, 76 );
inNoise->setModel( & controls->m_inNoise );
- inNoise->setLabel( tr( "NOISE" ) );
inNoise->setHintText( tr( "Input noise:" ) , "%" );
// output knobs
- auto outGain = new Knob(KnobType::Bright26, this);
+ auto outGain = new Knob(KnobType::Bright26, tr("GAIN"), SMALL_FONT_SIZE, this);
outGain->move( 138, 32 );
outGain->setModel( & controls->m_outGain );
- outGain->setLabel( tr( "GAIN" ) );
outGain->setHintText( tr( "Output gain:" ) , " dBFS" );
- auto outClip = new Knob(KnobType::Bright26, this);
+ auto outClip = new Knob(KnobType::Bright26, tr("CLIP"), SMALL_FONT_SIZE, this);
outClip->move( 138, 76 );
outClip->setModel( & controls->m_outClip );
- outClip->setLabel( tr( "CLIP" ) );
outClip->setHintText( tr( "Output clip:" ) , " dBFS");
@@ -94,24 +95,21 @@ BitcrushControlDialog::BitcrushControlDialog( BitcrushControls * controls ) :
// rate crushing knobs
- auto rate = new Knob(KnobType::Bright26, this);
+ auto rate = new Knob(KnobType::Bright26, tr("FREQ"), SMALL_FONT_SIZE, this);
rate->move( 59, 32 );
rate->setModel( & controls->m_rate );
- rate->setLabel( tr( "FREQ" ) );
rate->setHintText( tr( "Sample rate:" ) , " Hz" );
- auto stereoDiff = new Knob(KnobType::Bright26, this);
+ auto stereoDiff = new Knob(KnobType::Bright26, tr("STEREO"), SMALL_FONT_SIZE, this);
stereoDiff->move( 72, 76 );
stereoDiff->setModel( & controls->m_stereoDiff );
- stereoDiff->setLabel( tr( "STEREO" ) );
stereoDiff->setHintText( tr( "Stereo difference:" ) , "%" );
// depth crushing knob
- auto levels = new Knob(KnobType::Bright26, this);
+ auto levels = new Knob(KnobType::Bright26, tr("QUANT"), SMALL_FONT_SIZE, this);
levels->move( 92, 32 );
levels->setModel( & controls->m_levels );
- levels->setLabel( tr( "QUANT" ) );
levels->setHintText( tr( "Levels:" ) , "" );
}
diff --git a/plugins/Bitcrush/CMakeLists.txt b/plugins/Bitcrush/CMakeLists.txt
index f4810183e..88507f860 100644
--- a/plugins/Bitcrush/CMakeLists.txt
+++ b/plugins/Bitcrush/CMakeLists.txt
@@ -1,3 +1,3 @@
INCLUDE(BuildPlugin)
-BUILD_PLUGIN(bitcrush Bitcrush.cpp BitcrushControls.cpp BitcrushControlDialog.cpp MOCFILES BitcrushControls.h BitcrushControlDialog.h EMBEDDED_RESOURCES artwork.png logo.png)
+BUILD_PLUGIN(bitcrush Bitcrush.cpp BitcrushControls.cpp BitcrushControlDialog.cpp MOCFILES BitcrushControls.h BitcrushControlDialog.h EMBEDDED_RESOURCES artwork.svg logo.svg)
diff --git a/plugins/Bitcrush/artwork.png b/plugins/Bitcrush/artwork.png
deleted file mode 100755
index 72d980c91..000000000
Binary files a/plugins/Bitcrush/artwork.png and /dev/null differ
diff --git a/plugins/Bitcrush/artwork.svg b/plugins/Bitcrush/artwork.svg
new file mode 100644
index 000000000..dfc583974
--- /dev/null
+++ b/plugins/Bitcrush/artwork.svg
@@ -0,0 +1,21 @@
+
diff --git a/plugins/Bitcrush/logo.png b/plugins/Bitcrush/logo.png
deleted file mode 100644
index 9340da708..000000000
Binary files a/plugins/Bitcrush/logo.png and /dev/null differ
diff --git a/plugins/Bitcrush/logo.svg b/plugins/Bitcrush/logo.svg
new file mode 100644
index 000000000..7920fa6b0
--- /dev/null
+++ b/plugins/Bitcrush/logo.svg
@@ -0,0 +1,3 @@
+
diff --git a/plugins/CarlaBase/Carla.cpp b/plugins/CarlaBase/Carla.cpp
index 37cba078a..b572a13d4 100644
--- a/plugins/CarlaBase/Carla.cpp
+++ b/plugins/CarlaBase/Carla.cpp
@@ -1004,34 +1004,32 @@ void CarlaParamsView::refreshKnobs()
QStringList groupNameList;
groupNameList.reserve(m_carlaInstrument->m_paramGroupCount);
- for (uint32_t i = 0; i < m_carlaInstrument->m_paramModels.size(); ++i)
+ for (const auto currentParamModel : m_carlaInstrument->m_paramModels)
{
- bool enabled = m_carlaInstrument->m_paramModels[i]->enabled();
- 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);
- m_knobs[i]->setObjectName(name); // this is being used for filtering the knobs.
+ bool enabled = currentParamModel->enabled();
+ const QString name = currentParamModel->displayName();
+
+ auto currentKnob = new Knob(KnobType::Dark28, name, m_inputScrollAreaWidgetContent, Knob::LabelRendering::LegacyFixedFontSize);
+ currentKnob->setHintText(name, "");
+ currentKnob->setObjectName(name); // this is being used for filtering the knobs.
// Set the newly created model to the knob.
- m_knobs[i]->setModel(m_carlaInstrument->m_paramModels[i]);
- m_knobs[i]->setEnabled(enabled);
+ currentKnob->setModel(currentParamModel);
+ currentKnob->setEnabled(enabled);
+
+ m_knobs.push_back(currentKnob);
if (enabled)
{
// Collect group names
- if (!groupNameList.contains(m_carlaInstrument->m_paramModels[i]->groupName()))
+ if (!groupNameList.contains(currentParamModel->groupName()))
{
- groupNameList.append(m_carlaInstrument->m_paramModels[i]->groupName());
+ groupNameList.append(currentParamModel->groupName());
}
- // Store biggest knob width per group (so we can calc how many
- // knobs we can horizontaly fit)
- uint8_t groupId = m_carlaInstrument->m_paramModels[i]->groupId();
- if (m_maxKnobWidthPerGroup[groupId] < m_knobs[i]->width())
- {
- m_maxKnobWidthPerGroup[groupId] = m_knobs[i]->width();
- }
+ // Store biggest knob width per group (so we can calc how many knobs we can fit horizontally)
+ auto & maxGroupWidth = m_maxKnobWidthPerGroup[currentParamModel->groupId()];
+ maxGroupWidth = std::max(maxGroupWidth, static_cast(currentKnob->width()));
}
}
diff --git a/plugins/CrossoverEQ/CMakeLists.txt b/plugins/CrossoverEQ/CMakeLists.txt
index 447c92c11..32e700d6a 100644
--- a/plugins/CrossoverEQ/CMakeLists.txt
+++ b/plugins/CrossoverEQ/CMakeLists.txt
@@ -1,3 +1,3 @@
INCLUDE(BuildPlugin)
-BUILD_PLUGIN(crossovereq CrossoverEQ.cpp CrossoverEQControls.cpp CrossoverEQControlDialog.cpp MOCFILES CrossoverEQControls.h CrossoverEQControlDialog.h EMBEDDED_RESOURCES artwork.png fader_bg.png fader_empty.png fader_knob2.png logo.png)
+BUILD_PLUGIN(crossovereq CrossoverEQ.cpp CrossoverEQControls.cpp CrossoverEQControlDialog.cpp MOCFILES CrossoverEQControls.h CrossoverEQControlDialog.h EMBEDDED_RESOURCES artwork.svg logo.svg)
diff --git a/plugins/CrossoverEQ/CrossoverEQControlDialog.cpp b/plugins/CrossoverEQ/CrossoverEQControlDialog.cpp
index e7202556b..a04606601 100644
--- a/plugins/CrossoverEQ/CrossoverEQControlDialog.cpp
+++ b/plugins/CrossoverEQ/CrossoverEQControlDialog.cpp
@@ -28,93 +28,88 @@
#include "CrossoverEQControlDialog.h"
#include "CrossoverEQControls.h"
#include "embed.h"
+#include "FontHelper.h"
#include "LedCheckBox.h"
#include "Knob.h"
#include "Fader.h"
+#include "PixmapButton.h"
#include
+#include
+#include
namespace lmms::gui
{
-CrossoverEQControlDialog::CrossoverEQControlDialog( CrossoverEQControls * controls ) :
- EffectControlDialog( controls )
+CrossoverEQControlDialog::CrossoverEQControlDialog(CrossoverEQControls *controls) :
+ EffectControlDialog(controls)
{
- setAutoFillBackground( true );
+ setAutoFillBackground(true);
QPalette pal;
- pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) );
- setPalette( pal );
- setFixedSize( 167, 178 );
+ pal.setBrush(backgroundRole(), PLUGIN_NAME::getIconPixmap("artwork"));
+ setPalette(pal);
+ setFixedSize(167, 218);
+ auto layout = new QVBoxLayout(this);
+
+ auto knobsLayout = new QHBoxLayout();
+ layout->addLayout(knobsLayout);
+
+ const auto makeKnob = [this, knobsLayout](
+ FloatModel* model,
+ const QString& label,
+ const QString& txt_before
+ ) {
+ auto k = new Knob(KnobType::Bright26, label, SMALL_FONT_SIZE, this);
+ k->setModel(model);
+ k->setHintText(txt_before, "Hz");
+ knobsLayout->addWidget(k, 0, Qt::AlignHCenter);
+ };
+
+ makeKnob(&controls->m_xover12, "1/2", tr("Band 1/2 crossover"));
+ makeKnob(&controls->m_xover23, "2/3", tr("Band 2/3 crossover"));
+ makeKnob(&controls->m_xover34, "3/4", tr("Band 3/4 crossover"));
- // knobs
- 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 bandsLayout = new QGridLayout();
+ bandsLayout->setContentsMargins(4, 10, 4, 5);
+ layout->addLayout(bandsLayout);
- 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" );
+ const auto makeFader = [this, bandsLayout](
+ FloatModel* model,
+ const QString& label,
+ int column
+ ) {
+ auto f = new Fader(model, label, this, false);
+ f->setHintText(label, "dBFS");
+ f->setDisplayConversion(false);
+ f->setRenderUnityLine(false);
+ bandsLayout->addWidget(f, 0, column, Qt::AlignHCenter);
+ };
- auto xover34 = new Knob(KnobType::Bright26, this);
- xover34->move( 109, 11 );
- xover34->setModel( & controls->m_xover34 );
- xover34->setLabel( "3/4" );
- xover34->setHintText( tr( "Band 3/4 crossover:" ), " Hz" );
-
- QPixmap const fader_knob(PLUGIN_NAME::getIconPixmap("fader_knob2"));
-
- // faders
- auto gain1 = new Fader(&controls->m_gain1, tr("Band 1 gain"), this, fader_knob, false);
- gain1->move( 7, 56 );
- gain1->setDisplayConversion( false );
- gain1->setHintText( tr( "Band 1 gain:" ), " dBFS" );
- gain1->setRenderUnityLine(false);
+ makeFader(&controls->m_gain1, tr("Band 1 gain"), 0);
+ makeFader(&controls->m_gain2, tr("Band 2 gain"), 1);
+ makeFader(&controls->m_gain3, tr("Band 3 gain"), 2);
+ makeFader(&controls->m_gain4, tr("Band 4 gain"), 3);
- auto gain2 = new Fader(&controls->m_gain2, tr("Band 2 gain"), this, fader_knob, false);
- gain2->move( 47, 56 );
- gain2->setDisplayConversion( false );
- gain2->setHintText( tr( "Band 2 gain:" ), " dBFS" );
- gain2->setRenderUnityLine(false);
+ const auto makeMuteBtn = [this, bandsLayout](
+ BoolModel* model,
+ const QString& label,
+ int column
+ ) {
+ auto b = new AutomatableButton(this, label);
+ b->setCheckable(true);
+ b->setModel(model);
+ b->setToolTip(label);
+ b->setObjectName("btn-mute-inv");
+ bandsLayout->addWidget(b, 1, column, Qt::AlignCenter);
+ };
- auto gain3 = new Fader(&controls->m_gain3, tr("Band 3 gain"), this, fader_knob, false);
- gain3->move( 87, 56 );
- gain3->setDisplayConversion( false );
- gain3->setHintText( tr( "Band 3 gain:" ), " dBFS" );
- gain3->setRenderUnityLine(false);
-
- auto gain4 = new Fader(&controls->m_gain4, tr("Band 4 gain"), this, fader_knob, false);
- gain4->move( 127, 56 );
- gain4->setDisplayConversion( false );
- gain4->setHintText( tr( "Band 4 gain:" ), " dBFS" );
- gain4->setRenderUnityLine(false);
-
- // leds
- 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::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::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::LedColor::Green);
- mute4->move( 135, 154 );
- mute4->setModel( & controls->m_mute4 );
- mute4->setToolTip(tr("Mute band 4"));
+ makeMuteBtn(&controls->m_mute1, tr("Mute band 1"), 0);
+ makeMuteBtn(&controls->m_mute2, tr("Mute band 2"), 1);
+ makeMuteBtn(&controls->m_mute3, tr("Mute band 3"), 2);
+ makeMuteBtn(&controls->m_mute4, tr("Mute band 4"), 3);
}
-} // namespace lmms::gui
\ No newline at end of file
+} // namespace lmms::gui
diff --git a/plugins/CrossoverEQ/CrossoverEQControls.cpp b/plugins/CrossoverEQ/CrossoverEQControls.cpp
index 9758d804a..928797dc5 100644
--- a/plugins/CrossoverEQ/CrossoverEQControls.cpp
+++ b/plugins/CrossoverEQ/CrossoverEQControls.cpp
@@ -121,4 +121,4 @@ void CrossoverEQControls::sampleRateChanged()
}
-} // namespace lmms
\ No newline at end of file
+} // namespace lmms
diff --git a/plugins/CrossoverEQ/artwork.png b/plugins/CrossoverEQ/artwork.png
deleted file mode 100644
index ffd2788ab..000000000
Binary files a/plugins/CrossoverEQ/artwork.png and /dev/null differ
diff --git a/plugins/CrossoverEQ/artwork.svg b/plugins/CrossoverEQ/artwork.svg
new file mode 100644
index 000000000..59ccf992a
--- /dev/null
+++ b/plugins/CrossoverEQ/artwork.svg
@@ -0,0 +1,18 @@
+
diff --git a/plugins/CrossoverEQ/fader_knob2.png b/plugins/CrossoverEQ/fader_knob2.png
deleted file mode 100644
index b5238ac06..000000000
Binary files a/plugins/CrossoverEQ/fader_knob2.png and /dev/null differ
diff --git a/plugins/CrossoverEQ/logo.png b/plugins/CrossoverEQ/logo.png
deleted file mode 100644
index 9340da708..000000000
Binary files a/plugins/CrossoverEQ/logo.png and /dev/null differ
diff --git a/plugins/CrossoverEQ/logo.svg b/plugins/CrossoverEQ/logo.svg
new file mode 100644
index 000000000..7920fa6b0
--- /dev/null
+++ b/plugins/CrossoverEQ/logo.svg
@@ -0,0 +1,3 @@
+
diff --git a/plugins/Delay/DelayControlsDialog.cpp b/plugins/Delay/DelayControlsDialog.cpp
index 065b3d1e4..6d3e4a3ec 100644
--- a/plugins/Delay/DelayControlsDialog.cpp
+++ b/plugins/Delay/DelayControlsDialog.cpp
@@ -44,32 +44,28 @@ DelayControlsDialog::DelayControlsDialog( DelayControls *controls ) :
setPalette( pal );
setFixedSize( 300, 208 );
- auto sampleDelayKnob = new TempoSyncKnob(KnobType::Bright26, this);
+ auto sampleDelayKnob = new TempoSyncKnob(KnobType::Bright26, tr("DELAY"), this, Knob::LabelRendering::LegacyFixedFontSize);
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(KnobType::Bright26, this);
+ auto feedbackKnob = new Knob(KnobType::Bright26, tr("FDBK"), this, Knob::LabelRendering::LegacyFixedFontSize);
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(KnobType::Bright26, this);
+ auto lfoFreqKnob = new TempoSyncKnob(KnobType::Bright26, tr("RATE"), this, Knob::LabelRendering::LegacyFixedFontSize);
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(KnobType::Bright26, this);
+ auto lfoAmtKnob = new TempoSyncKnob(KnobType::Bright26, tr("AMNT"), this, Knob::LabelRendering::LegacyFixedFontSize);
lfoAmtKnob->move( 11, 159 );
lfoAmtKnob->setVolumeKnob( false );
lfoAmtKnob->setModel( &controls->m_lfoAmountModel );
- lfoAmtKnob->setLabel( tr( "AMNT" ) );
lfoAmtKnob->setHintText( tr ( "LFO amount" ) + " " , " s" );
auto outFader
diff --git a/plugins/Delay/StereoDelay.cpp b/plugins/Delay/StereoDelay.cpp
index 3187b3f2a..7381dc3e3 100644
--- a/plugins/Delay/StereoDelay.cpp
+++ b/plugins/Delay/StereoDelay.cpp
@@ -24,7 +24,7 @@
#include "StereoDelay.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#include "SampleFrame.h"
namespace lmms
diff --git a/plugins/Delay/StereoDelay.h b/plugins/Delay/StereoDelay.h
index ad0e020b5..72b49a9df 100644
--- a/plugins/Delay/StereoDelay.h
+++ b/plugins/Delay/StereoDelay.h
@@ -25,7 +25,7 @@
#ifndef STEREODELAY_H
#define STEREODELAY_H
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms
diff --git a/plugins/Dispersion/CMakeLists.txt b/plugins/Dispersion/CMakeLists.txt
index a40e04b80..190a4ae86 100644
--- a/plugins/Dispersion/CMakeLists.txt
+++ b/plugins/Dispersion/CMakeLists.txt
@@ -1,3 +1,3 @@
INCLUDE(BuildPlugin)
-BUILD_PLUGIN(dispersion Dispersion.cpp DispersionControls.cpp DispersionControlDialog.cpp MOCFILES DispersionControls.h DispersionControlDialog.h EMBEDDED_RESOURCES *.png)
+BUILD_PLUGIN(dispersion Dispersion.cpp DispersionControls.cpp DispersionControlDialog.cpp MOCFILES DispersionControls.h DispersionControlDialog.h EMBEDDED_RESOURCES logo.svg)
diff --git a/plugins/Dispersion/DispersionControlDialog.cpp b/plugins/Dispersion/DispersionControlDialog.cpp
index 2879e7613..aacb48290 100644
--- a/plugins/Dispersion/DispersionControlDialog.cpp
+++ b/plugins/Dispersion/DispersionControlDialog.cpp
@@ -24,12 +24,14 @@
#include "DispersionControlDialog.h"
-#include "DispersionControls.h"
+#include
+
+#include "AutomatableButton.h"
+#include "DispersionControls.h"
#include "embed.h"
#include "Knob.h"
#include "LcdSpinBox.h"
-#include "PixmapButton.h"
namespace lmms::gui
@@ -40,42 +42,37 @@ DispersionControlDialog::DispersionControlDialog(DispersionControls* controls) :
EffectControlDialog(controls)
{
setAutoFillBackground(true);
- QPalette pal;
- pal.setBrush(backgroundRole(), PLUGIN_NAME::getIconPixmap("artwork"));
- setPalette(pal);
- setFixedSize(207, 50);
+ auto layout = new QHBoxLayout(this);
+ layout->setSpacing(5);
- 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"));
+ auto amountBox = new LcdSpinBox(3, this, "Amount");
+ amountBox->setModel(&controls->m_amountModel);
+ amountBox->setLabel(tr("AMOUNT"));
+ amountBox->setToolTip(tr("Number of all-pass filters"));
+ layout->addWidget(amountBox);
- Knob * freqKnob = new Knob(KnobType::Bright26, this);
- freqKnob->move(59, 8);
+ auto freqKnob = new Knob(KnobType::Bright26, tr("FREQ"), this);
freqKnob->setModel(&controls->m_freqModel);
- freqKnob->setLabel(tr("FREQ"));
- freqKnob->setHintText(tr("Frequency:") , " Hz");
+ freqKnob->setHintText(tr("Frequency:") , tr("Hz"));
+ layout->addWidget(freqKnob);
- Knob * resoKnob = new Knob(KnobType::Bright26, this);
- resoKnob->move(99, 8);
+ auto resoKnob = new Knob(KnobType::Bright26, tr("RESO"), this);
resoKnob->setModel(&controls->m_resoModel);
- resoKnob->setLabel(tr("RESO"));
- resoKnob->setHintText(tr("Resonance:") , " octaves");
+ resoKnob->setHintText(tr("Resonance:") , tr("octaves"));
+ layout->addWidget(resoKnob);
- Knob * feedbackKnob = new Knob(KnobType::Bright26, this);
- feedbackKnob->move(139, 8);
+ auto feedbackKnob = new Knob(KnobType::Bright26, tr("FEED"), this);
feedbackKnob->setModel(&controls->m_feedbackModel);
- feedbackKnob->setLabel(tr("FEED"));
feedbackKnob->setHintText(tr("Feedback:") , "");
+ layout->addWidget(feedbackKnob);
- 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"));
+ auto dcButton = new AutomatableButton(this, tr("DC Offset Removal"));
dcButton->setCheckable(true);
+ dcButton->setText(tr("DC"));
dcButton->setModel(&controls->m_dcModel);
dcButton->setToolTip(tr("Remove DC Offset"));
+ dcButton->setObjectName("btn");
+ layout->addWidget(dcButton);
}
diff --git a/plugins/Dispersion/artwork.png b/plugins/Dispersion/artwork.png
deleted file mode 100644
index 17e3b9a11..000000000
Binary files a/plugins/Dispersion/artwork.png and /dev/null differ
diff --git a/plugins/Dispersion/dc_active.png b/plugins/Dispersion/dc_active.png
deleted file mode 100644
index d9c8c9378..000000000
Binary files a/plugins/Dispersion/dc_active.png and /dev/null differ
diff --git a/plugins/Dispersion/dc_inactive.png b/plugins/Dispersion/dc_inactive.png
deleted file mode 100644
index 9a0ee0693..000000000
Binary files a/plugins/Dispersion/dc_inactive.png and /dev/null differ
diff --git a/plugins/Dispersion/logo.png b/plugins/Dispersion/logo.png
deleted file mode 100644
index 9340da708..000000000
Binary files a/plugins/Dispersion/logo.png and /dev/null differ
diff --git a/plugins/Dispersion/logo.svg b/plugins/Dispersion/logo.svg
new file mode 100644
index 000000000..7920fa6b0
--- /dev/null
+++ b/plugins/Dispersion/logo.svg
@@ -0,0 +1,3 @@
+
diff --git a/plugins/DualFilter/CMakeLists.txt b/plugins/DualFilter/CMakeLists.txt
index 9aca1a7d5..a9839b4db 100644
--- a/plugins/DualFilter/CMakeLists.txt
+++ b/plugins/DualFilter/CMakeLists.txt
@@ -1,3 +1,3 @@
INCLUDE(BuildPlugin)
-BUILD_PLUGIN(dualfilter DualFilter.cpp DualFilterControls.cpp DualFilterControlDialog.cpp MOCFILES DualFilterControls.h DualFilterControlDialog.h EMBEDDED_RESOURCES artwork.png logo.png)
+BUILD_PLUGIN(dualfilter DualFilter.cpp DualFilterControls.cpp DualFilterControlDialog.cpp MOCFILES DualFilterControls.h DualFilterControlDialog.h EMBEDDED_RESOURCES artwork.svg logo.svg)
diff --git a/plugins/DualFilter/DualFilterControlDialog.cpp b/plugins/DualFilter/DualFilterControlDialog.cpp
index a674a4a42..6d051b256 100644
--- a/plugins/DualFilter/DualFilterControlDialog.cpp
+++ b/plugins/DualFilter/DualFilterControlDialog.cpp
@@ -26,6 +26,7 @@
#include "DualFilterControlDialog.h"
#include "DualFilterControls.h"
+#include "FontHelper.h"
#include "Knob.h"
#include "LedCheckBox.h"
#include "ComboBox.h"
@@ -35,10 +36,9 @@ namespace lmms::gui
#define makeknob( name, x, y, model, label, hint, unit ) \
- Knob * name = new Knob( KnobType::Bright26, this); \
+ Knob * name = new Knob(KnobType::Bright26, label, SMALL_FONT_SIZE, this); \
(name) -> move( x, y ); \
(name) ->setModel( &controls-> model ); \
- (name) ->setLabel( label ); \
(name) ->setHintText( hint, unit );
diff --git a/plugins/DualFilter/artwork.png b/plugins/DualFilter/artwork.png
deleted file mode 100644
index 00458f101..000000000
Binary files a/plugins/DualFilter/artwork.png and /dev/null differ
diff --git a/plugins/DualFilter/artwork.svg b/plugins/DualFilter/artwork.svg
new file mode 100644
index 000000000..d26ec9113
--- /dev/null
+++ b/plugins/DualFilter/artwork.svg
@@ -0,0 +1,22 @@
+
diff --git a/plugins/DualFilter/logo.png b/plugins/DualFilter/logo.png
deleted file mode 100644
index 9340da708..000000000
Binary files a/plugins/DualFilter/logo.png and /dev/null differ
diff --git a/plugins/DualFilter/logo.svg b/plugins/DualFilter/logo.svg
new file mode 100644
index 000000000..7920fa6b0
--- /dev/null
+++ b/plugins/DualFilter/logo.svg
@@ -0,0 +1,3 @@
+
diff --git a/plugins/DynamicsProcessor/DynamicsProcessorControlDialog.cpp b/plugins/DynamicsProcessor/DynamicsProcessorControlDialog.cpp
index bd076b946..62838d5f4 100644
--- a/plugins/DynamicsProcessor/DynamicsProcessorControlDialog.cpp
+++ b/plugins/DynamicsProcessor/DynamicsProcessorControlDialog.cpp
@@ -28,6 +28,7 @@
#include "DynamicsProcessorControlDialog.h"
#include "DynamicsProcessorControls.h"
#include "embed.h"
+#include "FontHelper.h"
#include "Graph.h"
#include "Knob.h"
#include "PixmapButton.h"
@@ -58,32 +59,28 @@ DynProcControlDialog::DynProcControlDialog(
waveGraph->setGraphColor( QColor( 85, 204, 145 ) );
waveGraph -> setMaximumSize( 204, 205 );
- auto inputKnob = new Knob(KnobType::Bright26, this);
+ auto inputKnob = new Knob(KnobType::Bright26, tr("INPUT"), SMALL_FONT_SIZE, this);
inputKnob -> setVolumeKnob( true );
inputKnob -> setVolumeRatio( 1.0 );
inputKnob -> move( 26, 223 );
inputKnob->setModel( &_controls->m_inputModel );
- inputKnob->setLabel( tr( "INPUT" ) );
inputKnob->setHintText( tr( "Input gain:" ) , "" );
- auto outputKnob = new Knob(KnobType::Bright26, this);
+ auto outputKnob = new Knob(KnobType::Bright26, tr("OUTPUT"), SMALL_FONT_SIZE, this);
outputKnob -> setVolumeKnob( true );
outputKnob -> setVolumeRatio( 1.0 );
outputKnob -> move( 76, 223 );
outputKnob->setModel( &_controls->m_outputModel );
- outputKnob->setLabel( tr( "OUTPUT" ) );
outputKnob->setHintText( tr( "Output gain:" ) , "" );
- auto attackKnob = new Knob(KnobType::Bright26, this);
+ auto attackKnob = new Knob(KnobType::Bright26, tr("ATTACK"), SMALL_FONT_SIZE, 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(KnobType::Bright26, this);
+ auto releaseKnob = new Knob(KnobType::Bright26, tr("RELEASE"), SMALL_FONT_SIZE, this);
releaseKnob -> move( 74, 268 );
releaseKnob->setModel( &_controls->m_releaseModel );
- releaseKnob->setLabel( tr( "RELEASE" ) );
releaseKnob->setHintText( tr( "Peak release time:" ) , "ms" );
//wavegraph control buttons
diff --git a/plugins/Eq/EqSpectrumView.h b/plugins/Eq/EqSpectrumView.h
index 448c0e378..8246c89bb 100644
--- a/plugins/Eq/EqSpectrumView.h
+++ b/plugins/Eq/EqSpectrumView.h
@@ -27,7 +27,7 @@
#include
#include "fft_helpers.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms
{
diff --git a/plugins/Flanger/CMakeLists.txt b/plugins/Flanger/CMakeLists.txt
index e74b2838f..54ecdd85e 100644
--- a/plugins/Flanger/CMakeLists.txt
+++ b/plugins/Flanger/CMakeLists.txt
@@ -3,5 +3,5 @@ INCLUDE(BuildPlugin)
BUILD_PLUGIN(
flanger FlangerEffect.cpp FlangerControls.cpp FlangerControlsDialog.cpp MonoDelay.cpp
MOCFILES FlangerControls.h FlangerControlsDialog.h
- EMBEDDED_RESOURCES artwork.png logo.png
+ EMBEDDED_RESOURCES artwork.svg logo.svg
)
diff --git a/plugins/Flanger/FlangerControlsDialog.cpp b/plugins/Flanger/FlangerControlsDialog.cpp
index 3ac5dc9c6..e39b122ce 100644
--- a/plugins/Flanger/FlangerControlsDialog.cpp
+++ b/plugins/Flanger/FlangerControlsDialog.cpp
@@ -29,6 +29,8 @@
#include "LedCheckBox.h"
#include "TempoSyncKnob.h"
+#include
+
namespace lmms::gui
{
@@ -40,55 +42,52 @@ FlangerControlsDialog::FlangerControlsDialog( FlangerControls *controls ) :
QPalette pal;
pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) );
setPalette( pal );
- setFixedSize( 233, 75 );
- auto delayKnob = new Knob(KnobType::Bright26, this);
- delayKnob->move( 10,10 );
+ auto mainLayout = new QVBoxLayout(this);
+ auto knobLayout = new QHBoxLayout();
+ mainLayout->addLayout(knobLayout);
+
+ auto delayKnob = new Knob(KnobType::Bright26, tr("DELAY"), this);
delayKnob->setVolumeKnob( false );
delayKnob->setModel( &controls->m_delayTimeModel );
- delayKnob->setLabel( tr( "DELAY" ) );
delayKnob->setHintText( tr( "Delay time:" ) + " ", "s" );
- auto lfoFreqKnob = new TempoSyncKnob(KnobType::Bright26, this);
- lfoFreqKnob->move( 48,10 );
+ auto lfoFreqKnob = new TempoSyncKnob(KnobType::Bright26, tr("RATE"), this);
lfoFreqKnob->setVolumeKnob( false );
lfoFreqKnob->setModel( &controls->m_lfoFrequencyModel );
- lfoFreqKnob->setLabel( tr( "RATE" ) );
lfoFreqKnob->setHintText( tr( "Period:" ) , " Sec" );
- auto lfoAmtKnob = new Knob(KnobType::Bright26, this);
- lfoAmtKnob->move( 85,10 );
+ auto lfoAmtKnob = new Knob(KnobType::Bright26, tr("AMNT"), this);
lfoAmtKnob->setVolumeKnob( false );
lfoAmtKnob->setModel( &controls->m_lfoAmountModel );
- lfoAmtKnob->setLabel( tr( "AMNT" ) );
lfoAmtKnob->setHintText( tr( "Amount:" ) , "" );
- auto lfoPhaseKnob = new Knob(KnobType::Bright26, this);
- lfoPhaseKnob->move( 123,10 );
+ auto lfoPhaseKnob = new Knob(KnobType::Bright26, tr("PHASE"), this);
lfoPhaseKnob->setVolumeKnob( false );
lfoPhaseKnob->setModel( &controls->m_lfoPhaseModel );
- lfoPhaseKnob->setLabel( tr( "PHASE" ) );
lfoPhaseKnob->setHintText( tr( "Phase:" ) , " degrees" );
- auto feedbackKnob = new Knob(KnobType::Bright26, this);
- feedbackKnob->move( 160,10 );
+ auto feedbackKnob = new Knob(KnobType::Bright26, tr("FDBK"), this);
feedbackKnob->setVolumeKnob( true) ;
feedbackKnob->setModel( &controls->m_feedbackModel );
- feedbackKnob->setLabel( tr( "FDBK" ) );
feedbackKnob->setHintText( tr( "Feedback amount:" ) , "" );
- auto whiteNoiseKnob = new Knob(KnobType::Bright26, this);
- whiteNoiseKnob->move( 196,10 );
+ auto whiteNoiseKnob = new Knob(KnobType::Bright26, tr("NOISE"), this);
whiteNoiseKnob->setVolumeKnob( true) ;
whiteNoiseKnob->setModel( &controls->m_whiteNoiseAmountModel );
- whiteNoiseKnob->setLabel( tr( "NOISE" ) );
whiteNoiseKnob->setHintText( tr( "White noise amount:" ) , "" );
+ knobLayout->addWidget(delayKnob);
+ knobLayout->addWidget(lfoFreqKnob);
+ knobLayout->addWidget(lfoAmtKnob);
+ knobLayout->addWidget(lfoPhaseKnob);
+ knobLayout->addWidget(feedbackKnob);
+ knobLayout->addWidget(whiteNoiseKnob);
+
auto invertCb = new LedCheckBox(tr("Invert"), this);
- invertCb->move( 10,53 );
-
-
-
+ invertCb->setModel(&controls->m_invertFeedbackModel);
+
+ mainLayout->addWidget(invertCb, 0, Qt::AlignLeft);
}
diff --git a/plugins/Flanger/MonoDelay.h b/plugins/Flanger/MonoDelay.h
index 2e9324a7d..95bf460c5 100644
--- a/plugins/Flanger/MonoDelay.h
+++ b/plugins/Flanger/MonoDelay.h
@@ -25,7 +25,7 @@
#ifndef MONODELAY_H
#define MONODELAY_H
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms
{
diff --git a/plugins/Flanger/artwork.png b/plugins/Flanger/artwork.png
deleted file mode 100644
index bbe80e598..000000000
Binary files a/plugins/Flanger/artwork.png and /dev/null differ
diff --git a/plugins/Flanger/artwork.svg b/plugins/Flanger/artwork.svg
new file mode 100644
index 000000000..e2aaa2862
--- /dev/null
+++ b/plugins/Flanger/artwork.svg
@@ -0,0 +1,10 @@
+
diff --git a/plugins/Flanger/logo.png b/plugins/Flanger/logo.png
deleted file mode 100644
index 9340da708..000000000
Binary files a/plugins/Flanger/logo.png and /dev/null differ
diff --git a/plugins/Flanger/logo.svg b/plugins/Flanger/logo.svg
new file mode 100644
index 000000000..7920fa6b0
--- /dev/null
+++ b/plugins/Flanger/logo.svg
@@ -0,0 +1,3 @@
+
diff --git a/plugins/LOMM/LOMMControlDialog.cpp b/plugins/LOMM/LOMMControlDialog.cpp
index e53987a05..b3cf34506 100644
--- a/plugins/LOMM/LOMMControlDialog.cpp
+++ b/plugins/LOMM/LOMMControlDialog.cpp
@@ -47,24 +47,24 @@ LOMMControlDialog::LOMMControlDialog(LOMMControls* controls) :
createKnob(KnobType::Bright26, this, 363, 220, &controls->m_outVolModel, tr("Output Volume:"), " dB", tr("Output volume"));
createKnob(KnobType::Bright26, this, 10, 179, &controls->m_upwardModel, tr("Upward Depth:"), "", tr("Upward compression amount for all bands"));
createKnob(KnobType::Bright26, this, 363, 179, &controls->m_downwardModel, tr("Downward Depth:"), "", tr("Downward compression amount for all bands"));
-
+
createLcdFloatSpinBox(5, 2, "11green", tr("High/Mid Crossover"), this, 352, 76, &controls->m_split1Model, tr("High/Mid Crossover"));
createLcdFloatSpinBox(5, 2, "11green", tr("Mid/Low Crossover"), this, 352, 156, &controls->m_split2Model, tr("Mid/Low Crossover"));
-
+
createPixmapButton(tr("High/mid band split"), this, 369, 104, &controls->m_split1EnabledModel, "crossover_led_green", "crossover_led_off", tr("High/mid band split"));
createPixmapButton(tr("Mid/low band split"), this, 369, 126, &controls->m_split2EnabledModel, "crossover_led_green", "crossover_led_off", tr("Mid/low band split"));
-
+
createPixmapButton(tr("Enable High Band"), this, 143, 66, &controls->m_band1EnabledModel, "high_band_active", "high_band_inactive", tr("Enable High Band"));
createPixmapButton(tr("Enable Mid Band"), this, 143, 146, &controls->m_band2EnabledModel, "mid_band_active", "mid_band_inactive", tr("Enable Mid Band"));
createPixmapButton(tr("Enable Low Band"), this, 143, 226, &controls->m_band3EnabledModel, "low_band_active", "low_band_inactive", tr("Enable Low Band"));
-
+
createKnob(KnobType::Bright26, this, 53, 43, &controls->m_inHighModel, tr("High Input Volume:"), " dB", tr("Input volume for high band"));
createKnob(KnobType::Bright26, this, 53, 123, &controls->m_inMidModel, tr("Mid Input Volume:"), " dB", tr("Input volume for mid band"));
createKnob(KnobType::Bright26, this, 53, 203, &controls->m_inLowModel, tr("Low Input Volume:"), " dB", tr("Input volume for low band"));
createKnob(KnobType::Bright26, this, 320, 43, &controls->m_outHighModel, tr("High Output Volume:"), " dB", tr("Output volume for high band"));
createKnob(KnobType::Bright26, this, 320, 123, &controls->m_outMidModel, tr("Mid Output Volume:"), " dB", tr("Output volume for mid band"));
createKnob(KnobType::Bright26, this, 320, 203, &controls->m_outLowModel, tr("Low Output Volume:"), " dB", tr("Output volume for low band"));
-
+
createLcdFloatSpinBox(3, 3, "11green", tr("Above Threshold High"), this, 300, 13, &controls->m_aThreshHModel, tr("Downward compression threshold for high band"));
createLcdFloatSpinBox(3, 3, "11green", tr("Above Threshold Mid"), this, 300, 93, &controls->m_aThreshMModel, tr("Downward compression threshold for mid band"));
createLcdFloatSpinBox(3, 3, "11green", tr("Above Threshold Low"), this, 300, 173, &controls->m_aThreshLModel, tr("Downward compression threshold for low band"));
@@ -78,27 +78,27 @@ LOMMControlDialog::LOMMControlDialog(LOMMControls* controls) :
createLcdFloatSpinBox(2, 2, "11green", tr("Below Ratio High"), this, 87, 44, &controls->m_bRatioHModel, tr("Upward compression ratio for high band"));
createLcdFloatSpinBox(2, 2, "11green", tr("Below Ratio Mid"), this, 87, 124, &controls->m_bRatioMModel, tr("Upward compression ratio for mid band"));
createLcdFloatSpinBox(2, 2, "11green", tr("Below Ratio Low"), this, 87, 204, &controls->m_bRatioLModel, tr("Upward compression ratio for low band"));
-
+
createKnob(KnobType::Small17, this, 120, 61, &controls->m_atkHModel, tr("Attack High:"), " ms", tr("Attack time for high band"));
createKnob(KnobType::Small17, this, 120, 141, &controls->m_atkMModel, tr("Attack Mid:"), " ms", tr("Attack time for mid band"));
createKnob(KnobType::Small17, this, 120, 221, &controls->m_atkLModel, tr("Attack Low:"), " ms", tr("Attack time for low band"));
createKnob(KnobType::Small17, this, 261, 61, &controls->m_relHModel, tr("Release High:"), " ms", tr("Release time for high band"));
createKnob(KnobType::Small17, this, 261, 141, &controls->m_relMModel, tr("Release Mid:"), " ms", tr("Release time for mid band"));
createKnob(KnobType::Small17, this, 261, 221, &controls->m_relLModel, tr("Release Low:"), " ms", tr("Release time for low band"));
-
+
createKnob(KnobType::Small17, this, 380, 42, &controls->m_rmsTimeModel, tr("RMS Time:"), " ms", tr("RMS size for sidechain signal (set to 0 for Peak mode)"));
createKnob(KnobType::Small17, this, 356, 42, &controls->m_kneeModel, tr("Knee:"), " dB", tr("Knee size for all compressors"));
createKnob(KnobType::Small17, this, 24, 146, &controls->m_rangeModel, tr("Range:"), " dB", tr("Maximum gain increase for all bands"));
createKnob(KnobType::Small17, this, 13, 114, &controls->m_balanceModel, tr("Balance:"), " dB", tr("Bias input volume towards one channel"));
-
+
createPixmapButton(tr("Scale output volume with Depth"), this, 51, 0, &controls->m_depthScalingModel, "depthScaling_active", "depthScaling_inactive",
tr("Scale output volume with Depth parameter"));
createPixmapButton(tr("Stereo Link"), this, 52, 237, &controls->m_stereoLinkModel, "stereoLink_active", "stereoLink_inactive",
tr("Apply same gain change to both channels"));
-
+
createKnob(KnobType::Small17, this, 24, 80, &controls->m_autoTimeModel, tr("Auto Time:"), "", tr("Speed up attack and release times when transients occur"));
createKnob(KnobType::Bright26, this, 363, 4, &controls->m_mixModel, tr("Mix:"), "", tr("Wet/Dry of all bands"));
-
+
m_feedbackButton = createPixmapButton(tr("Feedback"), this, 317, 238, &controls->m_feedbackModel, "feedback_active", "feedback_inactive",
tr("Use output as sidechain signal instead of input"));
createPixmapButton(tr("Mid/Side"), this, 285, 238, &controls->m_midsideModel, "midside_active", "midside_inactive", tr("Compress mid/side channels instead of left/right"));
@@ -107,14 +107,15 @@ LOMMControlDialog::LOMMControlDialog(LOMMControls* controls) :
createPixmapButton(tr("Lookahead"), this, 147, 0, &controls->m_lookaheadEnableModel, "lookahead_active", "lookahead_inactive",
tr(("Enable lookahead with fixed " + std::to_string(int(LOMM_MAX_LOOKAHEAD)) + " ms latency").c_str()));
createLcdFloatSpinBox(2, 2, "11green", tr("Lookahead"), this, 214, 2, &controls->m_lookaheadModel, tr("Lookahead length"));
-
+
PixmapButton* initButton = createPixmapButton(tr("Clear all parameters"), this, 84, 237, nullptr, "init_active", "init_inactive", tr("Clear all parameters"));
-
+ initButton->setCheckable(false);
+
connect(initButton, SIGNAL(clicked()), m_controls, SLOT(resetAllParameters()));
connect(&controls->m_lookaheadEnableModel, SIGNAL(dataChanged()), this, SLOT(updateFeedbackVisibility()));
connect(&controls->m_midsideModel, SIGNAL(dataChanged()), this, SLOT(updateLowSideUpwardSuppressVisibility()));
connect(getGUI()->mainWindow(), SIGNAL(periodicUpdate()), this, SLOT(updateDisplay()));
-
+
emit updateFeedbackVisibility();
emit updateLowSideUpwardSuppressVisibility();
}
@@ -161,7 +162,7 @@ void LOMMControlDialog::paintEvent(QPaintEvent *event)
p.fillRect(LOMM_DISPLAY_X, LOMM_DISPLAY_Y[2 * i], thresholdsX[i + 3] - LOMM_DISPLAY_X, LOMM_DISPLAY_Y[2 * i + 1] + LOMM_DISPLAY_HEIGHT - LOMM_DISPLAY_Y[2 * i], bColor);
p.drawLine(thresholdsX[i + 3], LOMM_DISPLAY_Y[2 * i], thresholdsX[i + 3], LOMM_DISPLAY_Y[2 * i + 1] + LOMM_DISPLAY_HEIGHT);
}
-
+
QPen inputPen(QColor(200, 200, 200, 80), 1);
QPen outputPen(QColor(255, 255, 255, 255), 1);
for (int i = 0; i < 3; ++i) {
@@ -239,10 +240,10 @@ void LOMMControlDialog::mouseMoveEvent(QMouseEvent * event)
const float distance = event->pos().x() - m_lastMousePos.x();
float dbDistance = distance * LOMM_DISPLAY_DB_PER_PIXEL;
m_lastMousePos = event->pos();
-
+
FloatModel* aModel[] = {&m_controls->m_aThreshHModel, &m_controls->m_aThreshMModel, &m_controls->m_aThreshLModel};
FloatModel* bModel[] = {&m_controls->m_bThreshHModel, &m_controls->m_bThreshMModel, &m_controls->m_bThreshLModel};
-
+
float bVal = bModel[m_bandDrag]->value();
float aVal = aModel[m_bandDrag]->value();
if (m_dragType == 0)
diff --git a/plugins/LadspaEffect/LadspaMatrixControlDialog.h b/plugins/LadspaEffect/LadspaMatrixControlDialog.h
index c5949fa15..fa9a6e1b3 100644
--- a/plugins/LadspaEffect/LadspaMatrixControlDialog.h
+++ b/plugins/LadspaEffect/LadspaMatrixControlDialog.h
@@ -28,7 +28,7 @@
#include "EffectControlDialog.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
class QGridLayout;
diff --git a/plugins/Lb302/Lb302.cpp b/plugins/Lb302/Lb302.cpp
index 5a085df4d..ab910d134 100644
--- a/plugins/Lb302/Lb302.cpp
+++ b/plugins/Lb302/Lb302.cpp
@@ -831,22 +831,18 @@ Lb302SynthView::Lb302SynthView( Instrument * _instrument, QWidget * _parent ) :
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( KnobType::Bright26, this );
m_vcfResKnob->move( 120, 130 );
m_vcfResKnob->setHintText( tr( "Resonance:" ), "" );
- m_vcfResKnob->setLabel( "" );
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( KnobType::Bright26, this );
m_vcfDecKnob->move( 210, 130 );
m_vcfDecKnob->setHintText( tr( "Decay:" ), "" );
- m_vcfDecKnob->setLabel( "" );
m_slideToggle = new LedCheckBox( "", this );
m_slideToggle->move( 10, 180 );
@@ -867,12 +863,10 @@ Lb302SynthView::Lb302SynthView( Instrument * _instrument, QWidget * _parent ) :
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( KnobType::Bright26, this );
m_distKnob->move( 210, 190 );
m_distKnob->setHintText( tr( "DIST:" ), "" );
- m_distKnob->setLabel( tr( ""));
// Shapes
diff --git a/plugins/MidiImport/MidiImport.cpp b/plugins/MidiImport/MidiImport.cpp
index 785cd079a..24fed85df 100644
--- a/plugins/MidiImport/MidiImport.cpp
+++ b/plugins/MidiImport/MidiImport.cpp
@@ -43,7 +43,6 @@
#include "GuiApplication.h"
#include "MainWindow.h"
#include "TimePos.h"
-#include "debug.h"
#include "Song.h"
#include "plugin_export.h"
diff --git a/plugins/MultitapEcho/MultitapEcho.cpp b/plugins/MultitapEcho/MultitapEcho.cpp
index 3d92e5ae8..ab84138aa 100644
--- a/plugins/MultitapEcho/MultitapEcho.cpp
+++ b/plugins/MultitapEcho/MultitapEcho.cpp
@@ -25,7 +25,7 @@
#include "MultitapEcho.h"
#include "embed.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#include "lmms_math.h"
#include "plugin_export.h"
diff --git a/plugins/MultitapEcho/MultitapEchoControlDialog.cpp b/plugins/MultitapEcho/MultitapEchoControlDialog.cpp
index e89137bf0..8a7c40a37 100644
--- a/plugins/MultitapEcho/MultitapEchoControlDialog.cpp
+++ b/plugins/MultitapEcho/MultitapEchoControlDialog.cpp
@@ -27,6 +27,7 @@
#include "MultitapEchoControlDialog.h"
#include "MultitapEchoControls.h"
#include "embed.h"
+#include "FontHelper.h"
#include "Graph.h"
#include "LedCheckBox.h"
#include "Knob.h"
@@ -78,22 +79,19 @@ MultitapEchoControlDialog::MultitapEchoControlDialog( MultitapEchoControls * con
// knobs
- auto stepLength = new TempoSyncKnob(KnobType::Bright26, this);
+ auto stepLength = new TempoSyncKnob(KnobType::Bright26, tr("Length"), SMALL_FONT_SIZE, this);
stepLength->move( 100, 245 );
stepLength->setModel( & controls->m_stepLength );
- stepLength->setLabel( tr( "Length" ) );
stepLength->setHintText( tr( "Step length:" ) , " ms" );
- auto dryGain = new Knob(KnobType::Bright26, this);
+ auto dryGain = new Knob(KnobType::Bright26, tr("Dry"), SMALL_FONT_SIZE, this);
dryGain->move( 150, 245 );
dryGain->setModel( & controls->m_dryGain );
- dryGain->setLabel( tr( "Dry" ) );
dryGain->setHintText( tr( "Dry gain:" ) , " dBFS" );
- auto stages = new Knob(KnobType::Bright26, this);
+ auto stages = new Knob(KnobType::Bright26, tr("Stages"), SMALL_FONT_SIZE, this);
stages->move( 200, 245 );
stages->setModel( & controls->m_stages );
- stages->setLabel( tr( "Stages" ) );
stages->setHintText( tr( "Low-pass stages:" ) , "x" );
// switch led
diff --git a/plugins/OpulenZ/OpulenZ.cpp b/plugins/OpulenZ/OpulenZ.cpp
index 48dfb6c8c..f5c0e1a8d 100644
--- a/plugins/OpulenZ/OpulenZ.cpp
+++ b/plugins/OpulenZ/OpulenZ.cpp
@@ -51,7 +51,6 @@
#include
#include "embed.h"
-#include "debug.h"
#include "Knob.h"
#include "PixmapButton.h"
diff --git a/plugins/PeakControllerEffect/CMakeLists.txt b/plugins/PeakControllerEffect/CMakeLists.txt
index 0bdb73123..eca93f671 100644
--- a/plugins/PeakControllerEffect/CMakeLists.txt
+++ b/plugins/PeakControllerEffect/CMakeLists.txt
@@ -1,3 +1,3 @@
INCLUDE(BuildPlugin)
-BUILD_PLUGIN(peakcontrollereffect PeakControllerEffect.cpp PeakControllerEffectControls.cpp PeakControllerEffectControlDialog.cpp PeakControllerEffect.h PeakControllerEffectControls.h PeakControllerEffectControlDialog.h MOCFILES PeakControllerEffectControls.h PeakControllerEffectControlDialog.h EMBEDDED_RESOURCES artwork.png logo.png)
+BUILD_PLUGIN(peakcontrollereffect PeakControllerEffect.cpp PeakControllerEffectControls.cpp PeakControllerEffectControlDialog.cpp PeakControllerEffect.h PeakControllerEffectControls.h PeakControllerEffectControlDialog.h MOCFILES PeakControllerEffectControls.h PeakControllerEffectControlDialog.h EMBEDDED_RESOURCES artwork.svg logo.svg)
diff --git a/plugins/PeakControllerEffect/PeakControllerEffect.cpp b/plugins/PeakControllerEffect/PeakControllerEffect.cpp
index b6d053257..394a80efd 100644
--- a/plugins/PeakControllerEffect/PeakControllerEffect.cpp
+++ b/plugins/PeakControllerEffect/PeakControllerEffect.cpp
@@ -132,18 +132,8 @@ Effect::ProcessStatus PeakControllerEffect::processImpl(SampleFrame* buf, const
float curRMS = sqrt_neg(sum / frames);
const float tres = c.m_tresholdModel.value();
const float amount = c.m_amountModel.value() * c.m_amountMultModel.value();
- const float attack = 1.0f - c.m_attackModel.value();
- const float decay = 1.0f - c.m_decayModel.value();
-
curRMS = qAbs( curRMS ) < tres ? 0.0f : curRMS;
- float target = c.m_baseModel.value() + amount * curRMS;
- // Use decay when the volume is decreasing, attack otherwise.
- // Since direction can change as often as every sampleBuffer, it's difficult
- // to witness attack/decay working in isolation unless using large buffer sizes.
- const float t = target < m_lastSample ? decay : attack;
- // Set m_lastSample to the interpolation between itself and target.
- // When t is 1.0, m_lastSample snaps to target. When t is 0.0, m_lastSample shouldn't change.
- m_lastSample = std::clamp(m_lastSample + t * (target - m_lastSample), 0.0f, 1.0f);
+ m_lastSample = qBound( 0.0f, c.m_baseModel.value() + amount * curRMS, 1.0f );
return ProcessStatus::Continue;
}
diff --git a/plugins/PeakControllerEffect/PeakControllerEffectControlDialog.cpp b/plugins/PeakControllerEffect/PeakControllerEffectControlDialog.cpp
index e44d5bcc2..7ce05bc45 100644
--- a/plugins/PeakControllerEffect/PeakControllerEffectControlDialog.cpp
+++ b/plugins/PeakControllerEffect/PeakControllerEffectControlDialog.cpp
@@ -47,35 +47,28 @@ PeakControllerEffectControlDialog::PeakControllerEffectControlDialog(
QPalette pal;
pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) );
setPalette( pal );
- setFixedSize( 240, 80 );
- m_baseKnob = new Knob( KnobType::Bright26, this );
- m_baseKnob->setLabel( tr( "BASE" ) );
+ m_baseKnob = new Knob(KnobType::Bright26, tr("BASE"), this);
m_baseKnob->setModel( &_controls->m_baseModel );
m_baseKnob->setHintText( tr( "Base:" ) , "" );
- m_amountKnob = new Knob( KnobType::Bright26, this );
- m_amountKnob->setLabel( tr( "AMNT" ) );
+ m_amountKnob = new Knob(KnobType::Bright26, tr("AMNT"), this);
m_amountKnob->setModel( &_controls->m_amountModel );
m_amountKnob->setHintText( tr( "Modulation amount:" ) , "" );
- m_amountMultKnob = new Knob( KnobType::Bright26, this );
- m_amountMultKnob->setLabel( tr( "MULT" ) );
+ m_amountMultKnob = new Knob(KnobType::Bright26, tr("MULT"), this);
m_amountMultKnob->setModel( &_controls->m_amountMultModel );
m_amountMultKnob->setHintText( tr( "Amount multiplicator:" ) , "" );
- m_attackKnob = new Knob( KnobType::Bright26, this );
- m_attackKnob->setLabel( tr( "ATCK" ) );
+ m_attackKnob = new Knob(KnobType::Bright26, tr("ATCK"), this);
m_attackKnob->setModel( &_controls->m_attackModel );
m_attackKnob->setHintText( tr( "Attack:" ) , "" );
- m_decayKnob = new Knob( KnobType::Bright26, this );
- m_decayKnob->setLabel( tr( "DCAY" ) );
+ m_decayKnob = new Knob(KnobType::Bright26, tr("DCAY"), this);
m_decayKnob->setModel( &_controls->m_decayModel );
m_decayKnob->setHintText( tr( "Release:" ) , "" );
- m_tresholdKnob = new Knob( KnobType::Bright26, this );
- m_tresholdKnob->setLabel( tr( "TRSH" ) );
+ m_tresholdKnob = new Knob(KnobType::Bright26, tr("TRSH"), this);
m_tresholdKnob->setModel( &_controls->m_tresholdModel );
m_tresholdKnob->setHintText( tr( "Treshold:" ) , "" );
@@ -99,7 +92,6 @@ PeakControllerEffectControlDialog::PeakControllerEffectControlDialog(
ledLayout->addWidget( m_muteLed );
ledLayout->addWidget( m_absLed );
- mainLayout->setContentsMargins( 3, 10, 0, 0 );
mainLayout->addLayout( knobLayout );
mainLayout->addLayout( ledLayout );
diff --git a/plugins/PeakControllerEffect/artwork.png b/plugins/PeakControllerEffect/artwork.png
deleted file mode 100644
index 5977f83cc..000000000
Binary files a/plugins/PeakControllerEffect/artwork.png and /dev/null differ
diff --git a/plugins/PeakControllerEffect/artwork.svg b/plugins/PeakControllerEffect/artwork.svg
new file mode 100644
index 000000000..b3e7ba076
--- /dev/null
+++ b/plugins/PeakControllerEffect/artwork.svg
@@ -0,0 +1,10 @@
+
diff --git a/plugins/PeakControllerEffect/logo.png b/plugins/PeakControllerEffect/logo.png
deleted file mode 100644
index 9340da708..000000000
Binary files a/plugins/PeakControllerEffect/logo.png and /dev/null differ
diff --git a/plugins/PeakControllerEffect/logo.svg b/plugins/PeakControllerEffect/logo.svg
new file mode 100644
index 000000000..7920fa6b0
--- /dev/null
+++ b/plugins/PeakControllerEffect/logo.svg
@@ -0,0 +1,3 @@
+
diff --git a/plugins/ReverbSC/CMakeLists.txt b/plugins/ReverbSC/CMakeLists.txt
index f6f6c7ee7..4c0d7623c 100644
--- a/plugins/ReverbSC/CMakeLists.txt
+++ b/plugins/ReverbSC/CMakeLists.txt
@@ -15,5 +15,5 @@ BUILD_PLUGIN(
MOCFILES
ReverbSCControls.h
ReverbSCControlDialog.h
- EMBEDDED_RESOURCES artwork.png logo.png
+ EMBEDDED_RESOURCES artwork.svg logo.svg
)
diff --git a/plugins/ReverbSC/ReverbSCControlDialog.cpp b/plugins/ReverbSC/ReverbSCControlDialog.cpp
index 615d3823e..3be156396 100644
--- a/plugins/ReverbSC/ReverbSCControlDialog.cpp
+++ b/plugins/ReverbSC/ReverbSCControlDialog.cpp
@@ -29,6 +29,8 @@
#include "Knob.h"
#include "ReverbSCControls.h"
+#include
+
namespace lmms::gui
{
@@ -40,31 +42,29 @@ ReverbSCControlDialog::ReverbSCControlDialog( ReverbSCControls* controls ) :
QPalette pal;
pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) );
setPalette( pal );
- setFixedSize( 185, 55 );
- auto inputGainKnob = new Knob(KnobType::Bright26, this);
- inputGainKnob -> move( 16, 10 );
+ auto knobLayout = new QHBoxLayout(this);
+
+ auto inputGainKnob = new Knob(KnobType::Bright26, tr("Input"), this);
inputGainKnob->setModel( &controls->m_inputGainModel );
- inputGainKnob->setLabel( tr( "Input" ) );
inputGainKnob->setHintText( tr( "Input gain:" ) , "dB" );
- auto sizeKnob = new Knob(KnobType::Bright26, this);
- sizeKnob -> move( 57, 10 );
+ auto sizeKnob = new Knob(KnobType::Bright26, tr("Size"), this);
sizeKnob->setModel( &controls->m_sizeModel );
- sizeKnob->setLabel( tr( "Size" ) );
sizeKnob->setHintText( tr( "Size:" ) , "" );
- auto colorKnob = new Knob(KnobType::Bright26, this);
- colorKnob -> move( 98, 10 );
+ auto colorKnob = new Knob(KnobType::Bright26, tr("Color"), this);
colorKnob->setModel( &controls->m_colorModel );
- colorKnob->setLabel( tr( "Color" ) );
colorKnob->setHintText( tr( "Color:" ) , "" );
- auto outputGainKnob = new Knob(KnobType::Bright26, this);
- outputGainKnob -> move( 139, 10 );
+ auto outputGainKnob = new Knob(KnobType::Bright26, tr("Output"), this);
outputGainKnob->setModel( &controls->m_outputGainModel );
- outputGainKnob->setLabel( tr( "Output" ) );
outputGainKnob->setHintText( tr( "Output gain:" ) , "dB" );
+
+ knobLayout->addWidget(inputGainKnob);
+ knobLayout->addWidget(sizeKnob);
+ knobLayout->addWidget(colorKnob);
+ knobLayout->addWidget(outputGainKnob);
}
diff --git a/plugins/ReverbSC/artwork.png b/plugins/ReverbSC/artwork.png
deleted file mode 100644
index 6fe5168fa..000000000
Binary files a/plugins/ReverbSC/artwork.png and /dev/null differ
diff --git a/plugins/ReverbSC/artwork.svg b/plugins/ReverbSC/artwork.svg
new file mode 100644
index 000000000..04f0bb87e
--- /dev/null
+++ b/plugins/ReverbSC/artwork.svg
@@ -0,0 +1,10 @@
+
diff --git a/plugins/ReverbSC/logo.png b/plugins/ReverbSC/logo.png
deleted file mode 100644
index 9340da708..000000000
Binary files a/plugins/ReverbSC/logo.png and /dev/null differ
diff --git a/plugins/ReverbSC/logo.svg b/plugins/ReverbSC/logo.svg
new file mode 100644
index 000000000..7920fa6b0
--- /dev/null
+++ b/plugins/ReverbSC/logo.svg
@@ -0,0 +1,3 @@
+
diff --git a/plugins/SlicerT/SlicerT.h b/plugins/SlicerT/SlicerT.h
index 53b8bfb2a..6021f44a3 100644
--- a/plugins/SlicerT/SlicerT.h
+++ b/plugins/SlicerT/SlicerT.h
@@ -36,7 +36,7 @@
#include "Sample.h"
#include "SampleBuffer.h"
#include "SlicerTView.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms {
diff --git a/plugins/SlicerT/SlicerTView.cpp b/plugins/SlicerT/SlicerTView.cpp
index 7af2db143..1fc3effe7 100644
--- a/plugins/SlicerT/SlicerTView.cpp
+++ b/plugins/SlicerT/SlicerTView.cpp
@@ -71,6 +71,12 @@ SlicerTView::SlicerTView(SlicerT* instrument, QWidget* parent)
m_syncToggle->setToolTip(tr("Enable BPM sync"));
m_syncToggle->setModel(&m_slicerTParent->m_enableSync);
+ m_clearButton = new PixmapButton(this, tr("Clear all slices"));
+ m_clearButton->setActiveGraphic(PLUGIN_NAME::getIconPixmap("clear_slices_active"));
+ m_clearButton->setInactiveGraphic(PLUGIN_NAME::getIconPixmap("clear_slices_inactive"));
+ m_clearButton->setToolTip(tr("Clear all slices"));
+ connect(m_clearButton, &PixmapButton::clicked, this, &SlicerTView::clearSlices);
+
m_bpmBox = new LcdSpinBox(3, "19purple", this);
m_bpmBox->setToolTip(tr("Original sample BPM"));
m_bpmBox->setModel(&m_slicerTParent->m_originalBPM);
@@ -111,6 +117,19 @@ Knob* SlicerTView::createStyledKnob()
return newKnob;
}
+// Clear all notes
+void SlicerTView::clearSlices()
+{
+ m_slicerTParent->m_slicePoints.clear();
+
+ // Points are added to the start (0) and end (1) of the sample,
+ // so the whole sample can still be copied using MIDI.
+ m_slicerTParent->m_slicePoints.emplace_back(0);
+ m_slicerTParent->m_slicePoints.emplace_back(1);
+
+ emit m_slicerTParent->dataChanged();
+}
+
// copied from piano roll
void SlicerTView::exportMidi()
{
@@ -261,7 +280,7 @@ void SlicerTView::resizeEvent(QResizeEvent* re)
{
m_y1 = height() - s_bottomBoxOffset;
- // left box
+ // Left box
m_noteThresholdKnob->move(s_x1 - 25, m_y1);
m_fadeOutKnob->move(s_x2 - 25, m_y1);
@@ -271,8 +290,10 @@ void SlicerTView::resizeEvent(QResizeEvent* re)
m_bpmBox->move(s_x5 - 13, m_y1 + 4);
m_snapSetting->move(s_x6 - 8, m_y1 + 3);
- // right box
- m_syncToggle->move((width() - 100), m_y1 + 5);
+ // Right box
+ // For explanation on the choice of constants, look at #7850
+ m_syncToggle->move((width() - 100), m_y1 - 7);
+ m_clearButton->move((width() - 100), m_y1 + 17);
m_folderButton->move(width() - 20, height() - s_bottomBoxHeight - s_sampleBoxHeight + 1);
diff --git a/plugins/SlicerT/SlicerTView.h b/plugins/SlicerT/SlicerTView.h
index f24246621..c4d0da959 100644
--- a/plugins/SlicerT/SlicerTView.h
+++ b/plugins/SlicerT/SlicerTView.h
@@ -49,6 +49,7 @@ class SlicerTView : public InstrumentView
public slots:
void exportMidi();
void openFiles();
+ void clearSlices();
public:
SlicerTView(SlicerT* instrument, QWidget* parent);
@@ -87,6 +88,7 @@ private:
LcdSpinBox* m_bpmBox;
ComboBox* m_snapSetting;
PixmapButton* m_syncToggle;
+ PixmapButton* m_clearButton;
PixmapButton* m_folderButton;
QPushButton* m_resetButton;
diff --git a/plugins/SlicerT/clear_slices_active.png b/plugins/SlicerT/clear_slices_active.png
new file mode 100644
index 000000000..36b7f0f7e
Binary files /dev/null and b/plugins/SlicerT/clear_slices_active.png differ
diff --git a/plugins/SlicerT/clear_slices_inactive.png b/plugins/SlicerT/clear_slices_inactive.png
new file mode 100644
index 000000000..b39fb4974
Binary files /dev/null and b/plugins/SlicerT/clear_slices_inactive.png differ
diff --git a/plugins/SpectrumAnalyzer/Analyzer.cpp b/plugins/SpectrumAnalyzer/Analyzer.cpp
index 7b6086ed2..725c175a4 100644
--- a/plugins/SpectrumAnalyzer/Analyzer.cpp
+++ b/plugins/SpectrumAnalyzer/Analyzer.cpp
@@ -33,7 +33,7 @@
#endif
#include "embed.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#include "plugin_export.h"
namespace lmms
diff --git a/plugins/SpectrumAnalyzer/SaControlsDialog.cpp b/plugins/SpectrumAnalyzer/SaControlsDialog.cpp
index 8b2c0f35e..9645f7b83 100644
--- a/plugins/SpectrumAnalyzer/SaControlsDialog.cpp
+++ b/plugins/SpectrumAnalyzer/SaControlsDialog.cpp
@@ -32,6 +32,7 @@
#include "ComboBox.h"
#include "ComboBoxModel.h"
+#include "FontHelper.h"
#include "Knob.h"
#include "LedCheckBox.h"
#include "PixmapButton.h"
@@ -236,41 +237,36 @@ SaControlsDialog::SaControlsDialog(SaControls *controls, SaProcessor *processor)
controls_layout->setStretchFactor(advanced_widget, 10);
// Peak envelope resolution
- auto envelopeResolutionKnob = new Knob(KnobType::Small17, this);
+ auto envelopeResolutionKnob = new Knob(KnobType::Small17, tr("Envelope res."), SMALL_FONT_SIZE, 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."));
envelopeResolutionKnob->setHintText(tr("Maximum number of envelope points drawn per pixel:"), "");
advanced_layout->addWidget(envelopeResolutionKnob, 0, 0, 1, 1, Qt::AlignCenter);
// Spectrum graph resolution
- auto spectrumResolutionKnob = new Knob(KnobType::Small17, this);
+ auto spectrumResolutionKnob = new Knob(KnobType::Small17, tr("Spectrum res."), SMALL_FONT_SIZE, 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."));
spectrumResolutionKnob->setHintText(tr("Maximum number of spectrum points drawn per pixel:"), "");
advanced_layout->addWidget(spectrumResolutionKnob, 1, 0, 1, 1, Qt::AlignCenter);
// Peak falloff speed
- auto peakDecayFactorKnob = new Knob(KnobType::Small17, this);
+ auto peakDecayFactorKnob = new Knob(KnobType::Small17, tr("Falloff factor"), SMALL_FONT_SIZE, this);
peakDecayFactorKnob->setModel(&controls->m_peakDecayFactorModel);
- peakDecayFactorKnob->setLabel(tr("Falloff factor"));
peakDecayFactorKnob->setToolTip(tr("Decrease to make peaks fall faster."));
peakDecayFactorKnob->setHintText(tr("Multiply buffered value by"), "");
advanced_layout->addWidget(peakDecayFactorKnob, 0, 1, 1, 1, Qt::AlignCenter);
// Averaging weight
- auto averagingWeightKnob = new Knob(KnobType::Small17, this);
+ auto averagingWeightKnob = new Knob(KnobType::Small17, tr("Averaging weight"), SMALL_FONT_SIZE, this);
averagingWeightKnob->setModel(&controls->m_averagingWeightModel);
- averagingWeightKnob->setLabel(tr("Averaging weight"));
averagingWeightKnob->setToolTip(tr("Decrease to make averaging slower and smoother."));
averagingWeightKnob->setHintText(tr("New sample contributes"), "");
advanced_layout->addWidget(averagingWeightKnob, 1, 1, 1, 1, Qt::AlignCenter);
// Waterfall history size
- auto waterfallHeightKnob = new Knob(KnobType::Small17, this);
+ auto waterfallHeightKnob = new Knob(KnobType::Small17, tr("Waterfall height"), SMALL_FONT_SIZE, 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."));
waterfallHeightKnob->setHintText(tr("Number of lines to keep:"), "");
advanced_layout->addWidget(waterfallHeightKnob, 0, 2, 1, 1, Qt::AlignCenter);
@@ -278,25 +274,22 @@ SaControlsDialog::SaControlsDialog(SaControls *controls, SaProcessor *processor)
connect(&controls->m_waterfallHeightModel, &FloatModel::dataChanged, [=] {processor->reallocateBuffers();});
// Waterfall gamma correction
- auto waterfallGammaKnob = new Knob(KnobType::Small17, this);
+ auto waterfallGammaKnob = new Knob(KnobType::Small17, tr("Waterfall gamma"), SMALL_FONT_SIZE, 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."));
waterfallGammaKnob->setHintText(tr("Gamma value:"), "");
advanced_layout->addWidget(waterfallGammaKnob, 1, 2, 1, 1, Qt::AlignCenter);
// FFT window overlap
- auto windowOverlapKnob = new Knob(KnobType::Small17, this);
+ auto windowOverlapKnob = new Knob(KnobType::Small17, tr("Window overlap"), SMALL_FONT_SIZE, 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."));
windowOverlapKnob->setHintText(tr("Number of times each sample is processed:"), "");
advanced_layout->addWidget(windowOverlapKnob, 0, 3, 1, 1, Qt::AlignCenter);
// FFT zero padding
- auto zeroPaddingKnob = new Knob(KnobType::Small17, this);
+ auto zeroPaddingKnob = new Knob(KnobType::Small17, tr("Zero padding"), SMALL_FONT_SIZE, this);
zeroPaddingKnob->setModel(&controls->m_zeroPaddingModel);
- zeroPaddingKnob->setLabel(tr("Zero padding"));
zeroPaddingKnob->setToolTip(tr("Increase to get smoother-looking spectrum. Warning: high CPU usage."));
zeroPaddingKnob->setHintText(tr("Processing buffer is"), tr(" steps larger than input block"));
advanced_layout->addWidget(zeroPaddingKnob, 1, 3, 1, 1, Qt::AlignCenter);
diff --git a/plugins/SpectrumAnalyzer/SaProcessor.cpp b/plugins/SpectrumAnalyzer/SaProcessor.cpp
index 1ea80f126..d4e5456dc 100644
--- a/plugins/SpectrumAnalyzer/SaProcessor.cpp
+++ b/plugins/SpectrumAnalyzer/SaProcessor.cpp
@@ -27,11 +27,9 @@
#include
#include "lmms_math.h"
-#ifdef SA_DEBUG
- #include
-#endif
#include
#ifdef SA_DEBUG
+ #include
#include
#include
#endif
diff --git a/plugins/SpectrumAnalyzer/SaProcessor.h b/plugins/SpectrumAnalyzer/SaProcessor.h
index 3903bf9d6..12163f63b 100644
--- a/plugins/SpectrumAnalyzer/SaProcessor.h
+++ b/plugins/SpectrumAnalyzer/SaProcessor.h
@@ -33,7 +33,7 @@
#include
#include
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms
diff --git a/plugins/StereoEnhancer/StereoEnhancerControlDialog.cpp b/plugins/StereoEnhancer/StereoEnhancerControlDialog.cpp
index 05c78616e..1440a4be5 100644
--- a/plugins/StereoEnhancer/StereoEnhancerControlDialog.cpp
+++ b/plugins/StereoEnhancer/StereoEnhancerControlDialog.cpp
@@ -40,9 +40,8 @@ StereoEnhancerControlDialog::StereoEnhancerControlDialog(
{
auto l = new QHBoxLayout(this);
- auto widthKnob = new Knob(KnobType::Bright26, this);
+ auto widthKnob = new Knob(KnobType::Bright26, tr("WIDTH"), this);
widthKnob->setModel( &_controls->m_widthModel );
- widthKnob->setLabel( tr( "WIDTH" ) );
widthKnob->setHintText( tr( "Width:" ) , " samples" );
l->addWidget( widthKnob );
diff --git a/plugins/StereoMatrix/CMakeLists.txt b/plugins/StereoMatrix/CMakeLists.txt
index 4e6de02ca..2990f8ec8 100644
--- a/plugins/StereoMatrix/CMakeLists.txt
+++ b/plugins/StereoMatrix/CMakeLists.txt
@@ -1,4 +1,4 @@
INCLUDE(BuildPlugin)
-BUILD_PLUGIN(stereomatrix StereoMatrix.cpp StereoMatrixControls.cpp StereoMatrixControlDialog.cpp StereoMatrix.h StereoMatrixControls.h StereoMatrixControlDialog.h MOCFILES StereoMatrixControls.h StereoMatrixControlDialog.h EMBEDDED_RESOURCES artwork.png logo.png)
+BUILD_PLUGIN(stereomatrix StereoMatrix.cpp StereoMatrixControls.cpp StereoMatrixControlDialog.cpp StereoMatrix.h StereoMatrixControls.h StereoMatrixControlDialog.h MOCFILES StereoMatrixControls.h StereoMatrixControlDialog.h EMBEDDED_RESOURCES artwork.svg logo.svg)
diff --git a/plugins/StereoMatrix/StereoMatrixControlDialog.cpp b/plugins/StereoMatrix/StereoMatrixControlDialog.cpp
index da9a3aa9e..1530a0d25 100644
--- a/plugins/StereoMatrix/StereoMatrixControlDialog.cpp
+++ b/plugins/StereoMatrix/StereoMatrixControlDialog.cpp
@@ -23,10 +23,9 @@
*/
-
-
#include "StereoMatrixControlDialog.h"
+#include
#include "embed.h"
#include "Knob.h"
#include "StereoMatrixControls.h"
@@ -35,38 +34,32 @@ namespace lmms::gui
{
-StereoMatrixControlDialog::StereoMatrixControlDialog(
- StereoMatrixControls * _controls ) :
- EffectControlDialog( _controls )
+StereoMatrixControlDialog::StereoMatrixControlDialog(StereoMatrixControls* controls) :
+ EffectControlDialog(controls)
{
-
- setFixedSize( 160, 185 );
-
- setAutoFillBackground( true );
QPalette pal;
- pal.setBrush( backgroundRole(),
- PLUGIN_NAME::getIconPixmap( "artwork" ) );
- setPalette( pal );
+ setAutoFillBackground(true);
+ setFixedSize(160, 185);
+ pal.setBrush(backgroundRole(), PLUGIN_NAME::getIconPixmap("artwork"));
+ setPalette(pal);
- auto llKnob = new Knob(KnobType::Bright26, this);
- llKnob->setModel( &_controls->m_llModel );
- llKnob->setHintText( tr( "Left to Left Vol:" ) , "" );
- llKnob->move( 10, 79 );
+ auto layout = new QHBoxLayout(this);
- auto lrKnob = new Knob(KnobType::Bright26, this);
- lrKnob->setModel( &_controls->m_lrModel );
- lrKnob->setHintText( tr( "Left to Right Vol:" ) , "" );
- lrKnob->move( 48, 79 );
+ const auto makeKnob = [this, layout](
+ FloatModel *model,
+ const QString &txt_before
+ ) {
+ auto k = new Knob(KnobType::Bright26, this);
+ k->setModel(model);
+ k->setHintText(txt_before, "");
+ layout->addWidget(k, 0, Qt::AlignHCenter);
+ return k;
+ };
- 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(KnobType::Bright26, this);
- rrKnob->setModel( &_controls->m_rrModel );
- rrKnob->setHintText( tr( "Right to Right Vol:" ) , "" );
- rrKnob->move( 123, 79 );
+ makeKnob(&controls->m_llModel, tr("Left to Left Vol:"));
+ makeKnob(&controls->m_lrModel, tr("Left to Right Vol:"));
+ makeKnob(&controls->m_rlModel, tr("Right to Left Vol:"));
+ makeKnob(&controls->m_rrModel, tr("Right to Right Vol:"));
}
diff --git a/plugins/StereoMatrix/artwork.png b/plugins/StereoMatrix/artwork.png
deleted file mode 100644
index f76567fd2..000000000
Binary files a/plugins/StereoMatrix/artwork.png and /dev/null differ
diff --git a/plugins/StereoMatrix/artwork.svg b/plugins/StereoMatrix/artwork.svg
new file mode 100644
index 000000000..b54fa8530
--- /dev/null
+++ b/plugins/StereoMatrix/artwork.svg
@@ -0,0 +1,29 @@
+
diff --git a/plugins/StereoMatrix/logo.png b/plugins/StereoMatrix/logo.png
deleted file mode 100644
index 9340da708..000000000
Binary files a/plugins/StereoMatrix/logo.png and /dev/null differ
diff --git a/plugins/StereoMatrix/logo.svg b/plugins/StereoMatrix/logo.svg
new file mode 100644
index 000000000..7920fa6b0
--- /dev/null
+++ b/plugins/StereoMatrix/logo.svg
@@ -0,0 +1,3 @@
+
diff --git a/plugins/Stk/Mallets/Mallets.cpp b/plugins/Stk/Mallets/Mallets.cpp
index fecb15a76..5c9c11cca 100644
--- a/plugins/Stk/Mallets/Mallets.cpp
+++ b/plugins/Stk/Mallets/Mallets.cpp
@@ -37,6 +37,7 @@
#include "AudioEngine.h"
#include "ConfigManager.h"
#include "Engine.h"
+#include "FontHelper.h"
#include "GuiApplication.h"
#include "InstrumentTrack.h"
@@ -454,13 +455,11 @@ MalletsInstrumentView::MalletsInstrumentView( MalletsInstrument * _instrument,
connect( &_instrument->m_presetsModel, SIGNAL( dataChanged() ),
this, SLOT( changePreset() ) );
- m_spreadKnob = new Knob( KnobType::Vintage32, this );
- m_spreadKnob->setLabel( tr( "Spread" ) );
+ m_spreadKnob = new Knob(KnobType::Vintage32, tr("Spread"), SMALL_FONT_SIZE, this);
m_spreadKnob->move( 190, 140 );
m_spreadKnob->setHintText( tr( "Spread:" ), "" );
- m_randomKnob = new Knob(KnobType::Vintage32, this);
- m_randomKnob->setLabel(tr("Random"));
+ m_randomKnob = new Knob(KnobType::Vintage32, tr("Random"), SMALL_FONT_SIZE, this);
m_randomKnob->move(190, 190);
m_randomKnob->setHintText(tr("Random:"), "");
@@ -495,28 +494,23 @@ QWidget * MalletsInstrumentView::setupModalBarControls( QWidget * _parent )
auto widget = new QWidget(_parent);
widget->setFixedSize( 250, 250 );
- m_hardnessKnob = new Knob( KnobType::Vintage32, widget );
- m_hardnessKnob->setLabel( tr( "Hardness" ) );
+ m_hardnessKnob = new Knob(KnobType::Vintage32, tr("Hardness"), SMALL_FONT_SIZE, widget);
m_hardnessKnob->move( 30, 90 );
m_hardnessKnob->setHintText( tr( "Hardness:" ), "" );
- m_positionKnob = new Knob( KnobType::Vintage32, widget );
- m_positionKnob->setLabel( tr( "Position" ) );
+ m_positionKnob = new Knob(KnobType::Vintage32, tr("Position"), SMALL_FONT_SIZE, widget);
m_positionKnob->move( 110, 90 );
m_positionKnob->setHintText( tr( "Position:" ), "" );
- m_vibratoGainKnob = new Knob( KnobType::Vintage32, widget );
- m_vibratoGainKnob->setLabel( tr( "Vibrato gain" ) );
+ m_vibratoGainKnob = new Knob(KnobType::Vintage32, tr("Vibrato gain"), SMALL_FONT_SIZE, widget);
m_vibratoGainKnob->move( 30, 140 );
m_vibratoGainKnob->setHintText( tr( "Vibrato gain:" ), "" );
- m_vibratoFreqKnob = new Knob( KnobType::Vintage32, widget );
- m_vibratoFreqKnob->setLabel( tr( "Vibrato frequency" ) );
+ m_vibratoFreqKnob = new Knob(KnobType::Vintage32, tr("Vibrato frequency"), SMALL_FONT_SIZE, widget);
m_vibratoFreqKnob->move( 110, 140 );
m_vibratoFreqKnob->setHintText( tr( "Vibrato frequency:" ), "" );
- m_stickKnob = new Knob( KnobType::Vintage32, widget );
- m_stickKnob->setLabel( tr( "Stick mix" ) );
+ m_stickKnob = new Knob(KnobType::Vintage32, tr("Stick mix"), SMALL_FONT_SIZE, widget);
m_stickKnob->move( 190, 90 );
m_stickKnob->setHintText( tr( "Stick mix:" ), "" );
@@ -531,28 +525,23 @@ QWidget * MalletsInstrumentView::setupTubeBellControls( QWidget * _parent )
auto widget = new QWidget(_parent);
widget->setFixedSize( 250, 250 );
- m_modulatorKnob = new Knob( KnobType::Vintage32, widget );
- m_modulatorKnob->setLabel( tr( "Modulator" ) );
+ m_modulatorKnob = new Knob(KnobType::Vintage32, tr("Modulator"), SMALL_FONT_SIZE, widget);
m_modulatorKnob->move( 30, 90 );
m_modulatorKnob->setHintText( tr( "Modulator:" ), "" );
- m_crossfadeKnob = new Knob( KnobType::Vintage32, widget );
- m_crossfadeKnob->setLabel( tr( "Crossfade" ) );
+ m_crossfadeKnob = new Knob(KnobType::Vintage32, tr("Crossfade"), SMALL_FONT_SIZE, widget);
m_crossfadeKnob->move( 110, 90 );
m_crossfadeKnob->setHintText( tr( "Crossfade:" ), "" );
- m_lfoSpeedKnob = new Knob( KnobType::Vintage32, widget );
- m_lfoSpeedKnob->setLabel( tr( "LFO speed" ) );
+ m_lfoSpeedKnob = new Knob(KnobType::Vintage32, tr("LFO speed"), SMALL_FONT_SIZE, widget);
m_lfoSpeedKnob->move( 30, 140 );
m_lfoSpeedKnob->setHintText( tr( "LFO speed:" ), "" );
- m_lfoDepthKnob = new Knob( KnobType::Vintage32, widget );
- m_lfoDepthKnob->setLabel( tr( "LFO depth" ) );
+ m_lfoDepthKnob = new Knob(KnobType::Vintage32, tr("LFO depth"), SMALL_FONT_SIZE, widget);
m_lfoDepthKnob->move( 110, 140 );
m_lfoDepthKnob->setHintText( tr( "LFO depth:" ), "" );
- m_adsrKnob = new Knob( KnobType::Vintage32, widget );
- m_adsrKnob->setLabel( tr( "ADSR" ) );
+ m_adsrKnob = new Knob(KnobType::Vintage32, tr("ADSR"), SMALL_FONT_SIZE, widget);
m_adsrKnob->move( 190, 90 );
m_adsrKnob->setHintText( tr( "ADSR:" ), "" );
@@ -571,23 +560,19 @@ QWidget * MalletsInstrumentView::setupBandedWGControls( QWidget * _parent )
/* m_strikeLED = new LedCheckBox( tr( "Bowed" ), widget );
m_strikeLED->move( 138, 25 );*/
- m_pressureKnob = new Knob( KnobType::Vintage32, widget );
- m_pressureKnob->setLabel( tr( "Pressure" ) );
+ m_pressureKnob = new Knob(KnobType::Vintage32, tr("Pressure"), SMALL_FONT_SIZE, widget);
m_pressureKnob->move( 30, 90 );
m_pressureKnob->setHintText( tr( "Pressure:" ), "" );
-/* m_motionKnob = new Knob( KnobType::Vintage32, widget );
- m_motionKnob->setLabel( tr( "Motion" ) );
+/* m_motionKnob = new Knob(KnobType::Vintage32, tr("Motion"), SMALL_FONT_SIZE, widget);
m_motionKnob->move( 110, 90 );
m_motionKnob->setHintText( tr( "Motion:" ), "" );*/
- m_velocityKnob = new Knob( KnobType::Vintage32, widget );
- m_velocityKnob->setLabel( tr( "Speed" ) );
+ m_velocityKnob = new Knob(KnobType::Vintage32, tr("Speed"), SMALL_FONT_SIZE, widget);
m_velocityKnob->move( 30, 140 );
m_velocityKnob->setHintText( tr( "Speed:" ), "" );
-/* m_vibratoKnob = new Knob( KnobType::Vintage32, widget, tr( "Vibrato" ) );
- m_vibratoKnob->setLabel( tr( "Vibrato" ) );
+/* m_vibratoKnob = new Knob(KnobType::Vintage32, tr("Vibrato"), SMALL_FONT_SIZE, widget);
m_vibratoKnob->move( 110, 140 );
m_vibratoKnob->setHintText( tr( "Vibrato:" ), "" );*/
diff --git a/plugins/TripleOscillator/TripleOscillator.cpp b/plugins/TripleOscillator/TripleOscillator.cpp
index 61a6c4919..55ad80082 100644
--- a/plugins/TripleOscillator/TripleOscillator.cpp
+++ b/plugins/TripleOscillator/TripleOscillator.cpp
@@ -29,7 +29,6 @@
#include "TripleOscillator.h"
#include "AudioEngine.h"
#include "AutomatableButton.h"
-#include "debug.h"
#include "Engine.h"
#include "InstrumentTrack.h"
#include "Knob.h"
diff --git a/plugins/Vestige/CMakeLists.txt b/plugins/Vestige/CMakeLists.txt
index 0a5847889..874e8f61d 100644
--- a/plugins/Vestige/CMakeLists.txt
+++ b/plugins/Vestige/CMakeLists.txt
@@ -11,5 +11,5 @@ if(LMMS_BUILD_LINUX)
else()
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${PLUGIN_DIR}")
endif()
-build_plugin(vestige Vestige.cpp Vestige.h MOCFILES Vestige.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png")
+build_plugin(vestige Vestige.cpp Vestige.h MOCFILES Vestige.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png;*.svg")
target_link_libraries(vestige vstbase)
diff --git a/plugins/Vestige/Vestige.cpp b/plugins/Vestige/Vestige.cpp
index 05716008e..1bf9f257c 100644
--- a/plugins/Vestige/Vestige.cpp
+++ b/plugins/Vestige/Vestige.cpp
@@ -79,10 +79,14 @@ Plugin::Descriptor Q_DECL_EXPORT vestige_plugin_descriptor =
0x0100,
Plugin::Type::Instrument,
new PluginPixmapLoader( "logo" ),
-#ifdef LMMS_BUILD_LINUX
- "dll,so",
-#else
+#if defined(LMMS_BUILD_WIN32)
"dll",
+#elif defined(LMMS_BUILD_LINUX)
+# if defined(LMMS_HAVE_VST_32) || defined(LMMS_HAVE_VST_64)
+ "dll,so",
+# else
+ "so",
+# endif
#endif
nullptr,
} ;
@@ -669,13 +673,17 @@ void VestigeInstrumentView::openPlugin()
// set filters
QStringList types;
- types << tr( "DLL-files (*.dll)" )
- << tr( "EXE-files (*.exe)" )
-#ifdef LMMS_BUILD_LINUX
- << tr( "SO-files (*.so)" )
+#if defined(LMMS_BUILD_WIN32)
+ types << tr("VST2 files (*.dll)");
+#elif defined(LMMS_BUILD_LINUX)
+# if defined(LMMS_HAVE_VST_32) || defined(LMMS_HAVE_VST_64)
+ types << tr("All VST files (*.dll *.so)")
+ << tr("Windows VST2 files (*.dll)");
+# endif
+ types << tr("LinuxVST files (*.so)");
#endif
- ;
- ofd.setNameFilters( types );
+
+ ofd.setNameFilters(types);
if( m_vi->m_pluginDLL != "" )
{
@@ -990,9 +998,11 @@ ManageVestigeInstrumentView::ManageVestigeInstrumentView( Instrument * _instrume
std::snprintf(paramStr.data(), paramStr.size(), "param%d", i);
s_dumpValues = dump[paramStr.data()].split(":");
- 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 ) );
+ const auto & description = s_dumpValues.at(1);
+
+ auto knob = new CustomTextKnob(KnobType::Bright26, description.left(15), this, description);
+ knob->setDescription(description + ":");
+ vstKnobs[i] = knob;
if( !hasKnobModel )
{
diff --git a/plugins/Vestige/artwork.png b/plugins/Vestige/artwork.png
deleted file mode 100644
index cd08153eb..000000000
Binary files a/plugins/Vestige/artwork.png and /dev/null differ
diff --git a/plugins/Vestige/artwork.svg b/plugins/Vestige/artwork.svg
new file mode 100644
index 000000000..47e0275c3
--- /dev/null
+++ b/plugins/Vestige/artwork.svg
@@ -0,0 +1,105 @@
+
diff --git a/plugins/Vestige/controls.png b/plugins/Vestige/controls.png
deleted file mode 100644
index 4e03eb351..000000000
Binary files a/plugins/Vestige/controls.png and /dev/null differ
diff --git a/plugins/Vestige/controls.svg b/plugins/Vestige/controls.svg
new file mode 100644
index 000000000..dc900a770
--- /dev/null
+++ b/plugins/Vestige/controls.svg
@@ -0,0 +1,23 @@
+
diff --git a/plugins/Vestige/controls_active.png b/plugins/Vestige/controls_active.png
deleted file mode 100644
index 5759cd7bb..000000000
Binary files a/plugins/Vestige/controls_active.png and /dev/null differ
diff --git a/plugins/Vestige/controls_active.svg b/plugins/Vestige/controls_active.svg
new file mode 100644
index 000000000..42b6c563d
--- /dev/null
+++ b/plugins/Vestige/controls_active.svg
@@ -0,0 +1,23 @@
+
diff --git a/plugins/Vestige/logo-symbolic.svg b/plugins/Vestige/logo-symbolic.svg
new file mode 100644
index 000000000..136c204e8
--- /dev/null
+++ b/plugins/Vestige/logo-symbolic.svg
@@ -0,0 +1,15 @@
+
diff --git a/plugins/Vestige/logo.png b/plugins/Vestige/logo.png
deleted file mode 100644
index b8aa149b0..000000000
Binary files a/plugins/Vestige/logo.png and /dev/null differ
diff --git a/plugins/Vestige/logo.svg b/plugins/Vestige/logo.svg
new file mode 100644
index 000000000..01d4c0a28
--- /dev/null
+++ b/plugins/Vestige/logo.svg
@@ -0,0 +1,38 @@
+
diff --git a/plugins/Vestige/select_file.png b/plugins/Vestige/select_file.png
deleted file mode 100644
index 63af460f6..000000000
Binary files a/plugins/Vestige/select_file.png and /dev/null differ
diff --git a/plugins/Vestige/select_file.svg b/plugins/Vestige/select_file.svg
new file mode 100644
index 000000000..1af383dc3
--- /dev/null
+++ b/plugins/Vestige/select_file.svg
@@ -0,0 +1,25 @@
+
diff --git a/plugins/Vestige/select_file_active.png b/plugins/Vestige/select_file_active.png
deleted file mode 100644
index 029e58cfc..000000000
Binary files a/plugins/Vestige/select_file_active.png and /dev/null differ
diff --git a/plugins/Vestige/select_file_active.svg b/plugins/Vestige/select_file_active.svg
new file mode 100644
index 000000000..a5b84daa2
--- /dev/null
+++ b/plugins/Vestige/select_file_active.svg
@@ -0,0 +1,25 @@
+
diff --git a/plugins/Vibed/VibratingString.cpp b/plugins/Vibed/VibratingString.cpp
index 5a09a4549..00e178e24 100644
--- a/plugins/Vibed/VibratingString.cpp
+++ b/plugins/Vibed/VibratingString.cpp
@@ -26,7 +26,7 @@
#include "interpolation.h"
#include "AudioEngine.h"
#include "Engine.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#include
#include
diff --git a/plugins/Vibed/VibratingString.h b/plugins/Vibed/VibratingString.h
index d1691415b..3f61e39f0 100644
--- a/plugins/Vibed/VibratingString.h
+++ b/plugins/Vibed/VibratingString.h
@@ -28,7 +28,7 @@
#include
#include
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms
{
diff --git a/plugins/VstBase/RemoteVstPlugin.cpp b/plugins/VstBase/RemoteVstPlugin.cpp
index f8bf39a37..077216b30 100644
--- a/plugins/VstBase/RemoteVstPlugin.cpp
+++ b/plugins/VstBase/RemoteVstPlugin.cpp
@@ -41,10 +41,6 @@
#ifdef LMMS_BUILD_LINUX
-#ifndef NOMINMAX
-#define NOMINMAX
-#endif
-
#ifndef O_BINARY
#define O_BINARY 0
#endif
@@ -114,7 +110,7 @@ struct ERect
#endif
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#include "Midi.h"
#include "communication.h"
#include "IoHelper.h"
@@ -1521,9 +1517,9 @@ void RemoteVstPlugin::savePreset( const std::string & _file )
void RemoteVstPlugin::loadPresetFile( const std::string & _file )
{
void * chunk = nullptr;
- auto pLen = new unsigned int[1];
+ unsigned int pLen;
unsigned int len = 0;
- auto pBank = (sBank*)new char[sizeof(sBank)];
+ sBank pBank;
FILE * stream = F_OPEN_UTF8( _file, "rb" );
if (!stream)
{
@@ -1531,36 +1527,34 @@ void RemoteVstPlugin::loadPresetFile( const std::string & _file )
"Error opening file for loading preset.\n" );
return;
}
- if ( fread ( pBank, 1, 56, stream ) != 56 )
+ if ( fread ( &pBank, 1, 56, stream ) != 56 )
{
fprintf( stderr, "Error loading preset file.\n" );
}
- pBank->fxID = endian_swap( pBank->fxID );
- pBank->numPrograms = endian_swap( pBank->numPrograms );
+ pBank.fxID = endian_swap( pBank.fxID );
+ pBank.numPrograms = endian_swap( pBank.numPrograms );
unsigned int toUInt;
float * pFloat;
- if (static_cast(m_plugin->uniqueID) != pBank->fxID) {
+ if (static_cast(m_plugin->uniqueID) != pBank.fxID) {
sendMessage( message( IdVstCurrentProgramName ).
addString( "Error: Plugin UniqID not match" ) );
fclose( stream );
- delete[] (unsigned int*)pLen;
- delete[] (sBank*)pBank;
return;
}
if( _file.substr( _file.find_last_of( "." ) + 1 ) != "fxp" )
fseek ( stream , 156 , SEEK_SET );
- if(pBank->fxMagic != 0x6B427846) {
- if(pBank->fxMagic != 0x6B437846) {
- if ( fread (pLen, 1, 4, stream) != 4 )
+ if(pBank.fxMagic != 0x6B427846) {
+ if(pBank.fxMagic != 0x6B437846) {
+ if ( fread (&pLen, 1, 4, stream) != 4 )
{
fprintf( stderr,
"Error loading preset file.\n" );
}
- chunk = new char[len = endian_swap(*pLen)];
- } else chunk = new char[len = sizeof(float)*pBank->numPrograms];
+ chunk = new char[len = endian_swap(pLen)];
+ } else chunk = new char[len = sizeof(float)*pBank.numPrograms];
if ( fread (chunk, len, 1, stream) != 1 )
{
fprintf( stderr, "Error loading preset file.\n" );
@@ -1569,14 +1563,14 @@ void RemoteVstPlugin::loadPresetFile( const std::string & _file )
}
if(_file.substr(_file.find_last_of(".") + 1) == "fxp") {
- pBank->prgName[23] = 0;
- pluginDispatch( 4, 0, 0, pBank->prgName );
- if(pBank->fxMagic != 0x6B437846)
+ pBank.prgName[23] = 0;
+ pluginDispatch( 4, 0, 0, pBank.prgName );
+ if(pBank.fxMagic != 0x6B437846)
pluginDispatch( 24, 1, len, chunk );
else
{
auto toUIntArray = reinterpret_cast(chunk);
- for (auto i = 0u; i < pBank->numPrograms; i++)
+ for (auto i = 0u; i < pBank.numPrograms; i++)
{
toUInt = endian_swap( toUIntArray[ i ] );
pFloat = ( float* ) &toUInt;
@@ -1584,16 +1578,16 @@ void RemoteVstPlugin::loadPresetFile( const std::string & _file )
}
}
} else {
- if(pBank->fxMagic != 0x6B427846) {
+ if(pBank.fxMagic != 0x6B427846) {
pluginDispatch( 24, 0, len, chunk );
} else {
- int numPrograms = pBank->numPrograms;
+ int numPrograms = pBank.numPrograms;
unsigned int * toUIntArray;
int currProgram = pluginDispatch( effGetProgram );
chunk = new char[ len = sizeof(float)*m_plugin->numParams ];
toUIntArray = reinterpret_cast( chunk );
for (int i =0; i < numPrograms; i++) {
- if ( fread (pBank, 1, 56, stream) != 56 )
+ if ( fread (&pBank, 1, 56, stream) != 56 )
{
fprintf( stderr,
"Error loading preset file.\n" );
@@ -1604,8 +1598,8 @@ void RemoteVstPlugin::loadPresetFile( const std::string & _file )
"Error loading preset file.\n" );
}
pluginDispatch( effSetProgram, 0, i );
- pBank->prgName[23] = 0;
- pluginDispatch( 4, 0, 0, pBank->prgName );
+ pBank.prgName[23] = 0;
+ pluginDispatch( 4, 0, 0, pBank.prgName );
for (int j = 0; j < m_plugin->numParams; j++ ) {
toUInt = endian_swap( toUIntArray[ j ] );
pFloat = ( float* ) &toUInt;
@@ -1619,8 +1613,6 @@ void RemoteVstPlugin::loadPresetFile( const std::string & _file )
sendCurrentProgramName();
- delete[] (unsigned int*)pLen;
- delete[] (sBank*)pBank;
delete[] (char*)chunk;
}
diff --git a/plugins/VstBase/VstPlugin.cpp b/plugins/VstBase/VstPlugin.cpp
index 5dbe7a698..f26245728 100644
--- a/plugins/VstBase/VstPlugin.cpp
+++ b/plugins/VstBase/VstPlugin.cpp
@@ -49,12 +49,12 @@
#include "AudioEngine.h"
#include "ConfigManager.h"
+#include "FileDialog.h"
#include "GuiApplication.h"
#include "LocaleHelper.h"
#include "MainWindow.h"
#include "PathUtil.h"
#include "Song.h"
-#include "FileDialog.h"
#ifdef LMMS_BUILD_LINUX
# include
@@ -404,9 +404,8 @@ bool VstPlugin::processMessage( const message & _m )
{
case IdVstPluginWindowID:
m_pluginWindowID = _m.getInt();
- if( m_embedMethod == "none"
- && ConfigManager::inst()->value(
- "ui", "vstalwaysontop" ).toInt() )
+ if (m_embedMethod == "none" && !gui::GuiApplication::isWayland()
+ && ConfigManager::inst()->value("ui", "vstalwaysontop").toInt())
{
#ifdef LMMS_BUILD_WIN32
// We're changing the owner, not the parent,
diff --git a/plugins/VstBase/vst_base.cpp b/plugins/VstBase/vst_base.cpp
index 154dca975..544d05e0b 100644
--- a/plugins/VstBase/vst_base.cpp
+++ b/plugins/VstBase/vst_base.cpp
@@ -24,6 +24,7 @@
*/
+#include "LmmsCommonMacros.h"
#include "Plugin.h"
#include "vstbase_export.h"
diff --git a/plugins/VstEffect/CMakeLists.txt b/plugins/VstEffect/CMakeLists.txt
index 3cbe8e8cc..7bb42dc24 100644
--- a/plugins/VstEffect/CMakeLists.txt
+++ b/plugins/VstEffect/CMakeLists.txt
@@ -13,5 +13,5 @@ ELSE()
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${PLUGIN_DIR}")
ENDIF()
-BUILD_PLUGIN(vsteffect VstEffect.cpp VstEffectControls.cpp VstEffectControlDialog.cpp VstSubPluginFeatures.cpp VstEffect.h VstEffectControls.h VstEffectControlDialog.h VstSubPluginFeatures.h MOCFILES VstEffectControlDialog.h VstEffectControls.h EMBEDDED_RESOURCES *.png)
+BUILD_PLUGIN(vsteffect VstEffect.cpp VstEffectControls.cpp VstEffectControlDialog.cpp VstSubPluginFeatures.cpp VstEffect.h VstEffectControls.h VstEffectControlDialog.h VstSubPluginFeatures.h MOCFILES VstEffectControlDialog.h VstEffectControls.h EMBEDDED_RESOURCES *.png *.svg)
TARGET_LINK_LIBRARIES(vsteffect vstbase)
diff --git a/plugins/VstEffect/VstEffectControls.cpp b/plugins/VstEffect/VstEffectControls.cpp
index ef8bd38d0..c01aef0ce 100644
--- a/plugins/VstEffect/VstEffectControls.cpp
+++ b/plugins/VstEffect/VstEffectControls.cpp
@@ -389,9 +389,11 @@ ManageVSTEffectView::ManageVSTEffectView( VstEffect * _eff, VstEffectControls *
std::snprintf(paramStr.data(), paramStr.size(), "param%d", i);
s_dumpValues = dump[paramStr.data()].split(":");
- 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 ) );
+ const auto & description = s_dumpValues.at(1);
+
+ auto knob = new CustomTextKnob(KnobType::Bright26, description.left(15), widget, description);
+ knob->setDescription(description + ":");
+ vstKnobs[i] = knob;
if( !hasKnobModel )
{
diff --git a/plugins/VstEffect/controls.png b/plugins/VstEffect/controls.png
deleted file mode 100644
index 4e03eb351..000000000
Binary files a/plugins/VstEffect/controls.png and /dev/null differ
diff --git a/plugins/VstEffect/controls.svg b/plugins/VstEffect/controls.svg
new file mode 100644
index 000000000..dc900a770
--- /dev/null
+++ b/plugins/VstEffect/controls.svg
@@ -0,0 +1,23 @@
+
diff --git a/plugins/VstEffect/controls_active.png b/plugins/VstEffect/controls_active.png
deleted file mode 100644
index 5759cd7bb..000000000
Binary files a/plugins/VstEffect/controls_active.png and /dev/null differ
diff --git a/plugins/VstEffect/controls_active.svg b/plugins/VstEffect/controls_active.svg
new file mode 100644
index 000000000..42b6c563d
--- /dev/null
+++ b/plugins/VstEffect/controls_active.svg
@@ -0,0 +1,23 @@
+
diff --git a/plugins/VstEffect/logo.png b/plugins/VstEffect/logo.png
deleted file mode 100644
index ca98f15d4..000000000
Binary files a/plugins/VstEffect/logo.png and /dev/null differ
diff --git a/plugins/VstEffect/logo.svg b/plugins/VstEffect/logo.svg
new file mode 100644
index 000000000..5d70a5784
--- /dev/null
+++ b/plugins/VstEffect/logo.svg
@@ -0,0 +1,15 @@
+
diff --git a/plugins/WaveShaper/WaveShaperControlDialog.cpp b/plugins/WaveShaper/WaveShaperControlDialog.cpp
index 045f84763..17955fe28 100644
--- a/plugins/WaveShaper/WaveShaperControlDialog.cpp
+++ b/plugins/WaveShaper/WaveShaperControlDialog.cpp
@@ -28,6 +28,7 @@
#include "WaveShaperControlDialog.h"
#include "WaveShaperControls.h"
#include "embed.h"
+#include "FontHelper.h"
#include "Graph.h"
#include "Knob.h"
#include "PixmapButton.h"
@@ -59,20 +60,18 @@ WaveShaperControlDialog::WaveShaperControlDialog(
waveGraph->setGraphColor( QColor( 85, 204, 145 ) );
waveGraph -> setMaximumSize( 204, 205 );
- auto inputKnob = new Knob(KnobType::Bright26, this);
+ auto inputKnob = new Knob(KnobType::Bright26, tr("INPUT"), SMALL_FONT_SIZE, this);
inputKnob -> setVolumeKnob( true );
inputKnob -> setVolumeRatio( 1.0 );
inputKnob -> move( 26, 225 );
inputKnob->setModel( &_controls->m_inputModel );
- inputKnob->setLabel( tr( "INPUT" ) );
inputKnob->setHintText( tr( "Input gain:" ) , "" );
- auto outputKnob = new Knob(KnobType::Bright26, this);
+ auto outputKnob = new Knob(KnobType::Bright26, tr("OUTPUT"), SMALL_FONT_SIZE, this);
outputKnob -> setVolumeKnob( true );
outputKnob -> setVolumeRatio( 1.0 );
outputKnob -> move( 76, 225 );
outputKnob->setModel( &_controls->m_outputModel );
- outputKnob->setLabel( tr( "OUTPUT" ) );
outputKnob->setHintText( tr( "Output gain:" ), "" );
auto resetButton = new PixmapButton(this, tr("Reset wavegraph"));
diff --git a/plugins/ZynAddSubFx/ZynAddSubFx.cpp b/plugins/ZynAddSubFx/ZynAddSubFx.cpp
index 19864932d..27e286b66 100644
--- a/plugins/ZynAddSubFx/ZynAddSubFx.cpp
+++ b/plugins/ZynAddSubFx/ZynAddSubFx.cpp
@@ -109,7 +109,7 @@ ZynAddSubFxInstrument::ZynAddSubFxInstrument(
m_plugin( nullptr ),
m_remotePlugin( nullptr ),
m_portamentoModel( 0, 0, 127, 1, this, tr( "Portamento" ) ),
- m_filterFreqModel( 127, 0, 127, 1, this, tr( "Filter frequency" ) ),
+ m_filterFreqModel( 64, 0, 127, 1, this, tr( "Filter frequency" ) ),
m_filterQModel( 64, 0, 127, 1, this, tr( "Filter resonance" ) ),
m_bandwidthModel( 64, 0, 127, 1, this, tr( "Bandwidth" ) ),
m_fmGainModel( 127, 0, 127, 1, this, tr( "FM gain" ) ),
@@ -143,11 +143,6 @@ ZynAddSubFxInstrument::ZynAddSubFxInstrument(
connect( instrumentTrack()->pitchRangeModel(), SIGNAL( dataChanged() ),
this, SLOT( updatePitchRange() ), Qt::DirectConnection );
-
- // ZynAddSubFX's internal value that LMMS's FREQ knob controls
- // isn't set properly when the instrument is first loaded in,
- // and doesn't update until the FREQ knob is moved
- updateFilterFreq();
}
@@ -512,33 +507,26 @@ ZynAddSubFxView::ZynAddSubFxView( Instrument * _instrument, QWidget * _parent )
l->setVerticalSpacing( 16 );
l->setHorizontalSpacing( 10 );
- m_portamento = new Knob( KnobType::Bright26, this );
+ m_portamento = new Knob(KnobType::Bright26, tr("PORT"), SMALL_FONT_SIZE, this);
m_portamento->setHintText( tr( "Portamento:" ), "" );
- m_portamento->setLabel( tr( "PORT" ) );
- m_filterFreq = new Knob( KnobType::Bright26, this );
+ m_filterFreq = new Knob(KnobType::Bright26, tr("FREQ"), SMALL_FONT_SIZE, this);
m_filterFreq->setHintText( tr( "Filter frequency:" ), "" );
- m_filterFreq->setLabel( tr( "FREQ" ) );
- m_filterQ = new Knob( KnobType::Bright26, this );
+ m_filterQ = new Knob(KnobType::Bright26, tr("RES"), SMALL_FONT_SIZE, this);
m_filterQ->setHintText( tr( "Filter resonance:" ), "" );
- m_filterQ->setLabel( tr( "RES" ) );
- m_bandwidth = new Knob( KnobType::Bright26, this );
+ m_bandwidth = new Knob(KnobType::Bright26, tr("BW"), SMALL_FONT_SIZE, this);
m_bandwidth->setHintText( tr( "Bandwidth:" ), "" );
- m_bandwidth->setLabel( tr( "BW" ) );
- m_fmGain = new Knob( KnobType::Bright26, this );
+ m_fmGain = new Knob(KnobType::Bright26, tr("FM GAIN"), SMALL_FONT_SIZE, this);
m_fmGain->setHintText( tr( "FM gain:" ), "" );
- m_fmGain->setLabel( tr( "FM GAIN" ) );
- m_resCenterFreq = new Knob( KnobType::Bright26, this );
+ m_resCenterFreq = new Knob(KnobType::Bright26, tr("RES CF"), SMALL_FONT_SIZE, this);
m_resCenterFreq->setHintText( tr( "Resonance center frequency:" ), "" );
- m_resCenterFreq->setLabel( tr( "RES CF" ) );
- m_resBandwidth = new Knob( KnobType::Bright26, this );
+ m_resBandwidth = new Knob(KnobType::Bright26, tr("RES BW"), SMALL_FONT_SIZE, this);
m_resBandwidth->setHintText( tr( "Resonance bandwidth:" ), "" );
- m_resBandwidth->setLabel( tr( "RES BW" ) );
m_forwardMidiCC = new LedCheckBox( tr( "Forward MIDI control changes" ), this );
diff --git a/plugins/ZynAddSubFx/zynaddsubfx b/plugins/ZynAddSubFx/zynaddsubfx
index 9903fc44f..db8ffedb7 160000
--- a/plugins/ZynAddSubFx/zynaddsubfx
+++ b/plugins/ZynAddSubFx/zynaddsubfx
@@ -1 +1 @@
-Subproject commit 9903fc44ff61c932914fc5b43358c06b1946c446
+Subproject commit db8ffedb7212a7ed9777ffacb9118afbbf779d7c
diff --git a/src/3rdparty/qt5-x11embed b/src/3rdparty/qt5-x11embed
index 022b39a1d..499d737c8 160000
--- a/src/3rdparty/qt5-x11embed
+++ b/src/3rdparty/qt5-x11embed
@@ -1 +1 @@
-Subproject commit 022b39a1d496d72eb3e5b5188e5559f66afca957
+Subproject commit 499d737c8e8d6882c55ef6d26981d313b296e5ca
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9612190bf..eb69fd1a2 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,6 +1,18 @@
ADD_SUBDIRECTORY(3rdparty)
CONFIGURE_FILE("lmmsconfig.h.in" "${CMAKE_BINARY_DIR}/lmmsconfig.h")
+
+# Provide config flags to lmmsversion.h
+get_cmake_property(_define_vars VARIABLES)
+foreach (_define_var ${_define_vars})
+ if(_define_var MATCHES "^WANT|LMMS_(HAVE|DEBUG)" )
+ list(APPEND LMMS_BUILD_OPTIONS "${_define_var}='${${_define_var}}'")
+ endif()
+endforeach()
+
+# Format for readibility
+string(REPLACE ";" " " LMMS_BUILD_OPTIONS "${LMMS_BUILD_OPTIONS}")
+
CONFIGURE_FILE("lmmsversion.h.in" "${CMAKE_BINARY_DIR}/lmmsversion.h")
SET(LMMS_SRCS "")
diff --git a/src/core/AudioEngine.cpp b/src/core/AudioEngine.cpp
index b7f95018e..968de777a 100644
--- a/src/core/AudioEngine.cpp
+++ b/src/core/AudioEngine.cpp
@@ -36,7 +36,6 @@
#include "EnvelopeAndLfoParameters.h"
#include "NotePlayHandle.h"
#include "ConfigManager.h"
-#include "SamplePlayHandle.h"
// platform-specific audio-interface-classes
#include "AudioAlsa.h"
@@ -74,7 +73,7 @@ static thread_local bool s_renderingThread = false;
AudioEngine::AudioEngine( bool renderOnly ) :
m_renderOnly( renderOnly ),
m_framesPerPeriod( DEFAULT_BUFFER_SIZE ),
- m_baseSampleRate(std::max(ConfigManager::inst()->value("audioengine", "samplerate").toInt(), 44100)),
+ m_baseSampleRate(std::max(ConfigManager::inst()->value("audioengine", "samplerate").toInt(), SUPPORTED_SAMPLERATES.front())),
m_inputBufferRead( 0 ),
m_inputBufferWrite( 1 ),
m_outputBufferRead(nullptr),
diff --git a/src/core/AutomatableModel.cpp b/src/core/AutomatableModel.cpp
index e006be651..fa523e106 100644
--- a/src/core/AutomatableModel.cpp
+++ b/src/core/AutomatableModel.cpp
@@ -754,7 +754,7 @@ float AutomatableModel::globalAutomationValueAt( const TimePos& time )
if( latestClip )
{
// scale/fit the value appropriately and return it
- const float value = latestClip->valueAt( time - latestClip->startPosition() );
+ const float value = latestClip->valueAt(time - latestClip->startPosition() + latestClip->startTimeOffset());
const float scaled_value = scaledValue( value );
return fittedValue( scaled_value );
}
diff --git a/src/core/AutomationClip.cpp b/src/core/AutomationClip.cpp
index ef57a60d5..56ba8e9cf 100644
--- a/src/core/AutomationClip.cpp
+++ b/src/core/AutomationClip.cpp
@@ -65,13 +65,13 @@ AutomationClip::AutomationClip( AutomationTrack * _auto_track ) :
switch( getTrack()->trackContainer()->type() )
{
case TrackContainer::Type::Pattern:
- setAutoResize( true );
+ setResizable(false);
break;
case TrackContainer::Type::Song:
// move down
default:
- setAutoResize( false );
+ setResizable(true);
break;
}
}
@@ -81,14 +81,17 @@ AutomationClip::AutomationClip( AutomationTrack * _auto_track ) :
AutomationClip::AutomationClip( const AutomationClip & _clip_to_copy ) :
- Clip( _clip_to_copy.m_autoTrack ),
+ Clip(_clip_to_copy),
#if (QT_VERSION < QT_VERSION_CHECK(5,14,0))
m_clipMutex(QMutex::Recursive),
#endif
m_autoTrack( _clip_to_copy.m_autoTrack ),
m_objects( _clip_to_copy.m_objects ),
m_tension( _clip_to_copy.m_tension ),
- m_progressionType( _clip_to_copy.m_progressionType )
+ m_progressionType(_clip_to_copy.m_progressionType),
+ m_dragging(false),
+ m_isRecording(_clip_to_copy.m_isRecording),
+ m_lastRecordedValue(0)
{
// Locks the mutex of the copied AutomationClip to make sure it
// doesn't change while it's being copied
@@ -106,13 +109,13 @@ AutomationClip::AutomationClip( const AutomationClip & _clip_to_copy ) :
switch( getTrack()->trackContainer()->type() )
{
case TrackContainer::Type::Pattern:
- setAutoResize( true );
+ setResizable(false);
break;
case TrackContainer::Type::Song:
// move down
default:
- setAutoResize( false );
+ setResizable(true);
break;
}
}
@@ -225,8 +228,15 @@ TimePos AutomationClip::timeMapLength() const
void AutomationClip::updateLength()
{
- // Do not resize down in case user manually extended up
- changeLength(std::max(length(), timeMapLength()));
+ // Technically it only matters if the clip has been resized from the right, but this
+ // checks if it has been resized from either direction.
+ if (getAutoResize())
+ {
+ // Using 1 bar as the min length for an un-resized clip.
+ // This does not prevent the user from resizing the clip to be less than a bar later on.
+ changeLength(std::max(TimePos::ticksPerBar(), static_cast(timeMapLength())));
+ setStartTimeOffset(TimePos(0));
+ }
}
@@ -253,6 +263,7 @@ TimePos AutomationClip::putValue(
cleanObjects();
TimePos newTime = quantPos ? Note::quantized(time, quantization()) : time;
+ newTime = std::max(TimePos(0), newTime);
// Create a node or replace the existing one on newTime
m_timeMap[newTime] = AutomationNode(this, value, newTime);
@@ -308,6 +319,7 @@ TimePos AutomationClip::putValues(
cleanObjects();
TimePos newTime = quantPos ? Note::quantized(time, quantization()) : time;
+ newTime = std::max(TimePos(0), newTime);
// Create a node or replace the existing one on newTime
m_timeMap[newTime] = AutomationNode(this, inValue, outValue, newTime);
@@ -455,12 +467,12 @@ void AutomationClip::recordValue(TimePos time, float value)
if( value != m_lastRecordedValue )
{
- putValue( time, value, true );
+ putValue(time - startTimeOffset(), value, true);
m_lastRecordedValue = value;
}
- else if( valueAt( time ) != value )
+ else if( valueAt(time - startTimeOffset()) != value )
{
- removeNode(time);
+ removeNode(time - startTimeOffset());
}
}
@@ -721,90 +733,61 @@ void AutomationClip::flipY()
-void AutomationClip::flipX(int length)
+void AutomationClip::flipX(int start, int end)
{
QMutexLocker m(&m_clipMutex);
- timeMap::const_iterator it = m_timeMap.lowerBound(0);
+ timeMap::const_iterator firstIterator = m_timeMap.lowerBound(0);
- if (it == m_timeMap.end()) { return; }
+ if (firstIterator == m_timeMap.end()) { return; }
+
+ if (start == -1 && end == -1) { start = 0; end = length() - startTimeOffset(); }
+ else if (!(end >= 0 && start >= 0 && end > start)) { return; }
// Temporary map where we will store the flipped version
// of our clip
timeMap tempMap;
- float tempValue = 0;
- float tempOutValue = 0;
-
- // We know the QMap isn't empty, making this safe:
- float realLength = m_timeMap.lastKey();
-
- // If we have a positive length, we want to flip the area covered by that
- // length, even if it goes beyond the clip. A negative length means that
- // we just want to flip the nodes we have
- if (length >= 0 && length != realLength)
+ for (auto it = m_timeMap.begin(); it != m_timeMap.end(); ++it)
{
- // If length to be flipped is bigger than the real length
- if (realLength < length)
+ if (POS(it) < start || POS(it) > end)
{
- // We are flipping an area that goes beyond the last node. So we add a node to the
- // beginning of the flipped timeMap representing the value of the end of the area
- tempValue = valueAt(length);
- tempMap[0] = AutomationNode(this, tempValue, 0);
-
- // Now flip the nodes we have in relation to the length
- do
- {
- // We swap the inValue and outValue when flipping horizontally
- tempValue = OUTVAL(it);
- tempOutValue = INVAL(it);
- auto newTime = TimePos(length - POS(it));
-
- tempMap[newTime] = AutomationNode(this, tempValue, tempOutValue, newTime);
-
- ++it;
- } while (it != m_timeMap.end());
+ tempMap[POS(it)] = *it;
}
- else // If the length to be flipped is smaller than the real length
+ else
{
- do
+ // If the first node in the clip is not at the start, it can break things when clipping, so
+ // we have to set its in value to 0.
+ if (it == firstIterator && POS(firstIterator) > 0)
{
- TimePos newTime;
-
- // Only flips the length to be flipped and keep the remaining values in place
- // We also only swap the inValue and outValue if we are flipping the node
- if (POS(it) <= length)
- {
- newTime = length - POS(it);
- tempValue = OUTVAL(it);
- tempOutValue = INVAL(it);
- }
- else
- {
- newTime = POS(it);
- tempValue = INVAL(it);
- tempOutValue = OUTVAL(it);
- }
-
- tempMap[newTime] = AutomationNode(this, tempValue, tempOutValue, newTime);
-
- ++it;
- } while (it != m_timeMap.end());
+ tempMap[end - (POS(it) - start)] = AutomationNode(this, OUTVAL(it), 0, end - (POS(it) - start));
+ }
+ else
+ {
+ tempMap[end - (POS(it) - start)] = AutomationNode(this, OUTVAL(it), INVAL(it), end - (POS(it) - start));
+ }
}
}
- else // Length to be flipped is the same as the real length
+
+ if (m_timeMap.contains(start) && m_timeMap.contains(end))
{
- do
- {
- // Swap the inValue and outValue
- tempValue = OUTVAL(it);
- tempOutValue = INVAL(it);
-
- auto newTime = TimePos(realLength - POS(it));
- tempMap[newTime] = AutomationNode(this, tempValue, tempOutValue, newTime);
-
- ++it;
- } while (it != m_timeMap.end());
+ tempMap[start] = AutomationNode(this, m_timeMap[start].getInValue(), m_timeMap[end].getInValue(), start);
+ tempMap[end] = AutomationNode(this, m_timeMap[start].getOutValue(), m_timeMap[end].getOutValue(), end);
+ }
+ else if (m_timeMap.contains(start))
+ {
+ tempMap[start] = AutomationNode(this, m_timeMap[start].getInValue(), valueAt(end), start);
+ tempMap[end] = AutomationNode(this, m_timeMap[start].getOutValue(), valueAt(end), end);
+ }
+ else if (m_timeMap.contains(end))
+ {
+ tempMap[start] = AutomationNode(this, valueAt(start), m_timeMap[end].getInValue(), start);
+ tempMap[end] = AutomationNode(this, valueAt(start), m_timeMap[end].getOutValue(), end);
+ }
+ else
+ {
+ tempMap[start] = AutomationNode(this, valueAt(start), valueAt(end), start);
+ tempMap[end] = AutomationNode(this, valueAt(start), valueAt(end), end);
}
m_timeMap.clear();
@@ -830,6 +813,8 @@ void AutomationClip::saveSettings( QDomDocument & _doc, QDomElement & _this )
_this.setAttribute( "prog", QString::number( static_cast(progressionType()) ) );
_this.setAttribute( "tens", QString::number( getTension() ) );
_this.setAttribute( "mute", QString::number( isMuted() ) );
+ _this.setAttribute("off", startTimeOffset());
+ _this.setAttribute("autoresize", QString::number(getAutoResize()));
if (const auto& c = color())
{
@@ -880,6 +865,8 @@ void AutomationClip::loadSettings( const QDomElement & _this )
"prog" ).toInt() ) );
setTension( _this.attribute( "tens" ) );
setMuted(_this.attribute( "mute", QString::number( false ) ).toInt() );
+ setAutoResize(_this.attribute("autoresize", "1").toInt());
+ setStartTimeOffset(_this.attribute("off").toInt());
for( QDomNode node = _this.firstChild(); !node.isNull();
node = node.nextSibling() )
diff --git a/src/core/BufferManager.cpp b/src/core/BufferManager.cpp
index 47598c633..9059064ae 100644
--- a/src/core/BufferManager.cpp
+++ b/src/core/BufferManager.cpp
@@ -28,8 +28,6 @@
#include "SampleFrame.h"
-#include
-
namespace lmms
{
diff --git a/src/core/Clip.cpp b/src/core/Clip.cpp
index b18391df1..ea7d1f933 100644
--- a/src/core/Clip.cpp
+++ b/src/core/Clip.cpp
@@ -61,7 +61,30 @@ Clip::Clip( Track * track ) :
}
-
+/*! \brief Copy a Clip
+ *
+ * Creates a duplicate clip of the one provided.
+ *
+ * \param other The clip object which will be copied.
+ */
+Clip::Clip(const Clip& other):
+ Model(other.m_track),
+ m_track(other.m_track),
+ m_name(other.m_name),
+ m_startPosition(other.m_startPosition),
+ m_length(other.m_length),
+ m_startTimeOffset(other.m_startTimeOffset),
+ m_mutedModel(other.m_mutedModel.value(), this, tr( "Mute" )),
+ m_resizable(other.m_resizable),
+ m_autoResize(other.m_autoResize),
+ m_selectViewOnCreate{other.m_selectViewOnCreate},
+ m_color(other.m_color)
+{
+ if (getTrack())
+ {
+ getTrack()->addClip(this);
+ }
+}
/*! \brief Destroy a Clip
*
diff --git a/src/core/ConfigManager.cpp b/src/core/ConfigManager.cpp
index d3c973020..bdf4d6c32 100644
--- a/src/core/ConfigManager.cpp
+++ b/src/core/ConfigManager.cpp
@@ -22,19 +22,19 @@
*
*/
+#include "ConfigManager.h"
-#include
-#include
-#include
+#include
#include
+#include
+#include
+#include
#include
#include
-#include "ConfigManager.h"
+#include "GuiApplication.h"
#include "MainWindow.h"
#include "ProjectVersion.h"
-#include "GuiApplication.h"
-
#include "lmmsversion.h"
namespace lmms
@@ -299,9 +299,6 @@ void ConfigManager::setBackgroundPicFile(const QString & backgroundPicFile)
m_backgroundPicFile = backgroundPicFile;
}
-
-
-
void ConfigManager::createWorkingDir()
{
QDir().mkpath(m_workingDir);
@@ -335,8 +332,27 @@ void ConfigManager::addRecentlyOpenedProject(const QString & file)
}
}
+void ConfigManager::addFavoriteItem(const QString& item)
+{
+ m_favoriteItems.push_back(item);
+ saveConfigFile();
+ emit favoritesChanged();
+}
+void ConfigManager::removeFavoriteItem(const QString& item)
+{
+ m_favoriteItems.removeAll(item);
+ saveConfigFile();
+ emit favoritesChanged();
+}
+bool ConfigManager::isFavoriteItem(const QString& item)
+{
+ const auto& items = favoriteItems();
+ const auto it = std::find_if(items.begin(), items.end(),
+ [&](const auto& favoriteItem) { return QFileInfo{item} == QFileInfo{favoriteItem}; });
+ return it != items.end();
+}
QString ConfigManager::value(const QString& cls, const QString& attribute, const QString& defaultVal) const
{
@@ -466,8 +482,20 @@ void ConfigManager::loadConfigFile(const QString & configFile)
{
if(n.isElement() && n.toElement().hasAttributes())
{
- m_recentlyOpenedProjects <<
- n.toElement().attribute("path");
+ m_recentlyOpenedProjects << n.toElement().attribute("path");
+ }
+ n = n.nextSibling();
+ }
+ }
+ else if (node.nodeName() == "favoriteitems")
+ {
+ m_favoriteItems.clear();
+ QDomNode n = node.firstChild();
+ while (!n.isNull())
+ {
+ if (n.isElement() && n.toElement().hasAttributes())
+ {
+ m_favoriteItems << n.toElement().attribute("path");
}
n = n.nextSibling();
}
@@ -571,6 +599,16 @@ void ConfigManager::loadConfigFile(const QString & configFile)
{
createWorkingDir();
}
+
+ for (auto& file : m_recentlyOpenedProjects)
+ {
+ file = PathUtil::toAbsolute(file);
+ }
+
+ for (auto& file : m_favoriteItems)
+ {
+ file = PathUtil::toAbsolute(file);
+ }
}
@@ -614,11 +652,22 @@ void ConfigManager::saveConfigFile()
for (const auto& recentlyOpenedProject : m_recentlyOpenedProjects)
{
QDomElement n = doc.createElement("file");
- n.setAttribute("path", recentlyOpenedProject);
+ n.setAttribute("path", PathUtil::toShortestRelative(recentlyOpenedProject));
recent_files.appendChild(n);
}
lmms_config.appendChild(recent_files);
+ QDomElement favorite_items = doc.createElement("favoriteitems");
+
+ for (const auto& favoriteItem : m_favoriteItems)
+ {
+ QDomElement n = doc.createElement("item");
+ n.setAttribute("path", PathUtil::toShortestRelative(favoriteItem));
+ favorite_items.appendChild(n);
+ }
+
+ lmms_config.appendChild(favorite_items);
+
QString xml = "\n" + doc.toString(2);
QFile outfile(m_lmmsRcFile);
diff --git a/src/core/FileSearch.cpp b/src/core/FileSearch.cpp
index 8a668360e..cc9d49af2 100644
--- a/src/core/FileSearch.cpp
+++ b/src/core/FileSearch.cpp
@@ -26,8 +26,6 @@
#include
#include
-#include
-
#include
namespace lmms {
diff --git a/src/core/Instrument.cpp b/src/core/Instrument.cpp
index cae16dee8..07614c314 100644
--- a/src/core/Instrument.cpp
+++ b/src/core/Instrument.cpp
@@ -29,7 +29,7 @@
#include "DummyInstrument.h"
#include "InstrumentTrack.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms
{
diff --git a/src/core/LadspaManager.cpp b/src/core/LadspaManager.cpp
index 5b94cac3f..4c982397b 100644
--- a/src/core/LadspaManager.cpp
+++ b/src/core/LadspaManager.cpp
@@ -36,6 +36,7 @@
#include "ConfigManager.h"
#include "LadspaManager.h"
#include "PluginFactory.h"
+#include "lmms_constants.h"
namespace lmms
diff --git a/src/core/LfoController.cpp b/src/core/LfoController.cpp
index 96ea71f7b..dcdb59b7f 100644
--- a/src/core/LfoController.cpp
+++ b/src/core/LfoController.cpp
@@ -29,6 +29,7 @@
#include
#include "AudioEngine.h"
+#include "Oscillator.h"
#include "PathUtil.h"
#include "SampleLoader.h"
#include "Song.h"
diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp
index 0add6008d..6007be466 100644
--- a/src/core/Mixer.cpp
+++ b/src/core/Mixer.cpp
@@ -26,7 +26,6 @@
#include "AudioEngine.h"
#include "AudioEngineWorkerThread.h"
-#include "BufferManager.h"
#include "Mixer.h"
#include "MixHelpers.h"
#include "Song.h"
diff --git a/src/core/Note.cpp b/src/core/Note.cpp
index ed3a00f10..de57f63d2 100644
--- a/src/core/Note.cpp
+++ b/src/core/Note.cpp
@@ -36,7 +36,7 @@ namespace lmms
Note::Note( const TimePos & length, const TimePos & pos,
int key, volume_t volume, panning_t panning,
- DetuningHelper * detuning ) :
+ std::shared_ptr detuning ) :
m_selected( false ),
m_oldKey(std::clamp(key, 0, NumKeys)),
m_oldPos( pos ),
@@ -46,14 +46,10 @@ Note::Note( const TimePos & length, const TimePos & pos,
m_volume(std::clamp(volume, MinVolume, MaxVolume)),
m_panning(std::clamp(panning, PanningLeft, PanningRight)),
m_length( length ),
- m_pos( pos ),
- m_detuning( nullptr )
+ m_pos(pos),
+ m_detuning(std::move(detuning))
{
- if( detuning )
- {
- m_detuning = sharedObject::ref( detuning );
- }
- else
+ if (!detuning)
{
createDetuning();
}
@@ -74,24 +70,41 @@ Note::Note( const Note & note ) :
m_panning( note.m_panning ),
m_length( note.m_length ),
m_pos( note.m_pos ),
- m_detuning(nullptr),
+ m_detuning(note.m_detuning),
m_type(note.m_type)
{
- if( note.m_detuning )
- {
- m_detuning = sharedObject::ref( note.m_detuning );
- }
}
+Note& Note::operator=(const Note& note)
+{
+ m_selected = note.m_selected;
+ m_oldKey = note.m_oldKey;
+ m_oldPos = note.m_oldPos;
+ m_oldLength = note.m_oldLength;
+ m_isPlaying = note.m_isPlaying;
+ m_key = note.m_key;
+ m_volume = note.m_volume;
+ m_panning = note.m_panning;
+ m_length = note.m_length;
+ m_pos = note.m_pos;
+ m_type = note.m_type;
+ m_detuning = note.m_detuning;
+
+ return *this;
+}
+
+
+Note* Note::clone() const
+{
+ Note* newNote = new Note(*this);
+ newNote->m_detuning = std::make_shared(*newNote->m_detuning);
+ return newNote;
+}
Note::~Note()
{
- if( m_detuning )
- {
- sharedObject::unref( m_detuning );
- }
}
@@ -218,7 +231,7 @@ void Note::createDetuning()
{
if( m_detuning == nullptr )
{
- m_detuning = new DetuningHelper;
+ m_detuning = std::make_shared();
(void) m_detuning->automationClip();
m_detuning->setRange( -MaxDetuning, MaxDetuning, 0.5f );
m_detuning->automationClip()->setProgressionType( AutomationClip::ProgressionType::Linear );
diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp
index 0c27529df..01e78fe2e 100644
--- a/src/core/NotePlayHandle.cpp
+++ b/src/core/NotePlayHandle.cpp
@@ -54,7 +54,7 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack,
int midiEventChannel,
Origin origin ) :
PlayHandle( PlayHandle::Type::NotePlayHandle, _offset ),
- Note( n.length(), n.pos(), n.key(), n.getVolume(), n.getPanning(), n.detuning() ),
+ Note(n),
m_pluginData( nullptr ),
m_instrumentTrack( instrumentTrack ),
m_frames( 0 ),
@@ -84,7 +84,7 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack,
lock();
if( hasParent() == false )
{
- m_baseDetuning = new BaseDetuning( detuning() );
+ m_baseDetuning = new BaseDetuning(detuning().get());
m_instrumentTrack->m_processHandles.push_back( this );
}
else
diff --git a/src/core/Oscillator.cpp b/src/core/Oscillator.cpp
index 5b48ddf3e..7aad9c58e 100644
--- a/src/core/Oscillator.cpp
+++ b/src/core/Oscillator.cpp
@@ -31,7 +31,6 @@
#endif
#include
-#include "BufferManager.h"
#include "Engine.h"
#include "AudioEngine.h"
#include "AutomatableModel.h"
diff --git a/src/core/PathUtil.cpp b/src/core/PathUtil.cpp
index 03ec465a9..f374c60af 100644
--- a/src/core/PathUtil.cpp
+++ b/src/core/PathUtil.cpp
@@ -9,8 +9,8 @@
namespace lmms::PathUtil
{
- auto relativeBases = std::array{ Base::ProjectDir, Base::FactorySample, Base::UserSample, Base::UserVST, Base::Preset,
- Base::UserLADSPA, Base::DefaultLADSPA, Base::UserSoundfont, Base::DefaultSoundfont, Base::UserGIG, Base::DefaultGIG,
+ auto relativeBases = std::array{ Base::ProjectDir, Base::FactoryProjects, Base::FactorySample, Base::UserSample, Base::UserVST, Base::Preset,
+ Base::FactoryPresets, Base::UserLADSPA, Base::DefaultLADSPA, Base::UserSoundfont, Base::DefaultSoundfont, Base::UserGIG, Base::DefaultGIG,
Base::LocalDir };
QString baseLocation(const Base base, bool* error /* = nullptr*/)
@@ -22,6 +22,11 @@ namespace lmms::PathUtil
switch (base)
{
case Base::ProjectDir : loc = ConfigManager::inst()->userProjectsDir(); break;
+ case Base::FactoryProjects :
+ {
+ QDir fpd = QDir(ConfigManager::inst()->factoryProjectsDir());
+ loc = fpd.absolutePath(); break;
+ }
case Base::FactorySample :
{
QDir fsd = QDir(ConfigManager::inst()->factorySamplesDir());
@@ -30,6 +35,11 @@ namespace lmms::PathUtil
case Base::UserSample : loc = ConfigManager::inst()->userSamplesDir(); break;
case Base::UserVST : loc = ConfigManager::inst()->userVstDir(); break;
case Base::Preset : loc = ConfigManager::inst()->userPresetsDir(); break;
+ case Base::FactoryPresets :
+ {
+ QDir fpd = QDir(ConfigManager::inst()->factoryPresetsDir());
+ loc = fpd.absolutePath(); break;
+ }
case Base::UserLADSPA : loc = ConfigManager::inst()->ladspaDir(); break;
case Base::DefaultLADSPA : loc = ConfigManager::inst()->userLadspaDir(); break;
case Base::UserSoundfont : loc = ConfigManager::inst()->sf2Dir(); break;
@@ -70,10 +80,12 @@ namespace lmms::PathUtil
switch (base)
{
case Base::ProjectDir : return QStringLiteral("userprojects:");
+ case Base::FactoryProjects : return QStringLiteral("factoryprojects:");
case Base::FactorySample : return QStringLiteral("factorysample:");
case Base::UserSample : return QStringLiteral("usersample:");
case Base::UserVST : return QStringLiteral("uservst:");
case Base::Preset : return QStringLiteral("preset:");
+ case Base::FactoryPresets : return QStringLiteral("factorypreset:");
case Base::UserLADSPA : return QStringLiteral("userladspa:");
case Base::DefaultLADSPA : return QStringLiteral("defaultladspa:");
case Base::UserSoundfont : return QStringLiteral("usersoundfont:");
@@ -103,9 +115,9 @@ namespace lmms::PathUtil
return path.mid( basePrefix(baseLookup(path)).length() );
}
- QString cleanName(const QString & path)
+ QString cleanName(const QString& path)
{
- return stripPrefix(QFileInfo(path).baseName());
+ return stripPrefix(QFileInfo(path).completeBaseName());
}
diff --git a/src/core/PatternClip.cpp b/src/core/PatternClip.cpp
index 15a1d1f54..abc8a65fd 100644
--- a/src/core/PatternClip.cpp
+++ b/src/core/PatternClip.cpp
@@ -45,7 +45,7 @@ PatternClip::PatternClip(Track* track) :
changeLength( TimePos( t, 0 ) );
restoreJournallingState();
}
- setAutoResize( false );
+ setResizable(true);
}
void PatternClip::saveSettings(QDomDocument& doc, QDomElement& element)
@@ -62,6 +62,7 @@ void PatternClip::saveSettings(QDomDocument& doc, QDomElement& element)
element.setAttribute( "len", length() );
element.setAttribute("off", startTimeOffset());
element.setAttribute( "muted", isMuted() );
+ element.setAttribute("autoresize", QString::number(getAutoResize()));
if (const auto& c = color())
{
element.setAttribute("color", c->name());
@@ -79,6 +80,7 @@ void PatternClip::loadSettings(const QDomElement& element)
movePosition( element.attribute( "pos" ).toInt() );
}
changeLength( element.attribute( "len" ).toInt() );
+ setAutoResize(element.attribute("autoresize", "1").toInt());
setStartTimeOffset(element.attribute("off").toInt());
if (static_cast(element.attribute("muted").toInt()) != isMuted())
{
diff --git a/src/core/PeakController.cpp b/src/core/PeakController.cpp
index 1b819982a..1c38cf4cb 100644
--- a/src/core/PeakController.cpp
+++ b/src/core/PeakController.cpp
@@ -80,7 +80,9 @@ void PeakController::updateValueBuffer()
{
if( m_coeffNeedsUpdate )
{
- m_coeff = 100.0f / Engine::audioEngine()->outputSampleRate();
+ const float ratio = 44100.0f / Engine::audioEngine()->outputSampleRate();
+ m_attackCoeff = 1.0f - powf( 2.0f, -0.3f * ( 1.0f - m_peakEffect->attackModel()->value() ) * ratio );
+ m_decayCoeff = 1.0f - powf( 2.0f, -0.3f * ( 1.0f - m_peakEffect->decayModel()->value() ) * ratio );
m_coeffNeedsUpdate = false;
}
@@ -95,7 +97,14 @@ void PeakController::updateValueBuffer()
for( f_cnt_t f = 0; f < frames; ++f )
{
const float diff = ( targetSample - m_currentSample );
- m_currentSample += diff * m_coeff;
+ if( m_currentSample < targetSample ) // going up...
+ {
+ m_currentSample += diff * m_attackCoeff;
+ }
+ else if( m_currentSample > targetSample ) // going down
+ {
+ m_currentSample += diff * m_decayCoeff;
+ }
values[f] = m_currentSample;
}
}
diff --git a/src/core/RemotePlugin.cpp b/src/core/RemotePlugin.cpp
index e0eeff524..25085e3b6 100644
--- a/src/core/RemotePlugin.cpp
+++ b/src/core/RemotePlugin.cpp
@@ -33,7 +33,6 @@
#include
#endif
-#include "BufferManager.h"
#include "AudioEngine.h"
#include "Engine.h"
#include "Song.h"
diff --git a/src/core/SampleBuffer.cpp b/src/core/SampleBuffer.cpp
index fda3f2f66..3283a7142 100644
--- a/src/core/SampleBuffer.cpp
+++ b/src/core/SampleBuffer.cpp
@@ -27,7 +27,6 @@
#include "PathUtil.h"
#include "SampleDecoder.h"
-#include "lmms_basics.h"
namespace lmms {
diff --git a/src/core/SampleClip.cpp b/src/core/SampleClip.cpp
index 5ef001e20..007265c0c 100644
--- a/src/core/SampleClip.cpp
+++ b/src/core/SampleClip.cpp
@@ -70,13 +70,13 @@ SampleClip::SampleClip(Track* _track, Sample sample, bool isPlaying)
switch( getTrack()->trackContainer()->type() )
{
case TrackContainer::Type::Pattern:
- setAutoResize( true );
+ setResizable(false);
break;
case TrackContainer::Type::Song:
// move down
default:
- setAutoResize( false );
+ setResizable(true);
break;
}
updateTrackClips();
@@ -88,8 +88,48 @@ SampleClip::SampleClip(Track* track)
}
SampleClip::SampleClip(const SampleClip& orig) :
- SampleClip(orig.getTrack(), orig.m_sample, orig.m_isPlaying)
+ Clip(orig),
+ m_sample(std::move(orig.m_sample)),
+ m_isPlaying(orig.m_isPlaying)
{
+ saveJournallingState( false );
+ setSampleFile( "" );
+ restoreJournallingState();
+
+ // we need to receive bpm-change-events, because then we have to
+ // change length of this Clip
+ connect( Engine::getSong(), SIGNAL(tempoChanged(lmms::bpm_t)),
+ this, SLOT(updateLength()), Qt::DirectConnection );
+ connect( Engine::getSong(), SIGNAL(timeSignatureChanged(int,int)),
+ this, SLOT(updateLength()));
+
+ //playbutton clicked or space key / on Export Song set isPlaying to false
+ connect( Engine::getSong(), SIGNAL(playbackStateChanged()),
+ this, SLOT(playbackPositionChanged()), Qt::DirectConnection );
+ //care about loops and jumps
+ connect( Engine::getSong(), SIGNAL(updateSampleTracks()),
+ this, SLOT(playbackPositionChanged()), Qt::DirectConnection );
+ //care about mute Clips
+ connect( this, SIGNAL(dataChanged()), this, SLOT(playbackPositionChanged()));
+ //care about mute track
+ connect( getTrack()->getMutedModel(), SIGNAL(dataChanged()),
+ this, SLOT(playbackPositionChanged()), Qt::DirectConnection );
+ //care about Clip position
+ connect( this, SIGNAL(positionChanged()), this, SLOT(updateTrackClips()));
+
+ switch( getTrack()->trackContainer()->type() )
+ {
+ case TrackContainer::Type::Pattern:
+ setResizable(false);
+ break;
+
+ case TrackContainer::Type::Song:
+ // move down
+ default:
+ setResizable(true);
+ break;
+ }
+ updateTrackClips();
}
@@ -112,12 +152,6 @@ void SampleClip::changeLength( const TimePos & _length )
Clip::changeLength(std::max(static_cast(_length), 1));
}
-void SampleClip::changeLengthToSampleLength()
-{
- int length = m_sample.sampleSize() / Engine::framesPerTick();
- changeLength(length);
-}
-
const QString& SampleClip::sampleFile() const
@@ -145,26 +179,21 @@ void SampleClip::setSampleBuffer(std::shared_ptr sb)
void SampleClip::setSampleFile(const QString& sf)
{
- int length = 0;
-
+ // Remove any prior offset in the clip
+ setStartTimeOffset(0);
if (!sf.isEmpty())
{
- //Otherwise set it to the sample's length
m_sample = Sample(gui::SampleLoader::createBufferFromFile(sf));
- length = sampleLength();
+ updateLength();
}
-
- if (length == 0)
+ else
{
- //If there is no sample, make the clip a bar long
+ // 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(DefaultTicksPerBar * (nom / den));
}
- changeLength(length);
- setStartTimeOffset(0);
-
emit sampleChanged();
emit playbackPositionChanged();
}
@@ -221,6 +250,14 @@ void SampleClip::setIsPlaying(bool isPlaying)
void SampleClip::updateLength()
{
+ // If the clip has already been manually resized, don't automatically resize it.
+ // Unless we are in a pattern, where you can't resize stuff manually
+ if (getAutoResize() || !getResizable())
+ {
+ changeLength(sampleLength());
+ setStartTimeOffset(0);
+ }
+
emit sampleChanged();
Engine::getSong()->setModified();
@@ -267,6 +304,7 @@ void SampleClip::saveSettings( QDomDocument & _doc, QDomElement & _this )
_this.setAttribute( "muted", isMuted() );
_this.setAttribute( "src", sampleFile() );
_this.setAttribute( "off", startTimeOffset() );
+ _this.setAttribute("autoresize", QString::number(getAutoResize()));
if( sampleFile() == "" )
{
QString s;
@@ -315,6 +353,7 @@ void SampleClip::loadSettings( const QDomElement & _this )
changeLength( _this.attribute( "len" ).toInt() );
setMuted( _this.attribute( "muted" ).toInt() );
setStartTimeOffset( _this.attribute( "off" ).toInt() );
+ setAutoResize(_this.attribute("autoresize", "1").toInt());
if (_this.hasAttribute("color"))
{
diff --git a/src/core/SampleDecoder.cpp b/src/core/SampleDecoder.cpp
index d3ee091f4..eb640447c 100644
--- a/src/core/SampleDecoder.cpp
+++ b/src/core/SampleDecoder.cpp
@@ -37,7 +37,7 @@
#include "AudioEngine.h"
#include "DrumSynth.h"
#include "Engine.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
namespace lmms {
diff --git a/src/core/SampleRecordHandle.cpp b/src/core/SampleRecordHandle.cpp
index c378d467e..e38082c6a 100644
--- a/src/core/SampleRecordHandle.cpp
+++ b/src/core/SampleRecordHandle.cpp
@@ -29,7 +29,6 @@
#include "PatternTrack.h"
#include "SampleBuffer.h"
#include "SampleClip.h"
-#include "debug.h"
namespace lmms
diff --git a/src/core/Song.cpp b/src/core/Song.cpp
index ea60e349b..b052c775a 100644
--- a/src/core/Song.cpp
+++ b/src/core/Song.cpp
@@ -290,7 +290,7 @@ void Song::processNextBuffer()
}
else if (m_playMode == PlayMode::MidiClip && m_loopMidiClip && !loopEnabled)
{
- enforceLoop(TimePos{0}, m_midiClipToPlay->length());
+ enforceLoop(-m_midiClipToPlay->startTimeOffset(), m_midiClipToPlay->length() - m_midiClipToPlay->startTimeOffset());
}
// Handle loop points, and inform VST plugins of the loop status
@@ -366,7 +366,7 @@ void Song::processAutomations(const TrackList &tracklist, TimePos timeStart, fpp
break;
case PlayMode::Pattern:
{
- Q_ASSERT(tracklist.size() == 1);
+ if (tracklist.empty()) { return; }
Q_ASSERT(tracklist.at(0)->type() == Track::Type::Pattern);
auto patternTrack = dynamic_cast(tracklist.at(0));
container = Engine::patternStore();
@@ -493,6 +493,7 @@ void Song::playSong()
}
m_playMode = PlayMode::Song;
+ m_lastPlayMode = m_playMode;
m_playing = true;
m_paused = false;
@@ -532,6 +533,7 @@ void Song::playPattern()
}
m_playMode = PlayMode::Pattern;
+ m_lastPlayMode = m_playMode;
m_playing = true;
m_paused = false;
@@ -558,6 +560,7 @@ void Song::playMidiClip( const MidiClip* midiClipToPlay, bool loop )
if( m_midiClipToPlay != nullptr )
{
m_playMode = PlayMode::MidiClip;
+ m_lastPlayMode = m_playMode;
m_playing = true;
m_paused = false;
}
@@ -660,7 +663,14 @@ void Song::stop()
switch (timeline.stopBehaviour())
{
case Timeline::StopBehaviour::BackToZero:
- getPlayPos().setTicks(0);
+ if (m_playMode == PlayMode::MidiClip)
+ {
+ getPlayPos().setTicks(std::max(0, -m_midiClipToPlay->startTimeOffset()));
+ }
+ else
+ {
+ getPlayPos().setTicks(0);
+ }
m_elapsedMilliSeconds[static_cast(m_playMode)] = 0;
break;
diff --git a/src/core/TimePos.cpp b/src/core/TimePos.cpp
index 6e5e034fd..6cf657c72 100644
--- a/src/core/TimePos.cpp
+++ b/src/core/TimePos.cpp
@@ -53,7 +53,7 @@ TimePos::TimePos( const tick_t ticks ) :
{
}
-TimePos TimePos::quantize(float bars) const
+TimePos TimePos::quantize(float bars, bool forceRoundDown) const
{
//The intervals we should snap to, our new position should be a factor of this
int interval = s_ticksPerBar * bars;
@@ -65,7 +65,7 @@ TimePos TimePos::quantize(float bars) const
// Ternary expression is making sure that the snap happens in the direction to
// the right even if m_ticks is negative and the offset is exactly half-way
// More details on issue #5840 and PR #5847
- int snapUp = ((2 * offset) == -interval)
+ int snapUp = forceRoundDown || ((2 * offset) == -interval)
? 0
: (2 * offset) / interval;
diff --git a/src/core/TrackContainer.cpp b/src/core/TrackContainer.cpp
index d4120e761..c92d6edf0 100644
--- a/src/core/TrackContainer.cpp
+++ b/src/core/TrackContainer.cpp
@@ -297,9 +297,9 @@ AutomatedValueMap TrackContainer::automatedValuesFromTracks(const TrackList &tra
if (! p->hasAutomation()) {
continue;
}
- TimePos relTime = time - p->startPosition();
- if (! p->getAutoResize()) {
- relTime = std::min(relTime, p->length());
+ TimePos relTime = time - p->startPosition() - p->startTimeOffset();
+ if (p->getResizable()) {
+ relTime = std::min(static_cast(relTime), p->length() - p->startTimeOffset());
}
float value = p->valueAt(relTime);
diff --git a/src/core/audio/AudioDevice.cpp b/src/core/audio/AudioDevice.cpp
index c02ce5f99..c5d56c997 100644
--- a/src/core/audio/AudioDevice.cpp
+++ b/src/core/audio/AudioDevice.cpp
@@ -27,7 +27,6 @@
#include "AudioDevice.h"
#include "AudioEngine.h"
#include "ConfigManager.h"
-#include "debug.h"
namespace lmms
{
diff --git a/src/core/audio/AudioJack.cpp b/src/core/audio/AudioJack.cpp
index b6da7c845..9abbcc347 100644
--- a/src/core/audio/AudioJack.cpp
+++ b/src/core/audio/AudioJack.cpp
@@ -34,7 +34,6 @@
#include "ConfigManager.h"
#include "Engine.h"
#include "GuiApplication.h"
-#include "LcdSpinBox.h"
#include "MainWindow.h"
#include "MidiJack.h"
@@ -44,13 +43,7 @@ namespace lmms
AudioJack::AudioJack(bool& successful, AudioEngine* audioEngineParam)
: AudioDevice(
- // clang-format off
- std::clamp(
- ConfigManager::inst()->value("audiojack", "channels").toInt(),
- DEFAULT_CHANNELS,
- DEFAULT_CHANNELS
- ),
- // clang-format on
+ DEFAULT_CHANNELS,
audioEngineParam)
, m_client(nullptr)
, m_active(false)
@@ -66,6 +59,8 @@ AudioJack::AudioJack(bool& successful, AudioEngine* audioEngineParam)
if (successful) {
connect(this, SIGNAL(zombified()), this, SLOT(restartAfterZombified()), Qt::QueuedConnection);
}
+
+ m_supportsCapture = true;
}
@@ -154,6 +149,16 @@ bool AudioJack::initJackClient()
clientName.toLatin1().constData(), jack_get_client_name(m_client));
}
+ resizeInputBuffer(jack_get_buffer_size(m_client));
+
+ // set buffer-size callback
+ jack_set_buffer_size_callback(m_client,
+ [](jack_nframes_t nframes, void* udata) -> int {
+ static_cast(udata)->resizeInputBuffer(nframes);
+ return 0;
+ },
+ this);
+
// set process-callback
jack_set_process_callback(m_client, staticProcessCallback, this);
@@ -167,6 +172,10 @@ bool AudioJack::initJackClient()
QString name = QString("master out ") + ((ch % 2) ? "R" : "L") + QString::number(ch / 2 + 1);
m_outputPorts.push_back(
jack_port_register(m_client, name.toLatin1().constData(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0));
+
+ QString input_name = QString("master in ") + ((ch % 2) ? "R" : "L") + QString::number(ch / 2 + 1);
+ m_inputPorts.push_back(jack_port_register(m_client, input_name.toLatin1().constData(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0));
+
if (m_outputPorts.back() == nullptr)
{
printf("no more JACK-ports available!\n");
@@ -180,6 +189,14 @@ bool AudioJack::initJackClient()
+void AudioJack::resizeInputBuffer(jack_nframes_t nframes)
+{
+ m_inputFrameBuffer.resize(nframes);
+}
+
+
+
+
void AudioJack::startProcessing()
{
if (m_active || m_client == nullptr)
@@ -290,7 +307,6 @@ void AudioJack::renamePort(AudioBusHandle* port)
int AudioJack::processCallback(jack_nframes_t nframes)
{
-
// do midi processing first so that midi input can
// add to the following sound processing
if (m_midiClient && nframes > 0)
@@ -356,6 +372,16 @@ int AudioJack::processCallback(jack_nframes_t nframes)
}
}
+ for (int c = 0; c < channels(); ++c)
+ {
+ jack_default_audio_sample_t* jack_input_buffer = (jack_default_audio_sample_t*) jack_port_get_buffer(m_inputPorts[c], nframes);
+
+ for (jack_nframes_t frame = 0; frame < nframes; frame++)
+ {
+ m_inputFrameBuffer[frame][c] = static_cast(jack_input_buffer[frame]);
+ }
+ }
+ audioEngine()->pushInputFrames (m_inputFrameBuffer.data(), nframes);
return 0;
}
@@ -390,24 +416,6 @@ AudioJack::setupWidget::setupWidget(QWidget* parent)
m_clientName = new QLineEdit(cn, this);
form->addRow(tr("Client name"), m_clientName);
-
- auto m = new gui::LcdSpinBoxModel(/* this */);
- m->setRange(DEFAULT_CHANNELS, DEFAULT_CHANNELS);
- m->setStep(2);
- m->setValue(ConfigManager::inst()->value("audiojack", "channels").toInt());
-
- m_channels = new gui::LcdSpinBox(1, this);
- m_channels->setModel(m);
-
- form->addRow(tr("Channels"), m_channels);
-}
-
-
-
-
-AudioJack::setupWidget::~setupWidget()
-{
- delete m_channels->model();
}
@@ -416,7 +424,6 @@ AudioJack::setupWidget::~setupWidget()
void AudioJack::setupWidget::saveSettings()
{
ConfigManager::inst()->setValue("audiojack", "clientname", m_clientName->text());
- ConfigManager::inst()->setValue("audiojack", "channels", QString::number(m_channels->value()));
}
diff --git a/src/core/audio/AudioSampleRecorder.cpp b/src/core/audio/AudioSampleRecorder.cpp
index 0e51c9d2d..2e577d1c6 100644
--- a/src/core/audio/AudioSampleRecorder.cpp
+++ b/src/core/audio/AudioSampleRecorder.cpp
@@ -26,7 +26,6 @@
#include "AudioSampleRecorder.h"
#include "SampleBuffer.h"
-#include "debug.h"
namespace lmms
diff --git a/src/core/audio/AudioSdl.cpp b/src/core/audio/AudioSdl.cpp
index 8f533119c..dfbcde737 100644
--- a/src/core/audio/AudioSdl.cpp
+++ b/src/core/audio/AudioSdl.cpp
@@ -23,7 +23,7 @@
*/
#include "AudioSdl.h"
-#include "lmms_basics.h"
+#include "LmmsTypes.h"
#ifdef LMMS_HAVE_SDL
diff --git a/src/core/audio/AudioSoundIo.cpp b/src/core/audio/AudioSoundIo.cpp
index 851592018..01f804935 100644
--- a/src/core/audio/AudioSoundIo.cpp
+++ b/src/core/audio/AudioSoundIo.cpp
@@ -30,7 +30,6 @@
#include
#include "Engine.h"
-#include "debug.h"
#include "ConfigManager.h"
#include "ComboBox.h"
#include "AudioEngine.h"
diff --git a/src/core/lv2/Lv2ControlBase.cpp b/src/core/lv2/Lv2ControlBase.cpp
index 0147ebd6e..27e6348ae 100644
--- a/src/core/lv2/Lv2ControlBase.cpp
+++ b/src/core/lv2/Lv2ControlBase.cpp
@@ -31,6 +31,7 @@
#include
#include "Engine.h"
+#include "lmms_constants.h"
#include "Lv2Manager.h"
#include "Lv2Proc.h"
diff --git a/src/core/main.cpp b/src/core/main.cpp
index 995b49d2c..fb54feeab 100644
--- a/src/core/main.cpp
+++ b/src/core/main.cpp
@@ -55,7 +55,7 @@
#include
#endif
-#include
+#include // To register the signal handler
#include "MainApplication.h"
#include "ConfigManager.h"
@@ -76,12 +76,12 @@
#include // For feenableexcept
#include // For backtrace and backtrace_symbols_fd
#include // For STDERR_FILENO
-#include // To register the signal handler
#endif
#ifdef LMMS_DEBUG_FPE
-void signalHandler( int signum ) {
+void sigfpeHandler(int signum)
+{
// Get a back trace
void *array[10];
@@ -140,15 +140,16 @@ inline void loadTranslation( const QString & tname,
void printVersion( char *executableName )
{
- printf( "LMMS %s\n(%s %s, Qt %s, %s)\n\n"
+ printf("LMMS %s\n(%s %s, Qt %s, %s)\n\n"
+ "Build options:\n%s\n\n"
"Copyright (c) %s\n\n"
"This program is free software; you can redistribute it and/or\n"
"modify it under the terms of the GNU General Public\n"
"License as published by the Free Software Foundation; either\n"
"version 2 of the License, or (at your option) any later version.\n\n"
"Try \"%s --help\" for more information.\n\n", LMMS_VERSION,
- LMMS_BUILDCONF_PLATFORM, LMMS_BUILDCONF_MACHINE, QT_VERSION_STR, LMMS_BUILDCONF_COMPILER_VERSION,
- LMMS_PROJECT_COPYRIGHT, executableName );
+ LMMS_BUILDCONF_PLATFORM, LMMS_BUILDCONF_MACHINE, QT_VERSION_STR, LMMS_BUILDCONF_COMPILER_VERSION, LMMS_BUILD_OPTIONS,
+ LMMS_PROJECT_COPYRIGHT, executableName);
}
@@ -314,8 +315,9 @@ int main( int argc, char * * argv )
// Install the trap handler
// register signal SIGFPE and signal handler
- signal(SIGFPE, signalHandler);
+ signal(SIGFPE, sigfpeHandler);
#endif
+ signal(SIGINT, gui::GuiApplication::sigintHandler);
#ifdef LMMS_BUILD_WIN32
// Don't touch redirected streams here
diff --git a/src/gui/AudioAlsaSetupWidget.cpp b/src/gui/AudioAlsaSetupWidget.cpp
index 43872a12f..9764bd863 100644
--- a/src/gui/AudioAlsaSetupWidget.cpp
+++ b/src/gui/AudioAlsaSetupWidget.cpp
@@ -31,6 +31,7 @@
#include "ConfigManager.h"
#include "LcdSpinBox.h"
+#include "lmms_constants.h"
namespace lmms::gui
{
diff --git a/src/gui/Controls.cpp b/src/gui/Controls.cpp
index 209b0fce1..d75da6a7d 100644
--- a/src/gui/Controls.cpp
+++ b/src/gui/Controls.cpp
@@ -38,7 +38,11 @@ namespace lmms::gui
{
-void KnobControl::setText(const QString &text) { m_knob->setLabel(text); }
+void KnobControl::setText(const QString& text)
+{
+ // For KnobControls the text is set in the constructor
+ // so we do nothing here
+}
QWidget *KnobControl::topWidget() { return m_knob; }
@@ -51,8 +55,8 @@ FloatModel *KnobControl::model() { return m_knob->model(); }
AutomatableModelView* KnobControl::modelView() { return m_knob; }
-KnobControl::KnobControl(QWidget *parent) :
- m_knob(new Knob(parent)) {}
+KnobControl::KnobControl(const QString& text, QWidget *parent) :
+ m_knob(new Knob(KnobType::Bright26, text, parent)) {}
void ComboControl::setText(const QString &text) { m_label->setText(text); }
diff --git a/src/gui/EffectRackView.cpp b/src/gui/EffectRackView.cpp
index 6a4b3124d..c6d62b334 100644
--- a/src/gui/EffectRackView.cpp
+++ b/src/gui/EffectRackView.cpp
@@ -65,6 +65,7 @@ EffectRackView::EffectRackView( EffectChain* model, QWidget* parent ) :
auto addButton = new QPushButton;
addButton->setText( tr( "Add effect" ) );
+ addButton->setFocusPolicy(Qt::NoFocus);
effectsLayout->addWidget( addButton );
diff --git a/src/gui/EffectView.cpp b/src/gui/EffectView.cpp
index a5095ee6d..a77fc1d96 100644
--- a/src/gui/EffectView.cpp
+++ b/src/gui/EffectView.cpp
@@ -63,23 +63,19 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) :
m_bypass->setToolTip(tr("On/Off"));
-
- m_wetDry = new Knob( KnobType::Bright26, this );
- m_wetDry->setLabel( tr( "W/D" ) );
+ m_wetDry = new Knob(KnobType::Bright26, tr("W/D"), this, Knob::LabelRendering::LegacyFixedFontSize);
m_wetDry->move( 40 - m_wetDry->width() / 2, 5 );
m_wetDry->setEnabled( isEnabled );
m_wetDry->setHintText( tr( "Wet Level:" ), "" );
- m_autoQuit = new TempoSyncKnob( KnobType::Bright26, this );
- m_autoQuit->setLabel( tr( "DECAY" ) );
+ m_autoQuit = new TempoSyncKnob(KnobType::Bright26, tr("DECAY"), this, Knob::LabelRendering::LegacyFixedFontSize);
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( KnobType::Bright26, this );
- m_gate->setLabel( tr( "GATE" ) );
+ m_gate = new Knob(KnobType::Bright26, tr("GATE"), this, Knob::LabelRendering::LegacyFixedFontSize);
m_gate->move( 116 - m_gate->width() / 2, 5 );
m_gate->setEnabled( isEnabled && !effect()->m_autoQuitDisabled );
m_gate->setHintText( tr( "Gate:" ), "" );
@@ -93,6 +89,7 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) :
QFont f = ctls_btn->font();
ctls_btn->setFont(adjustedToPixelSize(f, DEFAULT_FONT_SIZE));
ctls_btn->setGeometry( 150, 14, 50, 20 );
+ ctls_btn->setFocusPolicy(Qt::NoFocus);
connect( ctls_btn, SIGNAL(clicked()),
this, SLOT(editControls()));
diff --git a/src/gui/FileBrowser.cpp b/src/gui/FileBrowser.cpp
index 5e8c84e33..11e48c00f 100644
--- a/src/gui/FileBrowser.cpp
+++ b/src/gui/FileBrowser.cpp
@@ -25,6 +25,7 @@
#include "FileBrowser.h"
+#include
#include
#include
#include
@@ -77,18 +78,15 @@ enum TreeWidgetItemTypes
TypeDirectoryItem
} ;
-
-FileBrowser::FileBrowser(const QString & directories, const QString & filter,
- const QString & title, const QPixmap & pm,
- QWidget * parent, bool dirs_as_items,
- const QString& userDir,
- const QString& factoryDir):
- SideBarWidget( title, pm, parent ),
- m_directories( directories ),
- m_filter( filter ),
- m_dirsAsItems( dirs_as_items ),
- m_userDir(userDir),
- m_factoryDir(factoryDir)
+FileBrowser::FileBrowser(Type type, const QString& directories, const QString& filter, const QString& title, const QPixmap& pm,
+ QWidget* parent, bool dirs_as_items, const QString& userDir, const QString& factoryDir)
+ : SideBarWidget(title, pm, parent)
+ , m_type(type)
+ , m_directories(directories)
+ , m_filter(filter)
+ , m_dirsAsItems(dirs_as_items)
+ , m_userDir(userDir)
+ , m_factoryDir(factoryDir)
{
setWindowTitle( tr( "Browser" ) );
@@ -136,6 +134,14 @@ FileBrowser::FileBrowser(const QString & directories, const QString & filter,
m_previousFilterValue = "";
+ if (m_type == Type::Favorites)
+ {
+ connect(ConfigManager::inst(), &ConfigManager::favoritesChanged, [this] {
+ m_directories = ConfigManager::inst()->favoriteItems().join("*");
+ reloadTree();
+ });
+ }
+
reloadTree();
show();
}
@@ -329,7 +335,7 @@ void FileBrowser::reloadTree()
m_fileBrowserTreeWidget->clear();
- QStringList paths = m_directories.split('*');
+ auto paths = m_directories.isEmpty() ? QStringList{} : m_directories.split('*');
if (m_showUserContent && !m_showUserContent->isChecked())
{
@@ -341,12 +347,37 @@ void FileBrowser::reloadTree()
paths.removeAll(m_factoryDir);
}
- if (!paths.isEmpty())
+ switch (m_type)
{
+ case Type::Favorites:
+ for (auto& path : paths)
+ {
+ while (path.endsWith('/') || path.endsWith('\\') || path.endsWith("."))
+ {
+ path.chop(1);
+ }
+
+ auto info = QFileInfo{PathUtil::toAbsolute(path)};
+
+ if (info.isDir())
+ {
+ auto dir = new Directory(info.fileName(), info.absolutePath(), m_filter);
+ dir->update();
+ m_fileBrowserTreeWidget->addTopLevelItem(dir);
+ }
+ else if (info.isFile())
+ {
+ auto file = new FileItem(info.fileName(), info.path());
+ m_fileBrowserTreeWidget->addTopLevelItem(file);
+ }
+ }
+ break;
+ case Type::Normal:
for (const auto& path : paths)
{
addItems(path);
}
+ break;
}
if (m_filterEdit->text().isEmpty())
@@ -642,17 +673,29 @@ void FileBrowserTreeWidget::contextMenuEvent(QContextMenuEvent* e)
{
case TypeFileItem: {
auto file = dynamic_cast(item);
-
- if (file->isTrack())
- {
- contextMenu.addAction(
- tr("Send to active instrument-track"), [=, this] { sendToActiveInstrumentTrack(file); });
- contextMenu.addSeparator();
- }
+ const auto path = QFileInfo{file->fullName()}.absoluteFilePath();
contextMenu.addAction(QIcon(embed::getIconPixmap("folder")), tr("Show in %1").arg(fileManager),
[=] { FileRevealer::reveal(file->fullName()); });
+ if (ConfigManager::inst()->isFavoriteItem(file->fullName()))
+ {
+ contextMenu.addAction(
+ QIcon(embed::getIconPixmap("star")), tr("Remove favorite file"), [path] { ConfigManager::inst()->removeFavoriteItem(path); });
+ }
+ else
+ {
+ contextMenu.addAction(
+ QIcon(embed::getIconPixmap("star")), tr("Add favorite file"), [path] { ConfigManager::inst()->addFavoriteItem(path); });
+ }
+
+ if (file->isTrack())
+ {
+ contextMenu.addSeparator();
+ contextMenu.addAction(
+ tr("Send to active instrument-track"), [=, this] { sendToActiveInstrumentTrack(file); });
+ }
+
auto songEditorHeader = new QAction(tr("Song Editor"), nullptr);
songEditorHeader->setDisabled(true);
contextMenu.addAction( songEditorHeader );
@@ -666,9 +709,20 @@ void FileBrowserTreeWidget::contextMenuEvent(QContextMenuEvent* e)
}
case TypeDirectoryItem: {
auto dir = dynamic_cast(item);
+ const auto path = QFileInfo{dir->fullName()}.absoluteFilePath();
+
contextMenu.addAction(QIcon(embed::getIconPixmap("folder")), tr("Open in %1").arg(fileManager), [=] {
FileRevealer::openDir(dir->fullName());
});
+
+ if (ConfigManager::inst()->isFavoriteItem(dir->fullName()))
+ {
+ contextMenu.addAction(QIcon(embed::getIconPixmap("star")), tr("Remove favorite folder"), [path] { ConfigManager::inst()->removeFavoriteItem(path); });
+ }
+ else
+ {
+ contextMenu.addAction(QIcon(embed::getIconPixmap("star")), tr("Add favorite folder"), [path] { ConfigManager::inst()->addFavoriteItem(path); });
+ }
break;
}
}
@@ -1222,15 +1276,21 @@ void FileItem::determineFileType()
m_type = FileType::Midi;
m_handling = FileHandling::ImportAsProject;
}
- else if( ext == "dll"
-#ifdef LMMS_BUILD_LINUX
- || ext == "so"
-#endif
+#ifdef LMMS_HAVE_VST
+ else if (
+# if defined(LMMS_BUILD_LINUX)
+ ext == "so" ||
+# endif
+# if defined(LMMS_HAVE_VST_32) || defined(LMMS_HAVE_VST_64)
+ ext == "dll" ||
+# endif
+ false
)
{
m_type = FileType::VstPlugin;
m_handling = FileHandling::LoadByPlugin;
}
+#endif
else if ( ext == "lv2" )
{
m_type = FileType::Preset;
diff --git a/src/gui/FileRevealer.cpp b/src/gui/FileRevealer.cpp
index e93cc7aed..6e2ad56b4 100644
--- a/src/gui/FileRevealer.cpp
+++ b/src/gui/FileRevealer.cpp
@@ -35,7 +35,7 @@
#include "lmmsconfig.h"
-namespace lmms {
+namespace lmms::gui {
bool FileRevealer::s_canSelect = false;
const QString& FileRevealer::getDefaultFileManager()
@@ -180,4 +180,4 @@ bool FileRevealer::supportsArg(const QString& command, const QString& arg)
return output.contains(arg);
}
-} // namespace lmms
+} // namespace lmms::gui
diff --git a/src/gui/GuiApplication.cpp b/src/gui/GuiApplication.cpp
index 8c674112d..292284b3c 100644
--- a/src/gui/GuiApplication.cpp
+++ b/src/gui/GuiApplication.cpp
@@ -41,14 +41,22 @@
#include "SongEditor.h"
#include
+#include
#include
#include
#include
#include
#include
+#include
+#include
#ifdef LMMS_BUILD_WIN32
+#include
+#include
#include
+#else
+#include
+#include
#endif
namespace lmms
@@ -71,10 +79,18 @@ GuiApplication* GuiApplication::instance()
return s_instance;
}
+bool GuiApplication::isWayland()
+{
+ return QGuiApplication::platformName().contains("wayland");
+}
+
GuiApplication::GuiApplication()
{
+ // Immediately register our SIGINT handler
+ createSocketNotifier();
+
// prompt the user to create the LMMS working directory (e.g. ~/Documents/lmms) if it doesn't exist
if ( !ConfigManager::inst()->hasWorkingDir() &&
QMessageBox::question( nullptr,
@@ -240,6 +256,52 @@ void GuiApplication::childDestroyed(QObject *obj)
}
}
+/** \brief Called from main when SIGINT is fired
+ *
+ * Unix signal handlers can only call async-signal-safe functions:
+ * write(fd) --> QSocketNotifier --> SLOT sigintOccurred()
+ *
+ * See https://doc.qt.io/qt-6/unix-signals.html
+ */
+void GuiApplication::sigintHandler(int)
+{
+#ifdef LMMS_BUILD_WIN32
+ char message[] = "Sorry, SIGINT is unhandled on this platform\n";
+ std::ignore = _write(_fileno(stderr), message, sizeof(message));
+#else
+ char a = 1;
+ std::ignore = ::write(s_sigintFd[0], &a, sizeof(a));
+#endif
+}
+
+// Create our unix signal notifiers
+void GuiApplication::createSocketNotifier()
+{
+#ifdef LMMS_BUILD_WIN32
+ // no-op
+#else
+ if (::socketpair(AF_UNIX, SOCK_STREAM, 0, s_sigintFd))
+ {
+ qFatal("Couldn't create SIGINT socketpair");
+ return;
+ }
+
+ // Listen on the file descriptor for SIGINT
+ m_sigintNotifier = new QSocketNotifier(s_sigintFd[1], QSocketNotifier::Read, this);
+ connect(m_sigintNotifier, SIGNAL(activated(QSocketDescriptor)), this, SLOT(sigintOccurred()), Qt::QueuedConnection);
+#endif
+}
+
+// Handle the shutdown event
+void GuiApplication::sigintOccurred()
+{
+ m_sigintNotifier->setEnabled(false);
+ qDebug() << "Shutting down...";
+ // cleanup, etc
+ qApp->exit(3);
+ m_sigintNotifier->setEnabled(true);
+}
+
#ifdef LMMS_BUILD_WIN32
/*!
* @brief Returns the Windows System font.
diff --git a/src/gui/LadspaControlView.cpp b/src/gui/LadspaControlView.cpp
index dbc3b8059..294500b75 100644
--- a/src/gui/LadspaControlView.cpp
+++ b/src/gui/LadspaControlView.cpp
@@ -81,11 +81,11 @@ LadspaControlView::LadspaControlView( QWidget * _parent,
case BufferDataType::Integer:
case BufferDataType::Enum:
case BufferDataType::Floating:
- knb = new Knob( KnobType::Bright26, this, m_ctl->port()->name );
+ knb = new Knob(KnobType::Bright26, m_ctl->port()->name, this, Knob::LabelRendering::WidgetFont, m_ctl->port()->name);
break;
case BufferDataType::Time:
- knb = new TempoSyncKnob( KnobType::Bright26, this, m_ctl->port()->name );
+ knb = new TempoSyncKnob(KnobType::Bright26, m_ctl->port()->name, this, Knob::LabelRendering::WidgetFont, m_ctl->port()->name);
break;
default:
@@ -102,7 +102,6 @@ LadspaControlView::LadspaControlView( QWidget * _parent,
{
knb->setModel( m_ctl->tempoSyncKnobModel() );
}
- knb->setLabel( m_ctl->port()->name );
knb->setHintText( tr( "Value:" ), "" );
layout->addWidget( knb );
if( link != nullptr )
diff --git a/src/gui/LfoControllerDialog.cpp b/src/gui/LfoControllerDialog.cpp
index 559ac1336..4a0ff158f 100644
--- a/src/gui/LfoControllerDialog.cpp
+++ b/src/gui/LfoControllerDialog.cpp
@@ -27,6 +27,7 @@
#include "embed.h"
+#include "FontHelper.h"
#include "LfoController.h"
#include "Knob.h"
#include "TempoSyncKnob.h"
@@ -62,23 +63,19 @@ LfoControllerDialog::LfoControllerDialog( Controller * _model, QWidget * _parent
setWindowIcon( embed::getIconPixmap( "controller" ) );
setFixedSize( 240, 58 );
- m_baseKnob = new Knob( KnobType::Bright26, this );
- m_baseKnob->setLabel( tr( "BASE" ) );
+ m_baseKnob = new Knob(KnobType::Bright26, tr("BASE"), SMALL_FONT_SIZE, this);
m_baseKnob->move( CD_LFO_BASE_CD_KNOB_X, CD_LFO_CD_KNOB_Y );
m_baseKnob->setHintText( tr( "Base:" ), "" );
- m_speedKnob = new TempoSyncKnob( KnobType::Bright26, this );
- m_speedKnob->setLabel( tr( "FREQ" ) );
+ m_speedKnob = new TempoSyncKnob(KnobType::Bright26, tr("FREQ"), SMALL_FONT_SIZE, this);
m_speedKnob->move( CD_LFO_SPEED_CD_KNOB_X, CD_LFO_CD_KNOB_Y );
m_speedKnob->setHintText( tr( "LFO frequency:" ), "" );
- m_amountKnob = new Knob( KnobType::Bright26, this );
- m_amountKnob->setLabel( tr( "AMNT" ) );
+ m_amountKnob = new Knob(KnobType::Bright26, tr("AMNT"), SMALL_FONT_SIZE, this);
m_amountKnob->move( CD_LFO_AMOUNT_CD_KNOB_X, CD_LFO_CD_KNOB_Y );
m_amountKnob->setHintText( tr( "Modulation amount:" ), "" );
- m_phaseKnob = new Knob( KnobType::Bright26, this );
- m_phaseKnob->setLabel( tr( "PHS" ) );
+ m_phaseKnob = new Knob(KnobType::Bright26, tr("PHS"), SMALL_FONT_SIZE, this);
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/Lv2ViewBase.cpp b/src/gui/Lv2ViewBase.cpp
index d6a25af83..0cd6a0ee4 100644
--- a/src/gui/Lv2ViewBase.cpp
+++ b/src/gui/Lv2ViewBase.cpp
@@ -70,7 +70,7 @@ Lv2ViewProc::Lv2ViewProc(QWidget* parent, Lv2Proc* proc, int colNum) :
switch (port.m_vis)
{
case PortVis::Generic:
- m_control = new KnobControl(m_parent);
+ m_control = new KnobControl(port.name(), m_parent);
break;
case PortVis::Integer:
{
diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp
index 275ef4d29..e18bb3cbb 100644
--- a/src/gui/MainWindow.cpp
+++ b/src/gui/MainWindow.cpp
@@ -111,30 +111,27 @@ MainWindow::MainWindow() :
emit initProgress(tr("Preparing plugin browser"));
sideBar->appendTab( new PluginBrowser( splitter ) );
emit initProgress(tr("Preparing file browsers"));
- sideBar->appendTab( new FileBrowser(
- confMgr->userProjectsDir() + "*" +
- confMgr->factoryProjectsDir(),
- "*.mmp *.mmpz *.xml *.mid *.mpt",
- tr( "My Projects" ),
- embed::getIconPixmap( "project_file" ).transformed( QTransform().rotate( 90 ) ),
- splitter, false,
- confMgr->userProjectsDir(),
- confMgr->factoryProjectsDir()));
- sideBar->appendTab(
- new FileBrowser(confMgr->userSamplesDir() + "*" + confMgr->factorySamplesDir(), FileItem::defaultFilters(),
- tr("My Samples"), embed::getIconPixmap("sample_file").transformed(QTransform().rotate(90)), splitter, false,
- confMgr->userSamplesDir(), confMgr->factorySamplesDir()));
- sideBar->appendTab( new FileBrowser(
- confMgr->userPresetsDir() + "*" +
- confMgr->factoryPresetsDir(),
- "*.xpf *.cs.xml *.xiz *.lv2",
- tr( "My Presets" ),
- embed::getIconPixmap( "preset_file" ).transformed( QTransform().rotate( 90 ) ),
- splitter , false,
- confMgr->userPresetsDir(),
- confMgr->factoryPresetsDir()));
- sideBar->appendTab(new FileBrowser(QDir::homePath(), FileItem::defaultFilters(), tr("My Home"),
- embed::getIconPixmap("home").transformed(QTransform().rotate(90)), splitter, false));
+
+ sideBar->appendTab(new FileBrowser(FileBrowser::Type::Favorites, ConfigManager::inst()->favoriteItems().join("*"), FileItem::defaultFilters(), "My Favorites",
+ embed::getIconPixmap("star").transformed(QTransform().rotate(90)), splitter, false, "", ""));
+
+ sideBar->appendTab(new FileBrowser(FileBrowser::Type::Normal,
+ confMgr->userProjectsDir() + "*" + confMgr->factoryProjectsDir(), "*.mmp *.mmpz *.xml *.mid *.mpt",
+ tr("My Projects"), embed::getIconPixmap("project_file").transformed(QTransform().rotate(90)), splitter, false,
+ confMgr->userProjectsDir(), confMgr->factoryProjectsDir()));
+
+ sideBar->appendTab(new FileBrowser(FileBrowser::Type::Normal,
+ confMgr->userSamplesDir() + "*" + confMgr->factorySamplesDir(), FileItem::defaultFilters(), tr("My Samples"),
+ embed::getIconPixmap("sample_file").transformed(QTransform().rotate(90)), splitter, false,
+ confMgr->userSamplesDir(), confMgr->factorySamplesDir()));
+
+ sideBar->appendTab(new FileBrowser(FileBrowser::Type::Normal,
+ confMgr->userPresetsDir() + "*" + confMgr->factoryPresetsDir(), "*.xpf *.cs.xml *.xiz *.lv2", tr("My Presets"),
+ embed::getIconPixmap("preset_file").transformed(QTransform().rotate(90)), splitter, false,
+ confMgr->userPresetsDir(), confMgr->factoryPresetsDir()));
+
+ sideBar->appendTab(new FileBrowser(FileBrowser::Type::Normal, QDir::homePath(), FileItem::defaultFilters(),
+ tr("My Home"), embed::getIconPixmap("home").transformed(QTransform().rotate(90)), splitter, false));
QStringList root_paths;
QString title = tr("Root Directory");
@@ -156,7 +153,7 @@ MainWindow::MainWindow() :
}
#endif
- sideBar->appendTab(new FileBrowser(root_paths.join("*"), FileItem::defaultFilters(), title,
+ sideBar->appendTab(new FileBrowser(FileBrowser::Type::Normal, root_paths.join("*"), FileItem::defaultFilters(), title,
embed::getIconPixmap("computer").transformed(QTransform().rotate(90)), splitter, dirs_as_items));
m_workspace = new MovableQMdiArea(splitter);
@@ -315,7 +312,7 @@ void MainWindow::finalize()
SLOT(onExportProject()),
combine(Qt::CTRL, Qt::Key_E));
project_menu->addAction( embed::getIconPixmap( "project_export" ),
- tr( "E&xport Tracks..." ),
+ tr("Export &Tracks..."),
this,
SLOT(onExportProjectTracks()),
combine(Qt::CTRL, Qt::SHIFT, Qt::Key_E));
@@ -1287,6 +1284,31 @@ void MainWindow::keyPressEvent( QKeyEvent * _ke )
case Qt::Key_Control: m_keyMods.m_ctrl = true; break;
case Qt::Key_Shift: m_keyMods.m_shift = true; break;
case Qt::Key_Alt: m_keyMods.m_alt = true; break;
+ case Qt::Key_Space:
+ {
+ Editor* lastEditor = nullptr;
+ switch (Engine::getSong()->lastPlayMode())
+ {
+ case Song::PlayMode::Song:
+ lastEditor = getGUI()->songEditor();
+ break;
+ case Song::PlayMode::MidiClip:
+ lastEditor = getGUI()->pianoRoll();
+ break;
+ case Song::PlayMode::Pattern:
+ lastEditor = getGUI()->patternEditor();
+ break;
+ case Song::PlayMode::AutomationClip:
+ lastEditor = getGUI()->automationEditor();
+ break;
+ default:
+ lastEditor = getGUI()->songEditor();
+ break;
+ }
+ if (m_keyMods.m_shift) { lastEditor->togglePause(); }
+ else { lastEditor->togglePlayStop(); }
+ break;
+ }
default:
{
InstrumentTrackWindow * w =
@@ -1642,7 +1664,16 @@ void MainWindow::MovableQMdiArea::mouseMoveEvent(QMouseEvent* event)
scrollY = scrollY < 0 && minY >= minYBoundary ? 0 : scrollY;
scrollY = scrollY > 0 && maxY <= maxYBoundary ? 0 : scrollY;
- scrollContentsBy(-scrollX, -scrollY);
+ for (auto* curWindow : subWindows)
+ {
+ // if widgets are maximized, then they shouldn't be moved
+ // moving a maximized window's normalGeometry is not implemented because of difficulties
+ if (curWindow->isMaximized() == false)
+ {
+ curWindow->move(curWindow->x() - scrollX, curWindow->y() - scrollY);
+ }
+ }
+
m_lastX = event->x();
m_lastY = event->y();
}
diff --git a/src/gui/MidiCCRackView.cpp b/src/gui/MidiCCRackView.cpp
index a0b1496fb..efeb46d46 100644
--- a/src/gui/MidiCCRackView.cpp
+++ b/src/gui/MidiCCRackView.cpp
@@ -79,6 +79,7 @@ MidiCCRackView::MidiCCRackView(InstrumentTrack * track) :
auto knobsScrollArea = new QScrollArea();
auto knobsArea = new QWidget();
auto knobsAreaLayout = new QGridLayout();
+ knobsAreaLayout->setVerticalSpacing(10);
knobsArea->setLayout(knobsAreaLayout);
knobsScrollArea->setWidget(knobsArea);
@@ -86,24 +87,21 @@ MidiCCRackView::MidiCCRackView(InstrumentTrack * track) :
knobsGroupBoxLayout->addWidget(knobsScrollArea);
- // Adds the controller knobs
+ // Adds the controller knobs and sets their models
for (int i = 0; i < MidiControllerCount; ++i)
{
- 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);
+ auto knob = new Knob(KnobType::Bright26, tr("CC %1").arg(i), this);
+ knob->setModel(m_track->m_midiCCModel[i].get());
+ knobsAreaLayout->addWidget(knob, i/4, i%4, Qt::AlignHCenter);
+
+ // TODO It seems that this is not really used/needed?
+ m_controllerKnob[i] = knob;
}
// Set all the models
// Set the LED button to enable/disable the track midi cc
m_midiCCGroupBox->setModel(m_track->m_midiCCEnable.get());
- // Set the model for each Knob
- for (int i = 0; i < MidiControllerCount; ++i)
- {
- m_controllerKnob[i]->setModel(m_track->m_midiCCModel[i].get());
- }
-
// Connection to update the name of the track on the label
connect(m_track, SIGNAL(nameChanged()),
this, SLOT(renameWindow()));
diff --git a/src/gui/MixerChannelView.cpp b/src/gui/MixerChannelView.cpp
index 1eb2fd1bb..3391affce 100644
--- a/src/gui/MixerChannelView.cpp
+++ b/src/gui/MixerChannelView.cpp
@@ -107,18 +107,16 @@ MixerChannelView::MixerChannelView(QWidget* parent, MixerView* mixerView, int ch
renameLineEditProxy->setRotation(-90);
m_renameLineEditView->setFixedSize(m_renameLineEdit->height() + 5, m_renameLineEdit->width() + 5);
- m_muteButton = new PixmapButton(this, tr("Mute"));
+ m_muteButton = new AutomatableButton(this, tr("Mute"));
m_muteButton->setModel(&mixerChannel->m_muteModel);
- m_muteButton->setActiveGraphic(embed::getIconPixmap("mute_active"));
- m_muteButton->setInactiveGraphic(embed::getIconPixmap("mute_inactive"));
m_muteButton->setCheckable(true);
+ m_muteButton->setObjectName("btn-mute");
m_muteButton->setToolTip(tr("Mute this channel"));
- m_soloButton = new PixmapButton(this, tr("Solo"));
+ m_soloButton = new AutomatableButton(this, tr("Solo"));
m_soloButton->setModel(&mixerChannel->m_soloModel);
- m_soloButton->setActiveGraphic(embed::getIconPixmap("solo_active"));
- m_soloButton->setInactiveGraphic(embed::getIconPixmap("solo_inactive"));
m_soloButton->setCheckable(true);
+ m_soloButton->setObjectName("btn-solo");
m_soloButton->setToolTip(tr("Solo this channel"));
auto soloMuteLayout = new QVBoxLayout();
@@ -149,6 +147,8 @@ MixerChannelView::MixerChannelView(QWidget* parent, MixerView* mixerView, int ch
mainLayout->addWidget(m_fader, 1, Qt::AlignHCenter);
connect(m_renameLineEdit, &QLineEdit::editingFinished, this, &MixerChannelView::renameFinished);
+
+ setFocusPolicy(Qt::StrongFocus);
}
void MixerChannelView::contextMenuEvent(QContextMenuEvent*)
@@ -222,23 +222,23 @@ void MixerChannelView::mouseDoubleClickEvent(QMouseEvent*)
renameChannel();
}
-bool MixerChannelView::eventFilter(QObject*, QEvent* event)
+void MixerChannelView::keyPressEvent(QKeyEvent* ke)
{
- // If we are in a rename, capture the enter/return events and handle them
- if (event->type() == QEvent::KeyPress)
+ if (ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return)
{
- auto keyEvent = static_cast(event);
- if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return)
+ if (m_inRename)
{
- if (m_inRename)
- {
- renameFinished();
- event->accept(); // Stop the event from propagating
- return true;
- }
+ renameFinished();
}
}
- return false;
+ else if (ke->key() == Qt::Key_Space)
+ {
+ m_fader->adjustByDialog();
+ }
+ else
+ {
+ ke->ignore();
+ }
}
void MixerChannelView::setChannelIndex(int index)
diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp
index d05ff097d..fd6391bf0 100644
--- a/src/gui/MixerView.cpp
+++ b/src/gui/MixerView.cpp
@@ -22,6 +22,7 @@
*
*/
+#include "MixerView.h"
#include
#include
@@ -29,10 +30,7 @@
#include
#include
-#include "lmms_math.h"
-
#include "MixerChannelView.h"
-#include "MixerView.h"
#include "Knob.h"
#include "Mixer.h"
#include "GuiApplication.h"
@@ -376,6 +374,7 @@ void MixerView::updateMixerChannel(int index)
}
thisLine->m_sendButton->updateLightStatus();
+ thisLine->m_renameLineEdit->setText(thisLine->elideName(thisLine->mixerChannel()->m_name));
thisLine->update();
}
@@ -537,15 +536,8 @@ void MixerView::keyPressEvent(QKeyEvent * e)
case Qt::Key_F2:
renameChannel(m_currentMixerChannel->channelIndex());
break;
- case Qt::Key_Space:
- {
- auto* mixerChannel = currentMixerChannel();
-
- if (mixerChannel)
- {
- mixerChannel->fader()->adjustByDialog();
- }
- }
+ default:
+ e->ignore();
break;
}
}
diff --git a/src/gui/SampleThumbnail.cpp b/src/gui/SampleThumbnail.cpp
index c31c0d93e..8ec18b5cb 100644
--- a/src/gui/SampleThumbnail.cpp
+++ b/src/gui/SampleThumbnail.cpp
@@ -70,6 +70,7 @@ SampleThumbnail::Thumbnail SampleThumbnail::Thumbnail::zoomOut(float factor) con
}
SampleThumbnail::SampleThumbnail(const Sample& sample)
+ : m_buffer(sample.buffer())
{
auto entry = SampleThumbnailEntry{sample.sampleFile(), QFileInfo{sample.sampleFile()}.lastModified()};
if (!entry.filePath.isEmpty())
@@ -91,11 +92,9 @@ SampleThumbnail::SampleThumbnail(const Sample& sample)
s_sampleThumbnailCacheMap[std::move(entry)] = m_thumbnailCache;
}
- if (!sample.buffer()) { throw std::runtime_error{"Cannot create a sample thumbnail with no buffer"}; }
- if (sample.sampleSize() == 0) { return; }
-
- const auto fullResolutionWidth = sample.sampleSize() * DEFAULT_CHANNELS;
- m_thumbnailCache->emplace_back(&sample.buffer()->data()->left(), fullResolutionWidth, fullResolutionWidth);
+ const auto flatBuffer = m_buffer->data()->data();
+ const auto flatBufferSize = m_buffer->size() * DEFAULT_CHANNELS;
+ m_thumbnailCache->emplace_back(flatBuffer, flatBufferSize, flatBufferSize / AggregationPerZoomStep);
while (m_thumbnailCache->back().width() >= AggregationPerZoomStep)
{
@@ -107,48 +106,71 @@ SampleThumbnail::SampleThumbnail(const Sample& sample)
void SampleThumbnail::visualize(VisualizeParameters parameters, QPainter& painter) const
{
const auto& sampleRect = parameters.sampleRect;
- const auto& drawRect = parameters.drawRect.isNull() ? sampleRect : parameters.drawRect;
- const auto& viewportRect = parameters.viewportRect.isNull() ? drawRect : parameters.viewportRect;
+ const auto& viewportRect = parameters.viewportRect.isNull() ? sampleRect : parameters.viewportRect;
- const auto renderRect = sampleRect.intersected(drawRect).intersected(viewportRect);
+ const auto renderRect = sampleRect.intersected(viewportRect);
if (renderRect.isNull()) { return; }
const auto sampleRange = parameters.sampleEnd - parameters.sampleStart;
- if (sampleRange <= 0 || sampleRange > 1) { return; }
+ if (sampleRange <= 0.0f || sampleRange > 1.0f) { return; }
- const auto targetThumbnailWidth = static_cast(static_cast(sampleRect.width()) / sampleRange);
+ const auto targetThumbnailWidth = static_cast(sampleRect.width() / sampleRange);
const auto finerThumbnail = std::find_if(m_thumbnailCache->rbegin(), m_thumbnailCache->rend(),
[&](const auto& thumbnail) { return thumbnail.width() >= targetThumbnailWidth; });
- if (finerThumbnail == m_thumbnailCache->rend())
- {
- qDebug() << "Could not find closest finer thumbnail for a target width of" << targetThumbnailWidth;
- return;
- }
+ const auto useOriginalBuffer = finerThumbnail == m_thumbnailCache->rend();
+ const auto drawOriginalBuffer = static_cast(targetThumbnailWidth) == m_buffer->size();
painter.save();
painter.setRenderHint(QPainter::Antialiasing, true);
- const auto thumbnailBeginForward = std::max(renderRect.x() - sampleRect.x(), static_cast(parameters.sampleStart * targetThumbnailWidth));
- const auto thumbnailEndForward = std::max(renderRect.x() + renderRect.width() - sampleRect.x(), static_cast(parameters.sampleEnd * targetThumbnailWidth));
+ const auto thumbnailBeginForward = std::max(renderRect.x() - sampleRect.x(), parameters.sampleStart * targetThumbnailWidth);
+ const auto thumbnailEndForward = std::max(renderRect.x() + renderRect.width() - sampleRect.x(), parameters.sampleEnd * targetThumbnailWidth);
const auto thumbnailBegin = parameters.reversed ? targetThumbnailWidth - thumbnailBeginForward - 1 : thumbnailBeginForward;
const auto thumbnailEnd = parameters.reversed ? targetThumbnailWidth - thumbnailEndForward : thumbnailEndForward;
const auto advanceThumbnailBy = parameters.reversed ? -1 : 1;
- const auto finerThumbnailScaleFactor = static_cast(finerThumbnail->width()) / targetThumbnailWidth;
- const auto yScale = drawRect.height() / 2 * parameters.amplification;
+ const auto finerThumbnailWidth = useOriginalBuffer ? m_buffer->size() : finerThumbnail->width();
+ const auto finerThumbnailScaleFactor = static_cast(finerThumbnailWidth) / targetThumbnailWidth;
+ const auto yScale = renderRect.height() / 2 * parameters.amplification;
for (auto x = renderRect.x(), i = thumbnailBegin; x < renderRect.x() + renderRect.width() && i != thumbnailEnd;
- ++x, i += advanceThumbnailBy)
+ ++x, i += advanceThumbnailBy)
{
- const auto beginAggregationAt = &(*finerThumbnail)[static_cast