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.

200 lines
5.0KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. #if JUCE_IOS
  18. using BaseClass = UIViewComponent;
  19. #else
  20. using BaseClass = NSViewComponent;
  21. #endif
  22. struct VideoComponent::Pimpl : public BaseClass
  23. {
  24. Pimpl()
  25. {
  26. setVisible (true);
  27. #if JUCE_MAC && JUCE_32BIT
  28. auto view = [[NSView alloc] init]; // 32-bit builds don't have AVPlayerView, so need to use a layer
  29. controller = [[AVPlayerLayer alloc] init];
  30. setView (view);
  31. [view setNextResponder: [view superview]];
  32. [view setWantsLayer: YES];
  33. [view setLayer: controller];
  34. [view release];
  35. #elif JUCE_MAC
  36. controller = [[AVPlayerView alloc] init];
  37. setView (controller);
  38. [controller setNextResponder: [controller superview]];
  39. [controller setWantsLayer: YES];
  40. #else
  41. controller = [[AVPlayerViewController alloc] init];
  42. setView ([controller view]);
  43. #endif
  44. }
  45. ~Pimpl()
  46. {
  47. close();
  48. setView (nil);
  49. [controller release];
  50. }
  51. Result load (const File& file)
  52. {
  53. auto r = load (createNSURLFromFile (file));
  54. if (r.wasOk())
  55. currentFile = file;
  56. return r;
  57. }
  58. Result load (const URL& url)
  59. {
  60. auto r = load ([NSURL URLWithString: juceStringToNS (url.toString (true))]);
  61. if (r.wasOk())
  62. currentURL = url;
  63. return r;
  64. }
  65. Result load (NSURL* url)
  66. {
  67. if (url != nil)
  68. {
  69. close();
  70. if (auto* player = [AVPlayer playerWithURL: url])
  71. {
  72. [controller setPlayer: player];
  73. return Result::ok();
  74. }
  75. }
  76. return Result::fail ("Couldn't open movie");
  77. }
  78. void close()
  79. {
  80. stop();
  81. [controller setPlayer: nil];
  82. currentFile = File();
  83. currentURL = {};
  84. }
  85. bool isOpen() const noexcept { return getAVPlayer() != nil; }
  86. bool isPlaying() const noexcept { return getSpeed() != 0; }
  87. void play() noexcept { [getAVPlayer() play]; }
  88. void stop() noexcept { [getAVPlayer() pause]; }
  89. void setPosition (double newPosition)
  90. {
  91. if (auto* p = getAVPlayer())
  92. {
  93. CMTime t = { (CMTimeValue) (100000.0 * newPosition),
  94. (CMTimeScale) 100000, kCMTimeFlags_Valid };
  95. [p seekToTime: t
  96. toleranceBefore: kCMTimeZero
  97. toleranceAfter: kCMTimeZero];
  98. }
  99. }
  100. double getPosition() const
  101. {
  102. if (auto* p = getAVPlayer())
  103. return toSeconds ([p currentTime]);
  104. return 0.0;
  105. }
  106. void setSpeed (double newSpeed)
  107. {
  108. [getAVPlayer() setRate: (float) newSpeed];
  109. }
  110. double getSpeed() const
  111. {
  112. if (auto* p = getAVPlayer())
  113. return [p rate];
  114. return 0.0;
  115. }
  116. Rectangle<int> getNativeSize() const
  117. {
  118. if (auto* player = getAVPlayer())
  119. {
  120. auto s = [[player currentItem] presentationSize];
  121. return { (int) s.width, (int) s.height };
  122. }
  123. return {};
  124. }
  125. double getDuration() const
  126. {
  127. if (auto* player = getAVPlayer())
  128. return toSeconds ([[player currentItem] duration]);
  129. return 0.0;
  130. }
  131. void setVolume (float newVolume)
  132. {
  133. [getAVPlayer() setVolume: newVolume];
  134. }
  135. float getVolume() const
  136. {
  137. if (auto* p = getAVPlayer())
  138. return [p volume];
  139. return 0.0f;
  140. }
  141. File currentFile;
  142. URL currentURL;
  143. private:
  144. #if JUCE_IOS
  145. AVPlayerViewController* controller = nil;
  146. #elif JUCE_32BIT
  147. AVPlayerLayer* controller = nil;
  148. #else
  149. AVPlayerView* controller = nil;
  150. #endif
  151. AVPlayer* getAVPlayer() const noexcept { return [controller player]; }
  152. static double toSeconds (const CMTime& t) noexcept
  153. {
  154. return t.timescale != 0 ? (t.value / (double) t.timescale) : 0.0;
  155. }
  156. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)
  157. };