Skip to content

Commit

Permalink
Add pop-up window for visualiser
Browse files Browse the repository at this point in the history
  • Loading branch information
jameshball committed Jun 2, 2024
1 parent 063b33e commit 4515e3a
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 25 deletions.
90 changes: 68 additions & 22 deletions Source/components/VisualiserComponent.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "VisualiserComponent.h"
#include "../LookAndFeel.h"

VisualiserComponent::VisualiserComponent(int numChannels, OscirenderAudioProcessor& p) : numChannels(numChannels), backgroundColour(juce::Colours::black), waveformColour(juce::Colour(0xff00ff00)), audioProcessor(p), juce::Thread("VisualiserComponent") {
VisualiserComponent::VisualiserComponent(int numChannels, OscirenderAudioProcessor& p, VisualiserComponent* parent) : numChannels(numChannels), backgroundColour(juce::Colours::black), waveformColour(juce::Colour(0xff00ff00)), audioProcessor(p), juce::Thread("VisualiserComponent"), parent(parent) {
resetBuffer();
startTimerHz(60);
startThread();
Expand All @@ -20,7 +20,12 @@ VisualiserComponent::VisualiserComponent(int numChannels, OscirenderAudioProcess
setMouseCursor(juce::MouseCursor::PointingHandCursor);
setWantsKeyboardFocus(true);

addChildComponent(fullScreenButton);
if (parent == nullptr) {
addChildComponent(fullScreenButton);
}
if (child == nullptr && parent == nullptr) {
addChildComponent(popOutButton);
}
addChildComponent(settingsButton);

fullScreenButton.onClick = [this]() {
Expand All @@ -35,6 +40,21 @@ VisualiserComponent::VisualiserComponent(int numChannels, OscirenderAudioProcess

menu.showMenuAsync(juce::PopupMenu::Options(), [this](int result) {});
};

popOutButton.onClick = [this, numChannels]() {
auto visualiser = new VisualiserComponent(numChannels, audioProcessor, this);
child = visualiser;
popOutButton.setVisible(false);
visualiser->setSize(300, 300);
popout = std::make_unique<VisualiserWindow>("Software Oscilloscope", this);
popout->setContentOwned(visualiser, true);
popout->setUsingNativeTitleBar(true);
popout->setResizable(true, false);
popout->setVisible(true);
setPaused(true);
resized();
popOutButton.setVisible(false);
};
}

VisualiserComponent::~VisualiserComponent() {
Expand Down Expand Up @@ -94,7 +114,8 @@ void VisualiserComponent::paint(juce::Graphics& g) {
// add text
g.setColour(juce::Colours::white);
g.setFont(14.0f);
g.drawFittedText("Paused", getLocalBounds(), juce::Justification::centred, 1);
auto text = child != nullptr ? "Open in separate window" : "Paused";
g.drawFittedText(text, getLocalBounds(), juce::Justification::centred, 1);
}
}

Expand All @@ -114,18 +135,22 @@ void VisualiserComponent::run() {
}
}

void VisualiserComponent::setPaused(bool paused) {
active = !paused;
if (active) {
startTimerHz(60);
startThread();
} else {
audioProcessor.consumerStop(consumer);
stopTimer();
stopThread(1000);
}
repaint();
}

void VisualiserComponent::mouseDown(const juce::MouseEvent& event) {
if (event.mods.isLeftButtonDown()) {
active = !active;
if (active) {
startTimerHz(60);
startThread();
} else {
audioProcessor.consumerStop(consumer);
stopTimer();
stopThread(1000);
}
repaint();
if (event.mods.isLeftButtonDown() && child == nullptr) {
setPaused(active);
}
}

Expand All @@ -138,16 +163,31 @@ void VisualiserComponent::mouseMove(const juce::MouseEvent& event) {

int newTimerId = juce::Random::getSystemRandom().nextInt();
timerId = newTimerId;
fullScreenButton.setVisible(true);
if (parent == nullptr) {
fullScreenButton.setVisible(true);
}
if (child == nullptr && parent == nullptr) {
popOutButton.setVisible(true);
}
settingsButton.setVisible(true);
auto pos = event.getScreenPosition();
auto parent = this->parent;

juce::Timer::callAfterDelay(1000, [this, newTimerId, pos]() {
bool onButtonRow = fullScreenButton.getScreenBounds().contains(pos) || settingsButton.getScreenBounds().contains(pos);
if (timerId == newTimerId && !onButtonRow) {
fullScreenButton.setVisible(false);
settingsButton.setVisible(false);
repaint();
juce::Timer::callAfterDelay(1000, [this, newTimerId, pos, parent]() {
if (parent == nullptr || parent->child == this) {
bool onButtonRow = settingsButton.getScreenBounds().contains(pos);
if (parent == nullptr) {
onButtonRow |= fullScreenButton.getScreenBounds().contains(pos);
}
if (child == nullptr && parent == nullptr) {
onButtonRow |= popOutButton.getScreenBounds().contains(pos);
}
if (timerId == newTimerId && !onButtonRow) {
fullScreenButton.setVisible(false);
popOutButton.setVisible(false);
settingsButton.setVisible(false);
repaint();
}
}
});
repaint();
Expand Down Expand Up @@ -227,6 +267,12 @@ void VisualiserComponent::resized() {
auto area = getLocalBounds();
area.removeFromBottom(5);
auto buttonRow = area.removeFromBottom(25);
fullScreenButton.setBounds(buttonRow.removeFromRight(30));

if (parent == nullptr) {
fullScreenButton.setBounds(buttonRow.removeFromRight(30));
}
if (child == nullptr && parent == nullptr) {
popOutButton.setBounds(buttonRow.removeFromRight(30));
}
settingsButton.setBounds(buttonRow.removeFromRight(30));
}
29 changes: 26 additions & 3 deletions Source/components/VisualiserComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ enum class FullScreenMode {
MAIN_COMPONENT,
};

class VisualiserWindow;
class VisualiserComponent : public juce::Component, public juce::Timer, public juce::Thread, public juce::MouseListener, public juce::SettableTooltipClient {
public:
VisualiserComponent(int numChannels, OscirenderAudioProcessor& p);
VisualiserComponent(int numChannels, OscirenderAudioProcessor& p, VisualiserComponent* parent = nullptr);
~VisualiserComponent() override;

void enableFullScreen();
Expand All @@ -29,16 +30,23 @@ class VisualiserComponent : public juce::Component, public juce::Timer, public j
void resized() override;
void timerCallback() override;
void run() override;
void setPaused(bool paused);
void mouseDown(const juce::MouseEvent& event) override;
void mouseMove(const juce::MouseEvent& event) override;
bool keyPressed(const juce::KeyPress& key) override;

void setFullScreen(bool fullScreen);

VisualiserComponent* parent = nullptr;
VisualiserComponent* child = nullptr;
std::unique_ptr<VisualiserWindow> popout = nullptr;

std::atomic<bool> active = true;

private:
const double BUFFER_LENGTH_SECS = 0.02;
const double DEFAULT_SAMPLE_RATE = 192000.0;


std::atomic<int> timerId;
std::atomic<int> lastMouseX;
Expand All @@ -55,12 +63,11 @@ class VisualiserComponent : public juce::Component, public juce::Timer, public j
LabelledTextBox intensity{"Intensity", 0, 1, 0.01};

SvgButton fullScreenButton{ "fullScreen", BinaryData::fullscreen_svg, juce::Colours::white, juce::Colours::white };
SvgButton popOutButton{ "popOut", BinaryData::open_in_new_svg, juce::Colours::white, juce::Colours::white };
SvgButton settingsButton{ "settings", BinaryData::cog_svg, juce::Colours::white, juce::Colours::white };

std::vector<float> tempBuffer;
int precision = 4;

std::atomic<bool> active = true;

std::shared_ptr<BufferConsumer> consumer;

Expand All @@ -70,3 +77,19 @@ class VisualiserComponent : public juce::Component, public juce::Timer, public j

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VisualiserComponent)
};

class VisualiserWindow : public juce::DocumentWindow {
public:
VisualiserWindow(juce::String name, VisualiserComponent* parent) : parent(parent), wasPaused(!parent->active), juce::DocumentWindow(name, juce::Colours::black, juce::DocumentWindow::TitleBarButtons::allButtons) {}

void closeButtonPressed() override {
parent->setPaused(wasPaused);
parent->child = nullptr;
parent->resized();
parent->popout.reset();
}

private:
VisualiserComponent* parent;
bool wasPaused;
};

0 comments on commit 4515e3a

Please sign in to comment.