From 93c8c733990bffa26b67f784e9cea3a534efb67f Mon Sep 17 00:00:00 2001 From: Armin Date: Wed, 22 Jul 2026 13:27:26 +0200 Subject: [PATCH] Move scroll buttons to title bar, add build info status bar - Replace broken bottom waveform scroll buttons with title bar < > buttons - Add scrollLeft()/scrollRight() methods to WaveformDisplay - Add status bar showing git branch, commit, dirty state, and build timestamp - Inject git version info via CMake at configure time - Enable COPY_PLUGIN_AFTER_BUILD - Increase baseHeight by 20px for status bar --- CMakeLists.txt | 46 +++++++++++++++++++++++++++++++++++++- Source/PluginEditor.cpp | 25 +++++++++++++++++++++ Source/PluginEditor.h | 5 ++++- Source/WaveformDisplay.cpp | 36 ++++++++++++++--------------- Source/WaveformDisplay.h | 5 ++--- 5 files changed, 93 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a8b77e..6994d15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ juce_add_plugin(Monoslicer NEEDS_MIDI_OUTPUT FALSE IS_MIDI_EFFECT FALSE EDITOR_WANTS_KEYBOARD_FOCUS TRUE - COPY_PLUGIN_AFTER_BUILD FALSE + COPY_PLUGIN_AFTER_BUILD TRUE VST3_CATEGORIES Instrument Sampler ) @@ -29,10 +29,54 @@ target_sources(Monoslicer PRIVATE Source/PianoRollDisplay.cpp ) +execute_process( + COMMAND git rev-parse --short HEAD + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE GIT_COMMIT_HASH + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET +) + +if(NOT GIT_COMMIT_HASH) + set(GIT_COMMIT_HASH "unknown") +endif() + +execute_process( + COMMAND git symbolic-ref --short HEAD + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE GIT_BRANCH + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET +) + +execute_process( + COMMAND git diff --quiet HEAD + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + RESULT_VARIABLE GIT_DIRTY_RESULT +) + +execute_process( + COMMAND git diff --cached --quiet + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + RESULT_VARIABLE GIT_CACHED_DIRTY_RESULT +) + +set(GIT_DIRTY "") +if(NOT GIT_DIRTY_RESULT EQUAL 0 OR NOT GIT_CACHED_DIRTY_RESULT EQUAL 0) + set(GIT_DIRTY "-dirty") +endif() + +if(GIT_BRANCH) + set(GIT_VERSION "${GIT_BRANCH} @ ${GIT_COMMIT_HASH}${GIT_DIRTY}") +else() + set(GIT_VERSION "detached @ ${GIT_COMMIT_HASH}${GIT_DIRTY}") +endif() + target_compile_definitions(Monoslicer PUBLIC JUCE_WEB_BROWSER=0 JUCE_USE_CURL=0 JUCE_VST3_CAN_REPLACE_VST2=0 + GIT_VERSION="${GIT_VERSION}" ) target_link_libraries(Monoslicer diff --git a/Source/PluginEditor.cpp b/Source/PluginEditor.cpp index 0d8d9b3..328e964 100644 --- a/Source/PluginEditor.cpp +++ b/Source/PluginEditor.cpp @@ -24,6 +24,8 @@ MonoslicerEditor::MonoslicerEditor(MonoslicerProcessor& p) setupTitleBtn(zoomInButton, "Zoom In"); setupTitleBtn(zoomOutButton, "Zoom Out"); setupTitleBtn(zoomResetButton, "Reset Zoom"); + setupTitleBtn(scrollLeftButton, "Scroll waveform left"); + setupTitleBtn(scrollRightButton, "Scroll waveform right"); addAndMakeVisible(scaleComboBox); scaleComboBox.addItem("75%", 1); @@ -55,6 +57,14 @@ MonoslicerEditor::MonoslicerEditor(MonoslicerProcessor& p) addAndMakeVisible(waveformDisplay); + // Status bar + addAndMakeVisible(statusBar); + statusBar.setText("Build: " GIT_VERSION " (" __DATE__ ", " __TIME__ ")", + juce::dontSendNotification); + statusBar.setColour(juce::Label::textColourId, juce::Colour(0xff666688)); + statusBar.setFont(juce::Font(juce::FontOptions(11.0f))); + statusBar.setJustificationType(juce::Justification::centredRight); + // Slice knobs attachSlider(bassSlider, bassLabel, "Bass", "bass", bassAttachment); attachSlider(trebleSlider, trebleLabel, "Treble", "treble", trebleAttachment); @@ -197,6 +207,8 @@ MonoslicerEditor::~MonoslicerEditor() zoomInButton.removeListener(this); zoomOutButton.removeListener(this); zoomResetButton.removeListener(this); + scrollLeftButton.removeListener(this); + scrollRightButton.removeListener(this); stretchButton.removeListener(this); } @@ -242,6 +254,8 @@ void MonoslicerEditor::resized() auto bounds = getLocalBounds(); auto titleBar = bounds.removeFromTop(40); + auto statusBarArea = bounds.removeFromBottom(18).withTrimmedRight(5); + statusBar.setBounds(statusBarArea); int tx = 120; @@ -263,6 +277,9 @@ void MonoslicerEditor::resized() placeBtn(zoomOutButton, 28); placeBtn(zoomResetButton, 32); placeBtn(zoomInButton, 28); + tx += 6; + placeBtn(scrollLeftButton, 24); + placeBtn(scrollRightButton, 24); scaleComboBox.setBounds(titleBar.getRight() - 100, titleBar.getY() + 8, 90, 24); octaveComboBox.setBounds(titleBar.getRight() - 176, titleBar.getY() + 8, 72, 24); @@ -446,6 +463,14 @@ void MonoslicerEditor::buttonClicked(juce::Button* button) { waveformDisplay.zoomReset(); } + else if (button == &scrollLeftButton) + { + waveformDisplay.scrollLeft(); + } + else if (button == &scrollRightButton) + { + waveformDisplay.scrollRight(); + } } void MonoslicerEditor::comboBoxChanged(juce::ComboBox* comboBoxThatHasChanged) diff --git a/Source/PluginEditor.h b/Source/PluginEditor.h index c6e7cb9..0689574 100644 --- a/Source/PluginEditor.h +++ b/Source/PluginEditor.h @@ -41,11 +41,13 @@ private: juce::TextButton zoomInButton { "+" }; juce::TextButton zoomOutButton { "-" }; juce::TextButton zoomResetButton { "1:1" }; + juce::TextButton scrollLeftButton { "<" }; + juce::TextButton scrollRightButton { ">" }; juce::ComboBox scaleComboBox; juce::ComboBox octaveComboBox; static constexpr int baseWidth = 1100; - static constexpr int baseHeight = 550; + static constexpr int baseHeight = 570; // Slice knobs juce::Slider bassSlider, trebleSlider, sensitivitySlider; @@ -88,6 +90,7 @@ private: std::unique_ptr filterTypeAttachment; juce::FileChooser fileChooser { "Load Audio File", juce::File{}, "*.wav;*.aiff;*.flac;*.ogg" }; + juce::Label statusBar; void setupSlider(juce::Slider& slider, juce::Label& label, const juce::String& name); void attachSlider(juce::Slider& slider, juce::Label& label, const juce::String& name, diff --git a/Source/WaveformDisplay.cpp b/Source/WaveformDisplay.cpp index 44665f1..1ee465d 100644 --- a/Source/WaveformDisplay.cpp +++ b/Source/WaveformDisplay.cpp @@ -7,13 +7,6 @@ WaveformDisplay::WaveformDisplay(SliceManager& sm) : sliceManager(sm) hScrollBar.setRangeLimits(0.0, 1.0); hScrollBar.setCurrentRange(0.0, 1.0); - auto setupScrollBtn = [this](juce::TextButton& btn) { - addAndMakeVisible(btn); - btn.setColour(juce::TextButton::buttonColourId, juce::Colour(0xff2a2a4a)); - }; - setupScrollBtn(scrollLeftBtn); - setupScrollBtn(scrollRightBtn); - startTimerHz(30); } @@ -67,6 +60,22 @@ void WaveformDisplay::zoomReset() repaint(); } +void WaveformDisplay::scrollLeft() +{ + scrollOffset -= 1.0f / zoomFactor; + scrollOffset = juce::jlimit(0.0f, 1.0f, scrollOffset); + syncScrollBar(); + repaint(); +} + +void WaveformDisplay::scrollRight() +{ + scrollOffset += 1.0f / zoomFactor; + scrollOffset = juce::jlimit(0.0f, 1.0f, scrollOffset); + syncScrollBar(); + repaint(); +} + void WaveformDisplay::syncScrollBar() { if (updatingScroll) return; @@ -209,7 +218,6 @@ void WaveformDisplay::paint(juce::Graphics& g) g.setColour(juce::Colours::grey); g.setFont(14.0f); g.drawText("No audio file loaded.", textArea, juce::Justification::centred); - hScrollBar.setBounds(bounds.removeFromBottom(scrollbarHeight).toNearestInt()); return; } @@ -225,13 +233,6 @@ void WaveformDisplay::paint(juce::Graphics& g) auto waveArea = waveBounds.withTrimmedLeft(keyWidth); drawWaveform(g, waveArea); drawSliceMarkers(g, waveArea); - - // Scrollbar at bottom - hScrollBar.setBounds(juce::Rectangle( - static_cast(bounds.getBottomLeft().getX()), - static_cast(bounds.getBottom() - scrollbarHeight), - static_cast(bounds.getWidth()), - static_cast(scrollbarHeight))); } void WaveformDisplay::drawKeys(juce::Graphics& g, juce::Rectangle bounds) @@ -531,10 +532,7 @@ void WaveformDisplay::resized() { auto bounds = getLocalBounds(); auto scrollBarRow = bounds.removeFromBottom(static_cast(scrollbarHeight)); - scrollLeftBtn.setBounds(scrollBarRow.getX(), scrollBarRow.getY(), scrollBtnWidth, scrollBarRow.getHeight()); - scrollRightBtn.setBounds(scrollBarRow.getRight() - scrollBtnWidth, scrollBarRow.getY(), scrollBtnWidth, scrollBarRow.getHeight()); - hScrollBar.setBounds(scrollBarRow.getX() + scrollBtnWidth, scrollBarRow.getY(), - scrollBarRow.getWidth() - scrollBtnWidth * 2, scrollBarRow.getHeight()); + hScrollBar.setBounds(scrollBarRow); } void WaveformDisplay::mouseDown(const juce::MouseEvent& e) diff --git a/Source/WaveformDisplay.h b/Source/WaveformDisplay.h index 1d1c8ae..959eab2 100644 --- a/Source/WaveformDisplay.h +++ b/Source/WaveformDisplay.h @@ -34,6 +34,8 @@ public: void zoomIn(); void zoomOut(); void zoomReset(); + void scrollLeft(); + void scrollRight(); int xToSample(int x) const; int sampleToX(int sample) const; @@ -63,10 +65,7 @@ private: std::function onKeyClick; juce::ScrollBar hScrollBar { false }; - juce::TextButton scrollLeftBtn { "<" }; - juce::TextButton scrollRightBtn { ">" }; bool updatingScroll = false; - static constexpr int scrollBtnWidth = 16; juce::AudioBuffer overviewBuffer; bool overviewDirty = true;