The following code demonstrates a simple media player application. It utilizes most of the functions available in the ltmmPlay object.
// 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 asssociated 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;
HGLOBAL hDIB;
IPictureDisp* pPictureDisp;
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 the source file
bstr = SysAllocString((OLECHAR*)MAKE_MEDIA_PATH("source.avi"));
hr = IltmmPlay_put_SourceFile(g_pPlay, bstr);
SysFreeString(bstr);
if(SUCCEEDED(hr))
{
IltmmPlay_get_UnrenderedStreams(g_pPlay, &l);
if(l != 0)
MessageBox(hwnd, _T("Not all the streams could be rendered."), _T("Play"), MB_ICONEXCLAMATION | MB_OK);
}
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);
// enable still options
IltmmPlay_get_RenderedStreams (g_pPlay, &l);
EnableMenuItem((HMENU) wParam, ID_CONTROL_COPYDIB, (l & ltmmPlay_Stream_Video) ? MF_ENABLED : MF_GRAYED);
EnableMenuItem((HMENU) wParam, ID_CONTROL_SAVEPICTURE, (l & ltmmPlay_Stream_Video) ? MF_ENABLED : MF_GRAYED);
}
break;
case WM_PLAYNOTIFY:
switch(wParam)
{
case ltmmPlay_Notify_TrackingSelectionChanged:
break;
case ltmmPlay_Notify_TrackingPositionChanged:
p = sz;
*p = _T('\0');
IltmmPlay_get_RenderedStreams (g_pPlay, &l);
if((l & ltmmPlay_Stream_Audio) && !(l & ltmmPlay_Stream_Video))
{
// audio only stream
if(p != sz)
p += _stprintf(p, _T(", "));
p += _stprintf(p, _T("Audio"));
}
else if(l & ltmmPlay_Stream_Midi)
{
// midi stream
if(p != sz)
p += _stprintf(p, _T(", "));
p += _stprintf(p, _T("Midi"));
}
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 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, (VARIANT_BOOL) (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 seconds
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, (VARIANT_BOOL) (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, (VARIANT_BOOL) (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;
case ID_CONTROL_COPYDIB:
// device independent bitmap
hr = IltmmPlay_GetStillDIB(g_pPlay, 5000, (long*) &hDIB);
if(SUCCEEDED(hr))
{
// copy to the clipboard
OpenClipboard(hwnd);
EmptyClipboard();
SetClipboardData(CF_DIB, hDIB);
CloseClipboard();
}
return 0;
break;
case ID_CONTROL_SAVEPICTURE:
// ole picture object
hr = IltmmPlay_GetStillPicture(g_pPlay, 5000, &pPictureDisp);
if(SUCCEEDED(hr))
{
// save the picture
bstr = SysAllocString((OLECHAR*)MAKE_MEDIA_PATH("still.bmp"));
OleSavePictureFile((IDispatch*) pPictureDisp, bstr);
SysFreeString(bstr);
IUnknown_Release(pPictureDisp);
}
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;
}