PicHandle QTEffects_GetPosterPictFromFirstVideoTrackInMovieFile (FSSpec *theSpec)
{
	PicHandle	myPict = NULL;
	Movie		myMovie = NULL;
	Track		myTrack = NULL;
	short		myRefNum = 0;
	OSErr		myErr = noErr;
	
	myErr = OpenMovieFile(theSpec, &myRefNum, fsRdPerm);
	BailError(myErr);

	myErr = NewMovieFromFile(&myMovie, myRefNum, NULL, NULL, 0, NULL);
	BailError(myErr);
	
	SetMoviePlayHints(myMovie, hintsHighQuality, hintsHighQuality);

	myErr = CloseMovieFile(myRefNum);
	BailError(myErr);
	
	myErr = QTEffects_GetFirstVideoTrackInMovie(myMovie, &myTrack);
	BailNil(myTrack);
	
	myPict = GetTrackPict(myTrack, GetMoviePosterTime(myMovie));

bail:
	if (myMovie != NULL)
		DisposeMovie(myMovie);
	
	return(myPict);
}
Ejemplo n.º 2
0
ImportFileHandle *QTImportPlugin::Open(wxString Filename)
{
   FSSpec inFile;
   FInfo fileInfo;
   Movie theMovie = 0;
   Media theMedia;

   // Make sure QuickTime is initialized
   //::EnterMovies();

#ifdef WIN32
   char* specFilename = strdup(Filename.GetData());
   if (FSMakeFSSpec(0,0,c2pstr(specFilename), &inFile) != noErr)
   {
       free(specFilename);
       return false;
   }
   free(specFilename);
#else
   wxMacFilename2FSSpec(Filename, &inFile);
#endif

   OSErr err = FSpGetFInfo(&inFile, &fileInfo);

   if(err != noErr)
      return NULL;

   if (kQTFileTypeSystemSevenSound == fileInfo.fdType)
   {
      // TODO: handle this case.  it is special because system seven sounds cannot
      // be opened in place
   }
   else
   {
      short theRefNum;
      short theResID = 0;  // we want the first movie
      Boolean wasChanged;

      // open the movie file
      err = OpenMovieFile(&inFile, &theRefNum, fsRdPerm);
      if(err != noErr)
         return NULL;

      // instantiate the movie
      err = NewMovieFromFile(&theMovie, theRefNum, &theResID, NULL, newMovieActive, &wasChanged);
      CloseMovieFile(theRefNum);
      if(err != noErr)
         return NULL;
   }


   // get and return the sound track media
   theMedia = GetMediaFromMovie(theMovie);
   if(theMedia == NULL)
      return NULL;

   return new QTImportFileHandle(theMovie, theMedia);
}
bool 	createMovieFromPath(char * path, Movie &movie){



	Boolean 	isdir			= false;
	OSErr 		result 			= 0;
	FSSpec 		theFSSpec;

	short 		actualResId 	= DoTheRightThing;

	#ifdef TARGET_WIN32
		result = NativePathNameToFSSpec (path, &theFSSpec, 0);
		if (result != noErr) {
			ofLog(OF_LOG_ERROR,"NativePathNameToFSSpec failed %d", result);
			ofLog(OF_LOG_ERROR,"Error loading movie");
			return false;
		}

	#endif



	#ifdef TARGET_OSX
		FSRef 		fsref;
		result = FSPathMakeRef((const UInt8*)path, &fsref, &isdir);
		if (result) {
			ofLog(OF_LOG_ERROR,"FSPathMakeRef failed %d", result);
			ofLog(OF_LOG_ERROR,"Error loading movie");
			return false;
		}
		result = FSGetCatalogInfo(&fsref, kFSCatInfoNone, NULL, NULL, &theFSSpec, NULL);
		if (result) {
			ofLog(OF_LOG_ERROR,"FSGetCatalogInfo failed %d", result);
			ofLog(OF_LOG_ERROR,"Error loading movie");
			return false;
		}
	#endif


	short movieResFile;
	result = OpenMovieFile (&theFSSpec, &movieResFile, fsRdPerm);
	if (result == noErr) {

		short   movieResID = 0;
		result = NewMovieFromFile(&movie, movieResFile, &movieResID, (unsigned char *) 0, newMovieActive, (Boolean *) 0);
		if (result == noErr){
			CloseMovieFile (movieResFile);
		} else {
			ofLog(OF_LOG_ERROR,"NewMovieFromFile failed %d", result);
			return false;
		}
	} else {
		ofLog(OF_LOG_ERROR,"OpenMovieFile failed %d", result);
		return false;
	}

	return true;
}
Ejemplo n.º 4
0
TLevelReader3gp::TLevelReader3gp(const TFilePath &path)
	: TLevelReader(path), m_IOError(QTNoError), m_track(0), m_movie(0), m_depth(0)
