SIMPLECL.CPP


//=========================================================================
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1996 - 1997 Microsoft Corporation. All Rights Reserved.
//
//=========================================================================

#include <windows.h>
#include <streams.h>
#include <strmif.h>
#include <cutlist.h>
#include "simplecl.h"

ICutListGraphBuilder *pCLGraphBuilder = NULL;
IStandardCutList *pVideoCL = NULL;
IStandardCutList *pAudioCL = NULL;
IGraphBuilder *pigb = NULL;
IMediaControl *pimc = NULL;
IMediaEventEx *pimex = NULL;
IVideoWindow *pivw = NULL;

IFileClip *pVidFileClip[MAX_CLIPS];
IFileClip *pAudFileClip[MAX_CLIPS];
IAMCutListElement *pVidCLElem[MAX_CLIPS];
IAMCutListElement *pAudCLElem[MAX_CLIPS];

HRESULT hr;

int nVidElems, nAudElems;

void SimpleCutList ()

{ // SimpleCutList //

WCHAR wFile[MAX_PATH]; // file name

// Initialize video and audio file clips and elements to NULL
// so we can easily free objects later.
for (int x = 0; x < MAX_CLIPS; ++x)

{
pVidFileClip[x] = NULL;
pAudFileClip[x] = NULL;
pVidCLElem[x] = NULL;
pAudCLElem[x] = NULL;
};

// Create cutlist graph builder object
hr = CoCreateInstance(CLSID_CutListGraphBuilder, NULL,
CLSCTX_INPROC, IID_ICutListGraphBuilder,
(void**)&pCLGraphBuilder);

if (FAILED(hr))
{ // CoCreateInstance of CutListGraphBuiler failed
MessageBox(ghApp,
"CoCreateInstance of CutListGraphBuiler failed",
APPLICATIONNAME, MB_OK);
TearDownTheGraph();
return;
} // CoCreateInstance of CutListGraphBuiler failed

// Create simple (standard) cutlist object for video
hr = CoCreateInstance(CLSID_SimpleCutList, NULL,
CLSCTX_INPROC, IID_IStandardCutList,
(void**)&pVideoCL);
if (FAILED(hr))
{ // CoCreateInstance of video SimpleCutList failed
MessageBox(ghApp,
"CoCreateInstance of video SimpleCutList failed",
APPLICATIONNAME, MB_OK);
TearDownTheGraph();
return;
} // CoCreateInstance of video SimpleCutList failed

// Create simple (standard) cutlist object for audio
hr = CoCreateInstance(CLSID_SimpleCutList, NULL,
CLSCTX_INPROC, IID_IStandardCutList,
(void**)&pAudioCL);

if (FAILED(hr))
{ // CoCreateInstance of audio SimpleCutList failed
MessageBox(ghApp,
"CoCreateInstance of audio SimpleCutList failed",
APPLICATIONNAME, MB_OK);
TearDownTheGraph();
return;
} // CoCreateInstance of audio SimpleCutList failed

// Create the individual clips and add them to the cutlist
nVidElems = nAudElems = 0;
for (x = 0; x < gTheSet.nNumClips; ++x)

{ // Individual clips

MultiByteToWideChar(CP_ACP, 0,
gTheSet.List[x].szFilename,
-1, wFile, MAX_PATH );

// Create a video clip object and give it the file and stream
// to read from.
// SetFileAndStream will fail if we call it from a video clip
// object and the clip is not a video clip.
hr = CoCreateInstance(CLSID_VideoFileClip, NULL,
CLSCTX_INPROC, IID_IFileClip,
(void**)&pVidFileClip[nVidElems]);

hr = pVidFileClip[nVidElems]->SetFileAndStream(wFile, 0);

if (SUCCEEDED(hr))

{ // Create video cut and add the clip (element) to the cutlist

hr = pVidFileClip[nVidElems]->CreateCut(&pVidCLElem[nVidElems],
gTheSet.List[x].start*SCALE,
gTheSet.List[x].stop*SCALE,
0,
(gTheSet.List[x].stop-gTheSet.List[x].start)*SCALE,
0);

if (SUCCEEDED(hr))

{ // Add the element to the cutlist

hr = pVideoCL->AddElement(pVidCLElem[nVidElems], CL_DEFAULT_TIME, CL_DEFAULT_TIME);

if (SUCCEEDED(hr))
++nVidElems;

else

{ // AddElement failed so release associated objects

HELPER_RELEASE(pVidCLElem[nVidElems]);
HELPER_RELEASE(pVidFileClip[nVidElems]);
MessageBox(ghApp, "AddElement (video) failed!", APPLICATIONNAME, MB_OK);

} // AddElement failed so release associated objects

} // Add the element to the cutlist

else MessageBox(ghApp, "CreateCut (video) failed!", APPLICATIONNAME, MB_OK);

} // Create video cut

else

{ // Problems creating video stream

HELPER_RELEASE(pVidFileClip[nVidElems]);
MessageBox(ghApp, "SetFileAndStream (video) failed!", APPLICATIONNAME, MB_OK);

} // Problems creating video stream

// Create an audio clip object and give it the file and stream
// to read from.
// SetFileAndStream will fail if we call it from an audio clip
// object and the clip is not an audio clip
hr = CoCreateInstance(CLSID_AudioFileClip, NULL,
CLSCTX_INPROC, IID_IFileClip,
(void**)&pAudFileClip[nAudElems]);

hr = pAudFileClip[nAudElems]->SetFileAndStream(wFile, 0);

if (SUCCEEDED(hr))

{ // Create audio cut and add the clip (element) to the cutlist

hr = pAudFileClip[nAudElems]->CreateCut(&pAudCLElem[nAudElems],
gTheSet.List[x].start*SCALE,
gTheSet.List[x].stop*SCALE,
0,
(gTheSet.List[x].stop-gTheSet.List[x].start)*SCALE,
0);

if (SUCCEEDED(hr))

{ // Add the element to the cutlist

hr = pAudioCL->AddElement(pAudCLElem[nAudElems],
CL_DEFAULT_TIME,
CL_DEFAULT_TIME);

if (SUCCEEDED(hr))
++nAudElems;

else

{ // AddElement failed so release associated objects

HELPER_RELEASE(pAudCLElem[nAudElems]);
HELPER_RELEASE(pAudFileClip[nAudElems]);
MessageBox(ghApp, "AddElement (audio) failed!", APPLICATIONNAME, MB_OK);

} // AddElement failed so release associated objects

} // Add the element to the cutlist

else MessageBox(ghApp, "CreateCut (audio) failed!", APPLICATIONNAME, MB_OK);

} // Create audio cut

else

{ // Problems creating audio stream

HELPER_RELEASE(pAudFileClip[nAudElems]);
MessageBox(ghApp, "SetFileAndStream (audio) failed!", APPLICATIONNAME, MB_OK);

} // Problems creating audio stream

} // Individual clips

// Add the video cutlist to the filter graph
hr = pCLGraphBuilder->AddCutList(pVideoCL, NULL);

if (FAILED(hr)) // AddCutList (video) failed
MessageBox(ghApp, "AddCutList (video) failed", APPLICATIONNAME, MB_OK);

// Add the audio cutlist to the filter graph
hr = pCLGraphBuilder->AddCutList(pAudioCL, NULL);

if (FAILED(hr)) // AddCutList (audio) failed
MessageBox(ghApp, "AddCutList (audio) failed", APPLICATIONNAME, MB_OK);

if ((!pVideoCL) && (!pAudioCL))

{ // Clean up

TearDownTheGraph();
return;

} // Clean up

// Let the filter graph manager construct the the appropriate graph
// automatically
hr = pCLGraphBuilder->Render();

if (FAILED(hr))
{ // Problems rendering the graph
if (!AMGetErrorText(hr, gszScratch, 2048))
MessageBox(ghApp, "Problems rendering the graph!", APPLICATIONNAME, MB_OK);
else
MessageBox(ghApp, gszScratch, APPLICATIONNAME, MB_OK);
TearDownTheGraph();
return;
} // Problems rendering the graph

// Retrieve the filter graph and useful interfaces
hr = pCLGraphBuilder->GetFilterGraph(&pigb);

if (FAILED(hr))
{ // Problems retrieving the graph pointer
if (!AMGetErrorText(hr, gszScratch, 2048))
MessageBox(ghApp, "Problems retrieving the graph pointer!", APPLICATIONNAME, MB_OK);
else
MessageBox(ghApp, gszScratch, APPLICATIONNAME, MB_OK);
TearDownTheGraph();
return;
} // Problems retrieving the graph pointer

// QueryInterface for some basic interfaces
pigb->QueryInterface(IID_IMediaControl, (void **)&pimc);
pigb->QueryInterface(IID_IMediaEventEx, (void **)&pimex);
pigb->QueryInterface(IID_IVideoWindow, (void **)&pivw);

// Decrement the ref count on the filter graph
pigb->Release();

// Prepare to play in the main application window's client area

RECT rc;
GetClientRect(ghApp, &rc);
hr = pivw->put_Owner((OAHWND)ghApp);
hr = pivw->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS);
hr = pivw->SetWindowPosition(rc.left, rc.top, rc.right, rc.bottom);

