Add remaining files
[juce-lv2.git] / juce / source / src / native / mac / juce_mac_QuickTimeMovieComponent.mm
blob37c90b197618c4b5b34cb551396a992e4a9d9e09
1 /*\r
2   ==============================================================================\r
3 \r
4    This file is part of the JUCE library - "Jules' Utility Class Extensions"\r
5    Copyright 2004-11 by Raw Material Software Ltd.\r
6 \r
7   ------------------------------------------------------------------------------\r
8 \r
9    JUCE can be redistributed and/or modified under the terms of the GNU General\r
10    Public License (Version 2), as published by the Free Software Foundation.\r
11    A copy of the license is included in the JUCE distribution, or can be found\r
12    online at www.gnu.org/licenses.\r
14    JUCE is distributed in the hope that it will be useful, but WITHOUT ANY\r
15    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\r
16    A PARTICULAR PURPOSE.  See the GNU General Public License for more details.\r
18   ------------------------------------------------------------------------------\r
20    To release a closed-source product which uses JUCE, commercial licenses are\r
21    available: visit www.rawmaterialsoftware.com/juce for more information.\r
23   ==============================================================================\r
24 */\r
26 // (This file gets included by juce_mac_NativeCode.mm, rather than being\r
27 // compiled on its own).\r
28 #if JUCE_INCLUDED_FILE && JUCE_QUICKTIME\r
30 END_JUCE_NAMESPACE\r
32 //==============================================================================\r
33 #define NonInterceptingQTMovieView MakeObjCClassName(NonInterceptingQTMovieView)\r
35 @interface NonInterceptingQTMovieView   : QTMovieView\r
36 {\r
37 }\r
39 - (id) initWithFrame: (NSRect) frame;\r
40 - (BOOL) acceptsFirstMouse: (NSEvent*) theEvent;\r
41 - (NSView*) hitTest: (NSPoint) p;\r
43 @end\r
45 @implementation NonInterceptingQTMovieView\r
47 - (id) initWithFrame: (NSRect) frame\r
48 {\r
49     self = [super initWithFrame: frame];\r
50     [self setNextResponder: [self superview]];\r
51     return self;\r
52 }\r
54 - (void) dealloc\r
55 {\r
56     [super dealloc];\r
57 }\r
59 - (NSView*) hitTest: (NSPoint) point\r
60 {\r
61     return [self isControllerVisible] ? [super hitTest: point] : nil;\r
62 }\r
64 - (BOOL) acceptsFirstMouse: (NSEvent*) theEvent\r
65 {\r
66     return YES;\r
67 }\r
69 @end\r
71 BEGIN_JUCE_NAMESPACE\r
73 //==============================================================================\r
74 #define theMovie (static_cast <QTMovie*> (movie))\r
76 //==============================================================================\r
77 QuickTimeMovieComponent::QuickTimeMovieComponent()\r
78     : movie (0)\r
79 {\r
80     setOpaque (true);\r
81     setVisible (true);\r
83     QTMovieView* view = [[NonInterceptingQTMovieView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)];\r
84     setView (view);\r
85     [view release];\r
86 }\r
88 QuickTimeMovieComponent::~QuickTimeMovieComponent()\r
89 {\r
90     closeMovie();\r
91     setView (nil);\r
92 }\r
94 bool QuickTimeMovieComponent::isQuickTimeAvailable() noexcept\r
95 {\r
96     return true;\r
97 }\r
99 static QTMovie* openMovieFromStream (InputStream* movieStream, File& movieFile)\r
101     // unfortunately, QTMovie objects can only be created on the main thread..\r
102     jassert (MessageManager::getInstance()->isThisTheMessageThread());\r
104     QTMovie* movie = nil;\r
106     FileInputStream* const fin = dynamic_cast <FileInputStream*> (movieStream);\r
108     if (fin != nullptr)\r
109     {\r
110         movieFile = fin->getFile();\r
111         movie = [QTMovie movieWithFile: juceStringToNS (movieFile.getFullPathName())\r
112                                  error: nil];\r
113     }\r
114     else\r
115     {\r
116         MemoryBlock temp;\r
117         movieStream->readIntoMemoryBlock (temp);\r
119         const char* const suffixesToTry[] = { ".mov", ".mp3", ".avi", ".m4a" };\r
121         for (int i = 0; i < numElementsInArray (suffixesToTry); ++i)\r
122         {\r
123             movie = [QTMovie movieWithDataReference: [QTDataReference dataReferenceWithReferenceToData: [NSData dataWithBytes: temp.getData()\r
124                                                                                                                        length: temp.getSize()]\r
125                                                                                                   name: [NSString stringWithUTF8String: suffixesToTry[i]]\r
126                                                                                               MIMEType: @""]\r
127                                               error: nil];\r
129             if (movie != 0)\r
130                 break;\r
131         }\r
132     }\r
134     return movie;\r
137 bool QuickTimeMovieComponent::loadMovie (const File& movieFile_,\r
138                                          const bool isControllerVisible_)\r
140     return loadMovie ((InputStream*) movieFile_.createInputStream(), isControllerVisible_);\r
143 bool QuickTimeMovieComponent::loadMovie (InputStream* movieStream,\r
144                                          const bool controllerVisible_)\r
146     closeMovie();\r
148     if (getPeer() == nullptr)\r
149     {\r
150         // To open a movie, this component must be visible inside a functioning window, so that\r
151         // the QT control can be assigned to the window.\r
152         jassertfalse;\r
153         return false;\r
154     }\r
156     movie = openMovieFromStream (movieStream, movieFile);\r
158     [theMovie retain];\r
159     QTMovieView* view = (QTMovieView*) getView();\r
160     [view setMovie: theMovie];\r
161     [view setControllerVisible: controllerVisible_];\r
162     setLooping (looping);\r
164     return movie != nil;\r
167 bool QuickTimeMovieComponent::loadMovie (const URL& movieURL,\r
168                                          const bool isControllerVisible_)\r
170     // unfortunately, QTMovie objects can only be created on the main thread..\r
171     jassert (MessageManager::getInstance()->isThisTheMessageThread());\r
173     closeMovie();\r
175     if (getPeer() == nullptr)\r
176     {\r
177         // To open a movie, this component must be visible inside a functioning window, so that\r
178         // the QT control can be assigned to the window.\r
179         jassertfalse;\r
180         return false;\r
181     }\r
183     NSURL* url = [NSURL URLWithString: juceStringToNS (movieURL.toString (true))];\r
184     NSError* err;\r
185     if ([QTMovie canInitWithURL: url])\r
186         movie = [QTMovie movieWithURL: url error: &err];\r
188     [theMovie retain];\r
189     QTMovieView* view = (QTMovieView*) getView();\r
190     [view setMovie: theMovie];\r
191     [view setControllerVisible: controllerVisible];\r
192     setLooping (looping);\r
194     return movie != nil;\r
197 void QuickTimeMovieComponent::closeMovie()\r
199     stop();\r
200     QTMovieView* view = (QTMovieView*) getView();\r
201     [view setMovie: nil];\r
202     [theMovie release];\r
203     movie = 0;\r
204     movieFile = File::nonexistent;\r
207 bool QuickTimeMovieComponent::isMovieOpen() const\r
209     return movie != nil;\r
212 File QuickTimeMovieComponent::getCurrentMovieFile() const\r
214     return movieFile;\r
217 void QuickTimeMovieComponent::play()\r
219     [theMovie play];\r
222 void QuickTimeMovieComponent::stop()\r
224     [theMovie stop];\r
227 bool QuickTimeMovieComponent::isPlaying() const\r
229     return movie != 0  && [theMovie rate] != 0;\r
232 void QuickTimeMovieComponent::setPosition (const double seconds)\r
234     if (movie != 0)\r
235     {\r
236         QTTime t;\r
237         t.timeValue = (uint64) (100000.0 * seconds);\r
238         t.timeScale = 100000;\r
239         t.flags = 0;\r
241         [theMovie setCurrentTime: t];\r
242     }\r
245 double QuickTimeMovieComponent::getPosition() const\r
247     if (movie == 0)\r
248         return 0.0;\r
250     QTTime t = [theMovie currentTime];\r
251     return t.timeValue / (double) t.timeScale;\r
254 void QuickTimeMovieComponent::setSpeed (const float newSpeed)\r
256     [theMovie setRate: newSpeed];\r
259 double QuickTimeMovieComponent::getMovieDuration() const\r
261     if (movie == 0)\r
262         return 0.0;\r
264     QTTime t = [theMovie duration];\r
265     return t.timeValue / (double) t.timeScale;\r
268 void QuickTimeMovieComponent::setLooping (const bool shouldLoop)\r
270     looping = shouldLoop;\r
272     [theMovie setAttribute: [NSNumber numberWithBool: shouldLoop]\r
273                     forKey: QTMovieLoopsAttribute];\r
276 bool QuickTimeMovieComponent::isLooping() const\r
278     return looping;\r
281 void QuickTimeMovieComponent::setMovieVolume (const float newVolume)\r
283     [theMovie setVolume: newVolume];\r
286 float QuickTimeMovieComponent::getMovieVolume() const\r
288     return movie != 0 ? [theMovie volume] : 0.0f;\r
291 void QuickTimeMovieComponent::getMovieNormalSize (int& width, int& height) const\r
293     width = 0;\r
294     height = 0;\r
296     if (movie != 0)\r
297     {\r
298         NSSize s = [[theMovie attributeForKey: QTMovieNaturalSizeAttribute] sizeValue];\r
299         width = (int) s.width;\r
300         height = (int) s.height;\r
301     }\r
304 void QuickTimeMovieComponent::paint (Graphics& g)\r
306     if (movie == 0)\r
307         g.fillAll (Colours::black);\r
310 bool QuickTimeMovieComponent::isControllerVisible() const\r
312     return controllerVisible;\r
315 //==============================================================================\r
316 void QuickTimeMovieComponent::goToStart()\r
318     setPosition (0.0);\r
321 void QuickTimeMovieComponent::setBoundsWithCorrectAspectRatio (const Rectangle<int>& spaceToFitWithin,\r
322                                                                const RectanglePlacement& placement)\r
324     int normalWidth, normalHeight;\r
325     getMovieNormalSize (normalWidth, normalHeight);\r
327     const Rectangle<int> normalSize (0, 0, normalWidth, normalHeight);\r
329     if (! (spaceToFitWithin.isEmpty() || normalSize.isEmpty()))\r
330         setBounds (placement.appliedTo (normalSize, spaceToFitWithin));\r
331     else\r
332         setBounds (spaceToFitWithin);\r
336 //==============================================================================\r
337 #if ! (JUCE_MAC && JUCE_64BIT)\r
339 bool juce_OpenQuickTimeMovieFromStream (InputStream* movieStream, Movie& result, Handle& dataHandle)\r
341     if (movieStream == nullptr)\r
342         return false;\r
344     File file;\r
345     QTMovie* movie = openMovieFromStream (movieStream, file);\r
347     if (movie != nil)\r
348         result = [movie quickTimeMovie];\r
350     return movie != nil;\r
353 #endif\r
355 #endif\r