 /*
	File:		QTime.c

	Written by: Keith Gurganus

  	Copyright:	© 1997 by Apple Computer, Inc., all rights reserved.
*/

#include "QTML.h"
#include "Movies.h"
#include "stdwin.h"
#include "QTime.h"
#include "TextUtils.h"

#define USEEXPLORERSTYLE (LOBYTE(LOWORD(GetVersion()))>=4)

static UINT APIENTRY GenericHook(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void CreateNewMovieController(HWND hwnd, Movie theMovie, MovieController *theMC);
Boolean MCFilter(MovieController mc, short action, void*params, long refCon);
void GetMaxBounds(Rect *maxRect);

BOOL GetFile(char *fileName)
{
    OPENFILENAME    ofn;

    memset(&ofn, 0, sizeof(OPENFILENAME));
	*fileName = '\0';
    ofn.lStructSize = sizeof(OPENFILENAME);
    ofn.hwndOwner = GetActiveWindow();
    ofn.lpstrFile = (LPSTR)fileName;
    ofn.nMaxFile  = 255;
	ofn.lpstrFilter  = "QuickTime Movies (*.mov;*.avi) \0 *.mov;*.avi\0All Files (*.*) \0 *.*\0";	// Robert requested *.* to be added 07/10/96 BSF
    ofn.nFilterIndex = 1;
    ofn.lpstrInitialDir = NULL;
	if(USEEXPLORERSTYLE)
		ofn.Flags |= OFN_ENABLEHOOK | OFN_EXPLORER;
	else
		ofn.Flags |= OFN_ENABLEHOOK;
	ofn.lpfnHook = GenericHook;

    if (GetOpenFileName(&ofn))
    {
        return TRUE;
	} else
        return FALSE;
}


static UINT APIENTRY GenericHook(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
		case WM_INITDIALOG:		// Center window
		{
			Point	ptTopLeft;
			RECT	rcWindow;
			BOOL	retValue;
			HWND	theWnd = hWnd;
			RECT	rcDesktopWindow;
			long	width;
			long	height;

			// if we are using 95 or NT 4.0 use the new explorer style
			if(USEEXPLORERSTYLE)
				theWnd = GetParent(hWnd);

			GetWindowRect(theWnd, &rcWindow);

			width = rcWindow.right - rcWindow.left;
			height = rcWindow.bottom - rcWindow.top;
			GetWindowRect(GetDesktopWindow(), &rcDesktopWindow);
			ptTopLeft.h = (short)((rcDesktopWindow.right + rcDesktopWindow.left)/2 - width/2);
			ptTopLeft.v = (short)((rcDesktopWindow.top + rcDesktopWindow.bottom)/3 - height/3);
		
			retValue = SetWindowPos(theWnd, 0, ptTopLeft.h, ptTopLeft.v, 0, 0, SWP_NOZORDER|SWP_NOSIZE);
	
			return true;
		}
	}
	return 0;
}

BOOL OpenMovie(HWND hwnd, MovieStuff *movieStuff)
{
	BOOL	isMovieGood = FALSE;

	if ( strlen ((char*)movieStuff->filename ) != 0)
	{
		OSErr				err;
		short				theFile = 0;
		long				controllerFlags = 0L;
		FSSpec				sfFile;
		short				movieResFile;
		char				theFullPath[255];

		// make a copy of our full path name
		strcpy ( (char *)theFullPath, (const char *) movieStuff->filename );

		// convert theFullPath to pstring
		c2pstr((char*)theFullPath);

		// Make a FSSpec with a pascal string filename
		FSMakeFSSpec(0,0L,theFullPath, &sfFile);
		
		// Set the port	
		SetGWorld((CGrafPtr)GetNativeWindowPort((void *)hwnd), nil);

		// Open the movie file
		err = OpenMovieFile(&sfFile, &movieResFile, fsRdPerm);
		if (err == noErr)
		{
			// Get the Movie from the file
			err = NewMovieFromFile(&movieStuff->theMovie,movieResFile, 
									nil, 
									nil, 
									newMovieActive, /* flags */
									nil);
		
			// Close the movie file
			CloseMovieFile(movieResFile);

			if (err == noErr)
			{
				// Create the movie controller
			   	CreateNewMovieController(hwnd, movieStuff->theMovie, &movieStuff->theMC);
				movieStuff->movieOpened = TRUE;
				isMovieGood = TRUE;	
				p2cstr((char*)theFullPath);

				SetWindowTitle(movieStuff->theHwnd, theFullPath);
			} else
				theFullPath[0] = '\0'; 
				
		} else
			theFullPath[0] = '\0';
	}

	return isMovieGood;
}