//                ,m_timeScale(0)
{

	FSSpec fspec;
	QDErr err;
	Boolean dataRefWasChanged;
	if (QuickTimeStuff::instance()->getStatus() != noErr) {
		m_IOError = QTNotInstalled;
		return;
	}

	const char *pStr = toString(m_path.getWideString()).c_str();
	FSMakeFSSpec(0, 0, (const unsigned char *)pStr, &fspec);
	getFSSpecFromPosixPath(pStr, &fspec, false);
	pStr = 0;

	if ((err = OpenMovieFile(&fspec, &m_refNum, fsRdPerm))) {
		m_IOError = QTUnableToOpenFile;
		return;
	}

	m_resId = 0;
	Str255 name;
	err = NewMovieFromFile(&m_movie, m_refNum, &m_resId,
						   name, fsRdPerm, &dataRefWasChanged);

	int numTracks = GetMovieTrackCount(m_movie);
	assert(numTracks == 1 || numTracks == 2);

	m_track = GetMovieIndTrackType(m_movie, 1, VideoMediaType, movieTrackMediaType);

	//m_track=GetMovieTrack(m_movie,numTracks);

	ImageDescriptionHandle imageH;
	imageH = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription));
	TINT32 index = 1;
	Media theMedia = GetTrackMedia(m_track);

	GetMediaSampleDescription(theMedia, index, (SampleDescriptionHandle)imageH);
	ImageDescriptionPtr imagePtr = *imageH;
	m_lx = imagePtr->width;
	m_ly = imagePtr->height;
	m_depth = imagePtr->depth;
	m_info = new TImageInfo();
	m_info->m_lx = m_lx;
	m_info->m_ly = m_ly;
	Tiio::MovWriterProperties *prop = new Tiio::MovWriterProperties();
	m_info->m_properties = prop;

	DisposeHandle((Handle)imageH);

	m_info->m_frameRate = GetMediaTimeScale(theMedia);
}
void ofQtVideoSaver::addAudioTrack(string audioPath)
{
	if(audioPath == "")
        return;
    OSErr err;
    Handle dataRef = NULL;

    FSSpec    fileSpec;
    short audioMovieRefNum = 0;
    short audioMovieResId = 0;

    Movie audioMovie = NULL;
    Track audioCopyTrack = NULL;
    Media audioCopyMedia = NULL;

    Track destTrack = NULL;
    Media destMedia = NULL;

    destTrack =    NewMovieTrack (movie, 0, 0, kFullVolume);

    destMedia = NewTrackMedia (destTrack, SoundMediaType,
                            30. * 100, /* Video Time Scale */
                            nil, 0);

    err = BeginMediaEdits (destMedia);
   
 
    char * p = new char[audioPath.length()+1];
    strcpy(p, audioPath.c_str());

    NativePathNameToFSSpec(p, &fileSpec, 0L);
    err = OpenMovieFile(&fileSpec, &audioMovieRefNum, fsRdPerm);

    err = NewMovieFromFile(&audioMovie, audioMovieRefNum, &audioMovieResId, NULL, newMovieActive, NULL);

    err = CloseMovieFile(audioMovieRefNum);

    SetMovieTimeScale(audioMovie, 30.*100);

    audioCopyTrack = GetMovieTrack(audioMovie, 1);

    audioCopyMedia = GetTrackMedia(audioCopyTrack);

    long duration = GetMovieDuration(audioMovie);

    err = AddEmptyTrackToMovie (audioCopyTrack, movie, nil, nil, &destTrack);

    err = InsertTrackSegment(audioCopyTrack, destTrack, 0, duration, 0);

	err = EndMediaEdits(destMedia);

}
Ejemplo n.º 6
0
OSErr QTCode_NewMovieFromWinPathname(char	*pathName,		/* c-string path to movie */
									Movie	*theMovie,		/* Movie returned here */
									short	*movieRefNum,	/* Movie RefNum returned here */
									short	*movieResId)	/* Movie Resource ID returned here */
{
	FSSpec	fileSpec;
	OSErr	err;


	*theMovie = NULL;
	*movieRefNum = 0;
	*movieResId = 0;

	// Open up the movie file...

	// Fill in an FSSpec.
	NativePathNameToFSSpec(pathName, &fileSpec, 0L);

	err = OpenMovieFile(&fileSpec, movieRefNum, fsRdWrPerm);
	if (err)
	{
		err = OpenMovieFile(&fileSpec, movieRefNum, fsRdPerm);
	}

	if (!err)
	{
		err = NewMovieFromFile(theMovie, *movieRefNum, movieResId, NULL, newMovieActive, NULL);
	}

	if (err)
	{
		if (*theMovie)
		{
			DisposeMovie(*theMovie);
		}
	}

	return err;
}
Ejemplo n.º 7
0
bool 	createMovieFromPath(char * path, Movie &movie){

	Boolean 	isdir			= false;
	OSErr 		result 			= 0;
	FSSpec 		theFSSpec;

	short 		actualResId 	= DoTheRightThing;

	#ifdef TARGET_WIN32
		result = NativePathNameToFSSpec (path, &theFSSpec, 0);
		if (result != noErr) {
			ofLogError("ofQuickTimePlayer") << "createMovieFromPath(): couldn't load movie, NativePathNameToFSSpec failed: OSErr " << result;
			return false;
		}

	#endif

	#ifdef TARGET_OSX
		FSRef 		fsref;
		result = FSPathMakeRef((const UInt8*)path, &fsref, &isdir);
		if (result) {
			ofLogError("ofQuickTimePlayer") << "createMovieFromPath(): couldn't load movie, FSPathMakeRef failed: OSErr " << result;
			return false;
		}
		result = FSGetCatalogInfo(&fsref, kFSCatInfoNone, NULL, NULL, &theFSSpec, NULL);
		if (result) {
			ofLogError("ofQuickTimePlayer") << "createMovieFromPath(): couldn't load movie, FSGetCatalogInfo failed: OSErr ", result;
			return false;
		}
	#endif

	short movieResFile;
	result = OpenMovieFile (&theFSSpec, &movieResFile, fsRdPerm);
	if (result == noErr) {

		short   movieResID = 0;
		result = NewMovieFromFile(&movie, movieResFile, &movieResID, (unsigned char *) 0, newMovieActive, (Boolean *) 0);
		if (result == noErr){
			CloseMovieFile (movieResFile);
		} else {
			ofLogError("ofQuickTimePlayer") << "createMovieFromPath(): couldn't load movie, NewMovieFromFile failed: OSErr " << result;
			return false;
		}
	} else {
		ofLogError("ofQuickTimePlayer") << "createMovoeFromPath(): couldn't load movie, OpenMovieFile failed: OSErr " << result;
		return false;
	}

	return true;
}
Ejemplo n.º 8
0
/**
 * Loads a MIDI file and returns it as a QuickTime Movie structure.
 *
 * @param *path String with the path of an existing MIDI file.
 * @param *moov Pointer to a @c Movie where the result will be stored.
 * @return Whether the file was loaded and the @c Movie successfully created.
 */
