
// ---------------------------------------------------------------------
//
// PlayMain.c - Movie Player - QuickTime for Windows
//
//              Version 1.0
//
//              (c) 1988-1992 Apple Computer, Inc. All Rights Reserved.
//
// ---------------------------------------------------------------------


// Includes
// --------
#include <Windows.h> // Required by Windows

#include <qtw.h>   // Interface to QuickTime
#include <qtole.h> // Interface to qtole dll's

#include "common.h" // Interface to common.c routines

#include "player.h"  // Interface to other *.c files
#include "player.hr" // Defines used in *.rc files


// Message-Persistent Data
// -----------------------
static struct // Hungarian notation: g
  {HINSTANCE      hInstance;          // Instance handle
   HINSTANCE      hResources;         // Resource-only DLL handle
   HWND           hwndFrame;          // Frame window handle
   HWND           hwndClient;         // MDI client window
   HMENU          hMenu;              // Frame window menu
   HACCEL         hAccel;             // Frame window accelerators
   HWND           hActiveModelessDlg; // Handle of active modeless dlg if any
   QTOLE_OLEDATA  qtoleOleData;       // OLE data struct

  } g;


// Internal Function Declarations
// ------------------------------
static LPSTR NEAR PlayerParseCmdLine    (LPSTR);
static  BOOL NEAR PlayerInitAppl        (VOID);
static  HWND NEAR PlayerInitInst        (HINSTANCE, LPSTR, int);
static  LONG NEAR PlayerTerminateInst   (VOID);
static  BOOL NEAR DoQuickTimeInit       (HINSTANCE, LPSTR, LPINT);
static  VOID NEAR KillQuickTime         (VOID);