OSErr SaveMovie(MovieStuff *movieStuff)
{
	OSErr			theErr = noErr;
	if (strlen(movieStuff->filename) != 0) {
		long			movieFlattenFlags = flattenAddMovieToDataFork;
		FSSpec			sfFile;
		OSType			creator = FOUR_CHAR_CODE('TVOD');
		long			createMovieFlags = createMovieFileDeleteCurFile;
		char			theFullPath[255];

		strcpy(theFullPath, movieStuff->filename);

		// Convert full path name to pstring
		c2pstr((char *)theFullPath);	

		// Make a FSSpec with a pascal string filename
		FSMakeFSSpec(0,0L,theFullPath, &sfFile);

		// Try to delete the original
		DeleteMovieFile(&sfFile);		

		// FlattenMovie
		FlattenMovie(	movieStuff->theMovie,
						movieFlattenFlags,
						&sfFile,
						creator,
						-1,
						createMovieFlags,
						nil,
						NULL );
	
		theErr = GetMoviesError();
	}
	return theErr;
}

OSErr SaveAsMovie(MovieStuff *movieStuff)
{
	unsigned char	lpszPathName[256];
	OPENFILENAME	ofn;
	OSErr			theErr = noErr;

    memset(&ofn, 0, sizeof(OPENFILENAME));
	lpszPathName[0] = '\0';

    ofn.lStructSize = sizeof(OPENFILENAME);
    ofn.hwndOwner = GetActiveWindow();
    ofn.lpstrFilter = "QuickTime Movies (*.mov) \0 *.mov\0";
    ofn.lpstrFile = (char *)lpszPathName;
    ofn.nMaxFile = sizeof(lpszPathName);
    ofn.lpstrFileTitle = NULL;
    ofn.nMaxFileTitle = (unsigned long)NULL;
    ofn.lpstrInitialDir = NULL;
    ofn.Flags = OFN_OVERWRITEPROMPT;

	// Put up a save file dialog
    if (GetSaveFileName(&ofn)) {
		long			movieFlattenFlags = flattenAddMovieToDataFork;
		FSSpec			sfFile;
		OSType			creator = FOUR_CHAR_CODE('TVOD');
		long			createMovieFlags = createMovieFileDeleteCurFile;

		// Convert full path name to pstring
		c2pstr((char *)lpszPathName);	

		// Make a FSSpec with a pascal string filename
		FSMakeFSSpec(0,0L,lpszPathName, &sfFile);

		// Try to delete the original
		DeleteMovieFile(&sfFile);		

		// FlattenMovie
		FlattenMovie(	movieStuff->theMovie,
						movieFlattenFlags,
						&sfFile,
						creator,
						-1,
						createMovieFlags,
						nil,
						NULL );

		theErr = GetMoviesError();
		p2cstr((char *)lpszPathName);
		SetWindowTitle(movieStuff->theHwnd, lpszPathName);
	}
	return theErr;
}

void CloseMovie(MovieStuff *movieStuff)
{
	if (movieStuff->movieOpened == TRUE ){
		movieStuff->movieOpened = FALSE;
 	
		if (movieStuff->theMC)
			DisposeMovieController(movieStuff->theMC);

		if (movieStuff->theMovie)
			DisposeMovie(movieStuff->theMovie);

		movieStuff->theMovie = NULL;
		movieStuff->theMC = NULL;
	}
}


void CreateNewMovieController(HWND hwnd, Movie theMovie, MovieController *theMC)
{
	Rect	bounds;
	Rect	maxBounds;
	long 	controllerFlags;
	Rect	theMovieRect;

	// 0,0 Movie coordinates
	GetMovieBox(theMovie, &theMovieRect);
	MacOffsetRect(&theMovieRect, -theMovieRect.left, -theMovieRect.top);

	// Attach a movie controller
	*theMC = NewMovieController(theMovie, &theMovieRect, mcTopLeftMovie );

	// Get the controller rect 
	MCGetControllerBoundsRect(*theMC, &bounds);

	// Enable editing
	MCEnableEditing(*theMC,TRUE);

	// Tell the controller to attach a movie's CLUT to the window as appropriate.
	MCDoAction(*theMC, mcActionGetFlags, &controllerFlags);
	MCDoAction(*theMC, mcActionSetFlags, (void *)(controllerFlags | mcFlagsUseWindowPalette));

	// Allow the controller to accept keyboard events
	MCDoAction(*theMC, mcActionSetKeysEnabled, (void *)TRUE);

	// Set the controller action filter
	MCSetActionFilterWithRefCon(*theMC, MCFilter, (long)hwnd);

	// Set the grow box amount
	GetMaxBounds(&maxBounds);
	MCDoAction(*theMC, mcActionSetGrowBoxBounds, &maxBounds);

	// Size our window
	SizeWindow((WindowPtr)GetNativeWindowPort(hwnd), bounds.right, bounds.bottom, FALSE);
}


