| @@ -1,248 +1,248 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library. | |||||
| Copyright (c) 2015 - ROLI Ltd. | |||||
| Permission is granted to use this software under the terms of either: | |||||
| a) the GPL v2 (or any later version) | |||||
| b) the Affero GPL v3 | |||||
| Details of these licenses can be found 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.juce.com for more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #include "../JuceDemoHeader.h" | |||||
| #if JUCE_QUICKTIME || JUCE_DIRECTSHOW | |||||
| //============================================================================== | |||||
| // so that we can easily have two video windows each with a file browser, wrap this up as a class.. | |||||
| class MovieComponentWithFileBrowser : public Component, | |||||
| public DragAndDropTarget, | |||||
| private FilenameComponentListener | |||||
| { | |||||
| public: | |||||
| MovieComponentWithFileBrowser() | |||||
| : isDragOver (false), | |||||
| fileChooser ("movie", File::nonexistent, true, false, false, | |||||
| "*", String::empty, "(choose a video file to play)") | |||||
| { | |||||
| addAndMakeVisible (videoComp); | |||||
| addAndMakeVisible (fileChooser); | |||||
| fileChooser.addListener (this); | |||||
| fileChooser.setBrowseButtonText ("browse"); | |||||
| } | |||||
| void setFile (const File& file) | |||||
| { | |||||
| fileChooser.setCurrentFile (file, true); | |||||
| } | |||||
| void paintOverChildren (Graphics& g) | |||||
| { | |||||
| if (isDragOver) | |||||
| { | |||||
| g.setColour (Colours::red); | |||||
| g.drawRect (fileChooser.getBounds(), 2); | |||||
| } | |||||
| } | |||||
| void resized() | |||||
| { | |||||
| videoComp.setBoundsWithCorrectAspectRatio (Rectangle<int> (0, 0, getWidth(), getHeight() - 30), | |||||
| Justification::centred); | |||||
| fileChooser.setBounds (0, getHeight() - 24, getWidth(), 24); | |||||
| } | |||||
| bool isInterestedInDragSource (const SourceDetails&) { return true; } | |||||
| void itemDragEnter (const SourceDetails&) | |||||
| { | |||||
| isDragOver = true; | |||||
| repaint(); | |||||
| } | |||||
| void itemDragExit (const SourceDetails&) | |||||
| { | |||||
| isDragOver = false; | |||||
| repaint(); | |||||
| } | |||||
| void itemDropped (const SourceDetails& dragSourceDetails) | |||||
| { | |||||
| setFile (dragSourceDetails.description.toString()); | |||||
| isDragOver = false; | |||||
| repaint(); | |||||
| } | |||||
| private: | |||||
| #if JUCE_QUICKTIME | |||||
| QuickTimeMovieComponent videoComp; | |||||
| #elif JUCE_DIRECTSHOW | |||||
| DirectShowComponent videoComp; | |||||
| #endif | |||||
| bool isDragOver; | |||||
| FilenameComponent fileChooser; | |||||
| void filenameComponentChanged (FilenameComponent*) override | |||||
| { | |||||
| // this is called when the user changes the filename in the file chooser box | |||||
| #if JUCE_QUICKTIME | |||||
| if (videoComp.loadMovie (fileChooser.getCurrentFile(), true)) | |||||
| #elif JUCE_DIRECTSHOW | |||||
| if (videoComp.loadMovie (fileChooser.getCurrentFile())) | |||||
| #endif | |||||
| { | |||||
| // loaded the file ok, so let's start it playing.. | |||||
| videoComp.play(); | |||||
| resized(); // update to reflect the video's aspect ratio | |||||
| } | |||||
| else | |||||
| { | |||||
| AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||||
| "Couldn't load the file!", | |||||
| r.getErrorMessage()); | |||||
| } | |||||
| } | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MovieComponentWithFileBrowser) | |||||
| }; | |||||
| //============================================================================== | |||||
| class VideoDemo : public Component, | |||||
| public DragAndDropContainer, | |||||
| private Button::Listener, | |||||
| private FileBrowserListener | |||||
| { | |||||
| public: | |||||
| VideoDemo() | |||||
| : moviesWildcardFilter ("*", "*", "Movies File Filter"), | |||||
| directoryThread ("Movie File Scanner Thread"), | |||||
| movieList (&moviesWildcardFilter, directoryThread), | |||||
| fileTree (movieList), | |||||
| resizerBar (&stretchableManager, 1, false) | |||||
| { | |||||
| setOpaque (true); | |||||
| movieList.setDirectory (File::getSpecialLocation (File::userMoviesDirectory), true, true); | |||||
| directoryThread.startThread (1); | |||||
| fileTree.addListener (this); | |||||
| fileTree.setColour (TreeView::backgroundColourId, Colours::lightgrey); | |||||
| addAndMakeVisible (fileTree); | |||||
| addAndMakeVisible (resizerBar); | |||||
| loadLeftButton.setButtonText ("Load Left"); | |||||
| loadRightButton.setButtonText ("Load Right"); | |||||
| loadLeftButton.addListener (this); | |||||
| loadRightButton.addListener (this); | |||||
| addAndMakeVisible (loadLeftButton); | |||||
| addAndMakeVisible (loadRightButton); | |||||
| addAndMakeVisible (movieCompLeft); | |||||
| addAndMakeVisible (movieCompRight); | |||||
| // we have to set up our StretchableLayoutManager so it know the limits and preferred sizes of it's contents | |||||
| stretchableManager.setItemLayout (0, // for the fileTree | |||||
| -0.1, -0.9, // must be between 50 pixels and 90% of the available space | |||||
| -0.3); // and its preferred size is 30% of the total available space | |||||
| stretchableManager.setItemLayout (1, // for the resize bar | |||||
| 5, 5, 5); // hard limit to 5 pixels | |||||
| stretchableManager.setItemLayout (2, // for the movie components | |||||
| -0.1, -0.9, // size must be between 50 pixels and 90% of the available space | |||||
| -0.7); // and its preferred size is 70% of the total available space | |||||
| } | |||||
| ~VideoDemo() | |||||
| { | |||||
| loadLeftButton.removeListener (this); | |||||
| loadRightButton.removeListener (this); | |||||
| fileTree.removeListener (this); | |||||
| } | |||||
| void paint (Graphics& g) override | |||||
| { | |||||
| fillStandardDemoBackground (g); | |||||
| } | |||||
| void resized() override | |||||
| { | |||||
| // make a list of two of our child components that we want to reposition | |||||
| Component* comps[] = { &fileTree, &resizerBar, nullptr }; | |||||
| // this will position the 3 components, one above the other, to fit | |||||
| // vertically into the rectangle provided. | |||||
| stretchableManager.layOutComponents (comps, 3, | |||||
| 0, 0, getWidth(), getHeight(), | |||||
| true, true); | |||||
| // now position out two video components in the space that's left | |||||
| Rectangle<int> area (getLocalBounds().removeFromBottom (getHeight() - resizerBar.getBottom())); | |||||
| { | |||||
| Rectangle<int> buttonArea (area.removeFromTop (30)); | |||||
| loadLeftButton.setBounds (buttonArea.removeFromLeft (buttonArea.getWidth() / 2).reduced (5)); | |||||
| loadRightButton.setBounds (buttonArea.reduced (5)); | |||||
| } | |||||
| movieCompLeft.setBounds (area.removeFromLeft (area.getWidth() / 2).reduced (5)); | |||||
| movieCompRight.setBounds (area.reduced (5)); | |||||
| } | |||||
| private: | |||||
| WildcardFileFilter moviesWildcardFilter; | |||||
| TimeSliceThread directoryThread; | |||||
| DirectoryContentsList movieList; | |||||
| FileTreeComponent fileTree; | |||||
| StretchableLayoutManager stretchableManager; | |||||
| StretchableLayoutResizerBar resizerBar; | |||||
| TextButton loadLeftButton, loadRightButton; | |||||
| MovieComponentWithFileBrowser movieCompLeft, movieCompRight; | |||||
| void buttonClicked (Button* button) override | |||||
| { | |||||
| if (button == &loadLeftButton) | |||||
| movieCompLeft.setFile (fileTree.getSelectedFile (0)); | |||||
| else if (button == &loadRightButton) | |||||
| movieCompRight.setFile (fileTree.getSelectedFile (0)); | |||||
| } | |||||
| void selectionChanged() override | |||||
| { | |||||
| // we're just going to update the drag description of out tree so that rows can be dragged onto the file players | |||||
| fileTree.setDragAndDropDescription (fileTree.getSelectedFile().getFullPathName()); | |||||
| } | |||||
| void fileClicked (const File&, const MouseEvent&) override {} | |||||
| void fileDoubleClicked (const File&) override {} | |||||
| void browserRootChanged (const File&) override {} | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VideoDemo) | |||||
| }; | |||||
| // This static object will register this demo type in a global list of demos.. | |||||
| static JuceDemoType<VideoDemo> demo ("29 Graphics: Video Playback"); | |||||
| #endif | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library. | |||||
| Copyright (c) 2015 - ROLI Ltd. | |||||
| Permission is granted to use this software under the terms of either: | |||||
| a) the GPL v2 (or any later version) | |||||
| b) the Affero GPL v3 | |||||
| Details of these licenses can be found 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.juce.com for more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #include "../JuceDemoHeader.h" | |||||
| #if JUCE_QUICKTIME || JUCE_DIRECTSHOW | |||||
| //============================================================================== | |||||
| // so that we can easily have two video windows each with a file browser, wrap this up as a class.. | |||||
| class MovieComponentWithFileBrowser : public Component, | |||||
| public DragAndDropTarget, | |||||
| private FilenameComponentListener | |||||
| { | |||||
| public: | |||||
| MovieComponentWithFileBrowser() | |||||
| : isDragOver (false), | |||||
| fileChooser ("movie", File::nonexistent, true, false, false, | |||||
| "*", String::empty, "(choose a video file to play)") | |||||
| { | |||||
| addAndMakeVisible (videoComp); | |||||
| addAndMakeVisible (fileChooser); | |||||
| fileChooser.addListener (this); | |||||
| fileChooser.setBrowseButtonText ("browse"); | |||||
| } | |||||
| void setFile (const File& file) | |||||
| { | |||||
| fileChooser.setCurrentFile (file, true); | |||||
| } | |||||
| void paintOverChildren (Graphics& g) | |||||
| { | |||||
| if (isDragOver) | |||||
| { | |||||
| g.setColour (Colours::red); | |||||
| g.drawRect (fileChooser.getBounds(), 2); | |||||
| } | |||||
| } | |||||
| void resized() | |||||
| { | |||||
| videoComp.setBoundsWithCorrectAspectRatio (Rectangle<int> (0, 0, getWidth(), getHeight() - 30), | |||||
| Justification::centred); | |||||
| fileChooser.setBounds (0, getHeight() - 24, getWidth(), 24); | |||||
| } | |||||
| bool isInterestedInDragSource (const SourceDetails&) { return true; } | |||||
| void itemDragEnter (const SourceDetails&) | |||||
| { | |||||
| isDragOver = true; | |||||
| repaint(); | |||||
| } | |||||
| void itemDragExit (const SourceDetails&) | |||||
| { | |||||
| isDragOver = false; | |||||
| repaint(); | |||||
| } | |||||
| void itemDropped (const SourceDetails& dragSourceDetails) | |||||
| { | |||||
| setFile (dragSourceDetails.description.toString()); | |||||
| isDragOver = false; | |||||
| repaint(); | |||||
| } | |||||
| private: | |||||
| #if JUCE_QUICKTIME | |||||
| QuickTimeMovieComponent videoComp; | |||||
| #elif JUCE_DIRECTSHOW | |||||
| DirectShowComponent videoComp; | |||||
| #endif | |||||
| bool isDragOver; | |||||
| FilenameComponent fileChooser; | |||||
| void filenameComponentChanged (FilenameComponent*) override | |||||
| { | |||||
| // this is called when the user changes the filename in the file chooser box | |||||
| #if JUCE_QUICKTIME | |||||
| if (videoComp.loadMovie (fileChooser.getCurrentFile(), true)) | |||||
| #elif JUCE_DIRECTSHOW | |||||
| if (videoComp.loadMovie (fileChooser.getCurrentFile())) | |||||
| #endif | |||||
| { | |||||
| // loaded the file ok, so let's start it playing.. | |||||
| videoComp.play(); | |||||
| resized(); // update to reflect the video's aspect ratio | |||||
| } | |||||
| else | |||||
| { | |||||
| AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, | |||||
| "Couldn't load the file!", | |||||
| r.getErrorMessage()); | |||||
| } | |||||
| } | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MovieComponentWithFileBrowser) | |||||
| }; | |||||
| //============================================================================== | |||||
| class VideoDemo : public Component, | |||||
| public DragAndDropContainer, | |||||
| private Button::Listener, | |||||
| private FileBrowserListener | |||||
| { | |||||
| public: | |||||
| VideoDemo() | |||||
| : moviesWildcardFilter ("*", "*", "Movies File Filter"), | |||||
| directoryThread ("Movie File Scanner Thread"), | |||||
| movieList (&moviesWildcardFilter, directoryThread), | |||||
| fileTree (movieList), | |||||
| resizerBar (&stretchableManager, 1, false) | |||||
| { | |||||
| setOpaque (true); | |||||
| movieList.setDirectory (File::getSpecialLocation (File::userMoviesDirectory), true, true); | |||||
| directoryThread.startThread (1); | |||||
| fileTree.addListener (this); | |||||
| fileTree.setColour (TreeView::backgroundColourId, Colours::lightgrey); | |||||
| addAndMakeVisible (fileTree); | |||||
| addAndMakeVisible (resizerBar); | |||||
| loadLeftButton.setButtonText ("Load Left"); | |||||
| loadRightButton.setButtonText ("Load Right"); | |||||
| loadLeftButton.addListener (this); | |||||
| loadRightButton.addListener (this); | |||||
| addAndMakeVisible (loadLeftButton); | |||||
| addAndMakeVisible (loadRightButton); | |||||
| addAndMakeVisible (movieCompLeft); | |||||
| addAndMakeVisible (movieCompRight); | |||||
| // we have to set up our StretchableLayoutManager so it know the limits and preferred sizes of it's contents | |||||
| stretchableManager.setItemLayout (0, // for the fileTree | |||||
| -0.1, -0.9, // must be between 50 pixels and 90% of the available space | |||||
| -0.3); // and its preferred size is 30% of the total available space | |||||
| stretchableManager.setItemLayout (1, // for the resize bar | |||||
| 5, 5, 5); // hard limit to 5 pixels | |||||
| stretchableManager.setItemLayout (2, // for the movie components | |||||
| -0.1, -0.9, // size must be between 50 pixels and 90% of the available space | |||||
| -0.7); // and its preferred size is 70% of the total available space | |||||
| } | |||||
| ~VideoDemo() | |||||
| { | |||||
| loadLeftButton.removeListener (this); | |||||
| loadRightButton.removeListener (this); | |||||
| fileTree.removeListener (this); | |||||
| } | |||||
| void paint (Graphics& g) override | |||||
| { | |||||
| fillStandardDemoBackground (g); | |||||
| } | |||||
| void resized() override | |||||
| { | |||||
| // make a list of two of our child components that we want to reposition | |||||
| Component* comps[] = { &fileTree, &resizerBar, nullptr }; | |||||
| // this will position the 3 components, one above the other, to fit | |||||
| // vertically into the rectangle provided. | |||||
| stretchableManager.layOutComponents (comps, 3, | |||||
| 0, 0, getWidth(), getHeight(), | |||||
| true, true); | |||||
| // now position out two video components in the space that's left | |||||
| Rectangle<int> area (getLocalBounds().removeFromBottom (getHeight() - resizerBar.getBottom())); | |||||
| { | |||||
| Rectangle<int> buttonArea (area.removeFromTop (30)); | |||||
| loadLeftButton.setBounds (buttonArea.removeFromLeft (buttonArea.getWidth() / 2).reduced (5)); | |||||
| loadRightButton.setBounds (buttonArea.reduced (5)); | |||||
| } | |||||
| movieCompLeft.setBounds (area.removeFromLeft (area.getWidth() / 2).reduced (5)); | |||||
| movieCompRight.setBounds (area.reduced (5)); | |||||
| } | |||||
| private: | |||||
| WildcardFileFilter moviesWildcardFilter; | |||||
| TimeSliceThread directoryThread; | |||||
| DirectoryContentsList movieList; | |||||
| FileTreeComponent fileTree; | |||||
| StretchableLayoutManager stretchableManager; | |||||
| StretchableLayoutResizerBar resizerBar; | |||||
| TextButton loadLeftButton, loadRightButton; | |||||
| MovieComponentWithFileBrowser movieCompLeft, movieCompRight; | |||||
| void buttonClicked (Button* button) override | |||||
| { | |||||
| if (button == &loadLeftButton) | |||||
| movieCompLeft.setFile (fileTree.getSelectedFile (0)); | |||||
| else if (button == &loadRightButton) | |||||
| movieCompRight.setFile (fileTree.getSelectedFile (0)); | |||||
| } | |||||
| void selectionChanged() override | |||||
| { | |||||
| // we're just going to update the drag description of out tree so that rows can be dragged onto the file players | |||||
| fileTree.setDragAndDropDescription (fileTree.getSelectedFile().getFullPathName()); | |||||
| } | |||||
| void fileClicked (const File&, const MouseEvent&) override {} | |||||
| void fileDoubleClicked (const File&) override {} | |||||
| void browserRootChanged (const File&) override {} | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VideoDemo) | |||||
| }; | |||||
| // This static object will register this demo type in a global list of demos.. | |||||
| static JuceDemoType<VideoDemo> demo ("29 Graphics: Video Playback"); | |||||
| #endif | |||||