static bool LoadMovieForMIDIFile(const char *path, Movie *moov)
{
	int fd;
	int ret;
	char magic[4];
	FSRef fsref;
	FSSpec fsspec;
	short refnum = 0;
	short resid  = 0;

	assert(path != NULL);
	assert(moov != NULL);

	DEBUG(driver, 2, "qtmidi: start loading '%s'...", path);

	/*
	 * XXX Manual check for MIDI header ('MThd'), as I don't know how to make
	 * QuickTime load MIDI files without a .mid suffix without knowing it's
	 * a MIDI file and setting the OSType of the file to the 'Midi' value.
	 * Perhaps ugly, but it seems that it does the Right Thing(tm).
	 */
	fd = open(path, O_RDONLY, 0);
	if (fd == -1) return false;
	ret = read(fd, magic, 4);
	close(fd);
	if (ret < 4) return false;

	DEBUG(driver, 3, "qtmidi: header is '%.4s'", magic);
	if (magic[0] != 'M' || magic[1] != 'T' || magic[2] != 'h' || magic[3] != 'd') {
		return false;
	}

	if (noErr != FSPathMakeRef((const UInt8 *) path, &fsref, NULL)) return false;
	SetMIDITypeIfNeeded(&fsref);

	if (noErr != FSGetCatalogInfo(&fsref, kFSCatInfoNone, NULL, NULL, &fsspec, NULL)) return false;
	if (OpenMovieFile(&fsspec, &refnum, fsRdPerm) != noErr) return false;
	DEBUG(driver, 3, "qtmidi: '%s' successfully opened", path);

	if (noErr != NewMovieFromFile(moov, refnum, &resid, NULL,
				newMovieActive | newMovieDontAskUnresolvedDataRefs, NULL)) {
		CloseMovieFile(refnum);
		return false;
	}
	DEBUG(driver, 3, "qtmidi: movie container created");

	CloseMovieFile(refnum);
	return true;
}
void ofxQtVideoSaver::addAudioTrack(string audioPath)
{
	OSErr err;
	Handle dataRef = NULL;
	FSSpec    fileSpec;
	short audioMovieRefNum = 0;
	short audioMovieResId = 0;
	Movie audioMovie = NULL;
	Track audioCopyTrack = NULL;
	Media audioCopyMedia = NULL;
	Track destTrack = NULL;
	Media destMedia = NULL;

	destTrack = NewMovieTrack (movie, 0, 0, kFullVolume);
	destMedia = NewTrackMedia (destTrack, SoundMediaType,
							   (TimeScale) (30.f * 100), /* Video Time Scale */
							   nil, 0);

	err = BeginMediaEdits (destMedia);

	char * p = new char[audioPath.length()+1];
    strcpy(p, audioPath.c_str());
#ifdef TARGET_WIN32
    NativePathNameToFSSpec(p, &fileSpec, 0L);
#endif
#ifdef TARGET_OSX
	Boolean isdir;
	FSPathMakeRef((const UInt8*)p, &fsref, &isdir);
	FSGetCatalogInfo(&fsref, kFSCatInfoNone, NULL, NULL, &fileSpec, NULL);
#endif

	err = OpenMovieFile(&fileSpec, &audioMovieRefNum, fsRdPerm);
	err = NewMovieFromFile(&audioMovie, audioMovieRefNum, &audioMovieResId, NULL, newMovieActive, NULL);
	err = CloseMovieFile(audioMovieRefNum);

	SetMovieTimeScale(audioMovie, (TimeScale) (30.*100));

	audioCopyTrack = GetMovieTrack(audioMovie, 1);
	audioCopyMedia = GetTrackMedia(audioCopyTrack);

	long duration = GetMovieDuration(audioMovie);

	err = AddEmptyTrackToMovie (audioCopyTrack, movie, 0, 0, &destTrack);
	err = InsertTrackSegment(audioCopyTrack, destTrack, 0, duration, 0);
	err = EndMediaEdits(destMedia);
}
Ejemplo n.º 10
0
OSErr GetMovieFromFile(FSSpec *fsspecPtr, Movie *theMovie)
{
	short	resRefNum = -1;
    OSErr	result;

    *theMovie = NULL;
    
	result = OpenMovieFile(fsspecPtr, &resRefNum, 0);
	if (result == noErr)
    {
        short actualResId = DoTheRightThing;
        
        result = NewMovieFromFile(theMovie, 
                                resRefNum, 
                                &actualResId, 
                                (unsigned char *) 0,
                                0,
                                (Boolean *) 0);
        CloseMovieFile(resRefNum);
    }
    
    return result;
}
Ejemplo n.º 11
0
static boolean playeropenmoviefile (FSSpec *f) {
	
	/*
	7.0b4 PBS: open a movie from disk.
	*/
	
	OSErr err;
	
	short movieresref;
	
	playerdisposecurrentmovie (); /*dispose the current movie*/
	
	err = OpenMovieFile (f, &movieresref, fsRdPerm);
	
	if (err != noErr)
		
		return (false);
	
	NewMovieFromFile (&currentmovie, movieresref, nil, nil, newMovieActive, nil);	
	
	CloseMovieFile (movieresref);
		
	return (true);
	} /*playeropenmoviefile*/
