| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library - "Jules' Utility Class Extensions"
 -    Copyright 2004-12 by Raw Material Software Ltd.
 - 
 -   ------------------------------------------------------------------------------
 - 
 -    JUCE can be redistributed and/or modified under the terms of the GNU General
 -    Public License (Version 2), as published by the Free Software Foundation.
 -    A copy of the license is included in the JUCE distribution, or can be found
 -    online at www.gnu.org/licenses.
 - 
 -    JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
 -    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 -    A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 - 
 -   ------------------------------------------------------------------------------
 - 
 -    To release a closed-source product which uses JUCE, commercial licenses are
 -    available: visit www.rawmaterialsoftware.com/juce for more information.
 - 
 -   ==============================================================================
 - */
 - 
 - #include "../JuceDemoHeader.h"
 - 
 - //==============================================================================
 - class DemoThumbnailComp  : public Component,
 -                            public ChangeListener,
 -                            public FileDragAndDropTarget,
 -                            public ChangeBroadcaster,
 -                            private ScrollBar::Listener,
 -                            private Timer
 - {
 - public:
 -     DemoThumbnailComp (AudioFormatManager& formatManager,
 -                        AudioTransportSource& transportSource_,
 -                        Slider& slider)
 -         : transportSource (transportSource_),
 -           zoomSlider (slider),
 -           scrollbar (false),
 -           thumbnailCache (5),
 -           thumbnail (512, formatManager, thumbnailCache),
 -           isFollowingTransport (false)
 -     {
 -         thumbnail.addChangeListener (this);
 - 
 -         addAndMakeVisible (scrollbar);
 -         scrollbar.setRangeLimits (visibleRange);
 -         scrollbar.setAutoHide (false);
 -         scrollbar.addListener (this);
 - 
 -         currentPositionMarker.setFill (Colours::white.withAlpha (0.85f));
 -         addAndMakeVisible (currentPositionMarker);
 -     }
 - 
 -     ~DemoThumbnailComp()
 -     {
 -         scrollbar.removeListener (this);
 -         thumbnail.removeChangeListener (this);
 -     }
 - 
 -     void setFile (const File& file)
 -     {
 -         if (! file.isDirectory())
 -         {
 -             thumbnail.setSource (new FileInputSource (file));
 -             const Range<double> newRange (0.0, thumbnail.getTotalLength());
 -             scrollbar.setRangeLimits (newRange);
 -             setRange (newRange);
 - 
 -             startTimer (1000 / 40);
 -         }
 -     }
 - 
 -     File getLastDroppedFile() const noexcept                    { return lastFileDropped; }
 - 
 -     void setZoomFactor (double amount)
 -     {
 -         if (thumbnail.getTotalLength() > 0)
 -         {
 -             const double newScale = jmax (0.001, thumbnail.getTotalLength() * (1.0 - jlimit (0.0, 0.99, amount)));
 -             const double timeAtCentre = xToTime (getWidth() / 2.0f);
 -             setRange (Range<double> (timeAtCentre - newScale * 0.5, timeAtCentre + newScale * 0.5));
 -         }
 -     }
 - 
 -     void setRange (Range<double> newRange)
 -     {
 -         visibleRange = newRange;
 -         scrollbar.setCurrentRange (visibleRange);
 -         updateCursorPosition();
 -         repaint();
 -     }
 - 
 -     void setFollowsTransport (bool shouldFollow)
 -     {
 -         isFollowingTransport = shouldFollow;
 -     }
 - 
 -     void paint (Graphics& g) override
 -     {
 -         g.fillAll (Colours::darkgrey);
 -         g.setColour (Colours::lightblue);
 - 
 -         if (thumbnail.getTotalLength() > 0.0)
 -         {
 -             Rectangle<int> thumbArea (getLocalBounds());
 -             thumbArea.removeFromBottom (scrollbar.getHeight() + 4);
 -             thumbnail.drawChannels (g, thumbArea.reduced (2),
 -                                     visibleRange.getStart(), visibleRange.getEnd(), 1.0f);
 -         }
 -         else
 -         {
 -             g.setFont (14.0f);
 -             g.drawFittedText ("(No audio file selected)", getLocalBounds(), Justification::centred, 2);
 -         }
 -     }
 - 
 -     void resized() override
 -     {
 -         scrollbar.setBounds (getLocalBounds().removeFromBottom (14).reduced (2));
 -     }
 - 
 -     void changeListenerCallback (ChangeBroadcaster*) override
 -     {
 -         // this method is called by the thumbnail when it has changed, so we should repaint it..
 -         repaint();
 -     }
 - 
 -     bool isInterestedInFileDrag (const StringArray& /*files*/) override
 -     {
 -         return true;
 -     }
 - 
 -     void filesDropped (const StringArray& files, int /*x*/, int /*y*/) override
 -     {
 -         lastFileDropped = File (files[0]);
 -         sendChangeMessage();
 -     }
 - 
 -     void mouseDown (const MouseEvent& e) override
 -     {
 -         mouseDrag (e);
 -     }
 - 
 -     void mouseDrag (const MouseEvent& e) override
 -     {
 -         if (canMoveTransport())
 -             transportSource.setPosition (jmax (0.0, xToTime ((float) e.x)));
 -     }
 - 
 -     void mouseUp (const MouseEvent&) override
 -     {
 -         transportSource.start();
 -     }
 - 
 -     void mouseWheelMove (const MouseEvent&, const MouseWheelDetails& wheel) override
 -     {
 -         if (thumbnail.getTotalLength() > 0.0)
 -         {
 -             double newStart = visibleRange.getStart() - wheel.deltaX * (visibleRange.getLength()) / 10.0;
 -             newStart = jlimit (0.0, jmax (0.0, thumbnail.getTotalLength() - (visibleRange.getLength())), newStart);
 - 
 -             if (canMoveTransport())
 -                 setRange (Range<double> (newStart, newStart + visibleRange.getLength()));
 - 
 -             if (wheel.deltaY != 0.0f)
 -                 zoomSlider.setValue (zoomSlider.getValue() - wheel.deltaY);
 - 
 -             repaint();
 -         }
 -     }
 - 
 - 
 - private:
 -     AudioTransportSource& transportSource;
 -     Slider& zoomSlider;
 -     ScrollBar scrollbar;
 - 
 -     AudioThumbnailCache thumbnailCache;
 -     AudioThumbnail thumbnail;
 -     Range<double> visibleRange;
 -     bool isFollowingTransport;
 -     File lastFileDropped;
 - 
 -     DrawableRectangle currentPositionMarker;
 - 
 -     float timeToX (const double time) const
 -     {
 -         return getWidth() * (float) ((time - visibleRange.getStart()) / (visibleRange.getLength()));
 -     }
 - 
 -     double xToTime (const float x) const
 -     {
 -         return (x / getWidth()) * (visibleRange.getLength()) + visibleRange.getStart();
 -     }
 - 
 -     bool canMoveTransport() const noexcept
 -     {
 -         return ! (isFollowingTransport && transportSource.isPlaying());
 -     }
 - 
 -     void scrollBarMoved (ScrollBar* scrollBarThatHasMoved, double newRangeStart) override
 -     {
 -         if (scrollBarThatHasMoved == &scrollbar)
 -             if (! (isFollowingTransport && transportSource.isPlaying()))
 -                 setRange (visibleRange.movedToStartAt (newRangeStart));
 -     }
 - 
 -     void timerCallback() override
 -     {
 -         if (canMoveTransport())
 -             updateCursorPosition();
 -         else
 -             setRange (visibleRange.movedToStartAt (transportSource.getCurrentPosition() - (visibleRange.getLength() / 2.0)));
 -     }
 - 
 -     void updateCursorPosition()
 -     {
 -         currentPositionMarker.setVisible (transportSource.isPlaying() || isMouseButtonDown());
 - 
 -         currentPositionMarker.setRectangle (Rectangle<float> (timeToX (transportSource.getCurrentPosition()) - 0.75f, 0,
 -                                                               1.5f, (float) (getHeight() - scrollbar.getHeight())));
 -     }
 - };
 - 
 - //==============================================================================
 - class AudioPlaybackDemo  : public Component,
 -                            private FileBrowserListener,
 -                            private Button::Listener,
 -                            private Slider::Listener,
 -                            private ChangeListener
 - {
 - public:
 -     AudioPlaybackDemo()
 -         : deviceManager (MainAppWindow::getSharedAudioDeviceManager()),
 -           thread ("audio file preview"),
 -           directoryList (nullptr, thread),
 -           fileTreeComp (directoryList)
 -     {
 -         addAndMakeVisible (zoomLabel);
 -         zoomLabel.setText ("zoom:", dontSendNotification);
 -         zoomLabel.setFont (Font (15.00f, Font::plain));
 -         zoomLabel.setJustificationType (Justification::centredRight);
 -         zoomLabel.setEditable (false, false, false);
 -         zoomLabel.setColour (TextEditor::textColourId, Colours::black);
 -         zoomLabel.setColour (TextEditor::backgroundColourId, Colour (0x00000000));
 - 
 -         addAndMakeVisible (followTransportButton);
 -         followTransportButton.setButtonText ("Follow Transport");
 -         followTransportButton.addListener (this);
 - 
 -         addAndMakeVisible (explanation);
 -         explanation.setText ("Select an audio file in the treeview above, and this page will display its waveform, and let you play it..", dontSendNotification);
 -         explanation.setFont (Font (14.00f, Font::plain));
 -         explanation.setJustificationType (Justification::bottomRight);
 -         explanation.setEditable (false, false, false);
 -         explanation.setColour (TextEditor::textColourId, Colours::black);
 -         explanation.setColour (TextEditor::backgroundColourId, Colour (0x00000000));
 - 
 -         addAndMakeVisible (zoomSlider);
 -         zoomSlider.setRange (0, 1, 0);
 -         zoomSlider.setSliderStyle (Slider::LinearHorizontal);
 -         zoomSlider.setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
 -         zoomSlider.addListener (this);
 -         zoomSlider.setSkewFactor (2);
 - 
 -         addAndMakeVisible (thumbnail = new DemoThumbnailComp (formatManager, transportSource, zoomSlider));
 -         thumbnail->addChangeListener (this);
 - 
 -         addAndMakeVisible (startStopButton);
 -         startStopButton.setButtonText ("Play/Stop");
 -         startStopButton.addListener (this);
 -         startStopButton.setColour (TextButton::buttonColourId, Colour (0xff79ed7f));
 - 
 -         addAndMakeVisible (fileTreeComp);
 - 
 -         // audio setup
 -         formatManager.registerBasicFormats();
 - 
 -         directoryList.setDirectory (File::getSpecialLocation (File::userHomeDirectory), true, true);
 -         thread.startThread (3);
 - 
 -         fileTreeComp.setColour (FileTreeComponent::backgroundColourId, Colours::lightgrey.withAlpha (0.6f));
 -         fileTreeComp.addListener (this);
 - 
 -         deviceManager.addAudioCallback (&audioSourcePlayer);
 -         audioSourcePlayer.setSource (&transportSource);
 - 
 -         setOpaque (true);
 -     }
 - 
 -     ~AudioPlaybackDemo()
 -     {
 -         transportSource.setSource (nullptr);
 -         audioSourcePlayer.setSource (nullptr);
 - 
 -         deviceManager.removeAudioCallback (&audioSourcePlayer);
 -         fileTreeComp.removeListener (this);
 -         thumbnail->removeChangeListener (this);
 -         followTransportButton.removeListener (this);
 -         zoomSlider.removeListener (this);
 -     }
 - 
 -     void paint (Graphics& g) override
 -     {
 -         fillBrushedAluminiumBackground (g);
 -     }
 - 
 -     void resized() override
 -     {
 -         Rectangle<int> r (getLocalBounds().reduced (4));
 - 
 -         Rectangle<int> controls (r.removeFromBottom (90));
 - 
 -         explanation.setBounds (controls.removeFromRight (controls.getWidth() / 3));
 -         Rectangle<int> zoom (controls.removeFromTop (25));
 -         zoomLabel.setBounds (zoom.removeFromLeft (50));
 -         zoomSlider.setBounds (zoom);
 -         followTransportButton.setBounds (controls.removeFromTop (25));
 -         startStopButton.setBounds (controls);
 - 
 -         r.removeFromBottom (6);
 -         thumbnail->setBounds (r.removeFromBottom (140));
 -         r.removeFromBottom (6);
 -         fileTreeComp.setBounds (r);
 -     }
 - 
 - private:
 -     AudioDeviceManager& deviceManager;
 -     AudioFormatManager formatManager;
 -     TimeSliceThread thread;
 -     DirectoryContentsList directoryList;
 - 
 -     AudioSourcePlayer audioSourcePlayer;
 -     AudioTransportSource transportSource;
 -     ScopedPointer<AudioFormatReaderSource> currentAudioFileSource;
 - 
 -     ScopedPointer<DemoThumbnailComp> thumbnail;
 -     Label zoomLabel, explanation;
 -     Slider zoomSlider;
 -     ToggleButton followTransportButton;
 -     TextButton startStopButton;
 -     FileTreeComponent fileTreeComp;
 - 
 -     //==============================================================================
 -     void showFile (const File& file)
 -     {
 -         loadFileIntoTransport (file);
 - 
 -         zoomSlider.setValue (0, dontSendNotification);
 -         thumbnail->setFile (file);
 -     }
 - 
 -     void loadFileIntoTransport (const File& audioFile)
 -     {
 -         // unload the previous file source and delete it..
 -         transportSource.stop();
 -         transportSource.setSource (nullptr);
 -         currentAudioFileSource = nullptr;
 - 
 -         AudioFormatReader* reader = formatManager.createReaderFor (audioFile);
 - 
 -         if (reader != nullptr)
 -         {
 -             currentAudioFileSource = new AudioFormatReaderSource (reader, true);
 - 
 -             // ..and plug it into our transport source
 -             transportSource.setSource (currentAudioFileSource,
 -                                        32768,                   // tells it to buffer this many samples ahead
 -                                        &thread,                 // this is the background thread to use for reading-ahead
 -                                        reader->sampleRate);     // allows for sample rate correction
 -         }
 -     }
 - 
 -     void selectionChanged() override
 -     {
 -         showFile (fileTreeComp.getSelectedFile());
 -     }
 - 
 -     void fileClicked (const File&, const MouseEvent&) override          {}
 -     void fileDoubleClicked (const File&) override                       {}
 -     void browserRootChanged (const File&) override                      {}
 - 
 -     void sliderValueChanged (Slider* sliderThatWasMoved) override
 -     {
 -         if (sliderThatWasMoved == &zoomSlider)
 -             thumbnail->setZoomFactor (zoomSlider.getValue());
 -     }
 - 
 -     void buttonClicked (Button* buttonThatWasClicked) override
 -     {
 -         if (buttonThatWasClicked == &startStopButton)
 -         {
 -             if (transportSource.isPlaying())
 -             {
 -                 transportSource.stop();
 -             }
 -             else
 -             {
 -                 transportSource.setPosition (0);
 -                 transportSource.start();
 -             }
 -         }
 -         else if (buttonThatWasClicked == &followTransportButton)
 -         {
 -             thumbnail->setFollowsTransport (followTransportButton.getToggleState());
 -         }
 -     }
 - 
 -     void changeListenerCallback (ChangeBroadcaster* source) override
 -     {
 -         if (source == thumbnail)
 -             showFile (thumbnail->getLastDroppedFile());
 -     }
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioPlaybackDemo);
 - };
 - 
 - 
 - // This static object will register this demo type in a global list of demos..
 - static JuceDemoType<AudioPlaybackDemo> demo ("31 Audio: File Playback");
 
 
  |