From a2485907ef0e14416ad271bdb315d996c6aff20d Mon Sep 17 00:00:00 2001 From: Armin Date: Thu, 13 Aug 2026 12:51:42 +0200 Subject: [PATCH] Add bottom status bar with git build info and compile time --- CMakeLists.txt | 14 +++++++++++ Source/BuildInfo.cpp | 32 ++++++++++++++++++++++++ Source/BuildInfo.h.in | 8 ++++++ Source/PluginEditor.cpp | 14 +++++++++++ Source/PluginEditor.h | 4 ++- cmake/GenerateBuildInfo.cmake | 47 +++++++++++++++++++++++++++++++++++ 6 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 Source/BuildInfo.cpp create mode 100644 Source/BuildInfo.h.in create mode 100644 cmake/GenerateBuildInfo.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index d121253..72db57c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,8 +64,22 @@ juce_add_plugin(ChromaFlock target_sources(ChromaFlock PRIVATE Source/PluginProcessor.cpp Source/PluginEditor.cpp + Source/BuildInfo.cpp ) +# Generate git build info at BUILD time so it reflects the current commit/tree. +# Runs on every build; the rewritten header forces BuildInfo.cpp to recompile, +# so getBuildInfoString()'s __DATE__/__TIME__ reflect the actual compile time. +add_custom_target(ChromaFlockBuildInfo ALL + COMMAND ${CMAKE_COMMAND} + -DROOT_DIR="${CMAKE_CURRENT_SOURCE_DIR}" + -DOUT_DIR="${CMAKE_CURRENT_BINARY_DIR}/Generated" + -P "${CMAKE_CURRENT_SOURCE_DIR}/cmake/GenerateBuildInfo.cmake" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Generating BuildInfo.h (git build info)" +) +add_dependencies(ChromaFlock ChromaFlockBuildInfo) + target_compile_definitions(ChromaFlock PUBLIC JUCE_VST3_CAN_REPLACE_VST2=0 JUCE_WEB_BROWSER=0 diff --git a/Source/BuildInfo.cpp b/Source/BuildInfo.cpp new file mode 100644 index 0000000..7c2d84f --- /dev/null +++ b/Source/BuildInfo.cpp @@ -0,0 +1,32 @@ +#include "BuildInfo.h" +#include +#include + +std::string getBuildInfoString() { + // Actual compilation time from compiler built-ins. + // __DATE__ -> "Mmm dd yyyy", __TIME__ -> "HH:MM:SS" + const char* date = __DATE__; + const char* time = __TIME__; + + static const char* months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + char mon[4] = {0}; + int day = 0, year = 0, hh = 0, mm = 0, ss = 0; + std::sscanf(date, "%3s %d %d", mon, &day, &year); + std::sscanf(time, "%d:%d:%d", &hh, &mm, &ss); + + int mi = 1; + for (int i = 0; i < 12; ++i) + if (std::strcmp(mon, months[i]) == 0) { mi = i + 1; break; } + + char buf[64]; + std::snprintf(buf, sizeof(buf), "%04d-%02d-%02d__%02d-%02d-%02d", + year, mi, day, hh, mm, ss); + + std::string s = std::string("build ") + CHROMAFLOCK_GIT_HASH + + " (" + CHROMAFLOCK_GIT_BRANCH + ")"; + if (CHROMAFLOCK_GIT_DIRTY) + s += " *"; + s += " built " + std::string(buf); + return s; +} diff --git a/Source/BuildInfo.h.in b/Source/BuildInfo.h.in new file mode 100644 index 0000000..389cc3f --- /dev/null +++ b/Source/BuildInfo.h.in @@ -0,0 +1,8 @@ +#pragma once +// Generated at build time by cmake/GenerateBuildInfo.cmake. Do not edit manually. +#define CHROMAFLOCK_GIT_HASH "@CHROMAFLOCK_GIT_HASH@" +#define CHROMAFLOCK_GIT_BRANCH "@CHROMAFLOCK_GIT_BRANCH@" +#define CHROMAFLOCK_GIT_DIRTY @CHROMAFLOCK_GIT_DIRTY@ + +#include +std::string getBuildInfoString(); diff --git a/Source/PluginEditor.cpp b/Source/PluginEditor.cpp index 5c7f796..4610ace 100644 --- a/Source/PluginEditor.cpp +++ b/Source/PluginEditor.cpp @@ -1,4 +1,5 @@ #include "PluginEditor.h" +#include "BuildInfo.h" #include namespace @@ -698,6 +699,12 @@ MainContentComponent::MainContentComponent(ChromaFlockProcessor& p) setupParam(reverbDampKnob, reverbDampAttach, "reverbDamping", "DAMP"); setupParam(reverbMixKnob, reverbMixAttach, "reverbMix", "MIX"); + // Bottom status bar: git build info + actual compilation time + addAndMakeVisible(statusBar); + statusBar.setColour(juce::Label::textColourId, juce::Colour(0xff888888)); + statusBar.setFont(juce::Font(juce::FontOptions(11.0f))); + statusBar.setText(juce::String(getBuildInfoString()), juce::dontSendNotification); + // Preset section: title button + dot-matrix LCD + prev/next presetButton.setColour(juce::TextButton::buttonColourId, juce::Colour(0xcc2a2a2a)); presetButton.setColour(juce::TextButton::textColourOffId, juce::Colour(0xffccaa44)); @@ -1175,6 +1182,10 @@ void MainContentComponent::paint(juce::Graphics& g) { // Arpeggiator section (replaces the removed spectrum analyzer) drawSubSection(860, 754, 790, 128, "ARPEGGIATOR", 6); + + // Status bar divider + g.setColour(juce::Colour(0xff333333)); + g.drawHorizontalLine(1034, 10.0f, 1650.0f); } void MainContentComponent::resized() { @@ -1416,6 +1427,9 @@ void MainContentComponent::resized() { // Piano roll pianoRoll.setBounds(10, 892, 1640, 136); + + // Status bar (bottom strip) + statusBar.setBounds(10, 1036, 1640, 20); } // ===== PianoRollComponent ===== diff --git a/Source/PluginEditor.h b/Source/PluginEditor.h index 270c0fb..33ca245 100644 --- a/Source/PluginEditor.h +++ b/Source/PluginEditor.h @@ -209,6 +209,8 @@ private: juce::ComboBox uiScaleBox; + juce::Label statusBar; + using SliderAttachment = juce::AudioProcessorValueTreeState::SliderAttachment; using ComboBoxAttachment = juce::AudioProcessorValueTreeState::ComboBoxAttachment; @@ -275,7 +277,7 @@ private: MainContentComponent content; float currentScale = 1.0f; static constexpr int baseWidth = 1660; - static constexpr int baseHeight = 1036; + static constexpr int baseHeight = 1058; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ChromaFlockEditor) }; diff --git a/cmake/GenerateBuildInfo.cmake b/cmake/GenerateBuildInfo.cmake new file mode 100644 index 0000000..f122eaa --- /dev/null +++ b/cmake/GenerateBuildInfo.cmake @@ -0,0 +1,47 @@ +cmake_minimum_required(VERSION 3.22) + +set(ROOT_DIR "" CACHE STRING "ChromaFlock source root") +set(OUT_DIR "" CACHE STRING "Output directory for generated header") + +execute_process(COMMAND git rev-parse --short HEAD + WORKING_DIRECTORY "${ROOT_DIR}" + OUTPUT_VARIABLE GIT_HASH + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) +if(NOT GIT_HASH) + set(GIT_HASH "unknown") +endif() + +execute_process(COMMAND git rev-parse --abbrev-ref HEAD + WORKING_DIRECTORY "${ROOT_DIR}" + OUTPUT_VARIABLE GIT_BRANCH + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) +if(NOT GIT_BRANCH OR GIT_BRANCH STREQUAL "HEAD") + execute_process(COMMAND git describe --tags --always + WORKING_DIRECTORY "${ROOT_DIR}" + OUTPUT_VARIABLE GIT_BRANCH + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) +endif() +if(NOT GIT_BRANCH) + set(GIT_BRANCH "unknown") +endif() + +execute_process(COMMAND git status --porcelain + WORKING_DIRECTORY "${ROOT_DIR}" + OUTPUT_VARIABLE GIT_STATUS + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) +if(GIT_STATUS STREQUAL "") + set(GIT_DIRTY 0) +else() + set(GIT_DIRTY 1) +endif() + +set(CHROMAFLOCK_GIT_HASH "${GIT_HASH}") +set(CHROMAFLOCK_GIT_BRANCH "${GIT_BRANCH}") +set(CHROMAFLOCK_GIT_DIRTY ${GIT_DIRTY}) + +configure_file("${ROOT_DIR}/Source/BuildInfo.h.in" + "${OUT_DIR}/BuildInfo.h" @ONLY)