Skip to content

Commit

Permalink
Add sequencer track solo button
Browse files Browse the repository at this point in the history
  • Loading branch information
FangCunWuChang committed Dec 5, 2024
1 parent 6a611fd commit 99e31ed
Show file tree
Hide file tree
Showing 14 changed files with 184 additions and 60 deletions.
3 changes: 2 additions & 1 deletion src/audioCore/graph/SeqSourceProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ SeqSourceProcessor::SeqSourceProcessor(const juce::AudioChannelSet& type)
}

SeqSourceProcessor::~SeqSourceProcessor() {
this->setSolo(false);
this->releaseAudio();
this->releaseMIDI();
}
Expand Down Expand Up @@ -544,7 +545,7 @@ bool SeqSourceProcessor::getMute() const {
}

void SeqSourceProcessor::setSolo(bool solo) {
bool shouldChange = (this->isSolo == solo);
bool shouldChange = (this->isSolo != solo);

this->isSolo = solo;

Expand Down
14 changes: 13 additions & 1 deletion src/ui/component/sequencer/SeqTrackComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ SeqTrackComponent::SeqTrackComponent(
this->muteButton = std::make_unique<SeqTrackMuteComponent>();
this->addChildComponent(this->muteButton.get());

/** Solo Button */
this->soloButton = std::make_unique<SeqTrackSoloComponent>();
this->addChildComponent(this->soloButton.get());

/** Input Monitoring Button */
this->inputMonitoringButton = std::make_unique<SeqTrackInputMonitoringComponent>();
this->addChildComponent(this->inputMonitoringButton.get());
Expand Down Expand Up @@ -171,6 +175,7 @@ void SeqTrackComponent::updateBlock(int blockIndex) {

void SeqTrackComponent::updateMuteSolo() {
this->muteButton->update(this->index);
this->soloButton->update(this->index);
}

void SeqTrackComponent::updateInputMonitoring() {
Expand Down Expand Up @@ -327,9 +332,16 @@ void SeqTrackComponent::resized() {
this->muteButton->setBounds(muteRect);
this->muteButton->setVisible(isIOLineShown);

/** Solo Button */
juce::Rectangle<int> soloRect(
muteRect.getRight() + buttonSplitWidth, inputMonitoringRect.getY(),
ioLineHeight, ioLineHeight);
this->soloButton->setBounds(soloRect);
this->soloButton->setVisible(isIOLineShown);

/** MIDI Output */
juce::Rectangle<int> midiOutputRect(
muteRect.getRight() + buttonSplitWidth, inputMonitoringRect.getY(),
soloRect.getRight() + buttonSplitWidth, inputMonitoringRect.getY(),
ioLineHeight, ioLineHeight);
this->midiOutput->setBounds(midiOutputRect);
this->midiOutput->setVisible(isIOLineShown);
Expand Down
2 changes: 2 additions & 0 deletions src/ui/component/sequencer/SeqTrackComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <JuceHeader.h>
#include "SeqTrackMuteComponent.h"
#include "SeqTrackSoloComponent.h"
#include "SeqTrackInputMonitoringComponent.h"
#include "SeqTrackRecComponent.h"
#include "SeqTrackIOComponent.h"
Expand Down Expand Up @@ -78,6 +79,7 @@ class SeqTrackComponent final

std::unique_ptr<juce::TextButton> trackName = nullptr;
std::unique_ptr<SeqTrackMuteComponent> muteButton = nullptr;
std::unique_ptr<SeqTrackSoloComponent> soloButton = nullptr;
std::unique_ptr<SeqTrackInputMonitoringComponent> inputMonitoringButton = nullptr;
std::unique_ptr<SeqTrackRecComponent> recButton = nullptr;

Expand Down
38 changes: 1 addition & 37 deletions src/ui/component/sequencer/SeqTrackMuteComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ void SeqTrackMuteComponent::mouseUp(const juce::MouseEvent& event) {
this->changeMute();
}
else if (event.mods.isRightButtonDown()) {
this->showMenu();
this->changeMute();
}
}
}
Expand All @@ -102,39 +102,3 @@ void SeqTrackMuteComponent::update(int index) {
void SeqTrackMuteComponent::changeMute() {
CoreActions::setSeqMute(this->index, !(this->mute));
}

enum MixerMuteActionType {
Mute = 1, Solo, MuteAll, UnmuteAll
};

void SeqTrackMuteComponent::showMenu() {
auto menu = this->createMenu();
int result = menu.show();

switch (result) {
case MixerMuteActionType::Mute:
this->changeMute();
break;
case MixerMuteActionType::Solo:
CoreActions::setSeqSolo(this->index);
break;
case MixerMuteActionType::MuteAll:
CoreActions::setSeqMuteAll(true);
break;
case MixerMuteActionType::UnmuteAll:
CoreActions::setSeqMuteAll(false);
break;
}
}

juce::PopupMenu SeqTrackMuteComponent::createMenu() const {
juce::PopupMenu menu;

menu.addItem(MixerMuteActionType::Mute, TRANS("Mute"), true, this->mute);
menu.addItem(MixerMuteActionType::Solo, TRANS("Solo"));
menu.addSeparator();
menu.addItem(MixerMuteActionType::MuteAll, TRANS("Mute All"));
menu.addItem(MixerMuteActionType::UnmuteAll, TRANS("Unmute All"));

return menu;
}
3 changes: 0 additions & 3 deletions src/ui/component/sequencer/SeqTrackMuteComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ class SeqTrackMuteComponent final
bool equivalentMute = false;

void changeMute();
void showMenu();

juce::PopupMenu createMenu() const;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SeqTrackMuteComponent)
};
103 changes: 103 additions & 0 deletions src/ui/component/sequencer/SeqTrackSoloComponent.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#include "SeqTrackSoloComponent.h"
#include "../../lookAndFeel/LookAndFeelFactory.h"
#include "../../misc/CoreActions.h"
#include "../../Utils.h"
#include "../../../audioCore/AC_API.h"

SeqTrackSoloComponent::SeqTrackSoloComponent() {
this->setLookAndFeel(
LookAndFeelFactory::getInstance()->getLAFFor(LookAndFeelFactory::SoloButton));
}

void SeqTrackSoloComponent::paint(juce::Graphics& g) {
/** Size */
auto screenSize = utils::getScreenSize(this);
float lineThickness = screenSize.getHeight() * 0.001;

int buttonWidth = std::min(this->getWidth(), this->getHeight()) - lineThickness;
int buttonHeight = buttonWidth;

float textFontHeight = buttonWidth * 0.7;

/** Color */
auto& laf = this->getLookAndFeel();
juce::Colour backgroundColor = laf.findColour(this->solo
? juce::TextButton::ColourIds::buttonOnColourId
: juce::TextButton::ColourIds::buttonColourId);
juce::Colour textColor = laf.findColour(this->solo
? juce::TextButton::ColourIds::textColourOnId
: juce::TextButton::ColourIds::textColourOffId);

/** Font */
juce::Font textFont(juce::FontOptions{ textFontHeight });

/** Button */
juce::Rectangle<float> buttonRect(
this->getWidth() / 2.f - buttonWidth / 2.f,
this->getHeight() / 2.f - buttonHeight / 2.f,
buttonWidth, buttonHeight);
g.setColour(backgroundColor);
g.fillRect(buttonRect);

g.setColour(textColor);
g.drawRect(buttonRect, lineThickness);

g.setFont(textFont);
g.drawFittedText("S", buttonRect.toNearestInt(),
juce::Justification::centred, 1, 0.f);
}

void SeqTrackSoloComponent::mouseDrag(const juce::MouseEvent& event) {
this->mouseMove(event);
}

void SeqTrackSoloComponent::mouseMove(const juce::MouseEvent& event) {
/** Size */
auto screenSize = utils::getScreenSize(this);
float lineThickness = screenSize.getHeight() * 0.001;
int buttonWidth = std::min(this->getWidth(), this->getHeight()) - lineThickness;
int buttonHeight = buttonWidth;
juce::Rectangle<float> buttonRect(
this->getWidth() / 2.f - buttonWidth / 2.f,
this->getHeight() / 2.f - buttonHeight / 2.f,
buttonWidth, buttonHeight);

/** Cursor */
this->setMouseCursor(buttonRect.contains(event.position)
? juce::MouseCursor::PointingHandCursor
: juce::MouseCursor::NormalCursor);
}

void SeqTrackSoloComponent::mouseUp(const juce::MouseEvent& event) {
/** Size */
auto screenSize = utils::getScreenSize(this);
float lineThickness = screenSize.getHeight() * 0.001;
int buttonWidth = std::min(this->getWidth(), this->getHeight()) - lineThickness;
int buttonHeight = buttonWidth;
juce::Rectangle<float> buttonRect(
this->getWidth() / 2.f - buttonWidth / 2.f,
this->getHeight() / 2.f - buttonHeight / 2.f,
buttonWidth, buttonHeight);

if (buttonRect.contains(event.position)) {
if (event.mods.isLeftButtonDown()) {
this->changeSolo();
}
else if (event.mods.isRightButtonDown()) {
this->changeSolo();
}
}
}

void SeqTrackSoloComponent::update(int index) {
this->index = index;
if (index > -1) {
this->solo = quickAPI::getSeqTrackSolo(index);

this->repaint();
}
}

void SeqTrackSoloComponent::changeSolo() {
CoreActions::setSeqSolo(this->index, !(this->solo));
}
26 changes: 26 additions & 0 deletions src/ui/component/sequencer/SeqTrackSoloComponent.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include <JuceHeader.h>

class SeqTrackSoloComponent final
: public juce::Component,
public juce::SettableTooltipClient {
public:
SeqTrackSoloComponent();

void paint(juce::Graphics& g) override;

void mouseDrag(const juce::MouseEvent& event) override;
void mouseMove(const juce::MouseEvent& event) override;
void mouseUp(const juce::MouseEvent& event) override;

void update(int index);

private:
int index = -1;
bool solo = false;

void changeSolo();

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SeqTrackSoloComponent)
};
6 changes: 3 additions & 3 deletions src/ui/component/sequencer/SeqView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ void SeqView::TrackList::updateBlock(int track, int index) {
}
}

