// Graphics Importer and Exporter Samples
// This example opens a movie file, allows you to save
// the movie as a sequence of frames. It then creates a new
// reference movie from those images and saves it.
// Originally written by Sam Bushell for QuickTime "Live" '99
// WWDC 2000 Introduction to QuickTime

#include "MacShell.h"

void MovieToImage( void )
{
	OSErr  err = noErr;
	Handle hOpenTypeList = NewHandle(0);
	long  numTypes = 0;
	FSSpec theFSSpec;
	Boolean isSelected, isReplacing;
	Rect naturalBounds, windowBounds;
	WindowPtr window = NULL;
	short refNum = -1, resID = NULL;
	Movie movie = 0;
	MovieExportComponent movieExporter = 0;
	Boolean canceled = true;
	MovieImportComponent movieImporter = 0;
	Track usedTrack;
	TimeValue addedDuration;
	long outFlags;
	
    if ( !BuildMovieValidFileTypes( hOpenTypeList, &numTypes ) ) {
        HLock( hOpenTypeList );
    } else {
        DisposeHandle( hOpenTypeList );
        return;
    }

	err = GetOneFileWithPreview(numTypes, (OSTypePtr)*hOpenTypeList, &theFSSpec, NULL);
    DisposeHandle( hOpenTypeList );
	if ( err ) return;
	
	// open a movie file
	err = OpenMovieFile( &theFSSpec, &refNum, fsRdPerm );
	err = NewMovieFromFile( &movie, refNum, &resID, NULL, newMovieActive, NULL );
	err = CloseMovieFile( refNum );
	refNum = -1;
	
	GetMovieBox( movie, &naturalBounds );
	windowBounds = naturalBounds;
	OffsetRect( &windowBounds, 10, 45 );
	window = NewCWindow( NULL, &windowBounds, "\pMovie <-> Images", true, documentProc, (WindowPtr)-1, true, 0);
	SetPortWindowPort( window );
	
	// play the movie
	SetMovieGWorld( movie, GetWindowPort( window), NULL );
	GoToBeginningOfMovie( movie );
	StartMovie( movie );
	while( false == IsMovieDone( movie ) ) {
		MoviesTask( NULL, 0 );
	}
	StopMovie( movie );
	
	pause();

	// save the movie as a sequence of image files.
	err = PutFile( "\pSave as image sequence:", "\psequence", &theFSSpec, &isSelected, &isReplacing);
	if (err) return;
	
	// open a movie exporter
	err = OpenADefaultComponent( MovieExportType,				// component type
								 GraphicsExporterComponentType, // subType
								 &movieExporter );				// component instance
	
	// configure the export component by showing the dialog box
	err = MovieExportDoUserDialog( movieExporter,				// component instance
								   movie,						// movie to be exported					
								   NULL,						// specific track to export
								   0,							// start time
								   GetMovieDuration( movie ),	// duration to be exported
								   &canceled );					// boolean set to true if user canceled
	if( canceled ) return;
	
	// attach a progress function; -1 for default progress function
	SetMovieProgressProc( movie, (MovieProgressUPP)-1, 0 );
	
	// convert the movie into a specified file(s) and type
	err = ConvertMovieToFile( movie,			// movie specifier
							  NULL,				// specific track for export; NULL for all tracks
							  &theFSSpec,		// output file
							  0,				// file type				
							  0,				// file creator
							  smSystemScript,	// script 
							  NULL,				// resource id
							  0,				// flags
							  movieExporter );	// movie export component to use for the operation -- pass in a component instance
							  					// this allows setting any conversion parameters with the export component directly
	
	CloseComponent( movieExporter );
	DisposeMovie( movie );
	movie = 0;
	EraseRect( &naturalBounds );
	
    hOpenTypeList = NewHandle(0);
	// now re-open the sequence of image files as a reference movie
	if ( !BuildGraphicsImporterValidFileTypes( hOpenTypeList, &numTypes ) ) {
        HLock( hOpenTypeList );
    } else {
        DisposeHandle( hOpenTypeList );
        return;
    }

	err = GetOneFileWithPreview(numTypes, (OSTypePtr)*hOpenTypeList, &theFSSpec, NULL);
	DisposeHandle( hOpenTypeList );
	if ( err ) return;

	// open a movie importer
	err = OpenADefaultComponent( MovieImportType,				// component type
								 GraphicsImporterComponentType, // subType
								 &movieImporter );				// component instance
	
	// we're using a movie importer that imports images using graphics importers
	// this subType-specific call enables the "Import Image Sequence..." behaviour,
	// letting the movie importer search for adjacent files with names matching a numeric pattern.					 
	GraphicsImageImportSetSequenceEnabled( movieImporter, true );
	canceled = true;
	
	// configure the import component by showing the user dialog box
	err = MovieImportDoUserDialog( movieImporter,	// component instance
								   &theFSSpec,		// source file; NULL for handle
								   NULL,			// data; NULL for file
								   &canceled );		// boolean set to true if user canceled
	if( canceled ) return;
	
	// create the new movie
	movie = NewMovie(newMovieActive);
	
	// do the import of the sequence
	err = MovieImportFile( movieImporter,	// movie importer component instance
						   &theFSSpec,		// data file
						   movie,			// the movie to recieve the data
						   NULL,			// specific target track
						   &usedTrack,		// pointer to track that received the imported data
						   0,				// time to place imported data 
						   &addedDuration,	// the duration of the data added to the movie
						   0,				// in flags
						   &outFlags );		// out flags
	CloseComponent( movieImporter );

	// play the reference movie.
	SetMovieGWorld(movie, GetWindowPort(window), NULL);
	GoToBeginningOfMovie( movie );
	StartMovie( movie );
	while( false == IsMovieDone( movie ) ) {
		MoviesTask( NULL, 0 );
	}
	StopMovie( movie );
	
	// save the reference movie.
	err = PutFile( "\pSave as reference movie:", "\preference movie.mov", &theFSSpec, &isSelected, &isReplacing);
	if (err) return;

	// create a movie file; has options controled by flags
	err = CreateMovieFile( &theFSSpec,						// file specifier
						   FOUR_CHAR_CODE('TVOD'),			// creator
						   smSystemScript,					// script
						   createMovieFileDeleteCurFile 	// flags
						 | createMovieFileDontOpenFile
						 | createMovieFileDontCreateResFile
						 | createMovieFileDontCreateMovie,
						   0,								// resRefNum; 0 to not open file 
						   0 );								// newMovie; 0 not to create movie
	// open the movie
	err = OpenMovieFile( &theFSSpec, &refNum, fsRdWrPerm );
	resID = movieInDataForkResID;
	
	// add the movie resource to the file
	err = AddMovieResource( movie, refNum, &resID, NULL );
	err = CloseMovieFile( refNum );
	
	UpdateMovie( movie );
	MoviesTask( NULL, 0 );
	DisposeMovie( movie );
}
