The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

210 lines
7.4KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-12 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #include "../JuceDemoHeader.h"
  19. #if JUCE_USE_CAMERA
  20. //==============================================================================
  21. class CameraDemo : public Component,
  22. private ComboBoxListener,
  23. private ButtonListener,
  24. private CameraDevice::Listener,
  25. private AsyncUpdater
  26. {
  27. public:
  28. CameraDemo()
  29. : cameraSelectorComboBox ("Camera"),
  30. snapshotButton ("Take a snapshot"),
  31. recordMovieButton ("Record a movie (to your desktop)..."),
  32. recordingMovie (false)
  33. {
  34. setOpaque (true);
  35. addAndMakeVisible (cameraSelectorComboBox);
  36. updateCameraList();
  37. cameraSelectorComboBox.setSelectedId (1);
  38. cameraSelectorComboBox.addListener (this);
  39. addAndMakeVisible (snapshotButton);
  40. snapshotButton.addListener (this);
  41. snapshotButton.setEnabled (false);
  42. addAndMakeVisible (recordMovieButton);
  43. recordMovieButton.addListener (this);
  44. recordMovieButton.setEnabled (false);
  45. addAndMakeVisible (lastSnapshot);
  46. cameraSelectorComboBox.setSelectedId (2);
  47. }
  48. //==============================================================================
  49. void paint (Graphics& g) override
  50. {
  51. g.fillAll (Colours::black);
  52. }
  53. void resized() override
  54. {
  55. Rectangle<int> r (getLocalBounds().reduced (5));
  56. Rectangle<int> top (r.removeFromTop (25));
  57. cameraSelectorComboBox.setBounds (top.removeFromLeft (250));
  58. r.removeFromTop (4);
  59. top = r.removeFromTop (25);
  60. snapshotButton.changeWidthToFitText (24);
  61. snapshotButton.setBounds (top.removeFromLeft (snapshotButton.getWidth()));
  62. top.removeFromLeft (4);
  63. recordMovieButton.changeWidthToFitText (24);
  64. recordMovieButton.setBounds (top.removeFromLeft (recordMovieButton.getWidth()));
  65. r.removeFromTop (4);
  66. Rectangle<int> previewArea (r.removeFromTop (r.getHeight() / 2));
  67. if (cameraPreviewComp != nullptr)
  68. cameraPreviewComp->setBounds (previewArea);
  69. r.removeFromTop (4);
  70. lastSnapshot.setBounds (r);
  71. }
  72. private:
  73. //==============================================================================
  74. ScopedPointer<CameraDevice> cameraDevice;
  75. ScopedPointer<Component> cameraPreviewComp;
  76. ImageComponent lastSnapshot;
  77. ComboBox cameraSelectorComboBox;
  78. TextButton snapshotButton;
  79. TextButton recordMovieButton;
  80. bool recordingMovie;
  81. void updateCameraList()
  82. {
  83. cameraSelectorComboBox.clear();
  84. cameraSelectorComboBox.addItem ("No camera", 1);
  85. cameraSelectorComboBox.addSeparator();
  86. StringArray cameras = CameraDevice::getAvailableDevices();
  87. for (int i = 0; i < cameras.size(); ++i)
  88. cameraSelectorComboBox.addItem (cameras[i], i + 2);
  89. }
  90. void comboBoxChanged (ComboBox*) override
  91. {
  92. // This is called when the user chooses a camera from the drop-down list.
  93. cameraDevice = nullptr;
  94. cameraPreviewComp = nullptr;
  95. recordingMovie = false;
  96. if (cameraSelectorComboBox.getSelectedId() > 1)
  97. {
  98. // Try to open the user's choice of camera..
  99. cameraDevice = CameraDevice::openDevice (cameraSelectorComboBox.getSelectedId() - 2);
  100. // and if it worked, create a preview component for it..
  101. if (cameraDevice != nullptr)
  102. addAndMakeVisible (cameraPreviewComp = cameraDevice->createViewerComponent());
  103. }
  104. snapshotButton.setEnabled (cameraDevice != nullptr);
  105. recordMovieButton.setEnabled (cameraDevice != nullptr);
  106. resized();
  107. }
  108. void buttonClicked (Button* b) override
  109. {
  110. if (cameraDevice != nullptr)
  111. {
  112. if (b == &recordMovieButton)
  113. {
  114. // The user has clicked the record movie button..
  115. if (! recordingMovie)
  116. {
  117. // Start recording to a file on the user's desktop..
  118. recordingMovie = true;
  119. File file (File::getSpecialLocation (File::userDesktopDirectory)
  120. .getNonexistentChildFile ("JuceCameraDemo",
  121. CameraDevice::getFileExtension()));
  122. cameraDevice->startRecordingToFile (file);
  123. recordMovieButton.setButtonText ("Stop Recording");
  124. }
  125. else
  126. {
  127. // Already recording, so stop...
  128. recordingMovie = false;
  129. cameraDevice->stopRecording();
  130. recordMovieButton.setButtonText ("Start recording (to a file on your desktop)");
  131. }
  132. }
  133. else
  134. {
  135. // When the user clicks the snapshot button, we'll attach ourselves to
  136. // the camera as a listener, and wait for an image to arrive...
  137. cameraDevice->addListener (this);
  138. }
  139. }
  140. }
  141. // This is called by the camera device when a new image arrives
  142. void imageReceived (const Image& image) override
  143. {
  144. // In this app we just want to take one image, so as soon as this happens,
  145. // we'll unregister ourselves as a listener.
  146. if (cameraDevice != nullptr)
  147. cameraDevice->removeListener (this);
  148. // This callback won't be on the message thread, so to get the image back to
  149. // the message thread, we'll stash a pointer to it (which is reference-counted in
  150. // a thead-safe way), and trigger an async callback which will then display the
  151. // new image..
  152. incomingImage = image;
  153. triggerAsyncUpdate();
  154. }
  155. Image incomingImage;
  156. void handleAsyncUpdate() override
  157. {
  158. if (incomingImage.isValid())
  159. lastSnapshot.setImage (incomingImage);
  160. }
  161. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CameraDemo);
  162. };
  163. // This static object will register this demo type in a global list of demos..
  164. static JuceDemoType<CameraDemo> demo ("29 Graphics: Camera Capture");
  165. #endif // JUCE_USE_CAMERA