MFCQTClasses/CQuickTime.cpp

/*
    File:       CQuickTime.c
 
    Written by: Keith Gurganus
 
    Note: Set project settings to "Not using precompiled headers" for this file.
*/
 
#include "QTML.h"
#include "CQuickTime.h"
 
CQuickTime::CQuickTime()
{
    movieOpened = FALSE;
    theMovie = NULL;
    theMC = NULL;
    theHwnd = NULL;
    theViewHwnd = NULL;
    theAppName[0] = '\0';
    theFullPath[0] = '\0';
}
 
CQuickTime::~CQuickTime()
{
}
 
void CQuickTime::NewMovieFile(void){
    // Close any previously opened movie
    CloseMovie();
 
    // Set the port 
    SetGWorld((CGrafPtr)GetHWNDPort(theViewHwnd), nil);
 
    // Create a newMovie
    theMovie = NewMovie(newMovieActive);
 
    if ( theMovie != NULL ) {
        // set window title to name 
        strcpy((char*)theFullPath,"Untitled");
        SetWindowTitle();
 
        // Create the movie controller
        CreateNewMovieController(theMovie);
        
        movieOpened = TRUE;
    }   
}
 
 
BOOL CQuickTime::OpenMovie(unsigned char *fullPath)
{
    BOOL    isMovieGood = FALSE;
 
    if ( strlen ((char*)fullPath ) != 0)
    {
        OSErr               err;
        short               theFile = 0;
        long                controllerFlags = 0L;
        FSSpec              sfFile;
        short               movieResFile;
 
        // Close any previously opened movie
        CloseMovie();
    
        // make a copy of our full path name
        strcpy ( (char *)theFullPath, (const char *) fullPath );
 
        // convert theFullPath to pstring
        CToPstr((char*)theFullPath);
 
        // Make a FSSpec with a pascal string filename
        FSMakeFSSpec(0,0L,theFullPath, &sfFile);
        
        // Set the port 
        SetGWorld((CGrafPtr)GetHWNDPort(theViewHwnd), nil);
 
        // Open the movie file
        err = OpenMovieFile(&sfFile, &movieResFile, fsRdPerm);
        if (err == noErr)
        {
            // Get the Movie from the file
            err = NewMovieFromFile(&theMovie,movieResFile, 
                                    nil, 
                                    nil, 
                                    newMovieActive, /* flags */
                                    nil);
        
            // Close the movie file
            CloseMovieFile(movieResFile);
 
            if (err == noErr)
            {
                // Create the movie controller
                CreateNewMovieController(theMovie);
                isMovieGood = movieOpened = TRUE;   
                PToCstr((char*)theFullPath);
            } else
                theFullPath[0] = '\0'; 
                
        } else
            theFullPath[0] = '\0';
        
        SetWindowTitle();
    }
    return isMovieGood;
}
 
void CQuickTime::CloseMovie(void)
{
    if (movieOpened == TRUE ){
        movieOpened = FALSE;
    
        if (theMC)
            DisposeMovieController(theMC);
 
        if (theMovie)
            DisposeMovie(theMovie);
 
        theMovie = NULL;
        theMC = NULL;
    }
 
    Rect initialRect;
    initialRect.top = initialRect.left = initialRect.bottom = 0;
    initialRect.right = MINWINDOWWIDTH;
    
    //SizeWindow((WindowPtr)GetHWNDPort(theHwnd), initialRect.right, initialRect.bottom, FALSE);
    SizeWindow((WindowPtr)GetHWNDPort(theViewHwnd), initialRect.right, initialRect.bottom, FALSE);
 
    /* set window title to empty name */
    theFullPath[0] ='\0';
    SetWindowTitle ();
}
 
 
void CQuickTime::SaveAsMovie(void){
    unsigned char   lpszPathName[256];
    OPENFILENAME    ofn;
 
    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
        CToPstr((char *)lpszPathName);  
 
        // Make a FSSpec with a pascal string filename
        FSMakeFSSpec(0,0L,lpszPathName, &sfFile);
 
        // FlattenMovie
        FlattenMovie(   theMovie,
                        movieFlattenFlags,
                        &sfFile,
                        creator,
                        -1,
                        createMovieFlags,
                        nil,
                        NULL );
    
    }
}
 