// Have the graph signal event via window callbacks for performance
pimex->SetNotifyWindow((OAHWND)ghApp, WM_GRAPHNOTIFY, 0);

// Run the graph if RenderFile succeeded
pimc->Run();

} // SimpleCutList //

void TearDownTheGraph (void)

{ // TearDownTheGraph //

if (pimc)
pimc->Stop();

if (pivw)

{ // Hide the playback window first thing

pivw->put_Visible(OAFALSE);
pivw->put_Owner(NULL);

} //

HELPER_RELEASE(pimex);
HELPER_RELEASE(pimc);
HELPER_RELEASE(pivw);

// Remove the video cutlist from the filter graph to free resources
if (pCLGraphBuilder && pVideoCL)
pCLGraphBuilder->RemoveCutList(pVideoCL);

// Remove the audio cutlist from the filter graph to free resources
if (pCLGraphBuilder && pAudioCL)
pCLGraphBuilder->RemoveCutList(pAudioCL);

for (int x = 0; x < nAudElems; ++x)

{ // Release audio objects

HELPER_RELEASE(pAudCLElem[x]);
HELPER_RELEASE(pAudFileClip[x]);

} // Release audio objects

for (x = 0; x < nVidElems; ++x)

{ // Release video objects

HELPER_RELEASE(pVidCLElem[x]);
HELPER_RELEASE(pVidFileClip[x]);

} // Release video objects

HELPER_RELEASE(pVideoCL);
HELPER_RELEASE(pAudioCL);
HELPER_RELEASE(pCLGraphBuilder);

} // TearDownTheGraph //

