2 ==============================================================================
\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
7 ------------------------------------------------------------------------------
\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
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
32 //==============================================================================
\r
33 #define NonInterceptingQTMovieView MakeObjCClassName(NonInterceptingQTMovieView)
\r
35 @interface NonInterceptingQTMovieView : QTMovieView
\r
39 - (id) initWithFrame: (NSRect) frame;
\r
40 - (BOOL) acceptsFirstMouse: (NSEvent*) theEvent;
\r
41 - (NSView*) hitTest: (NSPoint) p;
\r
45 @implementation NonInterceptingQTMovieView
\r
47 - (id) initWithFrame: (NSRect) frame
\r
49 self = [super initWithFrame: frame];
\r
50 [self setNextResponder: [self superview]];
\r
59 - (NSView*) hitTest: (NSPoint) point
\r
61 return [self isControllerVisible] ? [super hitTest: point] : nil;
\r
64 - (BOOL) acceptsFirstMouse: (NSEvent*) theEvent
\r
71 BEGIN_JUCE_NAMESPACE
\r
73 //==============================================================================
\r
74 #define theMovie (static_cast <QTMovie*> (movie))
\r
76 //==============================================================================
\r
77 QuickTimeMovieComponent::QuickTimeMovieComponent()
\r
83 QTMovieView* view = [[NonInterceptingQTMovieView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)];
\r
88 QuickTimeMovieComponent::~QuickTimeMovieComponent()
\r
94 bool QuickTimeMovieComponent::isQuickTimeAvailable() noexcept
\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
110 movieFile = fin->getFile();
\r
111 movie = [QTMovie movieWithFile: juceStringToNS (movieFile.getFullPathName())
\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
123 movie = [QTMovie movieWithDataReference: [QTDataReference dataReferenceWithReferenceToData: [NSData dataWithBytes: temp.getData()
\r
124 length: temp.getSize()]
\r
125 name: [NSString stringWithUTF8String: suffixesToTry[i]]
\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
148 if (getPeer() == nullptr)
\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
156 movie = openMovieFromStream (movieStream, movieFile);
\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
175 if (getPeer() == nullptr)
\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
183 NSURL* url = [NSURL URLWithString: juceStringToNS (movieURL.toString (true))];
\r
185 if ([QTMovie canInitWithURL: url])
\r
186 movie = [QTMovie movieWithURL: url error: &err];
\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
200 QTMovieView* view = (QTMovieView*) getView();
\r
201 [view setMovie: nil];
\r
202 [theMovie release];
\r
204 movieFile = File::nonexistent;
\r
207 bool QuickTimeMovieComponent::isMovieOpen() const
\r
209 return movie != nil;
\r
212 File QuickTimeMovieComponent::getCurrentMovieFile() const
\r
217 void QuickTimeMovieComponent::play()
\r
222 void QuickTimeMovieComponent::stop()
\r
227 bool QuickTimeMovieComponent::isPlaying() const
\r
229 return movie != 0 && [theMovie rate] != 0;
\r
232 void QuickTimeMovieComponent::setPosition (const double seconds)
\r
237 t.timeValue = (uint64) (100000.0 * seconds);
\r
238 t.timeScale = 100000;
\r
241 [theMovie setCurrentTime: t];
\r
245 double QuickTimeMovieComponent::getPosition() const
\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
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
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
298 NSSize s = [[theMovie attributeForKey: QTMovieNaturalSizeAttribute] sizeValue];
\r
299 width = (int) s.width;
\r
300 height = (int) s.height;
\r
304 void QuickTimeMovieComponent::paint (Graphics& g)
\r
307 g.fillAll (Colours::black);
\r
310 bool QuickTimeMovieComponent::isControllerVisible() const
\r
312 return controllerVisible;
\r
315 //==============================================================================
\r
316 void QuickTimeMovieComponent::goToStart()
\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
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
345 QTMovie* movie = openMovieFromStream (movieStream, file);
\r
348 result = [movie quickTimeMovie];
\r
350 return movie != nil;
\r