diff --git a/src/audioCore/graph/SeqSourceProcessor.cpp b/src/audioCore/graph/SeqSourceProcessor.cpp index 3ca79da7..a2800386 100644 --- a/src/audioCore/graph/SeqSourceProcessor.cpp +++ b/src/audioCore/graph/SeqSourceProcessor.cpp @@ -301,8 +301,14 @@ void SeqSourceProcessor::initAudio(double sampleRate, double length) { /** Update Resample Source */ this->updateAudioResampler(); + /** Update Name */ + this->audioName = juce::String{}; + /** Set Flag */ this->audioChanged(); + + /** Callback */ + UICallbackAPI::invoke(UICallbackType::SeqDataRefChanged, this->index); } void SeqSourceProcessor::initMIDI() { @@ -313,8 +319,14 @@ void SeqSourceProcessor::initMIDI() { this->midiData = std::make_unique(); this->midiData->addTrack(juce::MidiMessageSequence{}); + /** Update Name */ + this->midiName = juce::String{}; + /** Set Flag */ this->midiChanged(); + + /** Callback */ + UICallbackAPI::invoke(UICallbackType::SeqDataRefChanged, this->index); } void SeqSourceProcessor::setAudio(double sampleRate, @@ -337,6 +349,9 @@ void SeqSourceProcessor::setAudio(double sampleRate, /** Set Flag */ this->audioChanged(); + + /** Callback */ + UICallbackAPI::invoke(UICallbackType::SeqDataRefChanged, this->index); } void SeqSourceProcessor::setMIDI( @@ -350,6 +365,9 @@ void SeqSourceProcessor::setMIDI( /** Set Flag */ this->midiChanged(); + + /** Callback */ + UICallbackAPI::invoke(UICallbackType::SeqDataRefChanged, this->index); } const std::tuple SeqSourceProcessor::getAudio() const { @@ -450,6 +468,14 @@ const juce::String SeqSourceProcessor::getMIDIFileName() const { return utils::getLegalFileName(name) + extension; } +const juce::String SeqSourceProcessor::getAudioName() const { + return this->audioName; +} + +const juce::String SeqSourceProcessor::getMIDIName() const { + return this->midiName; +} + void SeqSourceProcessor::audioChanged() { this->audioSavedFlag = false; } diff --git a/src/audioCore/graph/SeqSourceProcessor.h b/src/audioCore/graph/SeqSourceProcessor.h index f94609e7..c8c36b0f 100644 --- a/src/audioCore/graph/SeqSourceProcessor.h +++ b/src/audioCore/graph/SeqSourceProcessor.h @@ -59,6 +59,8 @@ class SeqSourceProcessor final : public juce::AudioProcessorGraph, void loadMIDI(const juce::String& path, bool getTempo = false); const juce::String getAudioFileName() const; const juce::String getMIDIFileName() const; + const juce::String getAudioName() const; + const juce::String getMIDIName() const; void audioChanged(); void midiChanged(); void audioSaved(); @@ -109,7 +111,7 @@ class SeqSourceProcessor final : public juce::AudioProcessorGraph, std::unique_ptr serialize() const override; private: - int index = -1; + std::atomic_int index = -1; const juce::AudioChannelSet audioChannels; diff --git a/src/audioCore/quickAPI/QuickGet.cpp b/src/audioCore/quickAPI/QuickGet.cpp index 875ca97a..3084498d 100644 --- a/src/audioCore/quickAPI/QuickGet.cpp +++ b/src/audioCore/quickAPI/QuickGet.cpp @@ -616,6 +616,24 @@ namespace quickAPI { return ""; } + const juce::String getSeqTrackDataRefAudio(int index) { + if (auto graph = AudioCore::getInstance()->getGraph()) { + if (auto track = graph->getSourceProcessor(index)) { + return track->getAudioName(); + } + } + return ""; + } + + const juce::String getSeqTrackDataRefMIDI(int index) { + if (auto graph = AudioCore::getInstance()->getGraph()) { + if (auto track = graph->getSourceProcessor(index)) { + return track->getMIDIName(); + } + } + return ""; + } + int getMixerTrackNum() { if (auto graph = AudioCore::getInstance()->getGraph()) { return graph->getTrackNum(); diff --git a/src/audioCore/quickAPI/QuickGet.h b/src/audioCore/quickAPI/QuickGet.h index b9f2a22e..247e9b7a 100644 --- a/src/audioCore/quickAPI/QuickGet.h +++ b/src/audioCore/quickAPI/QuickGet.h @@ -120,6 +120,8 @@ namespace quickAPI { bool getSeqTrackRecording(int index); const juce::Array getSeqTrackOutputLevel(int index); const juce::String getSeqTrackType(int index); + const juce::String getSeqTrackDataRefAudio(int index); + const juce::String getSeqTrackDataRefMIDI(int index); int getMixerTrackNum(); const juce::String getMixerTrackName(int index); diff --git a/src/audioCore/uiCallback/UICallbackType.h b/src/audioCore/uiCallback/UICallbackType.h index 9434d775..ae1113be 100644 --- a/src/audioCore/uiCallback/UICallbackType.h +++ b/src/audioCore/uiCallback/UICallbackType.h @@ -19,6 +19,7 @@ enum class UICallbackType : int { SeqMuteChanged, SeqRecChanged, TempoChanged, + SeqDataRefChanged, TypeMaxNum }; diff --git a/src/ui/component/SeqTrackComponent.cpp b/src/ui/component/SeqTrackComponent.cpp index d22027e0..0b4e92d8 100644 --- a/src/ui/component/SeqTrackComponent.cpp +++ b/src/ui/component/SeqTrackComponent.cpp @@ -190,6 +190,10 @@ void SeqTrackComponent::updateMixerTrack() { this->audioOutput->update(this->index); } +void SeqTrackComponent::updateDataRef() { + this->content->updateDataRef(); +} + void SeqTrackComponent::resized() { /** Size */ auto screenSize = utils::getScreenSize(this); diff --git a/src/ui/component/SeqTrackComponent.h b/src/ui/component/SeqTrackComponent.h index fd82eb50..9df3ae3f 100644 --- a/src/ui/component/SeqTrackComponent.h +++ b/src/ui/component/SeqTrackComponent.h @@ -22,6 +22,7 @@ class SeqTrackComponent final void updateInstr(); void updateHPos(double pos, double itemSize); void updateMixerTrack(); + void updateDataRef(); void resized() override; void paint(juce::Graphics& g) override; diff --git a/src/ui/component/SeqTrackContentViewer.cpp b/src/ui/component/SeqTrackContentViewer.cpp index e3fd3335..7d322a76 100644 --- a/src/ui/component/SeqTrackContentViewer.cpp +++ b/src/ui/component/SeqTrackContentViewer.cpp @@ -1,9 +1,12 @@ #include "SeqTrackContentViewer.h" +#include "../lookAndFeel/LookAndFeelFactory.h" #include "../Utils.h" #include "../../audioCore/AC_API.h" SeqTrackContentViewer::SeqTrackContentViewer() { - /** TODO */ + /** Look And Feel */ + this->setLookAndFeel( + LookAndFeelFactory::getInstance()->forSeqBlock()); } void SeqTrackContentViewer::setCompressed(bool isCompressed) { @@ -18,6 +21,18 @@ void SeqTrackContentViewer::update(int index) { this->trackColor = quickAPI::getSeqTrackColor(index); + auto& laf = this->getLookAndFeel(); + if (utils::isLightColor(this->trackColor)) { + this->nameColor = laf.findColour( + juce::Label::ColourIds::textWhenEditingColourId); + } + else { + this->nameColor = laf.findColour( + juce::Label::ColourIds::textColourId); + } + + this->updateDataRef(); + this->repaint(); } } @@ -62,11 +77,36 @@ void SeqTrackContentViewer::updateHPos(double pos, double itemSize) { this->repaint(); } +void SeqTrackContentViewer::updateDataRef() { + this->audioName = quickAPI::getSeqTrackDataRefAudio(this->index); + this->midiName = quickAPI::getSeqTrackDataRefMIDI(this->index); + + this->blockNameCombined = this->audioName + + ((this->audioName.isNotEmpty() && this->midiName.isNotEmpty()) ? " + " : "") + + this->midiName; + + this->repaint(); +} + void SeqTrackContentViewer::paint(juce::Graphics& g) { /** Size */ auto screenSize = utils::getScreenSize(this); float paddingHeight = screenSize.getHeight() * 0.0025; float blockRadius = screenSize.getHeight() * 0.005; + float outlineThickness = screenSize.getHeight() * 0.0015; + + float blockPaddingHeight = screenSize.getHeight() * 0.01; + float blockPaddingWidth = screenSize.getWidth() * 0.01; + + float blockNameFontHeight = screenSize.getHeight() * 0.015; + + /** Color */ + auto& laf = this->getLookAndFeel(); + juce::Colour outlineColor = laf.findColour( + juce::Label::ColourIds::outlineColourId); + + /** Font */ + juce::Font blockNameFont(blockNameFontHeight); /** Blocks */ for (auto block : this->blockTemp) { @@ -75,11 +115,25 @@ void SeqTrackContentViewer::paint(juce::Graphics& g) { float startPos = (block->startTime - this->secStart) / (this->secEnd - this->secStart) * this->getWidth(); float endPos = (block->endTime - this->secStart) / (this->secEnd - this->secStart) * this->getWidth(); + /** Rect */ juce::Rectangle blockRect( startPos, paddingHeight, endPos - startPos, this->getHeight() - paddingHeight * 2); g.setColour(this->trackColor.withAlpha(0.5f)); g.fillRoundedRectangle(blockRect, blockRadius); + g.setColour(outlineColor); + g.drawRoundedRectangle(blockRect, blockRadius, outlineThickness); + + /** Name */ + float nameStartPos = std::max(startPos, 0.f) + blockPaddingWidth; + float nameEndPos = std::min(endPos, (float)this->getWidth()) - blockPaddingWidth; + juce::Rectangle nameRect( + nameStartPos, this->compressed ? 0 : blockPaddingHeight, + nameEndPos - nameStartPos, this->compressed ? this->getHeight() : blockNameFontHeight); + g.setColour(this->nameColor); + g.setFont(blockNameFont); + g.drawFittedText(this->blockNameCombined, nameRect.toNearestInt(), + juce::Justification::centredLeft, 1, 1.f); } } } diff --git a/src/ui/component/SeqTrackContentViewer.h b/src/ui/component/SeqTrackContentViewer.h index eef99845..f596ffc8 100644 --- a/src/ui/component/SeqTrackContentViewer.h +++ b/src/ui/component/SeqTrackContentViewer.h @@ -11,6 +11,7 @@ class SeqTrackContentViewer final : public juce::Component { void update(int index); void updateBlock(int blockIndex); void updateHPos(double pos, double itemSize); + void updateDataRef(); void paint(juce::Graphics& g) override; @@ -19,7 +20,9 @@ class SeqTrackContentViewer final : public juce::Component { int index = -1; double pos = 0, itemSize = 0; double secStart = 0, secEnd = 0; - juce::Colour trackColor; + juce::Colour trackColor, nameColor; + juce::String audioName, midiName; + juce::String blockNameCombined; struct BlockItem final { double startTime = 0, endTime = 0, offset = 0; diff --git a/src/ui/component/SeqView.cpp b/src/ui/component/SeqView.cpp index 33a6fe1f..23c5fa88 100644 --- a/src/ui/component/SeqView.cpp +++ b/src/ui/component/SeqView.cpp @@ -62,6 +62,12 @@ void SeqView::TrackList::updateMixerTrack() { } } +void SeqView::TrackList::updateDataRef(int index) { + if (index >= 0 && index < this->list.size()) { + this->list[index]->updateDataRef(); + } +} + void SeqView::TrackList::updateHPos(double pos, double itemSize) { for (auto i : this->list) { i->updateHPos(pos, itemSize); @@ -219,6 +225,13 @@ SeqView::SeqView() } } ); + CoreCallbacks::getInstance()->addSeqDataRefChanged( + [comp = SeqView::SafePointer(this)](int index) { + if (comp) { + comp->updateDataRef(index); + } + } + ); /** Init Temp */ this->gridTemp = std::make_unique( @@ -512,6 +525,10 @@ void SeqView::updateMixerTrack(int /*index*/) { this->trackList->updateMixerTrack(); } +void SeqView::updateDataRef(int index) { + this->trackList->updateDataRef(index); +} + std::tuple SeqView::getViewArea( double pos, double itemSize) const { double secStart = pos / itemSize; diff --git a/src/ui/component/SeqView.h b/src/ui/component/SeqView.h index 6f46ab51..2c6eda89 100644 --- a/src/ui/component/SeqView.h +++ b/src/ui/component/SeqView.h @@ -26,6 +26,7 @@ class SeqView final void updateInstr(int index); void updateLevelMeter() override; void updateMixerTrack(int index); + void updateDataRef(int index); std::tuple getViewArea(double pos, double itemSize) const; @@ -47,6 +48,7 @@ class SeqView final void updateRec(int index); void updateInstr(int index); void updateMixerTrack(); + void updateDataRef(int index); void updateHPos(double pos, double itemSize); void updateVPos(double pos, double itemSize); diff --git a/src/ui/lookAndFeel/LookAndFeelFactory.cpp b/src/ui/lookAndFeel/LookAndFeelFactory.cpp index 40ce9a07..47c6620f 100644 --- a/src/ui/lookAndFeel/LookAndFeelFactory.cpp +++ b/src/ui/lookAndFeel/LookAndFeelFactory.cpp @@ -24,6 +24,7 @@ #include "SeqTrackLookAndFeel.h" #include "SeqTrackNameLookAndFeel.h" #include "InstrNameLookAndFeel.h" +#include "SeqBlockLookAndFeel.h" #include "../misc/ColorMap.h" #include @@ -130,6 +131,9 @@ void LookAndFeelFactory::initialise() { /** Instr Name */ this->instrNameLAF = std::make_unique(); + + /** Seq Block */ + this->seqBlockLAF = std::make_unique(); } void LookAndFeelFactory::setDefaultSansSerifTypeface(juce::Typeface::Ptr typeface) { @@ -233,6 +237,10 @@ juce::LookAndFeel_V4* LookAndFeelFactory::forInstrName() const { return this->instrNameLAF.get(); } +juce::LookAndFeel_V4* LookAndFeelFactory::forSeqBlock() const { + return this->seqBlockLAF.get(); +} + LookAndFeelFactory* LookAndFeelFactory::getInstance() { return LookAndFeelFactory::instance ? LookAndFeelFactory::instance : (LookAndFeelFactory::instance = new LookAndFeelFactory{}); diff --git a/src/ui/lookAndFeel/LookAndFeelFactory.h b/src/ui/lookAndFeel/LookAndFeelFactory.h index eaab441f..86c3693d 100644 --- a/src/ui/lookAndFeel/LookAndFeelFactory.h +++ b/src/ui/lookAndFeel/LookAndFeelFactory.h @@ -33,6 +33,7 @@ class LookAndFeelFactory final : private juce::DeletedAtShutdown { juce::LookAndFeel_V4* forSeqTrack() const; juce::LookAndFeel_V4* forSeqTrackName() const; juce::LookAndFeel_V4* forInstrName() const; + juce::LookAndFeel_V4* forSeqBlock() const; private: std::unique_ptr mainLAF = nullptr; @@ -60,6 +61,7 @@ class LookAndFeelFactory final : private juce::DeletedAtShutdown { std::unique_ptr seqTrackLAF = nullptr; std::unique_ptr seqTrackNameLAF = nullptr; std::unique_ptr instrNameLAF = nullptr; + std::unique_ptr seqBlockLAF = nullptr; public: static LookAndFeelFactory* getInstance(); diff --git a/src/ui/lookAndFeel/SeqBlockLookAndFeel.cpp b/src/ui/lookAndFeel/SeqBlockLookAndFeel.cpp new file mode 100644 index 00000000..30c15455 --- /dev/null +++ b/src/ui/lookAndFeel/SeqBlockLookAndFeel.cpp @@ -0,0 +1,19 @@ +#include "SeqBlockLookAndFeel.h" +#include "../misc/ColorMap.h" + +SeqBlockLookAndFeel::SeqBlockLookAndFeel() + : MainLookAndFeel() { + /** Block */ + this->setColour(juce::Label::ColourIds::backgroundColourId, + ColorMap::getInstance()->get("ThemeColorB2")); + this->setColour(juce::Label::ColourIds::textColourId, + ColorMap::getInstance()->get("ThemeColorB10"));/**< Block Name Light */ + this->setColour(juce::Label::ColourIds::outlineColourId, + ColorMap::getInstance()->get("ThemeColorB6"));/**< Block Outline */ + this->setColour(juce::Label::ColourIds::backgroundWhenEditingColourId, + ColorMap::getInstance()->get("ThemeColorB2")); + this->setColour(juce::Label::ColourIds::textWhenEditingColourId, + ColorMap::getInstance()->get("ThemeColorB0"));/**< Block Name Dark */ + this->setColour(juce::Label::ColourIds::outlineWhenEditingColourId, + ColorMap::getInstance()->get("ThemeColorA2"));/**< Block Hovered Outline */ +} diff --git a/src/ui/lookAndFeel/SeqBlockLookAndFeel.h b/src/ui/lookAndFeel/SeqBlockLookAndFeel.h new file mode 100644 index 00000000..cbef160a --- /dev/null +++ b/src/ui/lookAndFeel/SeqBlockLookAndFeel.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include "MainLookAndFeel.h" + +class SeqBlockLookAndFeel : public MainLookAndFeel { +public: + SeqBlockLookAndFeel(); + +private: + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SeqBlockLookAndFeel) +}; diff --git a/src/ui/misc/CoreCallbacks.cpp b/src/ui/misc/CoreCallbacks.cpp index dcbbf051..1be072da 100644 --- a/src/ui/misc/CoreCallbacks.cpp +++ b/src/ui/misc/CoreCallbacks.cpp @@ -74,6 +74,10 @@ CoreCallbacks::CoreCallbacks() { [](int index) { CoreCallbacks::getInstance()->invokeSeqRecChanged(index); }); + UICallbackAPI::set(UICallbackType::SeqDataRefChanged, + [](int index) { + CoreCallbacks::getInstance()->invokeSeqDataRefChanged(index); + }); } void CoreCallbacks::addError(const ErrorCallback& callback) { @@ -148,6 +152,10 @@ void CoreCallbacks::addSeqRecChanged(const SeqRecChangedCallback& callback) { this->seqRecChanged.add(callback); } +void CoreCallbacks::addSeqDataRefChanged(const SeqDataRefChangedCallback& callback) { + this->seqDataRefChanged.add(callback); +} + void CoreCallbacks::invokeError( const juce::String& title, const juce::String& mes) const { for (auto& i : this->error) { @@ -257,6 +265,12 @@ void CoreCallbacks::invokeSeqRecChanged(int index) const { } } +void CoreCallbacks::invokeSeqDataRefChanged(int index) const { + for (auto& i : this->seqDataRefChanged) { + i(index); + } +} + CoreCallbacks* CoreCallbacks::getInstance() { return CoreCallbacks::instance ? CoreCallbacks::instance : (CoreCallbacks::instance = new CoreCallbacks{}); diff --git a/src/ui/misc/CoreCallbacks.h b/src/ui/misc/CoreCallbacks.h index 877461e9..ca6c4a21 100644 --- a/src/ui/misc/CoreCallbacks.h +++ b/src/ui/misc/CoreCallbacks.h @@ -38,6 +38,8 @@ class CoreCallbacks final : private juce::DeletedAtShutdown { void addSeqMuteChanged(const SeqMuteChangedCallback& callback); using SeqRecChangedCallback = std::function; void addSeqRecChanged(const SeqRecChangedCallback& callback); + using SeqDataRefChangedCallback = std::function; + void addSeqDataRefChanged(const SeqDataRefChangedCallback& callback); void invokeError(const juce::String& title, const juce::String& mes) const; void invokePlayingStatus(bool status) const; @@ -57,6 +59,7 @@ class CoreCallbacks final : private juce::DeletedAtShutdown { void invokeTempoChanged() const; void invokeSeqMuteChanged(int index) const; void invokeSeqRecChanged(int index) const; + void invokeSeqDataRefChanged(int index) const; private: juce::Array error; @@ -77,6 +80,7 @@ class CoreCallbacks final : private juce::DeletedAtShutdown { juce::Array tempoChanged; juce::Array seqMuteChanged; juce::Array seqRecChanged; + juce::Array seqDataRefChanged; public: static CoreCallbacks* getInstance();