BOOL CALLBACK DialogProc (HWND h, UINT m, WPARAM w, LPARAM l)

{ // DialogProc //

switch(m)

{ // Msg handling

case WM_INITDIALOG:
if (wDlgRes == IDD_MEDIATIMES)
SetFocus(GetDlgItem(h, IDC_TRIMIN2));
else return TRUE;
break;

case WM_COMMAND:

switch(w)

{ // Command msg handling

case IDOKTIMES:

gTheSet.List[gTheSet.nNumClips].start = GetDlgItemInt(h, IDC_TRIMIN2, NULL, FALSE);
gTheSet.List[gTheSet.nNumClips].stop = GetDlgItemInt(h, IDC_TRIMOUT2, NULL, FALSE);

EndDialog(h,1);
break;

case IDOK:
EndDialog(h,1);
break;

case IDCANCEL:
EndDialog(h,0);
break;

} // Command msg handling

break;

} // Msg handling

return 0;

} // DialogProc //

BOOL GetClipFileName (LPSTR szName)

{ // GetClipFileName //

OPENFILENAME ofn;

ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = ghApp;
ofn.lpstrFilter = NULL;
ofn.lpstrFilter = "AVI/WAV (*.avi; *.wav)\0*.avi;*.wav\0\0\0";
ofn.lpstrCustomFilter = NULL;
ofn.nFilterIndex = 1;
*szName = 0;
ofn.lpstrFile = szName;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = NULL;
ofn.lpstrFileTitle = NULL;
ofn.lpstrDefExt = "AVI;WAV";
ofn.Flags = OFN_FILEMUSTEXIST | OFN_READONLY | OFN_PATHMUSTEXIST;

return GetOpenFileName((LPOPENFILENAME)&ofn);

} // GetClipFileName //