void CQuickTime::OnEditCut() 
{
    Movie               scrapMovie;
    ComponentResult     theErr = noErr;
    
    if (theMC){
        scrapMovie = MCCut(theMC);
        if ( scrapMovie ) {
            theErr = PutMovieOnScrap(scrapMovie, 0L);
            DisposeMovie(scrapMovie);
        } 
    }
}
 
void CQuickTime::OnEditCopy() 
{
    Movie               scrapMovie;
    ComponentResult     theErr = noErr;
    
    if (theMC){
        scrapMovie = MCCopy(theMC);
        if ( scrapMovie ) {
            theErr = PutMovieOnScrap(scrapMovie, 0L);
            DisposeMovie(scrapMovie);
        }
    }
}
 
void CQuickTime::OnEditPaste() 
{
    if (theMC)
        MCPaste(theMC, nil);
}
 
void CQuickTime::OnEditClear() 
{
    if (theMC)
        MCClear(theMC);
}
 
void CQuickTime::OnEditUndo() 
{
    if (theMC)
        MCUndo(theMC);
}
 
 
void CQuickTime::OnEditSelectall() 
{
    TimeRecord          tr;
    ComponentResult     theErr = noErr;
    
    if ( theMovie && theMC ) {
        tr.value.hi = 0;
        tr.value.lo = 0;
        tr.base = 0;
        tr.scale = GetMovieTimeScale(theMovie);
        MCDoAction(theMC, mcActionSetSelectionBegin, &tr);
        tr.value.lo = GetMovieDuration(theMovie);
        MCDoAction(theMC, mcActionSetSelectionDuration, &tr);
    } else {
        if ( theMovie == NULL )
            theErr = invalidMovie;
        else
            theErr = -1;
    }   
    
}
 
void CQuickTime::ProcessMovieEvent(HWND hWnd, unsigned int message, unsigned int wParam, long lParam) 
{   
    // Convert the Windows event to a QTML event
    MSG             theMsg;
    EventRecord     macEvent;
    LONG            thePoints = GetMessagePos();
 
    theMsg.hwnd = hWnd;
    theMsg.message = message;
    theMsg.wParam = wParam;
    theMsg.lParam = lParam;
    theMsg.time = GetMessageTime();
    theMsg.pt.x = LOWORD(thePoints);
    theMsg.pt.y = HIWORD(thePoints);
 
    // tranlate a windows event to a mac event
    WinEventToMacEvent(&theMsg, &macEvent);
 
    // Pump messages as mac event
    MCIsPlayerEvent(theMC,(const EventRecord *)&macEvent);
}
 
int CQuickTime::OnMovieWindowCreate(HWND hWnd, CREATESTRUCT *lpCreateStruct) 
{
 
    if ( hWnd != NULL) { 
        theViewHwnd = hWnd;                 // the view's hwnd
        theHwnd = ::GetParent(theViewHwnd); // the parent hwnd   hwndParent
 
        int borderWidth = GetWindowsBorderWidth();
        int titlebarHeight = GetWindowsTitleHeight();
        int captionHeight = GetWindowsCaptionHeight();  
 
        lpCreateStruct->cy = borderWidth + titlebarHeight + captionHeight;
        lpCreateStruct->cx = MINWINDOWWIDTH;
 
        SetWindowTitle();
        Rect initialRect;
        initialRect.top = initialRect.left = initialRect.bottom = 0;
        initialRect.right = MINWINDOWWIDTH;
 
        // Create GrafPort <-> HWND association
        CreatePortAssociation(theViewHwnd, NULL, 0);    
    }
 
    return 0;
}
 
void CQuickTime::CreateNewMovieController(Movie theMovie)
{
    Rect    bounds;
    Rect    maxBounds;
    long    controllerFlags;
 
    // 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)theViewHwnd);
 
    // Set the grow box amound
    GetMaxBounds(&maxBounds);
    MCDoAction(theMC, mcActionSetGrowBoxBounds, &maxBounds);
 
    // Size our window
    SizeWindow((WindowPtr)GetHWNDPort(theViewHwnd), bounds.right, bounds.bottom, FALSE);
}
 