Ejemplo n.º 12
0
int main( int argc, char **argv ) {

    Movie movie;
    Track track;
    Media media;
    short refNum;
    short resID = 0;
    Boolean wasChanged;
    OSErr err = noErr;
    FSSpec fsspec;
    AudioFormatAtomPtr outAudioAtom;
    CmpSoundHeader outSoundInfo;
    SoundComponentData theInputFormat,
                       theOutputFormat;
    SoundConverter mySoundConverter = NULL;
//    SCFillBufferData scFillBufferData = { NULL };
    Ptr pDecomBuffer0 = NULL,
        pDecomBuffer1 = NULL;
    long kMaxOutputBuffer = 64 * 1024;
    long noFrames = 0,
                  niFrames = 0,
                  noBytes = 0,
                  noSamples = 0;
#define MAX_BUFFER_SIZE 256 * 1024 * 1024


    /** Initialise MovieToolbox */
    EnterMovies();

    /** Open the movie file from the first argument */
    printf( "opening audio file: '%s'\n", argv[1] );
    path2fss( &fsspec, argv[1] );
    err = OpenMovieFile( &fsspec, &refNum, fsRdPerm );
    if ( err != noErr ) {
        printf( "failed to open audio: %d\n", GetMoviesError() );
        exit( -1 );
      }

    /** Instantiate the movie */
    err = NewMovieFromFile( &movie, refNum, &resID, NULL,
                            newMovieActive, &wasChanged );
    if ( err ) {
        printf( "failed to instantiate movie\n" );
        exit( -1 );
      }

    CloseMovieFile( refNum );
    refNum = 0;

    /** Get the first sound track */
    track = GetMovieIndTrackType( movie, 1, SoundMediaType,
                                  movieTrackMediaType );
    if ( track == NULL ) {
        printf( "failed to get sound track\n" );
        exit( -1 );
      }

    /** Get the sound track media */
    media = GetTrackMedia( track );
    if ( media == NULL ) {
        printf( "failed to get media from audio track\n" );
        exit( -1 );
      }

    Size size;
    Handle extension;
    SoundDescriptionHandle sourceSoundDescription;

    sourceSoundDescription = (SoundDescriptionHandle)NewHandle(0);

    /** Get the description of the sample data */
    GetMediaSampleDescription( media, 1,
                               (SampleDescriptionHandle)sourceSoundDescription );
    err = GetMoviesError();
    if ( err ) {
        printf( "failed to get description of sample data\n" );
        exit( -1 );
      }

    extension = NewHandle( 0 );

    // get the "magic" decompression atom
    // This extension to the SoundDescription information stores
    // data specific to a given audio decompressor. Some audio
    // decompression algorithms require a set of out-of-stream
    // values to configure the decompressor.
    err = 
        GetSoundDescriptionExtension( (SoundDescriptionHandle)sourceSoundDescription,
                                      &extension, siDecompressionParams );
    if ( noErr == err ) {
        size = GetHandleSize( extension );
        printf( "transferring data to audio buffer: %d bytes\n", size );
        HLock( extension );
        outAudioAtom = (AudioFormatAtom*)NewPtr( size );
        err = MemError();
        // copy the atom data to our buffer...
        BlockMoveData( *extension, outAudioAtom, size );
        HUnlock( extension );
      } else {
        // if it doesn't have an atom, that's ok
        outAudioAtom = NULL;
        err = noErr;
      }

    /** Setup our sound header */
    outSoundInfo.format = (*sourceSoundDescription)->dataFormat;
    outSoundInfo.numChannels = (*sourceSoundDescription)->numChannels;
    outSoundInfo.sampleSize = (*sourceSoundDescription)->sampleSize;
    outSoundInfo.sampleRate = (*sourceSoundDescription)->sampleRate;
    outSoundInfo.compressionID = (*sourceSoundDescription)->compressionID;

    float db = ((float)outSoundInfo.sampleRate)/(1<<16);

    printf( "sample: %d\tchannels: %d\tsample size: %d\tsample rate: %f\tcompressionID: %d\n",
            outSoundInfo.format, outSoundInfo.numChannels, outSoundInfo.sampleSize,
            db, outSoundInfo.compressionID );

    DisposeHandle( extension );
    DisposeHandle( (Handle)sourceSoundDescription );

    /** 
     * Now that we've figured out what the audio file is, allocate buffers
     * and so on for conversion and playback
     */

    printf( "initialising input/output conversion buffers\n" );

    /** setup input/output format for sound converter */
    theInputFormat.flags = 0;
    theInputFormat.format = outSoundInfo.format;
    theInputFormat.numChannels = outSoundInfo.numChannels;
    theInputFormat.sampleSize = outSoundInfo.sampleSize;
    theInputFormat.sampleRate = outSoundInfo. sampleRate;
    theInputFormat.sampleCount = 0;
    theInputFormat.buffer = NULL;
    theInputFormat.reserved = 0;

    theOutputFormat.flags = 0;
    theOutputFormat.format = kSoundNotCompressed;
    theOutputFormat.numChannels = theInputFormat.numChannels;
    theOutputFormat.sampleSize = theInputFormat.sampleSize;
    theOutputFormat.sampleRate = theInputFormat.sampleRate;
    theOutputFormat.sampleCount = 0;
    theOutputFormat.buffer = NULL;
    theOutputFormat.reserved = 0;

    // variableCompression means we're going to use the commonFrameSize field and the kExtendedSoundCommonFrameSizeValid flag
//    scFillBufferData.isSourceVBR = (outSoundInfo.compressionID == variableCompression );

    err = SoundConverterOpen( &theInputFormat, &theOutputFormat, 
                              &mySoundConverter );
    if ( err != noErr ) {
        printf( "failed to open sound converter\n" );
        exit( -1 );
      } else {
        printf( "opened sound converter ok\n" );
      }

    // this isn't crucial or even required for decompression only, but it does tell
    // the sound converter that we're cool with VBR audio
    Ptr tptr = NewPtr( 1 );
    tptr[0] = 1;
    SoundConverterSetInfo( mySoundConverter, siClientAcceptsVBR, tptr );
    free( tptr );

    /**
     * Set up the sound converters decompresson 'environment' by passing
     * in the 'magic' decompression atom
     */
    err = 
        SoundConverterSetInfo( mySoundConverter, siDecompressionParams,
                               outAudioAtom );
    if ( err != noErr ) {
        printf( "failed to set sound converter info\n" );
        exit( -1 );
      } else {
        printf( "set sound converter info ok\n" );
      }

    if ( outAudioAtom ) {
        DisposePtr( (Ptr)outAudioAtom );
      }

    if ( siUnknownInfoType == err ) {
        // clear this error, the decompressor didn't
        // need the decompression atom and that's OK
        err = noErr;
      } else {
//        BailErr(err);
      }

    /** 
     * The input buffer has to be large enough so GetMediaSample isn't
     * going to fail, your mileage may vary
     */
    Handle inputBuffer = NewHandle( MAX_BUFFER_SIZE );
//    HLock( inputBuffer );

    /** Start the sound conversion */
    err = SoundConverterBeginConversion(mySoundConverter);
//    BailErr(err);

    /** Extract compressed audio from media track */
    TimeValue tperSample = 0;
    err = 
        GetMediaSample( media, inputBuffer, 0, 
                        &noBytes, 0, NULL, &tperSample, NULL, NULL, 0, &noSamples, NULL );
    if ( err != noErr ) {
        printf( "failed to fetch media sample data: %d\n", GetMoviesError() );
        exit( -1 );
      } else {
        printf( "media sample: %d (%d) bytes / %ld samples / %d per sample\n", 
                noBytes, GetHandleSize( inputBuffer ), noSamples, tperSample );
      }

    unsigned long niBytes = 0;
    SoundConverterGetBufferSizes( mySoundConverter, noBytes * noSamples,
                                  &niFrames, &niBytes, &noBytes );

    printf( "buffer sizes: frames: %d\tibytes: %d\tobytes: %d\n",
            niFrames, niBytes, noBytes );

    /** Convert into uncompressed audio */
    Ptr outputBuffer = NewPtr( noBytes * 1.2 );
    SoundConverterConvertBuffer( mySoundConverter, inputBuffer, noSamples /* niFrames */, 
                                 outputBuffer, &noFrames, &noBytes );

    printf( "converted: %d frames / %d bytes\n", noFrames, noBytes );

    /** Shutdown the sound converter */
    err = SoundConverterEndConversion( mySoundConverter, outputBuffer, &noFrames, &noBytes );

    printf( "converted final: %d frames / %d bytes\n", noFrames, noBytes );

//    HUnlock( inputBuffer );

    /** We now should have decompressed audio for the input file */
    /** 
     * So, generate visuals using a sliding sample grid at the
     * given framerate
     */

    /** Create a new movie clip with audio and video tracks */

    /** PROJECTM CRAP HERE -- stuff frames into QuickTime */

    /** Close movie file */

    /** Shutdown MovieToolbox */
    ExitMovies();

    return 0;
  }