LRESULT CALLBACK WndMainProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{ // WndMainProc //

LONG evCode;
LONG evParam1;
LONG evParam2;

switch(message)

{ // Window msgs handling

case WM_COMMAND:

switch(wParam)

{ // Program menu option

case IDM_ADDFILE:

if (GetClipFileName(gTheSet.List[gTheSet.nNumClips].szFilename))

{ // Add file

TCHAR szTitleBar[200];

DialogBox(ghInst, MAKEINTRESOURCE(wDlgRes = IDD_MEDIATIMES), ghApp, (DLGPROC)DialogProc);
gTheSet.nNumClips = gTheSet.nNumClips + 1;
wsprintf(szTitleBar, "SimpleCutList - %d clips(s) added.", gTheSet.nNumClips);
SetWindowText(ghApp, szTitleBar);

} // Add file

break;

case IDM_RUN:
if (gTheSet.nNumClips > 1)
SimpleCutList();
else
DialogBox(ghInst, MAKEINTRESOURCE(wDlgRes = IDD_LESSTHAN2), ghApp, (DLGPROC)DialogProc);
break;

case ID_FILE_ABOUT:
DialogBox(ghInst, MAKEINTRESOURCE(wDlgRes = IDD_ABOUT), ghApp, (DLGPROC)DialogProc);
break;

case ID_FILE_EXIT:
if (gTheSet.nNumClips)
TearDownTheGraph();
PostQuitMessage(0);
break;

} // Program menu option

break;

case WM_GRAPHNOTIFY:

if (!pimex)
break;

while (SUCCEEDED(pimex->GetEvent(&evCode, &evParam1, &evParam2, 0)))

{ // Spin through the events

hr = pimex->FreeEventParams(evCode, evParam1, evParam2);

if ((EC_COMPLETE == evCode) || (EC_USERABORT == evCode))

{ // Finished

TearDownTheGraph();

if (EC_USERABORT == evCode)
gTheSet.nNumClips = 0;

break;

} // Finished

} // Spin through the events

break;

case WM_DESTROY:
PostQuitMessage(0);
break;

default:
return DefWindowProc(hWnd, message, wParam, lParam);

} // Window msgs handling

return FALSE;

} // WndMainProc //

int PASCAL WinMain(HINSTANCE hInstC, HINSTANCE hInstP, LPSTR lpCmdLine, int nCmdShow)

{ // WinMain //

MSG msg;
WNDCLASS wc;

// OLE subsystem requires applications to initialize things first!
CoInitialize(NULL);

ZeroMemory(&wc, sizeof wc);
wc.lpfnWndProc = WndMainProc;
ghInst = wc.hInstance = hInstC;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszClassName = CLASSNAME;
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(hInstC, MAKEINTRESOURCE(IDI_CUTLIST));
RegisterClass(&wc);

RECT rc;

GetWindowRect(GetDesktopWindow(), &rc);
rc.right >>= 1;
rc.bottom >>= 1;

ghApp = CreateWindow(CLASSNAME,
APPLICATIONNAME,
WS_OVERLAPPEDWINDOW,
rc.right-200,
rc.bottom-200,
400,
400,
0,
0,
ghInst,
0);

ShowWindow(ghApp, SW_NORMAL);
UpdateWindow(ghApp);

ZeroMemory(&gTheSet, sizeof gTheSet);

while (GetMessage(&msg,NULL,0,0))

{ // Message loop

TranslateMessage(&msg);
DispatchMessage(&msg);

} // Message loop

// Finished with OLE subsystem
CoUninitialize();

return msg.wParam;

} // WinMain //