00001 /* 00002 Copyright (c) 2010, The Barbarian Group 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that 00006 the following conditions are met: 00007 00008 * Redistributions of source code must retain the above copyright notice, this list of conditions and 00009 the following disclaimer. 00010 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and 00011 the following disclaimer in the documentation and/or other materials provided with the distribution. 00012 00013 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 00014 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00015 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 00016 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00017 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00018 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00019 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00020 POSSIBILITY OF SUCH DAMAGE. 00021 */ 00022 00023 #pragma once 00024 00025 // None of this works in 64 bit on the mac or Windows. We'll need to move to QTKit on the mac. 00026 #if ! defined( __LP64__ ) 00027 00028 #include "cinder/Cinder.h" 00029 #include "cinder/gl/gl.h" 00030 #include "cinder/Surface.h" 00031 #include "cinder/gl/Texture.h" 00032 #include "cinder/Display.h" 00033 #include "cinder/Url.h" 00034 #include "cinder/DataSource.h" 00035 #include "cinder/Thread.h" 00036 00037 #include <string> 00038 00039 #if defined( CINDER_MAC ) 00040 #include <QuickTime/QuickTime.h> 00041 #if defined( __OBJC__ ) 00042 @class QTMovie; 00043 #else 00044 class QTMovie; 00045 #endif 00046 #endif 00047 00048 00049 // these are forward-declared to avoid bringing all of QuickTime into the global namespace on Windows 00050 #if defined( CINDER_MSW ) 00051 typedef struct MovieType** Movie; 00052 typedef struct OpaqueQTVisualContext* QTVisualContextRef; 00053 typedef long TimeValue; 00054 typedef struct QTAudioFrequencyLevels QTAudioFrequencyLevels; 00055 typedef unsigned long FourCharCode; 00056 typedef struct __CVBuffer* CVBufferRef; 00057 typedef CVBufferRef CVImageBufferRef; 00058 #endif 00059 00060 namespace cinder { namespace qtime { 00061 00062 class MovieBase { 00063 public: 00064 virtual ~MovieBase() {} 00065 00067 bool checkPlayable(); 00068 00070 int32_t getWidth() const { return getObj()->mWidth; } 00072 int32_t getHeight() const { return getObj()->mHeight; } 00074 float getAspectRatio() const { return getObj()->mWidth / (float)getObj()->mHeight; } 00076 float getDuration() const { return getObj()->mDuration; } 00078 float getFramerate() const; 00080 int32_t getNumFrames() const; 00082 bool hasAlpha() const; 00083 00085 bool hasVisuals() const; 00087 bool hasAudio() const; 00088 00089 00091 float getCurrentTime() const; 00093 void seekToTime( float seconds ); 00095 void seekToFrame( int frame ); 00097 void seekToStart(); 00099 void seekToEnd(); 00101 void setActiveSegment( float startTime, float duration ); 00103 void resetActiveSegment(); 00104 00106 void setLoop( bool loop = true, bool palindrome = false ); 00108 void stepForward(); 00110 void stepBackward(); 00112 void setRate( float rate ); 00113 00115 void setVolume( float volume ); 00117 float getVolume() const; 00118 00120 void setupMonoFft( uint32_t numBands ); 00122 void setupStereoFft( uint32_t numBands ); 00124 void setupMultiChannelFft( uint32_t numBands ); 00125 00126 float* getFftData() const; 00127 uint32_t getNumFftBands() const; 00128 uint32_t getNumFftChannels() const; 00129 00131 bool isPlaying() const; 00133 bool isDone() const; 00135 void play(); 00137 void stop(); 00138 00140 void setNewFrameCallback( void(*aNewFrameCallback)( long, void * ), void *aNewFrameCallbackRefcon ); 00141 00143 ::Movie getMovieHandle() const { return getObj()->mMovie; } 00144 00145 protected: 00146 MovieBase() {} 00147 void init(); 00148 void updateFrame(); 00149 void updateLoadState(); 00150 00151 void setupFft( FourCharCode code, uint32_t bandNum, uint8_t channelNum ); 00152 00153 static int32_t countFrames( ::Movie theMovie ); 00154 TimeValue getStartTimeOfFirstSample() const; 00155 00156 protected: 00157 void initFromPath( const std::string &path ); 00158 void initFromLoader( const class MovieLoader &loader ); 00159 void initFromMemory( const void *data, size_t dataSize, const std::string &fileNameHint, const std::string &mimeTypeHint ); 00160 void initFromDataSource( DataSourceRef dataSource, const std::string &mimeTypeHint ); 00161 00162 struct Obj { 00163 Obj(); 00164 virtual ~Obj(); 00165 00166 void prepareForDestruction(); 00167 00168 void lock() { mMutex.lock(); } 00169 void unlock() { mMutex.unlock(); } 00170 00171 // because the MovieBase* might change over time, but the MovieBase::Obj* will not, we need our callbacks to take an Obj* as a refcon 00172 // which in turn means this functionality must be in the Obj, not the MovieBase 00173 virtual void releaseFrame() = 0; 00174 virtual void newFrame( CVImageBufferRef cvImage ) = 0; 00175 00176 int32_t mWidth, mHeight; 00177 int32_t mFrameCount; 00178 float mDuration; 00179 bool mLoaded, mPlayable; 00180 bool mPlayingForward, mLoop, mPalindrome; 00181 00182 QTAudioFrequencyLevels *mFFTData; 00183 FourCharCode mFFTFourCharCode; 00184 uint32_t mFFTNumBandLevels; 00185 uint32_t mFFTNumChannels; 00186 QTVisualContextRef mVisualContext; 00187 ::Movie mMovie; 00188 00189 void (*mNewFrameCallback)(long timeValue, void *refcon); 00190 void *mNewFrameCallbackRefcon; 00191 00192 std::mutex mMutex; 00193 DataSourceRef mDataSource; // sometimes used to retain a reference to a data source so that it doesn't go away before we do 00194 }; 00195 00196 virtual Obj* getObj() const = 0; 00197 }; 00198 00199 class MovieSurface : public MovieBase { 00200 public: 00201 MovieSurface() : MovieBase() {} 00202 MovieSurface( const std::string &path ); 00203 MovieSurface( const class MovieLoader &loader ); 00205 00206 MovieSurface( const void *data, size_t dataSize, const std::string &fileNameHint, const std::string &mimeTypeHint = "" ); 00207 MovieSurface( DataSourceRef dataSource, const std::string mimeTypeHint = "" ); 00208 00210 Surface getSurface(); 00211 00212 protected: 00213 void allocateVisualContext(); 00214 00215 struct Obj : public MovieBase::Obj { 00216 virtual ~Obj(); 00217 00218 virtual void releaseFrame(); 00219 virtual void newFrame( CVImageBufferRef cvImage ); 00220 00221 Surface mSurface; 00222 }; 00223 00224 shared_ptr<Obj> mObj; 00225 virtual MovieBase::Obj* getObj() const { return mObj.get(); } 00226 00227 public: 00229 00230 typedef shared_ptr<Obj> MovieSurface::*unspecified_bool_type; 00231 operator unspecified_bool_type() { return ( mObj.get() == 0 ) ? 0 : &MovieSurface::mObj; } 00232 void reset() { mObj.reset(); } 00234 }; 00235 00240 class MovieGl : public MovieBase { 00241 public: 00242 MovieGl() : MovieBase() {} 00243 MovieGl( const std::string &path ); 00244 MovieGl( const class MovieLoader &loader ); 00246 00247 MovieGl( const void *data, size_t dataSize, const std::string &fileNameHint, const std::string &mimeTypeHint = "" ); 00248 MovieGl( DataSourceRef dataSource, const std::string mimeTypeHint = "" ); 00249 00251 const gl::Texture getTexture(); 00252 00253 protected: 00254 void allocateVisualContext(); 00255 00256 struct Obj : public MovieBase::Obj { 00257 Obj(); 00258 ~Obj(); 00259 00260 virtual void releaseFrame(); 00261 virtual void newFrame( CVImageBufferRef cvImage ); 00262 00263 gl::Texture mTexture; 00264 #if defined( CINDER_MSW ) 00265 gl::TextureCache mTextureCache; 00266 #endif 00267 }; 00268 00269 shared_ptr<Obj> mObj; 00270 virtual MovieBase::Obj* getObj() const { return mObj.get(); } 00271 00272 public: 00274 00275 typedef shared_ptr<Obj> MovieGl::*unspecified_bool_type; 00276 operator unspecified_bool_type() { return ( mObj.get() == 0 ) ? 0 : &MovieGl::mObj; } 00277 void reset() { mObj.reset(); } 00279 }; 00280 00281 class MovieLoader { 00282 public: 00283 MovieLoader() {} 00284 MovieLoader( const Url &url ); 00285 00287 bool checkLoaded() const; 00289 bool checkPlayable() const; 00291 bool checkPlaythroughOk() const; 00292 00294 void waitForLoaded() const; 00296 void waitForPlayable() const; 00298 void waitForPlaythroughOk() const; 00299 00301 const Url& getUrl() const { return mObj->mUrl; } 00302 00304 ::Movie getMovieHandle() const { return mObj->mMovie; } 00305 00307 ::Movie transferMovieHandle() const { mObj->mOwnsMovie = false; return mObj->mMovie; } 00308 00309 protected: 00310 void updateLoadState() const; 00311 00312 struct Obj { 00313 Obj( const Url &url ); 00314 ~Obj(); 00315 00316 mutable bool mOwnsMovie; 00317 ::Movie mMovie; 00318 Url mUrl; 00319 mutable bool mLoaded, mPlayable, mPlaythroughOK; 00320 }; 00321 00322 shared_ptr<Obj> mObj; 00323 00324 public: 00326 00327 MovieLoader( const MovieLoader &other ) { mObj = other.mObj; } 00328 MovieLoader& operator=( const MovieLoader &other ) { mObj = other.mObj; return *this; } 00329 bool operator==( const MovieLoader &other ) { return mObj == other.mObj; } 00330 typedef shared_ptr<Obj> MovieLoader::*unspecified_bool_type; 00331 operator unspecified_bool_type() { return ( mObj.get() == 0 ) ? 0 : &MovieLoader::mObj; } 00332 void reset() { mObj.reset(); } 00334 }; 00335 00337 extern int32_t getQuickTimeVersion(); 00339 extern std::string getQuickTimeVersionString(); 00340 00342 extern void quickTimeTask(); 00343 00344 class QuickTimeExc : public std::exception { 00345 }; 00346 00347 class QuickTimePathInvalidExc : public QuickTimeExc { 00348 }; 00349 00350 class QuickTimeFileInvalidExc : public QuickTimeExc { 00351 }; 00352 00353 class QuickTimeExcUrlInvalid : public QuickTimeExc { 00354 }; 00355 00356 class QuickTimeErrorLoadingExc : public QuickTimeExc { 00357 }; 00358 00359 class QuickTimeExcFft : public QuickTimeExc { 00360 }; 00361 00362 } /* namespace qtime */ } /* namespace cinder */ 00363 #endif // ! defined( __LP64__ )