Ejemplo n.º 13
0
long platformLoadSoundFile (string theFilename)
{
#ifdef QuickTimeInstalled
	short			myRefNum;
	OSStatus		err = noErr;
	Movie			theMovie;
	FSSpec			theSoundFile;

#ifdef __APPLE__
	CFURLRef		musicURL;
	FSRef			musicfsRef;
#endif


	// get the full path to the sound file
	string fileLocation;
	fileLocation = pathToResourceDirectory() + theFilename;


#ifdef __APPLE__
	// create a URL to the file from the C string
	musicURL = CFURLCreateWithBytes (kCFAllocatorDefault, (UInt8 *)fileLocation.c_str(), fileLocation.length(), kCFStringEncodingASCII, NULL);
	if (musicURL == NULL)
	{
		cout << "error getting URL for sound file " << fileLocation << " (sound file may not exist)";
		return 0L;
	}

	// get a FSRef from the URL
	if (!CFURLGetFSRef(musicURL, &musicfsRef))
	{
		cout << "error getting FSRef for sound file " << fileLocation << " (sound file may not exist)";
		CFRelease(musicURL);
		return 0L;
	}
	
	// get the FSSpec from the FSRef
	if (FSGetCatalogInfo (&musicfsRef, kFSCatInfoNone, NULL, NULL, &theSoundFile, NULL))
	{
		cout << "error getting FSSpec for sound file " << fileLocation << " (sound file may not exist)";
		CFRelease(musicURL);
		return 0L;
	}
		
	// release the URL (not needed any more)
	CFRelease(musicURL);
#endif

#ifdef _WIN32
	// get an FSSpec from the pathname
	if (NativePathNameToFSSpec ((char *)fileLocation.c_str(), &theSoundFile, 0))
	{
		cout << "error getting FSSpec for sound file " << fileLocation << " (sound file may not exist)" << endl;
		return 0L;
	}
#endif
	


	// tell QuickTime to open the sound file
	err = OpenMovieFile(&theSoundFile, &myRefNum, fsRdPerm);
	if (err)
	{
		cout << "OpenMovieFile returned " << (long)err << endl;
		return 0L;
	}
	else
	{
		// tell QuickTime to imagine that this is a movie
		NewMovieFromFile(&theMovie, myRefNum, NULL, (StringPtr)NULL, newMovieActive, NULL);
		if (myRefNum != 0)
			CloseMovieFile(myRefNum);
	}
	
	
	// return the reference to the sound
	return (long)theMovie;

#endif // QuickTimeInstalled
}
Ejemplo n.º 14
0
boolean playeropenmovieinwindow ( ptrfilespec f ) {
	
	//
	// 2006-06-23 creedon: FSRef-zed
	//
	// 7.0b4 PBS: open a movie in the QuickTime Player window and display it.  If the window isn't already open, open it.
	//
	
	short movieresref;
	OSErr err;
	hdlwindowinfo hinfo;
	FSSpec fs;
	
	if (macgetfsspec (f, &fs) != noErr)
		return (false);
	
	if (!findplayerwindow (&hinfo))
		
		playeropencommand (); // If the Player window doesn't exist, create a new one.
		
	getwindowinfo (playerwindow, &playerwindowinfo);
		
	playerdisposecurrentmovie (); // make sure the current movie has been disposed
	
	SetGWorld (GetWindowPort (playerwindow), nil);
	
	err = OpenMovieFile ( &fs, &movieresref, fsRdPerm);
	
	if (err != noErr)
		
		return (false);
	
	NewMovieFromFile (&currentmovie, movieresref, nil, nil, newMovieActive, nil);
			
	CloseMovieFile (movieresref);
	
	SetMovieGWorld (currentmovie, GetWindowPort (playerwindow), nil);
	
	GetMovieBox (currentmovie, &currentmovierect);
	
	OffsetRect (&currentmovierect, -currentmovierect.left, -currentmovierect.top);
	
	SetMovieBox (currentmovie, &currentmovierect);		
		
	currentcontroller = NewMovieController (currentmovie, &currentmovierect, mcTopLeftMovie);
	
	MCGetControllerBoundsRect (currentcontroller, &currentmovierect);
	
	//MCSetActionFilterWithRefCon (currentcontroller, NewMCActionFilterWithRefConProc(playermoviecontrollereventfilter), (long) playerwindow);
	
	SizeWindow (playerwindow, currentmovierect.right, currentmovierect.bottom, false);
	
	(**playerwindowinfo).contentrect = currentmovierect;
	
	AlignWindow (playerwindow, false, nil, nil); // position for optimal playback
	
	//MCDoAction (currentcontroller, mcActionSetKeysEnabled, (void *) true); /*enable keyboard input*/ /*No!*/
	
	MoviesTask (nil, 0);
	
	MCIdle (currentcontroller);
		
	return (true);	
	} // playeropenmovieinwindow
void QTEffects_RespondToDialogSelection (OSErr theErr)
{
	Boolean					myDialogWasCancelled = false;
	short					myResID = movieInDataForkResID;
	UInt16					myMovieIter;
	short					mySrcMovieRefNum = 0;
	Movie					myPrevSrcMovie = NULL;
	Track					myPrevSrcTrack = NULL;
	Movie					myNextSrcMovie = NULL;
	Track					myNextSrcTrack = NULL;
	short					myDestMovieRefNum = 0;
	FSSpec					myFile;
	Boolean					myIsSelected = false;
	Boolean					myIsReplacing = false;	
	StringPtr 				myPrompt = QTUtils_ConvertCToPascalString(kEffectsSaveMoviePrompt);
	StringPtr 				myFileName = QTUtils_ConvertCToPascalString(kEffectsSaveMovieFileName);
	Movie					myDestMovie = NULL;
	Fixed					myDestMovieWidth, myDestMovieHeight;
	ImageDescriptionHandle	myDesc = NULL;
	Track					videoTrackFX, videoTrackA, videoTrackB;
	Media					videoMediaFX, videoMediaA, videoMediaB;
	TimeValue				myCurrentDuration = 0;
	TimeValue				myReturnedDuration;
	Boolean					isFirstTransition = true;
	TimeValue				myMediaTransitionDuration;
	TimeValue				myMediaFXStartTime, myMediaFXDuration;
	OSType					myEffectCode;
	long					myFlags = createMovieFileDeleteCurFile | createMovieFileDontCreateResFile;
	long					myLong;
	OSErr					myErr = noErr;

	// standard parameter box has been dismissed, so remember that fact
	gEffectsDialog = 0L;
	
	myDialogWasCancelled = (theErr == userCanceledErr);
	
	// we're finished with the effect list and movie posters	
	QTDisposeAtomContainer(gEffectList);
	
	if (gPosterA != NULL)
		KillPicture(gPosterA);
		
	if (gPosterB != NULL)
		KillPicture(gPosterB);
	
	// when the sign says stop, then stop
	if (myDialogWasCancelled)
		goto bail;

	// add atoms naming the sources to gEffectSample
	myLong = EndianU32_NtoB(kSourceOneName);
	QTInsertChild(gEffectSample, kParentAtomIsContainer, kEffectSourceName, 1, 0, sizeof(myLong), &myLong, NULL);

	myLong = EndianU32_NtoB(kSourceTwoName);
	QTInsertChild(gEffectSample, kParentAtomIsContainer, kEffectSourceName, 2, 0, sizeof(myLong), &myLong, NULL);
	
	// extract the 'what' atom to find out what kind of effect it is
	{
		QTAtom			myEffectAtom;
		QTAtomID		myEffectAtomID;
		long			myEffectCodeSize;
		Ptr				myEffectCodePtr;

		myEffectAtom = QTFindChildByIndex(gEffectSample, kParentAtomIsContainer, kParameterWhatName, kParameterWhatID, &myEffectAtomID);
		
		myErr = QTLockContainer(gEffectSample);
		BailError(myErr);

		myErr = QTGetAtomDataPtr(gEffectSample, myEffectAtom, &myEffectCodeSize, &myEffectCodePtr);
		BailError(myErr);

		if (myEffectCodeSize != sizeof(OSType)) {
			myErr = paramErr;
			goto bail;
		}
		
		myEffectCode = *(OSType *)myEffectCodePtr;		// "tsk"
		myEffectCode = EndianU32_BtoN(myEffectCode);	// because the data is read from an atom container
		
		myErr = QTUnlockContainer(gEffectSample);
		BailError(myErr);
	}

	// ask the user for the name of the new movie file
	QTFrame_PutFile(myPrompt, myFileName, &myFile, &myIsSelected, &myIsReplacing);
	if (!myIsSelected)
		goto bail;				// deal with user cancelling

	// create a movie file for the destination movie
	myErr = CreateMovieFile(&myFile, FOUR_CHAR_CODE('TVOD'), 0, myFlags, &myDestMovieRefNum, &myDestMovie);
	BailError(myErr);
	
	// open the first file as a movie; call the first movie myPrevSrcMovie
	myErr = OpenMovieFile(&gSpecList[0], &mySrcMovieRefNum, fsRdPerm);
	BailError(myErr);
	
	myErr = NewMovieFromFile(&myPrevSrcMovie, mySrcMovieRefNum, NULL, NULL, 0, NULL);
	BailError(myErr);
	
	myErr = CloseMovieFile(mySrcMovieRefNum);
	BailError(myErr);
	
	// if the movie is shorter than kMinimumDuration, scale it to that length
	SetMovieTimeScale(myPrevSrcMovie, kTimeScale);
	myErr = QTEffects_GetFirstVideoTrackInMovie(myPrevSrcMovie, &myPrevSrcTrack);
	BailNil(myPrevSrcTrack);
	
	if (GetTrackDuration(myPrevSrcTrack) < kMinimumDuration) {
		myErr = ScaleTrackSegment(myPrevSrcTrack, 0, GetTrackDuration(myPrevSrcTrack), kMinimumDuration);
		BailError(myErr);
	}
	
	// find out how big the first movie is; we'll use it as the size of all our tracks
	GetTrackDimensions(myPrevSrcTrack, &myDestMovieWidth, &myDestMovieHeight);
	
#if USES_MAKE_IMAGE_DESC_FOR_EFFECT
	// create a new sample description for the effect,
	// which is just an image description specifying the effect and its dimensions
	myErr = MakeImageDescriptionForEffect(myEffectCode, &myDesc);
	if (myErr != noErr)
		BailError(myErr);
#else
	// create a new sample description for the effect,
	// which is just an image description specifying the effect and its dimensions
	myDesc = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription));
	BailNil(myDesc);
	
	(**myDesc).idSize = sizeof(ImageDescription);
	(**myDesc).cType = myEffectCode;
	(**myDesc).hRes = 72L << 16;
	(**myDesc).vRes = 72L << 16;
	(**myDesc).dataSize = 0L;
	(**myDesc).frameCount = 1;
	(**myDesc).depth = 0;
	(**myDesc).clutID = -1;
