mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-11 23:54:18 +00:00
266 lines
8.2 KiB
C++
266 lines
8.2 KiB
C++
/*
|
|
==============================================================================
|
|
|
|
This file is part of the JUCE library.
|
|
Copyright (c) 2017 - ROLI Ltd.
|
|
|
|
JUCE is an open source library subject to commercial or open-source
|
|
licensing.
|
|
|
|
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
|
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
|
27th April 2017).
|
|
|
|
End User License Agreement: www.juce.com/juce-5-licence
|
|
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
|
|
|
Or: You may also use this code under the terms of the GPL v3 (see
|
|
www.gnu.org/licenses).
|
|
|
|
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
|
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
|
DISCLAIMED.
|
|
|
|
==============================================================================
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "../JuceLibraryCode/JuceHeader.h"
|
|
|
|
//==============================================================================
|
|
class AudioThumbnailComponent : public Component,
|
|
public FileDragAndDropTarget,
|
|
public ChangeBroadcaster,
|
|
private ChangeListener,
|
|
private Timer
|
|
{
|
|
public:
|
|
AudioThumbnailComponent (AudioDeviceManager& adm, AudioFormatManager& afm)
|
|
: audioDeviceManager (adm),
|
|
thumbnailCache (5),
|
|
thumbnail (128, afm, thumbnailCache)
|
|
{
|
|
thumbnail.addChangeListener (this);
|
|
}
|
|
|
|
~AudioThumbnailComponent()
|
|
{
|
|
thumbnail.removeChangeListener (this);
|
|
}
|
|
|
|
void paint (Graphics& g) override
|
|
{
|
|
g.fillAll (Colour (0xff495358));
|
|
|
|
g.setColour (Colours::white);
|
|
|
|
if (thumbnail.getTotalLength() > 0.0)
|
|
{
|
|
thumbnail.drawChannels (g, getLocalBounds().reduced (2),
|
|
0.0, thumbnail.getTotalLength(), 1.0f);
|
|
|
|
g.setColour (Colours::black);
|
|
g.fillRect (static_cast<float> (currentPosition * getWidth()), 0.0f,
|
|
1.0f, static_cast<float> (getHeight()));
|
|
}
|
|
else
|
|
{
|
|
g.drawFittedText ("No audio file loaded.\nDrop a file here or click the \"Load File...\" button.", getLocalBounds(),
|
|
Justification::centred, 2);
|
|
}
|
|
}
|
|
|
|
bool isInterestedInFileDrag (const StringArray&) override { return true; }
|
|
void filesDropped (const StringArray& files, int, int) override { loadFile (File (files[0]), true); }
|
|
|
|
void setCurrentFile (const File& f)
|
|
{
|
|
if (currentFile == f)
|
|
return;
|
|
|
|
loadFile (f);
|
|
}
|
|
|
|
File getCurrentFile() { return currentFile; }
|
|
|
|
void setTransportSource (AudioTransportSource* newSource)
|
|
{
|
|
transportSource = newSource;
|
|
|
|
struct ResetCallback : public CallbackMessage
|
|
{
|
|
ResetCallback (AudioThumbnailComponent& o) : owner (o) {}
|
|
void messageCallback() override { owner.reset(); }
|
|
|
|
AudioThumbnailComponent& owner;
|
|
};
|
|
|
|
(new ResetCallback (*this))->post();
|
|
}
|
|
|
|
private:
|
|
AudioDeviceManager& audioDeviceManager;
|
|
AudioThumbnailCache thumbnailCache;
|
|
AudioThumbnail thumbnail;
|
|
AudioTransportSource* transportSource = nullptr;
|
|
|
|
File currentFile;
|
|
double currentPosition = 0.0;
|
|
|
|
//==============================================================================
|
|
void changeListenerCallback (ChangeBroadcaster*) override { repaint(); }
|
|
|
|
void reset()
|
|
{
|
|
currentPosition = 0.0;
|
|
repaint();
|
|
|
|
if (transportSource == nullptr)
|
|
stopTimer();
|
|
else
|
|
startTimerHz (25);
|
|
}
|
|
|
|
void loadFile (const File& f, bool notify = false)
|
|
{
|
|
if (currentFile == f || ! f.existsAsFile())
|
|
return;
|
|
|
|
currentFile = f;
|
|
thumbnail.setSource (new FileInputSource (f));
|
|
|
|
if (notify)
|
|
sendChangeMessage();
|
|
}
|
|
|
|
void timerCallback() override
|
|
{
|
|
if (transportSource != nullptr)
|
|
{
|
|
currentPosition = transportSource->getCurrentPosition() / thumbnail.getTotalLength();
|
|
repaint();
|
|
}
|
|
}
|
|
|
|
void mouseDrag (const MouseEvent& e) override
|
|
{
|
|
if (transportSource != nullptr)
|
|
{
|
|
const ScopedLock sl (audioDeviceManager.getAudioCallbackLock());
|
|
|
|
transportSource->setPosition ((jmax (static_cast<double> (e.x), 0.0) / getWidth())
|
|
* thumbnail.getTotalLength());
|
|
}
|
|
}
|
|
};
|
|
|
|
//==============================================================================
|
|
class AudioPlayerHeader : public Component,
|
|
private Button::Listener,
|
|
private ChangeListener,
|
|
private Value::Listener
|
|
{
|
|
public:
|
|
AudioPlayerHeader();
|
|
~AudioPlayerHeader();
|
|
|
|
void paint (Graphics&) override;
|
|
void resized() override;
|
|
|
|
AudioThumbnailComponent thumbnailComp;
|
|
|
|
private:
|
|
//==============================================================================
|
|
void buttonClicked (Button*) override;
|
|
void changeListenerCallback (ChangeBroadcaster*) override;
|
|
void valueChanged (Value& value) override;
|
|
|
|
//==============================================================================
|
|
TextButton loadButton { "Load File..." }, playButton { "Play" };
|
|
ToggleButton loopButton { "Loop File" };
|
|
};
|
|
|
|
//==============================================================================
|
|
class DemoParametersComponent : public Component
|
|
{
|
|
public:
|
|
DemoParametersComponent (const std::vector<DSPDemoParameterBase*>& demoParams)
|
|
{
|
|
parameters = demoParams;
|
|
|
|
for (auto demoParameter : parameters)
|
|
{
|
|
addAndMakeVisible (demoParameter->getComponent());
|
|
|
|
auto* paramLabel = new Label ({}, demoParameter->name);
|
|
|
|
paramLabel->attachToComponent (demoParameter->getComponent(), true);
|
|
paramLabel->setJustificationType (Justification::centredLeft);
|
|
addAndMakeVisible (paramLabel);
|
|
labels.add (paramLabel);
|
|
}
|
|
}
|
|
|
|
void resized() override
|
|
{
|
|
auto bounds = getLocalBounds();
|
|
bounds.removeFromLeft (100);
|
|
|
|
for (auto* p : parameters)
|
|
{
|
|
auto* comp = p->getComponent();
|
|
|
|
comp->setSize (jmin (bounds.getWidth(), p->getPreferredWidth()), p->getPreferredHeight());
|
|
|
|
auto compBounds = bounds.removeFromTop (p->getPreferredHeight());
|
|
comp->setCentrePosition (compBounds.getCentre());
|
|
}
|
|
}
|
|
|
|
int getHeightNeeded()
|
|
{
|
|
auto height = 0;
|
|
|
|
for (auto* p : parameters)
|
|
height += p->getPreferredHeight();
|
|
|
|
return height + 10;
|
|
}
|
|
|
|
private:
|
|
std::vector<DSPDemoParameterBase*> parameters;
|
|
OwnedArray<Label> labels;
|
|
};
|
|
|
|
//==============================================================================
|
|
class MainContentComponent : public Component,
|
|
private ListBoxModel
|
|
{
|
|
public:
|
|
MainContentComponent();
|
|
|
|
void paint (Graphics&) override;
|
|
void resized() override;
|
|
|
|
AudioThumbnailComponent& getThumbnailComponent() { return header.thumbnailComp; }
|
|
void initParameters();
|
|
|
|
private:
|
|
//==============================================================================
|
|
void paintListBoxItem (int rowNumber, Graphics&, int width, int height, bool rowIsSelected) override;
|
|
int getNumRows() override;
|
|
void selectedRowsChanged (int lastRowSelected) override;
|
|
|
|
void setupDemoColours();
|
|
|
|
//==============================================================================
|
|
AudioPlayerHeader header;
|
|
ListBox demoList { "Demo List" };
|
|
|
|
CPlusPlusCodeTokeniser cppTokeniser;
|
|
CodeDocument codeDocument;
|
|
CodeEditorComponent codeEditor { codeDocument, &cppTokeniser };
|
|
|
|
ScopedPointer<DemoParametersComponent> parametersComponent;
|
|
};
|