Boolean MCFilter(MovieController mc, short action, void*params, long refCon)
{
	if(action == mcActionControllerSizeChanged) {
		Rect		bounds;
		WindowPtr	w;
		MCGetControllerBoundsRect(mc, &bounds);

		w = GetNativeWindowPort((HWND)refCon);
		SizeWindow((WindowPtr)w, bounds.right, bounds.bottom, TRUE);
	}
	return FALSE;
}

void GetMaxBounds(Rect *maxRect)
{
	RECT deskRect;

	GetWindowRect(GetDesktopWindow(), &deskRect);

	OffsetRect(&deskRect, -deskRect.left, -deskRect.top);

	maxRect->top = (short)deskRect.top;
	maxRect->bottom = (short)deskRect.bottom;
	maxRect->left = (short)deskRect.left;
	maxRect->right = (short)deskRect.right;
}

ComponentResult EditCut(MovieController mc) 
{
	Movie				scrapMovie;
	ComponentResult		theErr = invalidMovie;
	
	if (mc){
		scrapMovie = MCCut(mc);
		if ( scrapMovie ) {
			theErr = PutMovieOnScrap(scrapMovie, 0L);
			DisposeMovie(scrapMovie);
		} 
	}
	return theErr;
}

ComponentResult EditCopy(MovieController mc) 
{
	Movie				scrapMovie;
	ComponentResult		theErr = invalidMovie;
	
	if (mc){
		scrapMovie = MCCopy(mc);
		if ( scrapMovie ) {
			theErr = PutMovieOnScrap(scrapMovie, 0L);
			DisposeMovie(scrapMovie);
		}
	}
	return theErr;
}

ComponentResult EditPaste(MovieController mc) 
{
	ComponentResult		theErr = invalidMovie;

	if (mc)
		theErr = MCPaste(mc, nil);

	return theErr;
}

ComponentResult EditClear(MovieController mc) 
{
	ComponentResult		theErr = invalidMovie;
	
	if (mc)
		theErr = MCClear(mc);

	return theErr;
}

ComponentResult EditUndo(MovieController mc) 
{
	ComponentResult		theErr = invalidMovie;

	if (mc)
		theErr = MCUndo(mc);
	
	return theErr;
}

ComponentResult EditSelectAll(Movie movie, MovieController mc) 
{
	TimeRecord 			tr;
	ComponentResult		theErr = noErr;
	
	if ( movie && mc ) {
		tr.value.hi = 0;
		tr.value.lo = 0;
		tr.base = 0;
		tr.scale = GetMovieTimeScale(movie);
		MCDoAction(mc, mcActionSetSelectionBegin, &tr);
		tr.value.lo = GetMovieDuration(movie);
		MCDoAction(mc, mcActionSetSelectionDuration, &tr);
	} else {
		if ( movie == NULL )
			theErr = invalidMovie;
		else
			theErr = -1;
	}
	return theErr;
}

void SetWindowTitle(HWND hWnd, unsigned char *theFullPath) 
{
	/* set window title to name */
	unsigned char	titleName[256];
	titleName[0] = '\0';

	GetFileNameFromFullPath(theFullPath, (unsigned char *)&titleName);
	SetWindowText(hWnd, (const char *)titleName);
}

void GetFileNameFromFullPath(unsigned char *theFullPath, unsigned char *fileName) 
{
	/* pluck the filename from the fullpath, */
	int		i = 0, j = -1, stringLen = 0;

	stringLen = strlen((char *)theFullPath);
	if (stringLen > 0 ) {
		while(i<stringLen){
			if (theFullPath[i] == 0x5c || theFullPath[i] == '/' )
				j = i;
			i++;
		}
		if ( j>-1)
			strcpy((char *)fileName, (char *)&theFullPath[j+1]);
		else
			strcpy((char *)fileName, (char *)theFullPath);

	}
}