#endif
	
	// fill in the fields of the sample description
	(**myDesc).vendor = kAppleManufacturer;
	(**myDesc).temporalQuality = codecNormalQuality;
	(**myDesc).spatialQuality = codecNormalQuality;
	(**myDesc).width = FixRound(myDestMovieWidth);
	(**myDesc).height = FixRound(myDestMovieHeight);

	// add three video tracks to the destination movie:
	// 	- videoTrackFX is where the effects and stills live; it's user-visible.
	//	- videoTrackA is where the "source A"s for effects live; it's hidden by the input map
	//	- videoTrackB is where the "source B"s for effects live; it's hidden by the input map
	videoTrackFX = NewMovieTrack(myDestMovie, myDestMovieWidth, myDestMovieHeight, 0);
	BailNil(videoTrackFX);
	videoMediaFX = NewTrackMedia(videoTrackFX, VideoMediaType, kTimeScale, NULL, 0);
	BailNil(videoMediaFX);
	myErr = BeginMediaEdits(videoMediaFX);
	BailError(myErr);
	
	videoTrackA = NewMovieTrack(myDestMovie, myDestMovieWidth, myDestMovieHeight, 0);
	BailNil(videoTrackA);
	videoMediaA = NewTrackMedia(videoTrackA, VideoMediaType, kTimeScale, NULL, 0);
	BailNil(videoMediaA);

	videoTrackB = NewMovieTrack(myDestMovie, myDestMovieWidth, myDestMovieHeight, 0);
	BailNil(videoTrackB);
	videoMediaB = NewTrackMedia(videoTrackB, VideoMediaType, kTimeScale, NULL, 0);
	BailNil(videoMediaB);

	// create the input map
	{
		long				myRefIndex1, myRefIndex2;
		QTAtomContainer		myInputMap;
		QTAtom				myInputAtom;
		OSType				myInputType;

		QTNewAtomContainer(&myInputMap);

		// first input
		if (videoTrackA) {
		
			AddTrackReference(videoTrackFX, videoTrackA, kTrackModifierReference, &myRefIndex1);
			QTInsertChild(myInputMap, kParentAtomIsContainer, kTrackModifierInput, myRefIndex1, 0, 0, NULL, &myInputAtom);
	
			myInputType = EndianU32_NtoB(kTrackModifierTypeImage);
			QTInsertChild(myInputMap, myInputAtom, kTrackModifierType, 1, 0, sizeof(myInputType), &myInputType, NULL);
	
			myLong = EndianU32_NtoB(kSourceOneName);
			QTInsertChild(myInputMap, myInputAtom, kEffectDataSourceType, 1, 0, sizeof(myLong), &myLong, NULL);
		}

		// second input
		if (videoTrackB) {
		
			AddTrackReference(videoTrackFX, videoTrackB, kTrackModifierReference, &myRefIndex2);
			QTInsertChild(myInputMap, kParentAtomIsContainer, kTrackModifierInput, myRefIndex2, 0, 0, NULL, &myInputAtom);
	
			myInputType = EndianU32_NtoB(kTrackModifierTypeImage);
			QTInsertChild(myInputMap, myInputAtom, kTrackModifierType, 1, 0, sizeof(myInputType), &myInputType, NULL);
	
			myLong = EndianU32_NtoB(kSourceTwoName);
			QTInsertChild(myInputMap, myInputAtom, kEffectDataSourceType, 1, 0, sizeof(myLong), &myLong, NULL);
		}

		// set that map
		SetMediaInputMap(GetTrackMedia(videoTrackFX), myInputMap);
		
		QTDisposeAtomContainer(myInputMap);
	}

	myCurrentDuration = 0;

#if MAKE_STILL_SECTIONS
	// copy the first sample of the first video track of the first movie to videoTrackFX, with duration kStillDuration.
	myErr = CopyPortionOfTrackToTrack(myPrevSrcTrack, eStartPortion + eMiddlePortion, videoTrackFX, myCurrentDuration, &myReturnedDuration);
	BailError(myErr);
	
	myCurrentDuration += myReturnedDuration;