void CQuickTime::OnMovieWindowDestroy() 
{   
    CGrafPtr    windowPort = NULL;
    
    // close any movies before destroying PortAssocation
    CloseMovie();
 
    // Destroy the view's GrafPort <-> HWND association
    if (theViewHwnd)
        windowPort = (CGrafPtr)GetHWNDPort(theViewHwnd);
    
    if (windowPort)
        DestroyPortAssociation(windowPort);
 
}
 
void CQuickTime::SetWindowTitle(void) 
{
    /* set window title to name */
    unsigned char   fileName[64];
    unsigned char   appName[32];
    unsigned char   titleName[256];
 
    fileName[0] = '\0';
    appName[0] = '\0';
    titleName[0] = '\0';
 
    GetAppName((unsigned char *)&appName);
    if (strlen((char*)appName))
        strcpy ((char *)titleName, (char *)appName);
 
    GetFileNameFromFullPath((unsigned char *)&fileName);
    if (strlen((char*)fileName)){
        if (strlen((char*)appName))
            strcat ((char *)titleName, " - ");
 
        strcat ((char *)titleName, (char *)fileName);
    }
    ::SetWindowText(theHwnd, (const char *)titleName);
}
 
void CQuickTime::GetFileNameFromFullPath(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);
 
    }
}
 
void CQuickTime::GetAppName(unsigned char *appName)
{ 
#if (!WIN32)
    HINSTANCE theModule = (HINSTANCE)GetWindowLong(theHwnd, GWL_HINSTANCE);
    GetModuleFileName(theModule, (char *)appName, strlen((char *)appName) );
#else
    if (strlen((char*)theAppName) > 0)
        strcpy((char*)appName, (char*)theAppName);
#endif
}
 
void CQuickTime::CToPstr(char *theString)
{
    char    tempString[256];
 
    tempString[0] = strlen (theString);
    tempString[1] = '\0';
 
    strcat ( tempString, theString );
    strcpy  ( theString, tempString );
}
 
void CQuickTime::PToCstr(char *theString)
{
    char    tempString[256];
    int     len = theString[0];
 
    memcpy ( tempString, &theString[1], theString[0]);
    tempString[len] = '\0';
    strcpy  ( theString, tempString );
}
 
int CQuickTime::GetWindowsBorderWidth (void)
{
    RECT    windowRect, clientRect;
    int     windowWidth, clientWidth;
    
    ::GetWindowRect(theHwnd, &windowRect);
    ::GetClientRect(theHwnd, &clientRect);
 
    windowWidth = windowRect.right - windowRect.left;
    clientWidth = clientRect.right - clientRect.left;
 
    return windowWidth - clientWidth;
}
 
int CQuickTime::GetWindowsTitleHeight (void)
{
    RECT    windowRect, clientRect;
    int     windowHeight, clientHeight;
    int     windowWidth, clientWidth, bordersWidth;
    int     captionHeight, titlebarHeight;
    
    ::GetWindowRect(theHwnd, &windowRect);
    ::GetClientRect(theHwnd, &clientRect);
 
    windowWidth = windowRect.right - windowRect.left;
    clientWidth = clientRect.right - clientRect.left;
    bordersWidth = windowWidth - clientWidth;
 
    windowHeight = windowRect.bottom - windowRect.top;
    clientHeight = clientRect.bottom - clientRect.top;
    captionHeight = GetSystemMetrics(SM_CYCAPTION); 
    titlebarHeight = (windowHeight - clientHeight) - captionHeight;
 
    return titlebarHeight;
}
 
int CQuickTime::GetWindowsCaptionHeight(void)
{
    DWORD   dwStyle = 0L;
    int     retValue = 0L;
 
    if(!IsWindow(theHwnd))
        return 0L;
 
    dwStyle = GetWindowLong(theHwnd, GWL_STYLE);
 
    if (dwStyle & WS_CAPTION)
        retValue = GetSystemMetrics(SM_CYCAPTION);
 
    return retValue;
}
 
void CQuickTime::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;
}
 
Movie CQuickTime::GetMovie()
{
    return theMovie;
}
 
Boolean MCFilter(MovieController mc, short action, void*params, long refCon)
{
    if(action == mcActionControllerSizeChanged) {
        Rect        bounds;
        WindowPtr   w;
        MCGetControllerBoundsRect(mc, &bounds);
 
        w = GetHWNDPort((HWND)refCon);
        SizeWindow((WindowPtr)w, bounds.right, bounds.bottom, TRUE);
    }
    return FALSE;
}