bool ofQtVideoSaver::setCodecPhotoJpeg()	{
	initializeQuicktime();
	
	OSStatus error = noErr;
	CodecNameSpecListPtr list;
	CodecNameSpec * codecNameSpecPtr;
	char typeName[32];
	bool set = false;
	
	error = GetCodecNameList( &list, 0 );
	if ( error ) return false;
	
	int numCodecs = list->count;
	codecNameSpecPtr = (CodecNameSpec *)((short *)list + 1);
	
	for (int i = 0; i < numCodecs; i++ ){
		p2cstrcpy( typeName, codecNameSpecPtr->typeName );
		//printf("codec (%i) = %s \n", i, typeName);
		codecNameSpecPtr++;
		//if(string(typeName) == "Photo - JPEG")
		//if(string(typeName) == "H.264")
		if(string(typeName) == "MPEG-4 Video")
		{
			codecType = codecNameSpecPtr->cType;
			set = true;
			printf("Setting Codec to %s\n", typeName);
			break;
		}
	}
	DisposeCodecNameList( list );
	return set;
	
}
//--------------------------------------------------------------------
ofQuickTimeGrabber::ofQuickTimeGrabber(){

	//---------------------------------
	#ifdef OF_VIDEO_CAPTURE_QUICKTIME
	//---------------------------------

		initializeQuicktime();
		bSgInited				= false;
		gSeqGrabber				= NULL;
		offscreenGWorldPixels	= NULL;

	//---------------------------------
	#endif
	//---------------------------------

	// common
	bIsFrameNew				= false;
	bVerbose 				= false;
	bGrabberInited 			= false;
	bChooseDevice			= false;
	deviceID				= 0;
	//width 					= 320;	// default setting
	//height 					= 240;	// default setting
	//pixels					= NULL;
	attemptFramerate		= -1;

}
Example #3
0
//--------------------------------------------------------------------
ofVideoGrabber::ofVideoGrabber(){

	//---------------------------------
	#ifdef OF_VIDEO_CAPTURE_QUICKTIME
	//---------------------------------

		initializeQuicktime();
		bSgInited				= false;
		pixels					= NULL;
		gSeqGrabber				= NULL;
		offscreenGWorldPixels	= NULL;

	//---------------------------------
	#endif
	//---------------------------------


	//---------------------------------
	#ifdef OF_VIDEO_CAPTURE_DIRECTSHOW
	//---------------------------------

		bVerbose 			= false;
		bDoWeNeedToResize 	= false;

	//---------------------------------
	#endif
	//---------------------------------


	//---------------------------------
	#ifdef OF_VIDEO_CAPTURE_V4L				// kept around if people have unicap issues...
	//--------------------------------

		bV4LGrabberInited 	= false;

	//---------------------------------
	#endif
	//---------------------------------

	// common
	bIsFrameNew				= false;
	bVerbose 				= false;
	bGrabberInited 			= false;
	bUseTexture				= true;
	bChooseDevice			= false;
	deviceID				= 0;
	width 					= 320;	// default setting
	height 					= 240;	// default setting
	pixels					= NULL;
}
//--------------------------------------------------------------
void ofQtVideoSaver::listCodecs(){

	initializeQuicktime();

	OSStatus error = noErr;
	CodecNameSpecListPtr list;
	CodecNameSpec * codecNameSpecPtr;
	char typeName[32];

	error = GetCodecNameList( &list, 0 );
	if ( error ) return;

	int numCodecs = list->count;
	codecNameSpecPtr = (CodecNameSpec *)((short *)list + 1);

	for (int i = 0; i < numCodecs; i++ ){
		p2cstrcpy( typeName, codecNameSpecPtr->typeName );
		printf("codec (%i) = %s \n", i, typeName);
		codecNameSpecPtr++;
	}
	DisposeCodecNameList( list );
}
//--------------------------------------------------------------
void ofQtVideoSaver::setCodecType( int chosenCodec ){

	initializeQuicktime();

	OSStatus error = noErr;
	CodecNameSpecListPtr list;
	CodecNameSpec * codecNameSpecPtr;
	char typeName[32];

	error = GetCodecNameList( &list, 0 );
	if ( error ) return;

	int numCodecs = list->count;
	codecNameSpecPtr = (CodecNameSpec *)((short *)list + 1);

	for (int i = 0; i < numCodecs; i++ ){
		if (i == chosenCodec){
			p2cstrcpy( typeName, codecNameSpecPtr->typeName );
			printf("trying to set codec type to (%s) \n", typeName);
			codecType = codecNameSpecPtr->cType;
		}
		codecNameSpecPtr++;
	}
}
void ofQtVideoSaver::setup( int width , int height, string movieName){

	w = width;
	h = height;
    
   
    fileName = (ofToDataPath(movieName));
    //pszFlatFilename = flatFileName;
    
    initializeQuicktime();
    	/*  Load the FSSpec structure to describe the receiving file.  For a 
    description of this and related calls see 
    http://developer.apple.com/quicktime/icefloe/dispatch004.html.
    ================================================================  */


	#ifdef TARGET_WIN32
		//FILE * pFile = NULL;
		//pFile = fopen (fileName.c_str(),"w");
		//fclose (pFile);
		char fileNameStr[255];
		sprintf(fileNameStr, "%s", fileName.c_str());
		osErr = NativePathNameToFSSpec (fileNameStr, &fsSpec, 0);
		
	#endif
	#ifdef TARGET_OSX
	
		/// kill a file and make a new one if needed:		
		FILE * pFile;
		pFile = fopen (fileName.c_str(),"w");
		fclose (pFile);
	
		Boolean isdir;
		osErr = FSPathMakeRef((const UInt8*)fileName.c_str(), &fsref, &isdir);
		osErr = FSGetCatalogInfo(&fsref, kFSCatInfoNone, NULL, NULL, &fsSpec, NULL);
	#endif

    if (osErr && (osErr != fnfErr))    /* File-not-found error is ok         */
      { 
      printf ("getting FSS spec failed %d\n", osErr); 
      goto bail; 
     }
	 

	/*  Step 1:  Create a new, empty movie file and a movie that references that 
    file (CreateMovieFile).  
    ======================================================================== */
            
    osErr = CreateMovieFile 
      (
      &fsSpec,                         /* FSSpec specifier                   */
      FOUR_CHAR_CODE('TVOD'),          /* file creator type, TVOD = QT player*/
      smCurrentScript,                 /* movie script system to use         */
      createMovieFileDeleteCurFile     /* movie file creation flags          */
        | createMovieFileDontCreateResFile,
      &sResRefNum,                     /* returned file ref num to data fork */
      &movie                           /* returned handle to open empty movie*/
                                       /*   that references the created file */
      );
    if (osErr) 
      { 
      printf ("CreateMovieFile failed %d\n", osErr); 
      goto bail; 
      }


	/*  Step 2:  Add a new track to that movie (NewMovieTrack).
    =======================================================  */

    track = NewMovieTrack 
      (
      movie,                           /* the movie to add track to          */
      ((long) w << 16),              /* width of track in pixels (Fixed)   */
      FixRatio (h, 1),               /* height of track in pixels (Fixed)  */ 
      kNoVolume                        /* default volume level               */
      );
    osErr = GetMoviesError ();
    if (osErr) 
      { 
      printf ("NewMovieTrack failed %d\n", osErr); 
      goto bail; 
      }
    

	/*  Step 3:  Add a new media to that track (NewTrackMedia).
    =======================================================  */
    
    media = NewTrackMedia 
      (
      track,                           /* the track to add the media to      */
      VideoMediaType,                  /* media type, e.g. SoundMediaType    */
      600,                             /* num media time units that elapse/sec*/
      NULL,                            /* ptr to file that holds media sampls*/
      0                                /* type of ptr to media samples       */
      );
    osErr = GetMoviesError ();
    if (osErr) 
      { 
      printf ("NewTrackMedia failed %d\n", osErr); 
      goto bail; 
      }

	/*  Step 4:  Add media samples to the media. 
    ========================================  */
    
    BeginMediaEdits (media);           /* Inform the Movie Toolbox that we   */
                                       /*   want to change the media samples */
                                       /*   referenced by a track's media.   */
                                       /*   This opens the media container   */
                                       /*   and makes it ready to receive    */
                                       /*   and/or remove sample data.       */
    
    
    

    // Step 5: setup graphics port for qt movie and compression type ---
    
    /*  Create a new offscreen graphics world that will hold the movie's
    drawing surface.  draw_image() copies the image of IceFlow to this
    surface with varying amounts of transparency.
    =================================================================  */
    
    MacSetRect (&rect, 0, 0, w, h);

    osErr = NewGWorld 
      (
      &pMovieGWorld,                   /* receives the new GWorld.           */
      24,                              /* pixel depth in bits/pixel          */
      &rect,                           /* desired size of the GWorld.        */
      NULL, 
      NULL, 
      (GWorldFlags) 0
      );
    if (osErr != noErr) 
      { 
      printf ("NewGWorld 1 failed %d\n", osErr); 
      goto bail; 
      }


/*  Retrieve the pixel map associated with that graphics world and lock 
    the pixel map in memory.  GetMaxCompressionSize() and CompressImage()
    only operate on pixel maps, not graphics worlds.
    =====================================================================  */
    
    pixMapHandle = GetGWorldPixMap (pMovieGWorld);
    if (pixMapHandle == NULL) 
      { 
      printf ("GetGWorldPixMap failed\n"); 
      goto bail; 
      }
    LockPixels (pixMapHandle);


/*  Get the maximum number of bytes required to hold an image having the 
    specified characteristics compressed using the specified compressor.
    ====================================================================  */

     
    osErr = GetMaxCompressionSize 
      (
      pixMapHandle,							/* the pixel map to compress from.    */
      &rect,								/* the image rectangle.               */
      0,									/* let ICM choose image bit depth.    */
      codecHighQuality,						/* compression quality specifier.     */
      kRawCodecType,						/* desired compression type           */   // < set to RAW in case we set to a new compression type...
      (CompressorComponent) anyCodec,		/* codec specifier.                   */
      &lMaxCompressionSize					/* receives max bytes needed for cmp. */
      );
    if (osErr != noErr) 
      { 
      printf ("GetMaxCompressionSize failed %d\n", osErr); 
      goto bail; 
      }


/*  Allocate a buffer to hold the compressed image data by creating a new
    handle.
    =====================================================================  */
    hCompressedData = NewHandle (lMaxCompressionSize);
    if (hCompressedData == NULL) 
      { 
      printf ("NewHandle(%ld) failed\n", lMaxCompressionSize); 
      goto bail; 
      }

/*  Lock the handle and then dereference it to obtain a pointer to the data 
    buffer because CompressImage() wants us to pass it a pointer, not a 
    handle. 
    =======================================================================  */

    HLockHi (hCompressedData);
    pCompressedData = *hCompressedData;

/*  Create an image description object in memory of minimum size to pass 
    to CompressImage().  CompressImage() will resize the memory as 
    necessary so create it small here.
    ====================================================================  */
    
    hImageDescription = (ImageDescriptionHandle) NewHandle (4);
    if (hImageDescription == NULL) 
      { 
      printf ("NewHandle(4) failed\n"); 
      goto bail; 
      }
	
	
	
	bSetupForRecordingMovie = true;
    return;
    
    
    
    
  bail:    
	printf("got to bail somehows \n");
    if (sResRefNum != 0) CloseMovieFile (sResRefNum);
    if (movie     != NULL) DisposeMovie (movie);

    //ExitMovies ();                     /* Finalize Quicktime                 */
    
    return;
}
//--------------------------------------------------------------
ofxThreadedVideo::ofxThreadedVideo(){

    instanceID = ofxThreadedVideoGlobalInstanceID;
    ofxThreadedVideoGlobalInstanceID++;
    

#ifdef OF_VIDEO_PLAYER_GSTREAMER
    setPlayer<ofGstVideoPlayer>();
#else
    initializeQuicktime();
    setPlayer<ofQuickTimePlayer>();
#endif
    
    // setup video instances
    video[0].setUseTexture(false);
    video[1].setUseTexture(false);
    
    setPixelFormat(OF_PIXELS_RGB);
    
    drawTexture.allocate(1, 1, GL_RGB);
    ofPixels p;
    p.allocate(1, 1, OF_IMAGE_COLOR);
    p.set(0);
    drawTexture.loadData(p.getPixels(), 1, 1, GL_RGB);
    pixels = &video[0].getPixelsRef();
    
    // set vars to default values
    currentVideoID = VIDEO_FLIP;
    bCriticalSection = false;
    bLoaded = false;
    
    bUseTexture = true;
    bIsFrameNew = false;
    bIsPlaying = false;
    bIsLoading = false;
    bIsMovieDone = false;
    
    width = 0.0f;
    height = 0.0f;
    
    speed = 0.0f;
    position = 0.0f;
    duration = 0.0f;
    
    volume = 0.0f;
    pan = 0.0f;
    
    loopState = OF_LOOP_NORMAL;
    
    frameCurrent = 0;
    frameTotal = 0;
    
    movieName = "";
    moviePath = "";
    
    fade = 1.0f;
    fades.clear();
    
    prevMillis = ofGetElapsedTimeMillis();
    lastFrameTime = timeNow = timeThen = fps = frameRate = 0;
    
    ofxThreadedVideoNullCommand.setCommand("NULL_COMMAND", -1);
    
    bVerbose = false;
    
    // let's go!
    startThread();
}
//---------------------------------------------------------------------------
bool ofQuickTimePlayer::loadMovie(string name){


	//--------------------------------------
	#ifdef OF_VIDEO_PLAYER_QUICKTIME
	//--------------------------------------

		initializeQuicktime();			// init quicktime
		closeMovie();					// if we have a movie open, close it
		bLoaded 				= false;	// try to load now

		if( name.substr(0, 7) == "http://" || name.substr(0,7) == "rtsp://" ){
			if(! createMovieFromURL(name, moviePtr) ) return false;
		}else{
			name 					= ofToDataPath(name);
			if( !createMovieFromPath((char *)name.c_str(), moviePtr) ) return false;
		}

		bool bDoWeAlreadyHaveAGworld = false;
		if (width != 0 && height != 0){
			bDoWeAlreadyHaveAGworld = true;
		}
		Rect 				movieRect;
		GetMovieBox(moviePtr, &(movieRect));
		if (bDoWeAlreadyHaveAGworld){
			// is the gworld the same size, then lets *not* de-allocate and reallocate:
			if (width == movieRect.right &&
				height == movieRect.bottom){
				SetMovieGWorld (moviePtr, offscreenGWorld, nil);
			} else {
				width 	= movieRect.right;
				height 	= movieRect.bottom;
				pixels.clear();
				delete(offscreenGWorldPixels);
				if ((offscreenGWorld)) DisposeGWorld((offscreenGWorld));
				createImgMemAndGWorld();
			}
		} else {
			width	= movieRect.right;
			height 	= movieRect.bottom;
			createImgMemAndGWorld();
		}

		if (moviePtr == NULL){
			return false;
		}

		//----------------- callback method
	    myDrawCompleteProc = NewMovieDrawingCompleteUPP (DrawCompleteProc);
		SetMovieDrawingCompleteProc (moviePtr, movieDrawingCallWhenChanged,  myDrawCompleteProc, (long)this);

		// ------------- get the total # of frames:
		nFrames				= 0;
		TimeValue			curMovieTime;
		curMovieTime		= 0;
		TimeValue			duration;

		//OSType whichMediaType	= VIDEO_TYPE; // mingw chokes on this
		OSType whichMediaType	= FOUR_CHAR_CODE('vide');

		short flags				= nextTimeMediaSample + nextTimeEdgeOK;

		while( curMovieTime >= 0 ) {
			nFrames++;
			GetMovieNextInterestingTime(moviePtr,flags,1,&whichMediaType,curMovieTime,0,&curMovieTime,&duration);
			flags = nextTimeMediaSample;
		}
		nFrames--; // there's an extra time step at the end of themovie




		// ------------- get some pixels in there ------
		GoToBeginningOfMovie(moviePtr);
		SetMovieActiveSegment(moviePtr, -1,-1);
		MoviesTask(moviePtr,0);

		#if defined(TARGET_OSX) && defined(__BIG_ENDIAN__)
			convertPixels(offscreenGWorldPixels, pixels.getPixels(), width, height);
		#endif

		bStarted 				= false;
		bLoaded 				= true;
		bPlaying 				= false;
		bHavePixelsChanged 		= false;
		speed 					= 1;

		return true;

	//--------------------------------------
	#endif
	//--------------------------------------



}
//---------------------------------------------------------------------------
bool ofQuickTimePlayer::loadMovie(string name) {


    //--------------------------------------
#ifdef OF_VIDEO_PLAYER_QUICKTIME
    //--------------------------------------

    initializeQuicktime();			// init quicktime
    closeMovie();					// if we have a movie open, close it
    bLoaded 				= false;	// try to load now


    // from : https://github.com/openframeworks/openFrameworks/issues/244
    // http://developer.apple.com/library/mac/#documentation/QuickTime/RM/QTforWindows/QTforWindows/C-Chapter/3BuildingQuickTimeCa.html
    // Apple's documentation *seems* to state that a Gworld should have been set prior to calling NewMovieFromFile
    // So I set a dummy Gworld (1x1 pixel) before calling createMovieFromPath
    // it avoids crash at the creation of objet ofVideoPlayer after a previous ofVideoPlayer have been deleted

#ifdef TARGET_WIN32
    if (width != 0 && height != 0) {
        pixels.clear();
        delete [] offscreenGWorldPixels;
    }
    width = 1;
    height = 1;
    createImgMemAndGWorld();
#endif


    if( name.substr(0, 7) == "http://" || name.substr(0,7) == "rtsp://" ) {
        if(! createMovieFromURL(name, moviePtr) ) return false;
    } else {
        name 					= ofToDataPath(name);
        if( !createMovieFromPath((char *)name.c_str(), moviePtr) ) return false;
    }

    bool bDoWeAlreadyHaveAGworld = false;
    if (width != 0 && height != 0) {
        bDoWeAlreadyHaveAGworld = true;
    }
    Rect 				movieRect;
    GetMovieBox(moviePtr, &(movieRect));
    if (bDoWeAlreadyHaveAGworld) {
        // is the gworld the same size, then lets *not* de-allocate and reallocate:
        if (width == movieRect.right &&
                height == movieRect.bottom) {
            SetMovieGWorld (moviePtr, offscreenGWorld, nil);
        } else {
            width 	= movieRect.right;
            height 	= movieRect.bottom;
            pixels.clear();
            delete [] offscreenGWorldPixels;
            if ((offscreenGWorld)) DisposeGWorld((offscreenGWorld));
            createImgMemAndGWorld();
        }
    } else {
        width	= movieRect.right;
        height 	= movieRect.bottom;
        createImgMemAndGWorld();
    }

    if (moviePtr == NULL) {
        return false;
    }

    //----------------- callback method
    myDrawCompleteProc = NewMovieDrawingCompleteUPP (DrawCompleteProc);
    SetMovieDrawingCompleteProc (moviePtr, movieDrawingCallWhenChanged,  myDrawCompleteProc, (long)this);

    // ------------- get the total # of frames:
    nFrames				= 0;
    TimeValue			curMovieTime;
    curMovieTime		= 0;
    TimeValue			duration;

    //OSType whichMediaType	= VIDEO_TYPE; // mingw chokes on this
    OSType whichMediaType	= FOUR_CHAR_CODE('vide');

    short flags				= nextTimeMediaSample + nextTimeEdgeOK;

    while( curMovieTime >= 0 ) {
        nFrames++;
        GetMovieNextInterestingTime(moviePtr,flags,1,&whichMediaType,curMovieTime,0,&curMovieTime,&duration);
        flags = nextTimeMediaSample;
    }
    nFrames--; // there's an extra time step at the end of themovie




    // ------------- get some pixels in there ------
    GoToBeginningOfMovie(moviePtr);
    SetMovieActiveSegment(moviePtr, -1,-1);
    MoviesTask(moviePtr,0);

#if defined(TARGET_OSX) && defined(__BIG_ENDIAN__)
    convertPixels(offscreenGWorldPixels, pixels.getPixels(), width, height);
#endif

    bStarted 				= false;
    bLoaded 				= true;
    bPlaying 				= false;
    bHavePixelsChanged 		= false;
    speed 					= 1;

    return true;

    //--------------------------------------
#endif
    //--------------------------------------



}
//---------------------------------------------------------------------------
bool ofVideoPlayer::loadMovie(string name){


	//--------------------------------------
	#ifdef OF_VIDEO_PLAYER_QUICKTIME
	//--------------------------------------

		initializeQuicktime();			// init quicktime
		closeMovie();					// if we have a movie open, close it
		bLoaded 				= false;	// try to load now
		
		if( name.substr(0, 7) == "http://"){
			if(! createMovieFromURL(name, moviePtr) ) return false;
		}else{
			name 					= ofToDataPath(name);
			if( !createMovieFromPath((char *)name.c_str(), moviePtr) ) return false;
		}
		
		bool bDoWeAlreadyHaveAGworld = false;
		if (width != 0 && height != 0){
			bDoWeAlreadyHaveAGworld = true;
		}
		Rect 				movieRect;
		GetMovieBox(moviePtr, &(movieRect));
		if (bDoWeAlreadyHaveAGworld){
			// is the gworld the same size, then lets *not* de-allocate and reallocate:
			if (width == movieRect.right &&
				height == movieRect.bottom){
				SetMovieGWorld (moviePtr, offscreenGWorld, nil);
			} else {
				width 	= movieRect.right;
				height 	= movieRect.bottom;
				delete(pixels);
				delete(offscreenGWorldPixels);
				if ((offscreenGWorld)) DisposeGWorld((offscreenGWorld));
				createImgMemAndGWorld();
			}
		} else {
			width	= movieRect.right;
			height 	= movieRect.bottom;
			createImgMemAndGWorld();
		}

		if (moviePtr == NULL){
			return false;
		}

		//----------------- callback method
	    MovieDrawingCompleteUPP myDrawCompleteProc;
	    myDrawCompleteProc = NewMovieDrawingCompleteUPP (DrawCompleteProc);
		SetMovieDrawingCompleteProc (moviePtr, movieDrawingCallWhenChanged,  myDrawCompleteProc, (long)this);

		// ------------- get some pixels in there ------
		GoToBeginningOfMovie(moviePtr);
		SetMovieActiveSegment(moviePtr, -1,-1);
		MoviesTask(moviePtr,0);
		convertPixels(offscreenGWorldPixels, pixels, width, height);
		if (bUseTexture == true){
			tex.loadData(pixels, width, height, GL_RGB);
		}
		
		bStarted 				= false;
		bLoaded 				= true;
		bPlaying 				= false;
		bHavePixelsChanged 		= false;
		speed 					= 1;

		return true;

	//--------------------------------------
	#else
	//--------------------------------------

		bLoaded      		= false;
		bPaused 			= false;
		speed 				= 1.0f;
		bHavePixelsChanged 	= false;
		name 					= ofToDataPath(name);
		fobsDecoder 		= new omnividea::fobs::Decoder(name.c_str());
		omnividea::fobs::ReturnCode error = fobsDecoder->open();

		width 					= fobsDecoder->getWidth();
		height 					= fobsDecoder->getHeight();
		pixels					= new unsigned char[width*height*3];

		if (!fobsDecoder->isVideoPresent()){
			return false;
		}

		bLoaded = true;

		if (bUseTexture){
			// create the texture, set the pixels to black and
			// upload them to the texture (so at least we see nothing black the callback)
			tex.allocate(width,height,GL_RGB);
			memset(pixels, 0, width*height*3);
			tex.loadData(pixels, width, height, GL_RGB);
		}


		error = fobsDecoder->setFrame(0);

		if(error == omnividea::fobs::NoFrameError) {
			error = omnividea::fobs::OkCode;
			printf("NoFrameError\n");
		}

		if(omnividea::fobs::isOk(error)){
			// get some pixels in:
			unsigned char *rgb = fobsDecoder->getRGB();
			if(rgb == NULL) error = omnividea::fobs::GenericError;
			if(isOk(error))
			{
				memcpy(pixels, rgb, width*height*3);
				tex.loadData(pixels, width, height, GL_RGB);
			}
		}


		iTotalFrames		= (int)(fobsDecoder->getFrameRate()*fobsDecoder->getDurationSeconds());
		positionPct 		= 0;
		timeLastIdle 		= ofGetElapsedTimef();
        durationMillis      = fobsDecoder->getDurationSeconds() * 1000.0f;


		return true;


	//--------------------------------------
	#endif
	//--------------------------------------



}
ofxQtAudioRecorder::ofxQtAudioRecorder(){
	
	initializeQuicktime();
}
//------------------------------------------------------------
void ofQuicktimeSoundPlayer::loadSound(string fileName, bool stream){

	
	fileName = ofToDataPath(fileName);
	
	// TODO: hmm?
	bMultiPlay = false;

	// [1] init fmod, if necessary

	initializeQuicktime();

	// [2] try to unload any previously loaded sounds
	// & prevent user-created memory leaks
	// if they call "loadSound" repeatedly, for example

	if (bLoadedOk == true){
		unloadSound();
	}
	// [3] load sound

	OSErr error;
    
    //CFBundleRef gameBundle = CFBundleGetMainBundle();
    
    // Find the file in the application bundle.
    CFURLRef movieFileLocation;
    movieFileLocation = CFURLCreateFromFileSystemRepresentation(NULL, (UInt8*)fileName.c_str(), strlen(fileName.c_str()), false);
	
	//CFBundleCopyResourceURL(gameBundle, filename, fileExtension, subdirectory); 
    
    if (movieFileLocation == NULL)
        return;
    
    Handle dataRef;
    OSType dataRefType;
    
    dataRef = NewHandle(sizeof(AliasHandle));
    
    // Get the movie file set up so we can load it in memory.
    // The second parameter to QTNewDataReferenceFromCFURL is flags.
    // It should be set to 0.
    error = QTNewDataReferenceFromCFURL(movieFileLocation, 0, &dataRef, &dataRefType);
    if(error != noErr) {
        DisposeHandle(dataRef);
        CFRelease(movieFileLocation);
        return;
    }
    
    // Get the movie into memory
    short fileID = movieInDataForkResID;
    short flags = 0;
    error = NewMovieFromDataRef(&soundToPlay, flags, &fileID, dataRef, dataRefType);
    
    // Dispose of the memory we allocated.
    DisposeHandle(dataRef);
    CFRelease(movieFileLocation);
	
	// TODO: check here!  
	bLoadedOk = true;
	

}