#endif 

	// now process any remaining files
	myMovieIter = 1;
	while (myMovieIter < gSpecCount) {
		
		// open the next file as a movie; call it nextSourceMovie
		myErr = OpenMovieFile(&gSpecList[myMovieIter], &mySrcMovieRefNum, fsRdPerm);
		BailError(myErr);
		
		myErr = NewMovieFromFile(&myNextSrcMovie, mySrcMovieRefNum, NULL, NULL, 0, NULL);
		BailError(myErr);
		
		// we're done with the movie file, so close it
		myErr = CloseMovieFile(mySrcMovieRefNum);
		BailError(myErr);
		
		// if the movie is shorter than kMinimumDuration, scale it to that length
		SetMovieTimeScale(myNextSrcMovie, kTimeScale);
		myErr = QTEffects_GetFirstVideoTrackInMovie(myNextSrcMovie, &myNextSrcTrack);
		BailNil(myNextSrcTrack);
		
		if (GetTrackDuration(myNextSrcTrack) < kMinimumDuration) {
			myErr = ScaleTrackSegment(myNextSrcTrack, 0, GetTrackDuration(myNextSrcTrack), kMinimumDuration);
			BailError(myErr);
		}

		// create a transition effect from the previous source movie's first video sample to the next source movie's first video sample
		// (the effect should have duration kEffectDuration);
		// this involves adding one sample to each of the three video tracks:
		
		//    sample from previous source movie	 -> videoTrackA
		myErr = QTEffects_CopyPortionOfTrackToTrack(myPrevSrcTrack, eFinishPortion, videoTrackA, myCurrentDuration, &myReturnedDuration);
		BailError(myErr);
		
		//    sample from next source movie    	 -> videoTrackB
		myErr = QTEffects_CopyPortionOfTrackToTrack(myNextSrcTrack, eStartPortion, videoTrackB, myCurrentDuration, &myReturnedDuration);
		BailError(myErr);
		
		//    effect sample                 	  -> videoTrackFX
		if (isFirstTransition) {
			myMediaTransitionDuration = myReturnedDuration;
			myMediaFXStartTime = GetMediaDuration(videoMediaFX);
			myErr = AddMediaSample(videoMediaFX, gEffectSample, 0, GetHandleSize(gEffectSample), myMediaTransitionDuration, (SampleDescriptionHandle)myDesc, 1, 0, NULL);
			BailError(myErr);
			
			myMediaFXDuration = GetMediaDuration(videoMediaFX) - myMediaFXStartTime;
			isFirstTransition = false;
		}
		
		myErr = InsertMediaIntoTrack(videoTrackFX, myCurrentDuration, myMediaFXStartTime, myMediaFXDuration, FixRatio(myReturnedDuration, myMediaTransitionDuration));
		BailError(myErr);
		
		myCurrentDuration += myReturnedDuration;
		
#if MAKE_STILL_SECTIONS
		// copy the first video sample of myNextSrcMovie to videoTrackFX, with duration kStillDuration.
		myErr = QTEffects_CopyPortionOfTrackToTrack(myNextSrcTrack, eMiddlePortion + (myMovieIter + 1 == theSpecCount) ? eFinishPortion : 0, videoTrackFX, myCurrentDuration, &myReturnedDuration);
		BailError(myErr);
		
		myCurrentDuration += myReturnedDuration;
#endif // MAKE_STILL_SECTIONS
		
		// dispose of previous source movie.  
		DisposeMovie(myPrevSrcMovie);
		
		myPrevSrcMovie = myNextSrcMovie;
		myPrevSrcTrack = myNextSrcTrack;
		myNextSrcMovie = NULL;
		myNextSrcTrack = NULL;
		
		myMovieIter++;
	} // while
	
	myErr = EndMediaEdits(videoMediaFX);
	BailError(myErr);

	myErr = AddMovieResource(myDestMovie, myDestMovieRefNum, &myResID, "\pMovie 1");
	BailError(myErr);
	
	CloseMovieFile(myDestMovieRefNum);
	
	if (myPrevSrcMovie != NULL)
		DisposeMovie(myPrevSrcMovie);
		
	DisposeMovie(myDestMovie);
	
