LEADTOOLS Multimedia API Help > Programming with LEADTOOLS Multimedia > C Code > Simple Media Player for C |
The following code demonstrates a simple media player application. It utilizes most of the functions available in the ltmmPlay object.
#define MAKE_MEDIA_PATH(pFileName) (TEXT("C:\\LEADTOOLS 18\\Media\\")TEXT(pFileName)) // define helper macros for using interfaces under C #ifndef COBJMACROS #define COBJMACROS #endif // include the LEAD Multimedia TOOLKIT header #include "ltmm.h" #include "resource.h" #include <tchar.h> #include <stdio.h> #include <math.h> #define SZ_WNDCLASS_PLAY _T("PLAY WNDCLASS") #define WM_PLAYNOTIFY (WM_USER + 1000) HINSTANCE g_hInstance; // application instance handle HWND g_hwndPlay; // video frame window IltmmPlay* g_pPlay; // play object interface pointer int g_nPositionView; // current position indicator view mode enum { POSITIONVIEW_TIME, POSITIONVIEW_FRAME, POSITIONVIEW_TRACKING }; // // SnapFrameToVideo // resizes the frame window to match the video width and height // void SnapFrameToVideo(void) { HWND hwnd; RECT rcWindow, rcClient; long cx, cy; // get the frame window IltmmPlay_get_VideoWindowFrame (g_pPlay, (long*) &hwnd); // get the video dimensions IltmmPlay_get_VideoWidth (g_pPlay, &cx); IltmmPlay_get_VideoHeight (g_pPlay, &cy); // adjust by the border dimensions GetWindowRect(hwnd, &rcWindow); GetClientRect(hwnd, &rcClient); cx += ((rcWindow.right - rcWindow.left) - (rcClient.right - rcClient.left)); cy += ((rcWindow.bottom - rcWindow.top) - (rcClient.bottom - rcClient.top)); // resize the window SetWindowPos(hwnd, NULL, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER); } // // FreeSource // resets source and frees associated resources // void FreeSource(void) { long type; VARIANT var; HGLOBAL hglobal; IltmmPlay_get_SourceType (g_pPlay, &type); if(type == ltmmPlay_Source_Array) { IltmmPlay_get_SourceArray(g_pPlay, &var); IltmmPlay_ResetSource(g_pPlay); VariantClear(&var); } else if(type == ltmmPlay_Source_HGlobal) { IltmmPlay_get_SourceHGlobal (g_pPlay, (long*) &hglobal); IltmmPlay_ResetSource(g_pPlay); GlobalFree(hglobal); } else { IltmmPlay_ResetSource(g_pPlay); } } // // SetSourceArray // preloads a SAFEARRAY with media data and assigns it to the play object // void SetSourceArray(void) { HRESULT hr; HANDLE hfile; DWORD size, cb; void* buffer; VARIANT var; SAFEARRAY* psaSource; // open the source file hfile = CreateFile(MAKE_MEDIA_PATH("source.avi"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if(hfile == INVALID_HANDLE_VALUE) return; // allocate same-sized SAFEARRAY size = GetFileSize(hfile, NULL); psaSource = SafeArrayCreateVector(VT_UI1, 0, size); if(!psaSource) { CloseHandle(hfile); return; } // read entire source into array SafeArrayAccessData(psaSource, (void**) &buffer); if(!ReadFile(hfile, buffer, size, &cb, NULL) || cb != size) { SafeArrayUnaccessData(psaSource); CloseHandle(hfile); SafeArrayDestroy(psaSource); return; } SafeArrayUnaccessData(psaSource); // close file CloseHandle(hfile); // assign the source array VariantInit(&var); V_VT(&var) = (VT_ARRAY | VT_UI1); V_ARRAY(&var) = psaSource; hr = IltmmPlay_put_SourceArray (g_pPlay, var); if(FAILED(hr)) { SafeArrayDestroy(psaSource); return; } } // // SetSourceArray // preloads global memory with media data and assigns it to the play object // void SetSourceHGlobal(void) { HRESULT hr; HANDLE hfile; DWORD size, cb; void* buffer; HGLOBAL hglobal; // open the source file hfile = CreateFile(MAKE_MEDIA_PATH("source.avi"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if(hfile == INVALID_HANDLE_VALUE) return; // allocate same-sized global memory size = GetFileSize(hfile, NULL); hglobal = GlobalAlloc(GMEM_MOVEABLE, size); if(!hglobal) { CloseHandle(hfile); return; } // read entire source into memory buffer = GlobalLock(hglobal); if(!ReadFile(hfile, buffer, size, &cb, NULL) || cb != size) { GlobalUnlock(hglobal); CloseHandle(hfile); GlobalFree(hglobal); return; } GlobalUnlock(hglobal); // close file CloseHandle(hfile); hr = IltmmPlay_put_SourceHGlobal(g_pPlay, (long) hglobal); if(FAILED(hr)) { GlobalFree(hglobal); return; } } // // PlayWndProc // video frame window procedure // LRESULT CALLBACK PlayWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { BSTR bstr; VARIANT_BOOL f; long l; TCHAR sz[2048]; LPTSTR p; double d; HRESULT hr; ltmmSizeMode sm; long x, y, cx, cy; RECT rc; POINT pt; switch (message) { case WM_CREATE: g_hwndPlay = hwnd; // window is the video window frame IltmmPlay_put_VideoWindowFrame (g_pPlay, (long) hwnd); // want notification messages as well IltmmPlay_SetNotifyWindow (g_pPlay, (long) hwnd, WM_PLAYNOTIFY); // make sure we start playing immediately IltmmPlay_put_AutoStart (g_pPlay, VARIANT_TRUE); // set preferred renderer IltmmPlay_put_PreferredVideoRenderer (g_pPlay, ltmmVideoRenderer_VMR9); // set the source file bstr = SysAllocString((OLECHAR*)MAKE_MEDIA_PATH("source.avi")); IltmmPlay_put_SourceFile (g_pPlay, bstr); SysFreeString(bstr); SnapFrameToVideo(); return 0; break; case WM_INITMENUPOPUP: if(GetSubMenu(GetMenu(hwnd), 0) == (HMENU)wParam) { // enable menu items based on the play object state IltmmPlay_get_State (g_pPlay, &l); EnableMenuItem((HMENU) wParam, ID_CONTROL_PLAY, (l == ltmmPlay_State_Paused || l == ltmmPlay_State_Stopped) ? MF_ENABLED : MF_GRAYED); EnableMenuItem((HMENU) wParam, ID_CONTROL_PAUSE, (l == ltmmPlay_State_Running) ? MF_ENABLED : MF_GRAYED); EnableMenuItem((HMENU) wParam, ID_CONTROL_STOP, (l == ltmmPlay_State_Running || l == ltmmPlay_State_Paused) ? MF_ENABLED : MF_GRAYED); // enable menu items based on seeking capabilities IltmmPlay_CheckSeekingCapabilities (g_pPlay, ltmmPlay_Seeking_Forward | ltmmPlay_Seeking_Backward | ltmmPlay_Seeking_FrameForward | ltmmPlay_Seeking_FrameBackward, &l); EnableMenuItem((HMENU) wParam, ID_CONTROL_SEEKSTART, (l & ltmmPlay_Seeking_Backward) ? MF_ENABLED : MF_GRAYED); EnableMenuItem((HMENU) wParam, ID_CONTROL_SEEKEND, (l & ltmmPlay_Seeking_Forward) ? MF_ENABLED : MF_GRAYED); EnableMenuItem((HMENU) wParam, ID_CONTROL_NEXTFRAME, (l & ltmmPlay_Seeking_FrameForward) ? MF_ENABLED : MF_GRAYED); EnableMenuItem((HMENU) wParam, ID_CONTROL_PREVIOUSFRAME, (l & ltmmPlay_Seeking_FrameBackward) ? MF_ENABLED : MF_GRAYED); EnableMenuItem((HMENU) wParam, ID_CONTROL_SEEKSELECTIONSTART, (l & (ltmmPlay_Seeking_Forward | ltmmPlay_Seeking_Backward)) ? MF_ENABLED : MF_GRAYED); EnableMenuItem((HMENU) wParam, ID_CONTROL_SEEKSELECTIONEND, (l & (ltmmPlay_Seeking_Forward | ltmmPlay_Seeking_Backward)) ? MF_ENABLED : MF_GRAYED); EnableMenuItem((HMENU) wParam, ID_CONTROL_LASTFRAME, (l & ltmmPlay_Seeking_FrameForward) ? MF_ENABLED : MF_GRAYED); EnableMenuItem((HMENU) wParam, ID_CONTROL_FIRSTFRAME, (l & ltmmPlay_Seeking_FrameBackward) ? MF_ENABLED : MF_GRAYED); EnableMenuItem((HMENU) wParam, ID_CONTROL_STEPFORWARD1SEC, (l & ltmmPlay_Seeking_Forward) ? MF_ENABLED : MF_GRAYED); EnableMenuItem((HMENU) wParam, ID_CONTROL_STEPFORWARD10, (l & ltmmPlay_Seeking_Forward) ? MF_ENABLED : MF_GRAYED); // check the current speed IltmmPlay_get_Rate (g_pPlay, &d); CheckMenuItem((HMENU) wParam, ID_CONTROL_HALFSPEED, (fabs(d - 0.5) < 0.1) ? MF_CHECKED : MF_UNCHECKED); CheckMenuItem((HMENU) wParam, ID_CONTROL_NORMALSPEED, (fabs(d - 1.0) < 0.1) ? MF_CHECKED : MF_UNCHECKED); // check the current video size mode IltmmPlay_get_VideoWindowSizeMode (g_pPlay, &sm); CheckMenuItem((HMENU) wParam, ID_CONTROL_FITTOWINDOW, (sm == ltmmFit) ? MF_CHECKED : MF_UNCHECKED); CheckMenuItem((HMENU) wParam, ID_CONTROL_STRETCHTOWINDOW, (sm == ltmmStretch) ? MF_CHECKED : MF_UNCHECKED); // enable volume menu items IltmmPlay_get_Volume (g_pPlay, &l); EnableMenuItem((HMENU) wParam, ID_CONTROL_INCREASEVOLUME, (l < 0) ? MF_ENABLED : MF_GRAYED); EnableMenuItem((HMENU) wParam, ID_CONTROL_DECREASEVOLUME, (l > -10000) ? MF_ENABLED : MF_GRAYED); // enable balance menu items IltmmPlay_get_Balance (g_pPlay, &l); EnableMenuItem((HMENU) wParam, ID_CONTROL_PANRIGHT, (l < 10000) ? MF_ENABLED : MF_GRAYED); EnableMenuItem((HMENU) wParam, ID_CONTROL_PANLEFT, (l > -10000) ? MF_ENABLED : MF_GRAYED); // check mute IltmmPlay_get_Mute (g_pPlay, &f); CheckMenuItem((HMENU) wParam, ID_CONTROL_MUTE, f ? MF_CHECKED : MF_UNCHECKED); // check auto rewind IltmmPlay_get_AutoRewind (g_pPlay, &f); CheckMenuItem((HMENU) wParam, ID_CONTROL_AUTOREWIND, f ? MF_CHECKED : MF_UNCHECKED); // check loop IltmmPlay_get_PlayCount (g_pPlay, &l); CheckMenuItem((HMENU) wParam, ID_CONTROL_LOOP, (l == 0) ? MF_CHECKED : MF_UNCHECKED); // enable processors IltmmPlay_HasDialog(g_pPlay, ltmmPlay_Dlg_VideoProcessors, &f); EnableMenuItem((HMENU) wParam, ID_CONTROL_PROCESSORS_VIDEO, f ? MF_ENABLED : MF_GRAYED); IltmmPlay_HasDialog(g_pPlay, ltmmPlay_Dlg_AudioProcessors, &f); EnableMenuItem((HMENU) wParam, ID_CONTROL_PROCESSORS_AUDIO, f ? MF_ENABLED : MF_GRAYED); // check source IltmmPlay_get_SourceType (g_pPlay, &l); CheckMenuItem((HMENU) wParam, ID_CONTROL_SOURCE_FILE, (l == ltmmPlay_Source_File) ? MF_CHECKED : MF_UNCHECKED); CheckMenuItem((HMENU) wParam, ID_CONTROL_SOURCE_ARRAY, (l == ltmmPlay_Source_Array) ? MF_CHECKED : MF_UNCHECKED); CheckMenuItem((HMENU) wParam, ID_CONTROL_SOURCE_HGLOBAL, (l == ltmmPlay_Source_HGlobal) ? MF_CHECKED : MF_UNCHECKED); IltmmPlay_get_AutoStart (g_pPlay, &f); CheckMenuItem((HMENU) wParam, ID_CONTROL_AUTOSTART, f ? MF_CHECKED : MF_UNCHECKED); // check position view CheckMenuItem((HMENU) wParam, ID_CONTROL_POSITIONVIEW_FRAME, (g_nPositionView == POSITIONVIEW_FRAME) ? MF_CHECKED : MF_UNCHECKED); CheckMenuItem((HMENU) wParam, ID_CONTROL_POSITIONVIEW_TIME, (g_nPositionView == POSITIONVIEW_TIME) ? MF_CHECKED : MF_UNCHECKED); CheckMenuItem((HMENU) wParam, ID_CONTROL_POSITIONVIEW_TRACKING, (g_nPositionView == POSITIONVIEW_TRACKING) ? MF_CHECKED : MF_UNCHECKED); } break; case WM_PLAYNOTIFY: switch(wParam) { case ltmmPlay_Notify_TrackingSelectionChanged: break; case ltmmPlay_Notify_TrackingPositionChanged: p = sz; *p = _T('\0'); if(g_nPositionView == POSITIONVIEW_TRACKING) // tracking position based { // display current tracking position hr = IltmmPlay_get_CurrentTrackingPosition (g_pPlay, &l); if(SUCCEEDED(hr)) { if(p != sz) p += _stprintf(p, _T(", ")); p += _stprintf(p, _T("Trk. Pos.: %d"), l); } // display current tracking selection start hr = IltmmPlay_get_TrackingSelectionStart(g_pPlay, &l); if(SUCCEEDED(hr)) { if(p != sz) p += _stprintf(p, _T(", ")); p += _stprintf(p, _T("Trk. Start: %d"), l); } // display current tracking selection end hr= IltmmPlay_get_TrackingSelectionEnd (g_pPlay, &l); if(SUCCEEDED(hr)) { if(p != sz) p += _stprintf(p, _T(", ")); p += _stprintf(p, _T("Trk. End: %d"), l); } } else if(g_nPositionView == POSITIONVIEW_FRAME) // frame based { // display current frame position hr = IltmmPlay_get_CurrentFramePosition (g_pPlay, &l); if(SUCCEEDED(hr)) { if(p != sz) p += _stprintf(p, _T(", ")); p += _stprintf(p, _T("Frame: %d"), l + 1); } // display total number of frames hr = IltmmPlay_get_FrameDuration (g_pPlay, &l); if(SUCCEEDED(hr)) { if(p != sz) p += _stprintf(p, _T(", ")); p += _stprintf(p, _T("Total Frames: %d"), l); } } else // time based { // display the current position hr = IltmmPlay_get_CurrentPosition (g_pPlay, &d); if(SUCCEEDED(hr)) { if(p != sz) p += _stprintf(p, _T(", ")); p += _stprintf(p, _T("Position: %f"), d); } // display the total duration hr = IltmmPlay_get_Duration (g_pPlay, &d); if(SUCCEEDED(hr)) { if(p != sz) p += _stprintf(p, _T(", ")); p += _stprintf(p, _T("Duration: %f"), d); } // display current selection start hr = IltmmPlay_get_SelectionStart (g_pPlay, &d); if(SUCCEEDED(hr)) { if(p != sz) p += _stprintf(p, _T(", ")); p += _stprintf(p, _T("Start: %f"), d); } // display current selection end hr = IltmmPlay_get_SelectionEnd (g_pPlay, &d); if(SUCCEEDED(hr)) { if(p != sz) p += _stprintf(p, _T(", ")); p += _stprintf(p, _T("End: %f"), d); } } SetWindowText(hwnd, sz); break; case ltmmPlay_Notify_StateChanged: switch(LOWORD(lParam)) { case ltmmPlay_State_NotReady: _stprintf(sz, _T("Not Ready")); SetWindowText(hwnd, sz); break; case ltmmPlay_State_Stopped: // uncomment the following line to view the the graph in DirectShow GraphEdit // IltmmPlay_EditGraph(g_pPlay); IltmmPlay_get_SourceType (g_pPlay, &l); if(l == ltmmPlay_Source_Array) { _stprintf(sz, _T("Stopped - [array]")); } else if(l == ltmmPlay_Source_HGlobal) { _stprintf(sz, _T("Stopped - [hglobal]")); } else { IltmmPlay_get_SourceFile(g_pPlay, &bstr); _stprintf(sz, _T("Stopped - [%ls]"), bstr); SysFreeString(bstr); } SetWindowText(hwnd, sz); break; case ltmmPlay_State_Paused: IltmmPlay_get_SourceType (g_pPlay, &l); if(l == ltmmPlay_Source_Array) { _stprintf(sz, _T("Paused - [array]")); } else if(l == ltmmPlay_Source_HGlobal) { _stprintf(sz, _T("Paused - [hglobal]")); } else { IltmmPlay_get_SourceFile (g_pPlay, &bstr); _stprintf(sz, _T("Paused - [%ls]"), bstr); SysFreeString(bstr); } SetWindowText(hwnd, sz); break; case ltmmPlay_State_Running: _stprintf(sz, _T("Playing")); SetWindowText(hwnd, sz); break; } break; case ltmmPlay_Notify_Error: _stprintf(sz, _T("Error 0x%.8X. Playback stopped."), lParam); MessageBox(hwnd, sz, _T("Play"), MB_ICONEXCLAMATION | MB_OK); break; } return 0; break; case WM_KEYDOWN: if(wParam == VK_ESCAPE) { // if fullscreen mode then exit it IltmmPlay_get_FullScreenMode (g_pPlay, &f); if(f) { IltmmPlay_put_FullScreenMode (g_pPlay, VARIANT_FALSE); return 0; } } break; case WM_DESTROY: FreeSource(); // no more notifications IltmmPlay_SetNotifyWindow (g_pPlay, (long) NULL, 0); PostQuitMessage(0); break; case WM_COMMAND: switch(LOWORD(wParam)) { case ID_CONTROL_POSITIONVIEW_TIME: g_nPositionView = POSITIONVIEW_TIME; break; case ID_CONTROL_POSITIONVIEW_FRAME: g_nPositionView = POSITIONVIEW_FRAME; break; case ID_CONTROL_POSITIONVIEW_TRACKING: g_nPositionView = POSITIONVIEW_TRACKING; break; case ID_CONTROL_AUTOSTART: // toggle auto start IltmmPlay_get_AutoStart (g_pPlay, &f); IltmmPlay_put_AutoStart (g_pPlay, f ? VARIANT_FALSE : VARIANT_TRUE); return 0; break; case ID_CONTROL_PLAY: // play file IltmmPlay_Run (g_pPlay); return 0; break; case ID_CONTROL_PAUSE: // pause playback IltmmPlay_Pause (g_pPlay); return 0; break; case ID_CONTROL_STOP: // stop playback IltmmPlay_Stop (g_pPlay); return 0; break; case ID_CONTROL_HALFSPEED: // set to half the normal playback speed IltmmPlay_put_Rate (g_pPlay, 0.5); return 0; break; case ID_CONTROL_NORMALSPEED: // set to normal speed IltmmPlay_put_Rate (g_pPlay, 1.0); return 0; break; case ID_CONTROL_SEEKSTART: // seek to file start IltmmPlay_SeekStart(g_pPlay); return 0; break; case ID_CONTROL_SEEKEND: // seek to file end IltmmPlay_SeekEnd (g_pPlay); return 0; break; case ID_CONTROL_SEEKSELECTIONSTART: // seek to the start of the current selection IltmmPlay_SeekSelectionStart (g_pPlay); return 0; break; case ID_CONTROL_SEEKSELECTIONEND: // seek to the end of the current selection IltmmPlay_SeekSelectionEnd (g_pPlay); return 0; break; case ID_CONTROL_SETSELECTIONSTART: // set the start of the selection to the current position IltmmPlay_MarkSelectionStart (g_pPlay); return 0; break; case ID_CONTROL_SETSELECTIONEND: // set the end of the selection to the current position IltmmPlay_MarkSelectionEnd (g_pPlay); return 0; break; case ID_CONTROL_CLEARSELECTION: // clear the current selection IltmmPlay_get_Duration(g_pPlay, &d); IltmmPlay_put_SelectionStart (g_pPlay, 0.0); IltmmPlay_put_SelectionEnd (g_pPlay, d); return 0; break; case ID_CONTROL_NEXTFRAME: // goto the next frame IltmmPlay_NextFrame (g_pPlay); return 0; break; case ID_CONTROL_PREVIOUSFRAME: // goto the previous frame IltmmPlay_PreviousFrame (g_pPlay); return 0; break; case ID_CONTROL_FIRSTFRAME: // goto to the first frame IltmmPlay_put_CurrentFramePosition (g_pPlay, 0); return 0; break; case ID_CONTROL_LASTFRAME: // goto to the last frame IltmmPlay_get_FrameDuration (g_pPlay, &l); IltmmPlay_put_CurrentFramePosition (g_pPlay, l - 1); return 0; break; case ID_CONTROL_STEPFORWARD1SEC: // step forward 1 second IltmmPlay_get_CurrentPosition (g_pPlay, &d); IltmmPlay_put_CurrentPosition (g_pPlay, d + 1.0); return 0; break; case ID_CONTROL_STEPFORWARD10: // step forward 10% IltmmPlay_get_CurrentTrackingPosition (g_pPlay, &l); IltmmPlay_put_CurrentTrackingPosition(g_pPlay, l + 1000); return 0; break; case ID_CONTROL_FITTOWINDOW: // fit the video to the window IltmmPlay_put_VideoWindowSizeMode (g_pPlay, ltmmFit); return 0; break; case ID_CONTROL_STRETCHTOWINDOW: // stretch the video to the window IltmmPlay_put_VideoWindowSizeMode (g_pPlay, ltmmStretch); return 0; break; case ID_CONTROL_MUTE: // toggle mute IltmmPlay_get_Mute (g_pPlay, &f); IltmmPlay_put_Mute (g_pPlay, f ? VARIANT_FALSE : VARIANT_TRUE); return 0; break; case ID_CONTROL_INCREASEVOLUME: // increase the volume IltmmPlay_get_Volume (g_pPlay, &l); IltmmPlay_put_Volume (g_pPlay, min(0, l + 300)); return 0; break; case ID_CONTROL_DECREASEVOLUME: // decrease the volume IltmmPlay_get_Volume (g_pPlay, &l); IltmmPlay_put_Volume (g_pPlay, max(-10000, l - 300)); return 0; break; case ID_CONTROL_PANRIGHT: // pan balance to the right IltmmPlay_get_Balance (g_pPlay, &l); IltmmPlay_put_Balance(g_pPlay, min(10000, l + 300)); return 0; break; case ID_CONTROL_PANLEFT: // pan balance to the left IltmmPlay_get_Balance (g_pPlay, &l); IltmmPlay_put_Balance (g_pPlay, max(-10000, l - 300)); return 0; break; case ID_CONTROL_LOOP: // toggle looping IltmmPlay_get_PlayCount(g_pPlay, &l); IltmmPlay_put_PlayCount (g_pPlay, l ? 0 : 1); return 0; break; case ID_CONTROL_FULLSCREEN: // toggle fullscreen mode IltmmPlay_ToggleFullScreenMode (g_pPlay); return 0; break; case ID_CONTROL_AUTOREWIND: // toggle auto rewind IltmmPlay_get_AutoRewind (g_pPlay, &f); IltmmPlay_put_AutoRewind (g_pPlay, f ? VARIANT_FALSE : VARIANT_TRUE); return 0; break; case ID_CONTROL_PROCESSORS_VIDEO: // invoke video processor dialog box IltmmPlay_ShowDialog (g_pPlay, ltmmPlay_Dlg_VideoProcessors, (long) hwnd); return 0; break; case ID_CONTROL_PROCESSORS_AUDIO: // invoke audio processor dialog box IltmmPlay_ShowDialog (g_pPlay, ltmmPlay_Dlg_AudioProcessors, (long) hwnd); return 0; break; case ID_CONTROL_SOURCE_FILE: // set the source file FreeSource(); bstr = SysAllocString((OLECHAR*)MAKE_MEDIA_PATH("source.avi")); IltmmPlay_put_SourceFile (g_pPlay, bstr); SysFreeString(bstr); SnapFrameToVideo(); return 0; break; case ID_CONTROL_SOURCE_ARRAY: // set the source array FreeSource(); SetSourceArray(); SnapFrameToVideo(); return 0; break; case ID_CONTROL_SOURCE_HGLOBAL: // set the source hglobal FreeSource(); SetSourceHGlobal(); SnapFrameToVideo(); return 0; break; case ID_CONTROL_MEDIAINFORMATION: // display available media information p = sz; IltmmPlay_get_Title (g_pPlay, &bstr); p += _stprintf(p, _T("Title = '%ls'"), bstr ? bstr : L""); SysFreeString(bstr); IltmmPlay_get_Author (g_pPlay, &bstr); p += _stprintf(p, _T(", Author = '%ls'"), bstr ? bstr : L""); SysFreeString(bstr); IltmmPlay_get_Copyright (g_pPlay, &bstr); p += _stprintf(p, _T(", Copyright = '%ls'"), bstr ? bstr : L""); SysFreeString(bstr); IltmmPlay_get_Description (g_pPlay, &bstr); p += _stprintf(p, _T(", Description = '%ls'"), bstr ? bstr : L""); SysFreeString(bstr); IltmmPlay_get_Rating (g_pPlay, &bstr); p += _stprintf(p, _T(", Rating = '%ls'"), bstr ? bstr : L""); SysFreeString(bstr); MessageBox(hwnd, sz, _T("Media Information"), MB_OK); return 0; break; } break; case WM_LBUTTONDOWN: // perform play/pause if the user clicks in the video window IltmmPlay_get_VideoWindowLeft (g_pPlay, &x); IltmmPlay_get_VideoWindowTop (g_pPlay, &y); IltmmPlay_get_VideoWindowWidth (g_pPlay, &cx); IltmmPlay_get_VideoWindowHeight (g_pPlay, &cy); SetRect(&rc, x, y, x + cx, y + cy); pt.x = (short) LOWORD(lParam); pt.y = (short) HIWORD(lParam); if(PtInRect(&rc, pt)) { IltmmPlay_get_State (g_pPlay, &l); if(l == ltmmPlay_State_Stopped || l == ltmmPlay_State_Paused) IltmmPlay_Run (g_pPlay); else if(l == ltmmPlay_State_Running) IltmmPlay_Pause (g_pPlay); } return 0; break; } return DefWindowProc(hwnd, message, wParam, lParam); } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; HRESULT hr; WNDCLASSEX wcex; hPrevInstance = hPrevInstance ; lpCmdLine = lpCmdLine ; nCmdShow = nCmdShow ; g_hInstance = hInstance; // initialize COM library hr = CoInitialize(NULL); if(FAILED(hr)) goto error; // register the video frame window class wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = PlayWndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = g_hInstance; wcex.hIcon = NULL; wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE + 1); wcex.lpszMenuName = (LPCSTR)IDR_MENU; wcex.lpszClassName = SZ_WNDCLASS_PLAY; wcex.hIconSm = NULL; if(!RegisterClassEx(&wcex)) goto error; // create the play object hr = CoCreateInstance(&CLSID_ltmmPlay, NULL, CLSCTX_INPROC_SERVER, &IID_IltmmPlay, (void**) &g_pPlay); if(FAILED(hr)) goto error; // create the video frame window if(!CreateWindow(SZ_WNDCLASS_PLAY, _T("Play"), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, g_hInstance, NULL)) goto error; ShowWindow(g_hwndPlay, nCmdShow); UpdateWindow(g_hwndPlay); // process until done while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } error: if(g_pPlay) IUnknown_Release(g_pPlay); CoUninitialize(); return 0; }