/* Original: SimplePlayerSDI.c File : qtvoutplayer.c Written by: Keith Gurganus Modified by: Sumit Chawla and Judy Ting SimplePlayerSDI.exe is a SDI application that plays a movie with QuickTime. This is a part of the QuickTime sample source code and is provided as is. Copyright: © 1997 by Apple Computer, Inc., all rights reserved. */ #include #include #include #include #include "QTML.h" #include "Movies.h" #include "stdwin.h" #include "voutplayer.h" #include "resource.h" #include "QTime.h" #define APPNAME "Silicon Graphics QuickTime Video Output Player" // Global Variables: HINSTANCE hInst; // Current instance char szAppName[] = APPNAME; // The name of this application char szTitle[] = APPNAME; // The title bar text MovieStuff gMovieStuff; // Movie Structure WINDOWPOS gOldWindowPos = {nil, nil, 0, 0, 0, 0, 0}; CGrafPtr origPort; // Save old GWorld GDHandle origDevice; GWorldPtr videoOutputGWorld; ComponentInstance videoOutput; // Instance of a video output component BOOL videoOutOpened=false; // Prototypes BOOL InitApplication(HINSTANCE); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); ComponentResult startVideoOutput(); ComponentResult stopVideoOutput(); long getMovieDesc(); long findDisplayMode(QTAtomContainer displayModeList, long cType); /* WinMain */ int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; HANDLE hAccelTable; if (!hPrevInstance) { // Perform instance initialization: if (!InitApplication(hInstance)) { return (FALSE); } } // Initialize QuickTime Media Layer InitializeQTML(0); // Initialize QuickTime EnterMovies(); // Perform application initialization: if (!InitInstance(hInstance, nCmdShow)) { return (FALSE); } hAccelTable = LoadAccelerators (hInstance, MAKEINTRESOURCE(IDR_ACCELSIMPLESDI)); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator (msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } // Deinitialize QuickTime Media Layer ExitMovies(); // Deinitialize QuickTime Media Layer TerminateQTML(); return (msg.wParam); lpCmdLine; // This will prevent 'unused formal parameter' warnings } /* InitApplication */ BOOL InitApplication(HINSTANCE hInstance) { WNDCLASS wc; HWND hwnd; // Win32 will always set hPrevInstance to NULL, so lets check // things a little closer. This is because we only want a single // version of this app to run at a time hwnd = FindWindow (szAppName, NULL); if (hwnd) { // We found another version of ourself. Lets defer to it: if (IsIconic(hwnd)) { ShowWindow(hwnd, SW_RESTORE); } SetForegroundWindow (hwnd); return FALSE; } // Fill in window class structure with parameters that describe // the main window. wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC)WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_BIG)); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName = MAKEINTRESOURCE(IDR_SIMPLESDI); wc.lpszClassName = szAppName; // Register the window class and return success/failure code. return RegisterClass(&wc); } /* InitInstance */ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // Store instance handle in our global variable // Create our window hWnd = CreateWindow(szAppName, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return (FALSE); } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return (TRUE); } /* WndProc */ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; if(GetNativeWindowPort(hWnd)){ MSG msg; EventRecord macEvent; LONG thePoints = GetMessagePos(); msg.hwnd = hWnd; msg.message = message; msg.wParam = wParam; msg.lParam = lParam; msg.time = GetMessageTime(); msg.pt.x = LOWORD(thePoints); msg.pt.y = HIWORD(thePoints); WinEventToMacEvent(&msg, &macEvent); // Convert the message to a QTML event // if we have a Movie Controller, pass the QTML event if(gMovieStuff.theMC) MCIsPlayerEvent(gMovieStuff.theMC,(const EventRecord *)&macEvent); } switch (message) { case WM_CREATE: memset(&gMovieStuff, 0, sizeof(MovieStuff)); // Register this HWND with QTML CreatePortAssociation(hWnd, NULL, 0L); gMovieStuff.theHwnd = hWnd; break; case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); //Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, (DLGPROC)About); break; case IDM_EXIT: CloseMovie(&gMovieStuff); DestroyPortAssociation((CGrafPort *)GetNativeWindowPort(hWnd)); DestroyWindow(hWnd); stopVideoOutput(); break; case IDM_OPEN: // Open a movie file if(GetFile(gMovieStuff.filename)){ // Close any open movie CloseMovie(&gMovieStuff); OpenMovie(hWnd, &gMovieStuff); // open the movie and size the window if (startVideoOutput() != noErr) { MessageBox(NULL, "Can't start the video output", "", MB_OK); CloseMovie(&gMovieStuff); DestroyPortAssociation( (CGrafPort *)GetNativeWindowPort(hWnd)); DestroyWindow(hWnd); stopVideoOutput(); } } break; } break; case WM_PAINT: hdc = BeginPaint (hWnd, &ps); // Add any additional drawing code here... EndPaint (hWnd, &ps); break; case WM_CLOSE: // Unregister the HWND with QTML CloseMovie(&gMovieStuff); DestroyPortAssociation((CGrafPtr)GetNativeWindowPort(hWnd)); stopVideoOutput(); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_ENTERSIZEMOVE: { RECT clientRect; GetClientRect(hWnd, & clientRect ); gOldWindowPos.cx = clientRect.right - clientRect.left; gOldWindowPos.cy = clientRect.bottom - clientRect.top; } break; case WM_EXITSIZEMOVE: if ( gMovieStuff.theMovie ) { RECT clientRect; long widthAdjust = 0, heightAdjust = 0; GetClientRect(hWnd, &clientRect ); widthAdjust = (clientRect.right - clientRect.left) - gOldWindowPos.cx; heightAdjust = (clientRect.bottom - clientRect.top) - gOldWindowPos.cy; if ( widthAdjust || heightAdjust ) { Rect controllerBox; MCGetControllerBoundsRect(gMovieStuff.theMC, &controllerBox); controllerBox.right += (short)widthAdjust; controllerBox.bottom += (short)heightAdjust; MCSetControllerBoundsRect(gMovieStuff.theMC, &controllerBox); } } break; } return (DefWindowProc(hWnd, message, wParam, lParam)); } /* About */ LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, TRUE); return (TRUE); } break; } return FALSE; } short MyDialogFilter(DialogPtr dlg, EventRecord *theEvent, short *itemHit) { short iHandledIt = false; if (theEvent->what == nullEvent) { if (gMovieStuff.theMovie) MoviesTask(gMovieStuff.theMovie, 0); } return iHandledIt; } ComponentResult startVideoOutput() { QTAtomContainer displayModeList; long displayModeId=0; ComponentDescription cd; Component c = 0; int result=noErr; TimeValue movieCurrentTime, movieDuration; LONG movieCtype; if (videoOutOpened) return result; else videoOutOpened = true; cd.componentType = QTVideoOutputComponentType; cd.componentSubType = 0; cd.componentManufacturer = 0; cd.componentFlags = 0; cd.componentFlagsMask = kQTVideoOutputDontDisplayToUser; c = FindNextComponent (c, &cd); if ((videoOutput = OpenComponent(c)) == 0) return(codecOpenErr); if (result = QTVideoOutputGetDisplayModeList(videoOutput, &displayModeList)) goto bail; // query the movie type if (!(movieCtype = getMovieDesc())) goto bail; // find the display mode that matches the movie type displayModeId = findDisplayMode(displayModeList, movieCtype); if (displayModeId) if (result = QTVideoOutputSetDisplayMode(videoOutput, displayModeId)) goto bail; if (result = QTVideoOutputCustomConfigureDisplay(videoOutput, MyDialogFilter)) goto bail; if (result= QTVideoOutputBegin(videoOutput)) goto bail; if (result = QTVideoOutputGetGWorld (videoOutput, &videoOutputGWorld)) goto bail; GetGWorld(&origPort, &origDevice); // save window's graphics port movieCurrentTime = GetMovieTime (gMovieStuff.theMovie, nil); movieDuration = GetMovieDuration(gMovieStuff.theMovie); result = UpdateMovie(gMovieStuff.theMovie); MoviesTask(gMovieStuff.theMovie, 1000); SetMovieGWorld(gMovieStuff.theMovie, videoOutputGWorld, nil); bail: return result; } ComponentResult stopVideoOutput() { int result=noErr; if (!videoOutOpened || !videoOutput) return result; else videoOutOpened = false; result = QTVideoOutputEnd(videoOutput); result = CloseComponent(videoOutput); if (origPort || origDevice) SetGWorld(origPort, origDevice); // restore original graphics port return result; } long getMovieDesc() { long ctype; ImageDescriptionHandle desc = (ImageDescriptionHandle) NewHandle(0); Track track = GetMovieTrack(gMovieStuff.theMovie, 1); GetMediaSampleDescription(GetTrackMedia(track), 1, (SampleDescriptionHandle)desc); ctype = (**desc).cType; DisposeHandle((Handle) desc); return(ctype); } long findDisplayMode(QTAtomContainer displayModeList, long cType) { QTAtom current, next, decomp, decompType; QTAtomType atype; QTAtomID aid; int *ptr, size; long packingType, displayModeId; int result = noErr; current = next = 0; displayModeId = 0; size = 0; ptr = 0; do { result = QTNextChildAnyType(displayModeList, kParentAtomIsContainer, current, &next); if (result != noErr) break; if (next) { current = next; result = QTGetAtomTypeAndID(displayModeList, current, &atype, &aid); if (atype != kQTVODisplayModeItem) { break; } decomp = QTFindChildByID(displayModeList, current, kQTVODecompressors, 1, nil); if (decomp) { decompType = QTFindChildByID(displayModeList, decomp, kQTVODecompressorType, 1, nil); if (decompType) { QTGetAtomDataPtr(displayModeList, decompType, &size, (char **)&ptr); packingType = EndianU32_BtoN(ptr[0]); if (cType == packingType) { displayModeId = aid; break; } else if ((cType == 'jpeg' || cType == 'mjpa' || cType == 'dvc ' || cType == 'dvcp') && packingType == '2vuy') { // the special short cut displayModeId = aid; break; } } } } } while (next); return(displayModeId); }