bail:
	free(myPrompt);
	free(myFileName);

	QTDisposeAtomContainer(gEffectSample);
	DisposeHandle((Handle)myDesc);

	return;
}
Ejemplo n.º 16
0
void MIDI_Play (const char *Name)
{
	FILE		*midiFile;
	char	midiName[MAX_OSPATH], tempName[MAX_QPATH];
	OSErr	err;
	FSSpec	midiSpec;
	FSRef	midiRef;
	short	midiRefNum;

	if (!bMidiInited)	//don't try to play if there is no midi
		return;

	MIDI_Stop();

	if (!Name || !*Name)
	{
		Sys_Printf("no midi music to play\n");
		return;
	}

	q_snprintf (tempName, sizeof(tempName), "%s.%s", Name, "mid");
	FS_OpenFile (va("%s/%s", "midi", tempName), &midiFile, false);
	if (!midiFile)
	{
		Con_Printf("music file %s not found\n", tempName);
		return;
	}
	else
	{
		if (file_from_pak)
		{
			int		ret;

			Con_Printf("Extracting %s from pakfile\n", tempName);
			q_snprintf (midiName, sizeof(midiName), "%s/%s.%s", host_parms->userdir, TEMP_MUSICNAME, "mid");
			ret = FS_CopyFromFile (midiFile, midiName, fs_filesize);
			fclose (midiFile);
			if (ret != 0)
			{
				Con_Printf("Error while extracting from pak\n");
				return;
			}
		}
		else	/* use the file directly */
		{
			fclose (midiFile);
			q_snprintf (midiName, sizeof(midiName), "%s/%s/%s", fs_filepath, "midi", tempName);
		}
	}

	// converting path to FSSpec. found in CarbonCocoaIntegration.pdf:
	// page 27, Obtaining an FSSpec Structure
	err = FSPathMakeRef ((UInt8*)midiName, &midiRef, NULL);
	if (err != noErr)
	{
		Con_Printf ("MIDI: FSPathMakeRef: error while opening %s\n", midiName);
		return;
	}

	err = FSGetCatalogInfo (&midiRef, kFSCatInfoNone, NULL, NULL, &midiSpec, NULL);
	if (err != noErr)
	{
		Con_Printf ("MIDI: FSGetCatalogInfo: error while opening %s\n", midiName);
		return;
	}

	err = OpenMovieFile (&midiSpec, &midiRefNum, fsRdPerm);
	if (err != noErr)
	{
		Con_Printf ("MIDI: OpenMovieStream: error opening midi file\n");
		return;
	}

	err = NewMovieFromFile (&midiTrack, midiRefNum, NULL, NULL, newMovieActive, NULL);
	if (err != noErr || !midiTrack)
	{
		Con_Printf ("MIDI: QuickTime error in creating stream.\n");
		return;
	}

	GoToBeginningOfMovie (midiTrack);
	PrerollMovie (midiTrack, 0, 0);

	// pOx - set initial volume
	MIDI_SetVolume (&bgmvolume);

	StartMovie (midiTrack);
	Con_Printf ("Started midi music %s\n", tempName);
}
Ejemplo n.º 17
0
void
PlaySound_QuickTime(const char *cSoundFilename)
{
    int err;
    Str255 pSoundFilename;      /* file pathname in Pascal-string format */
    FSSpec fsSoundFile;         /* movie file location descriptor */
    short resRefNum;            /* open movie file reference */

    if (!fQTInitialised) {
        pthread_mutex_init(&mutexQTAccess, NULL);
        ListCreate(&movielist);
        fQTInitialised = TRUE;
    }

    /* QuickTime is NOT reentrant in Mac OS (it is in MS Windows!) */
    pthread_mutex_lock(&mutexQTAccess);

    EnterMovies();              /* can be called multiple times */

    err = NativePathNameToFSSpec(cSoundFilename, &fsSoundFile, 0);
    if (err != 0) {
        outputf(_("PlaySound_QuickTime: error #%d, can't find %s.\n"), err, cSoundFilename);
    } else {
        /* open movie (WAV or whatever) file */
        err = OpenMovieFile(&fsSoundFile, &resRefNum, fsRdPerm);
        if (err != 0) {
            outputf(_("PlaySound_QuickTime: error #%d opening %s.\n"), err, cSoundFilename);
        } else {
            /* create movie from movie file */
            Movie *movie = (Movie *) malloc(sizeof(Movie));
            err = NewMovieFromFile(movie, resRefNum, NULL, NULL, 0, NULL);
            CloseMovieFile(resRefNum);
            if (err != 0) {
                outputf(_("PlaySound_QuickTime: error #%d reading %s.\n"), err, cSoundFilename);
            } else {
                /* reset movie timebase */
                TimeRecord t = { 0 };
                t.base = GetMovieTimeBase(*movie);
                SetMovieTime(*movie, &t);
                /* add movie to list of running movies */
                ListInsert(&movielist, movie);
                /* run movie */
                StartMovie(*movie);
            }
        }
    }

    pthread_mutex_unlock(&mutexQTAccess);

    if (!fQTPlaying) {
        /* launch playing thread if necessary */
        int err;
        pthread_t qtthread;
        fQTPlaying = TRUE;
        err = pthread_create(&qtthread, 0L, Thread_PlaySound_QuickTime, NULL);
        if (err == 0)
            pthread_detach(qtthread);
        else
            fQTPlaying = FALSE;
    }
}
Ejemplo n.º 18
0
void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) {

  if (nlhs < 0) { mexErrMsgTxt("Too few output arguments."); return; }
  if (nlhs > 1) { mexErrMsgTxt("Too many output arguments."); return; }
  if (nrhs < 1) { mexErrMsgTxt("Too few input arguments."); return; }
  if (nrhs > 3) { mexErrMsgTxt("Too many input arguments."); return; }

  TimeValue duration;
  TimeRecord myTimeRecord;
  Rect bounds;
  OSErr result = 0;
  short resRefNum = -1;
  short actualResId = DoTheRightThing;
  FSSpec theFSSpec;
  GWorldPtr offWorld;
  Movie theMovie = nil;
  MovieController thePlayer = nil;
  MovieDrawingCompleteUPP myDrawCompleteProc;
  long frame_end;
  long myStep = 1;
  char location[PATH_BUFFER_SIZE];
  long frame_count;
  mwSize cdims[2];

  mxGetString(prhs[0], location, PATH_BUFFER_SIZE);

  if (nrhs > 2) {
    frame_start = rint(mxGetScalar(prhs[1]));
    frame_end = rint(mxGetScalar(prhs[2]));
  } else if (nrhs > 1) {
    frame_start = 1;
    frame_end = rint(mxGetScalar(prhs[1]));
  } else {
    frame_start = 1;
    frame_end = 0;
  }

  if (frame_start < 1) {
    mexErrMsgTxt("Error: the starting frame must be positive\n"); 
    return; 
  }

  if (frame_end < 0) {
    mexErrMsgTxt("Error: the ending frame must be positive\n"); 
    return; 
  }

  if (frame_end != 0 && frame_end < frame_start) {
    mexErrMsgTxt("Error: the ending frame must not be less than the starting frame\n"); 
    return; 
  }

  myDrawCompleteProc = NewMovieDrawingCompleteUPP(DrawCompleteProc);

  EnterMovies();            

  if (NativePathNameToFSSpec(location, &theFSSpec, 0) ||
      OpenMovieFile(&theFSSpec, &resRefNum, 0) ||
      NewMovieFromFile(&theMovie, resRefNum, &actualResId, 0, 0, 0)) {
    mexErrMsgTxt("Error: failed to open movie\n"); 
    return; 
  }

  if (resRefNum != -1) CloseMovieFile(resRefNum);

  GetMovieBox(theMovie, &bounds);
  QTNewGWorld(&offWorld, k32ARGBPixelFormat, &bounds, NULL, NULL, 0);
  LockPixels(GetGWorldPixMap(offWorld));
  SetGWorld(offWorld, NULL);

  thePlayer = NewMovieController(theMovie, &bounds, mcTopLeftMovie | mcNotVisible);
  SetMovieGWorld(theMovie, offWorld, NULL);
  SetMovieActive(theMovie, true);
  SetMovieDrawingCompleteProc(theMovie, movieDrawingCallWhenChanged, myDrawCompleteProc, (long) offWorld);
  GetMovieTime(theMovie, &myTimeRecord);
  duration = GetMovieDuration(theMovie);

  // Compute the number of frames for allocation of output structure
  frame_count = 0;
  while ((frame_end == 0 || frame_count < frame_end) && GetMovieTime(theMovie, NULL) < duration) {
    frame_count++;
    MCDoAction(thePlayer, mcActionStep, (Ptr) myStep);
  }
  SetMovieTime(theMovie, &myTimeRecord);
  
  // Ignore frames greater than those in the file
  if (frame_end == 0 || frame_count < frame_end) frame_end = frame_count;
  
  cdims[0] = frame_end - frame_start + 1; // Indices are one-based
  cdims[1] = 1; 

  plhs[0] = mxCreateCellArray(2, cdims);

  // Step through the movie and save the frame when in the chosen interval
  // Note: the step size seems to be handled as a short internally. 
  //       Using anything greater than 32758 will seek to an incorrect frame
  frame_num = 1;
  while (frame_num <= frame_end) {
    MCDoAction(thePlayer, mcActionStep, (Ptr) myStep);
    if (frame_num >= frame_start) {
      MCIdle(thePlayer);
      mxSetCell(plhs[0], frame_num - frame_start, framedata);
    }
    frame_num++;
  }

  UnlockPixels(GetGWorldPixMap (offWorld));
  DisposeGWorld(offWorld);
  DisposeMovieController (thePlayer);
  DisposeMovie(theMovie);
  DisposeMovieDrawingCompleteUPP(myDrawCompleteProc);
  ExitMovies();

  return;
}