Cinder

  • Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

include/cinder/qtime/QuickTime.h

Go to the documentation of this file.
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__ )