// Function: WinMain - Required Windows "Main" Routine
// --------------------------------------------------------------------
// Parameters: As required by Microsoft Windows
//
// Returns:    As required by Microsoft Windows
// --------------------------------------------------------------------
int PASCAL WinMain (HINSTANCE hInstance,
                 HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

// Define function data

{
    MSG  msg; // Message

    g.hInstance = hInstance; // Initialize global data

    // Load resource-only DLL
    if( !(g.hResources = CommonGetLocalizedResources
        ( PLAYER_ROOT_NAME, hInstance, PLAYER_STRING_NOMEMORY )))
        return 0;

    // Perform one-time initialization
    if ( !hPrevInstance && !PlayerInitAppl() )
        return 0;

    // Perform initializations that apply to a specific instance and create
    // create window
    if ( !PlayerInitInst( hPrevInstance, lpCmdLine, nCmdShow ))
        return 0;

    // Main message loop
    while (GetMessage (&msg, NULL, NULL, NULL)) {
        if( !g.hActiveModelessDlg ||
            !IsDialogMessage( g.hActiveModelessDlg, &msg )) {
            if( !g.hwndClient ||
                !TranslateMDISysAccel( g.hwndClient, &msg )) {
                if( !g.hwndFrame ||
                    !TranslateAccelerator( g.hwndFrame, g.hAccel, &msg )) {
                    TranslateMessage (&msg);
                    DispatchMessage  (&msg);
                }
            }
        }
    }

    // Cleanup movie player

    PlayerTerminateInst();

    return msg.wParam;
}


// Function: PlayerInitAppl - Perform One-time Initialization
// --------------------------------------------------------------------
// Parameters: None
//
// Returns:    TRUE if OK, else FALSE
// --------------------------------------------------------------------
static BOOL NEAR PlayerInitAppl ( VOID )

{
    WNDCLASS wc; // Window class information

    // Register the frame (main) window class

    wc.style         = 0;
    wc.lpfnWndProc   = PlayerFrameWndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = g.hInstance;
    wc.hIcon         = LoadIcon( g.hResources,
        MAKEINTRESOURCE( PLAYER_PLAYER_ICON ));
    wc.hCursor       = LoadCursor( NULL, IDC_ARROW );
    wc.hbrBackground = (HBRUSH) ( COLOR_APPWORKSPACE + 1 );
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = PLAYER_FRAME_CLASS;

    if( !RegisterClass( &wc ))
        return FALSE;

    // Register the movie window class

    wc.style         = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
    wc.lpfnWndProc   = PlayerMovieWndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = sizeof( VOID NEAR * );
    wc.hInstance     = g.hInstance;
    wc.hIcon         = NULL;
    wc.hCursor       = NULL; // Set to NULL so we can set cursor in the wndproc
    wc.hbrBackground = (HBRUSH) NULL;
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = PLAYER_MOVIE_CLASS;

    return RegisterClass( &wc );
}


// Function: PlayerInitInst - Perform Instance Initialization
// --------------------------------------------------------------------
// Parameters: HINSTANCE hPrevInstance;  Previous instance
//             LPSTR     lpCmdLine;      -->Command line arguments
//             int       nCmdShow;       Parameter for first ShowWindow()
//
// Returns:    HWND      hwndFrame;      Frame window handle
//                                       or NULL if initialization failed
// --------------------------------------------------------------------
static HWND NEAR PlayerInitInst
              ( HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )

{
    // Do QuickTime Initializations.
    if( !DoQuickTimeInit( hPrevInstance, lpCmdLine, &nCmdShow ) )
        return NULL;

    // get menu and accelerators from localized resource
    g.hAccel = LoadAccelerators ( g.hResources,
        MAKEINTRESOURCE( PLAYER_ACCELERATORS ));
    g.hMenu  = LoadMenu( g.hResources,
        MAKEINTRESOURCE( PLAYER_FRAME_MENU ));
    if( !g.hAccel || !g.hMenu ) {
        CommonTellUser( g.hResources, PLAYER_STRING_NOACCELORMENU,
            PLAYER_STRING_CAPTION, MB_OK );
        return NULL;
    }

    // Create a main window for this application instance.
    if ( !(g.hwndFrame = CreateWindow( PLAYER_FRAME_CLASS, "",
        WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, g.hMenu, g.hInstance, NULL ))) {
        CommonTellUser( g.hResources, PLAYER_STRING_NOWINDOW,
            PLAYER_STRING_CAPTION, MB_OK );
        return NULL;
    }

    // Tell qtole.dll the server hwnd
    QTOLE_SetApplicationHwnd( &g.qtoleOleData, g.hwndFrame ); 

    // get MDI client window created during WM_CREATE message processing
    g.hwndClient = PlayerQueryClientWindow(); // this is in FrameWnd.c

    // Display the frame window
    // If ole started the app, the window will be initially hidden
    ShowWindow  ( g.hwndFrame, nCmdShow );
    if( nCmdShow != SW_HIDE )
        UpdateWindow( g.hwndFrame );

    // Check command line for movie file.
    // Note: this must come after ShowWindow, UpdateWindow
    if( lpCmdLine = PlayerParseCmdLine( lpCmdLine ))
        SendMessage( g.hwndFrame, WM_PLAYER_CMDLINE,
        0, (LPARAM) lpCmdLine );

    return g.hwndFrame;
}

// Function: PlayerParseCmdLine - Parse the command line. Return -> to
//                                first argument and ignore any extras.
//                                The default extension is appended if
//                                name has no extension
// --------------------------------------------------------------------
// Parameters: LPSTR      lpCmdLine     command line pointer
//
// Returns:    LPSTR      lpCmdLine     command line pointer to first
//                                      argument, else NULL
// --------------------------------------------------------------------
static LPSTR NEAR PlayerParseCmdLine( LPSTR lpCmdLine )

{
    LPSTR  lpTemp;                        // Temp pointer
    char   szExtension[FILE_EXT_LEN + 1]; // Default file extension
    BOOL   bExtension;                    // Extension flag

    // Command line is already in Ansi char set even if entered from DOS
    // command line

    // remove any leading blanks
    while( *lpCmdLine == ' ' )
        lpCmdLine = AnsiNext( lpCmdLine );

    if( *lpCmdLine == '\0' )
        return NULL;

    // look for blank or end of string
    bExtension = FALSE;
    lpTemp = lpCmdLine;
    while( *lpTemp && (*lpTemp != ' ' )) {
        if( *lpTemp == '.' )
            bExtension = TRUE;
        lpTemp = AnsiNext( lpTemp );
    }
    *lpTemp = '\0';

    if( !bExtension ) {
        LoadString( g.hResources,
            PLAYER_STRING_FILEEXT, szExtension, sizeof( szExtension ));
        lstrcat( lpCmdLine, szExtension );
    }

    return lpCmdLine;
}


// Function: PlayerTerminateInst - Terminate Instance
// --------------------------------------------------------------------
// Parameters: VOID
//
// Returns:    Always 0L
// --------------------------------------------------------------------
static LONG NEAR PlayerTerminateInst( VOID )

{
    // Clean up OLE
    if( g.qtoleOleData.lpqtoleServer )
        QTOLE_OLECleanUp( &g.qtoleOleData );

    // Cut the connections to QuickTime.
    KillQuickTime();

    // Free the resource-only DLL
    if ( g.hResources && ( g.hInstance != g.hResources ))
        FreeLibrary( g.hResources );

    return 0L;
}


// The next two functions are used to initialize and kill QuickTime

// Function: DoQuickTimeInit - Establishes connections to QuickTime
// --------------------------------------------------------------------
// Parameters: HINSTANCE  hPrevInstance  Previous instance
//             LPSTR      lpCmdLine      -> command line
//             LPINT      lpnCmdShow     Parameter for first ShowWindow()
//
// Returns:    BOOL       TRUE if OK, else FALSE
// --------------------------------------------------------------------
static BOOL NEAR DoQuickTimeInit
            ( HINSTANCE hPrevInstance, LPSTR lpCmdLine, LPINT lpnCmdShow )

{
    OSErr       oserr;       // Temp return value
    WORD        wIDString;   // ID of error message string
    int         cQueue = 64; // Best queue size
    QTOLE_INIT  qtoleInit;
    QTOLE_ERR   qtole_err;
    char        szCaption[30];


    LoadString( g.hResources, PLAYER_STRING_CAPTION,
        szCaption, sizeof( szCaption ));

    // Do OLE initialization before QTInitialize so we
    // don't have to kill qt for install only
    if( !( qtoleInit.fpServerCallBack = (QTOLEPROC) MakeProcInstance( 
        (FARPROC) QTOLEServerCallBack, g.hInstance ))) {
        CommonTellUser( g.hResources, PLAYER_STRING_NOMEMORY,
            PLAYER_STRING_CAPTION, MB_OK );
        return FALSE;
    }
    else {
        qtoleInit.lStructSize           = sizeof( qtoleInit );
        qtoleInit.lVersion              = VERSION_1;
        qtoleInit.hInstance             = g.hInstance;
        qtoleInit.hResources            = g.hResources;
        qtoleInit.lpCmdLine             = lpCmdLine;
        qtoleInit.lpClassName           = PLAYER_FRAME_CLASS;
        qtoleInit.lpServerCaption       = szCaption;
        qtoleInit.lpnCmdShow            = lpnCmdShow;
        qtoleInit.wIDFirstString        = OLE_STRING_FIRST;
        qtoleInit.wIDFirstDlg           = OLE_DLG_FIRST;
        qtoleInit.bMultipleObjectServer = TRUE;

        g.qtoleOleData.lStructSize      = sizeof( g.qtoleOleData );
        g.qtoleOleData.lVersion         = VERSION_1;
        g.qtoleOleData.wObjectType      = MOVIE_OBJECT;

        if( QTOLE_OK != 
            ( qtole_err = QTOLE_Initialize( &g.qtoleOleData, &qtoleInit ))) {
            if( QTOLE_INSTALL_ONLY != qtole_err )
                CommonTellUser( g.hResources, 
                PLAYER_STRING_OLEINITFAILED,
                PLAYER_STRING_CAPTION, MB_OK );
            return FALSE;
        }
    }


    // Enlarge message queue to prevent occasional lose of posted messages
    while( SetMessageQueue( cQueue-- ) == 0 );

    if( ( oserr = QTInitialize( NULL )) != QTI_OK ) {
        switch( oserr ) {
            case QTI_FAIL_NOEXIST:
                wIDString = PLAYER_STRING_QTWNOEXIST;
                break;

            case QTI_FAIL_CORRUPTDLL:
                wIDString = PLAYER_STRING_QTWBADDLL;
                break;

            case QTI_FAIL_286:
                wIDString = PLAYER_STRING_QTW286;
                break;

            case QTI_FAIL_WIN30:
                wIDString = PLAYER_STRING_QTWWIN30;
                break;

            default:
                wIDString = PLAYER_STRING_QTWFAILED;
                break;
        }

        CommonTellUser( g.hResources, wIDString,
            PLAYER_STRING_CAPTION, MB_OK );
        return FALSE;
    }

    if( EnterMovies() ) {
        CommonTellUser( g.hResources, PLAYER_STRING_ENTMOVFAILED,
            PLAYER_STRING_CAPTION, MB_OK );
        return FALSE;
    }

    return TRUE;
}

// Function: KillQuickTime - Cuts the connections to QuickTime
// --------------------------------------------------------------------
// Parameters: VOID
//
// Returns:    VOID
// --------------------------------------------------------------------
static VOID NEAR KillQuickTime( VOID )

{
    ExitMovies();
    QTTerminate();

    return;
}


//  This function is called by other modules whenever a modeless dialog
//  is activated or deactivated

// Function: PlayerSetActiveModeless - Set handle of active modeless dlg
// --------------------------------------------------------------------
// Parameters: WPARAM   wParam          WA_ flag defined in Windows.h
//             HWND     hModelessDlg    Handle of dlg being activated or
//                                      deactivated
//
// Returns:    VOID
// --------------------------------------------------------------------
VOID FAR PlayerSetActiveModeless( WPARAM wParam, HWND hModelessDlg )

{
    if( wParam != WA_INACTIVE )
        g.hActiveModelessDlg = hModelessDlg;
    else if( g.hActiveModelessDlg == hModelessDlg )
        g.hActiveModelessDlg = NULL;

    return;
}

// Function: PlayerNoMoreWindow - Sets global handles to NULL. Called during
//                                frame window WM_DESTROY message processing
// --------------------------------------------------------------------
// Parameters: VOID
//
// Returns:    VOID
// --------------------------------------------------------------------
VOID FAR PlayerNoMoreWindow( VOID )

{
    g.hwndFrame  = NULL;
    g.hwndClient = NULL;

    return;
}

///  The remaining functions are the query functions called by other modules

// Function: PlayerQueryInstance - Query Instance Handle
// --------------------------------------------------------------------
// Parameters: None.
//
// Returns:    HINSTANCE hInstance;    Application instance handle
// --------------------------------------------------------------------
HINSTANCE FAR PlayerQueryInstance( VOID )

{
    return g.hInstance;
}

// Function: PlayerQueryResources - Query Resource-Only DLL Handle
// --------------------------------------------------------------------
// Parameters: None.
//
// Returns:    HINSTANCE hResources    Resource-only DLL handle
// --------------------------------------------------------------------
HINSTANCE FAR PlayerQueryResources( VOID )

{
    return g.hResources;
}

// Function: PlayerQueryFrameWindow - Query Frame Window Handle
// --------------------------------------------------------------------
// Parameters: None.
//
// Returns:    HWND hwndFrame;          Frame window handle
// --------------------------------------------------------------------
HWND FAR PlayerQueryFrameWindow( VOID )

{
    return g.hwndFrame;
}

// Function: PlayerQueryOleData - Query -> to Ole Data struct
// --------------------------------------------------------------------
// Parameters: None.
//
// Returns:    LPQTOLE_OLEDATA        -> ole data struct
// --------------------------------------------------------------------
LPQTOLE_OLEDATA FAR PlayerQueryOleData( VOID )

{
    return &g.qtoleOleData;
}