void SeqView::TrackList::updateMuteSolo(int index) {
if (index >= 0 && index < this->list.size()) {
this->list[index]->updateMuteSolo();
void SeqView::TrackList::updateMuteSolo(int /*index*/) {
for (auto i : this->list) {
i->updateMuteSolo();
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/ui/lookAndFeel/LookAndFeelFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "mixer/SideChainLookAndFeel.h"
#include "mixer/LevelMeterLookAndFeel.h"
#include "base/MuteButtonLookAndFeel.h"
#include "base/SoloButtonLookAndFeel.h"
#include "base/RecButtonLookAndFeel.h"
#include "mixer/EffectLookAndFeel.h"
#include "sequencer/SeqLookAndFeel.h"
Expand Down Expand Up @@ -85,6 +86,7 @@ void LookAndFeelFactory::initialise() {
new SideChainLookAndFeel{},
new LevelMeterLookAndFeel{},
new MuteButtonLookAndFeel{},
new SoloButtonLookAndFeel{},
new RecButtonLookAndFeel{},
new EffectLookAndFeel{},
new SeqLookAndFeel{},
Expand Down
2 changes: 1 addition & 1 deletion src/ui/lookAndFeel/LookAndFeelFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class LookAndFeelFactory final : private juce::DeletedAtShutdown {
ToolBar, MainMenu, SysStatus, Time, Controller, Tools,
Message, MessageView, PluginView, PluginEditor, ChannelLink,
Mixer, Scroller, ColorEditor, SideChain, LevelMeter,
MuteButton, RecButton, Effect, Seq, TimeRuler, SeqTrack,
MuteButton, SoloButton, RecButton, Effect, Seq, TimeRuler, SeqTrack,
SeqTrackName, InstrName, SeqBlock, Editor, EditorSwitchBar,
Piano, MidiContent, InputMonitoringButton,

Expand Down
15 changes: 15 additions & 0 deletions src/ui/lookAndFeel/base/SoloButtonLookAndFeel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include "SoloButtonLookAndFeel.h"
#include "../../misc/ColorMap.h"

SoloButtonLookAndFeel::SoloButtonLookAndFeel()
: MainLookAndFeel() {
/** Button */
this->setColour(juce::TextButton::ColourIds::buttonColourId,
ColorMap::getInstance()->get("ThemeColorB2"));
this->setColour(juce::TextButton::ColourIds::buttonOnColourId,
juce::Colours::red.withAlpha(0.6f));
this->setColour(juce::TextButton::ColourIds::textColourOffId,
ColorMap::getInstance()->get("ThemeColorB8"));
this->setColour(juce::TextButton::ColourIds::textColourOnId,
ColorMap::getInstance()->get("ThemeColorB10"));
}
12 changes: 12 additions & 0 deletions src/ui/lookAndFeel/base/SoloButtonLookAndFeel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once

#include <JuceHeader.h>
#include "../MainLookAndFeel.h"

class SoloButtonLookAndFeel : public MainLookAndFeel {
public:
SoloButtonLookAndFeel();

private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SoloButtonLookAndFeel)
};
15 changes: 3 additions & 12 deletions src/ui/misc/CoreActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -427,18 +427,9 @@ void CoreActions::setSeqMute(int index, bool mute) {
ActionDispatcher::getInstance()->dispatch(std::move(action));
}

void CoreActions::setSeqSolo(int index) {
int trackNum = quickAPI::getSeqTrackNum();
for (int i = 0; i < trackNum; i++) {
CoreActions::setSeqMute(i, i != index);
}
}

void CoreActions::setSeqMuteAll(bool mute) {
int trackNum = quickAPI::getSeqTrackNum();
for (int i = 0; i < trackNum; i++) {
CoreActions::setSeqMute(i, mute);
}
void CoreActions::setSeqSolo(int index, bool solo) {
auto action = std::unique_ptr<ActionBase>(new ActionSetSequencerTrackSolo{ index, solo });
ActionDispatcher::getInstance()->dispatch(std::move(action));
}

void CoreActions::setSeqInputMonitoring(int index, bool inputMonitoring) {
Expand Down
3 changes: 1 addition & 2 deletions src/ui/misc/CoreActions.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,7 @@ class CoreActions final {
static void setSeqMIDIOutputToMixer(int index, int mixerIndex, bool output);
static void setSeqAudioOutputToMixer(int index, int channel, int mixerIndex, int dstChannel, bool output);
static void setSeqMute(int index, bool mute);
static void setSeqSolo(int index);
static void setSeqMuteAll(bool mute);
static void setSeqSolo(int index, bool solo);
static void setSeqInputMonitoring(int index, bool inputMonitoring);
static void setSeqRec(int index, quickAPI::RecordState rec);
static void setSeqMIDITrack(int index, int midiTrack);
Expand Down

0 comments on commit 99e31ed

Please sign in to comment.