Initial commit: ROW Client source code
Game client codebase including: - CharacterActionControl: Character and creature management - GlobalScript: Network, items, skills, quests, utilities - RYLClient: Main client application with GUI and event handlers - Engine: 3D rendering engine (RYLGL) - MemoryManager: Custom memory allocation - Library: Third-party dependencies (DirectX, boost, etc.) - Tools: Development utilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,815 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: TimelineTest.cpp
|
||||
//
|
||||
// Desc: DirectShow sample code - creates two video tracks, using a
|
||||
// transition from the A track to the B track, and then back again.
|
||||
// It demonstrates how to add a transition to the timeline using a
|
||||
// CLSID.
|
||||
//
|
||||
// Copyright (c) 1998-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// This example creates 2 (video) tracks with a transition from the A track to
|
||||
// the B track and then from B back to A. It also crossfades two audio tracks
|
||||
// from A to B. This sample also demonstrates how to add a transition by CLSID
|
||||
// to the timeline and how to vary volume envelope properties by the
|
||||
// property setter.
|
||||
//
|
||||
// Note: Error checking is handled mostly with ASSERTs in order to keep
|
||||
// the sample as uncluttered as possible. In some cases where several
|
||||
// related function calls are made together, the HRESULT value returned from
|
||||
// the functions will be bitwise OR'ed with other HRESULT values. This value
|
||||
// will eventually be tested for failure using the FAILED macro.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <streams.h>
|
||||
#include <atlbase.h>
|
||||
#include <qedit.h>
|
||||
#include <dxutil.h>
|
||||
|
||||
#ifdef STRICT
|
||||
#undef STRICT
|
||||
#endif
|
||||
#include <dxutil.cpp>
|
||||
|
||||
//
|
||||
// Conditional compilation flags to enable/disable effects
|
||||
//
|
||||
//#define CUTS_ONLY
|
||||
|
||||
// define this to show an example of calling ConnectFrontEnd( )
|
||||
// a second time on the render engine and having it rerender
|
||||
// the graph
|
||||
#define DO_RECONNECT
|
||||
|
||||
// define this to do an audio crossfade
|
||||
#define DO_CROSSFADE
|
||||
|
||||
// define this to only render a portion of the full timeline
|
||||
#define DO_RENDERRANGE
|
||||
|
||||
// define this to enable transitions
|
||||
#define DO_TRANSITION
|
||||
|
||||
//
|
||||
// Global data
|
||||
//
|
||||
|
||||
// Use bitmaps and audio files known to install with the DirectX 8 SDK
|
||||
WCHAR * wszVideo1Name = L"dx5_logo.bmp";
|
||||
WCHAR * wszVideo2Name = L"env3.bmp";
|
||||
WCHAR * wszAudio1Name = L"track2.mp3";
|
||||
WCHAR * wszAudio2Name = L"track3.mp3";
|
||||
WCHAR * wszTitle = L"Timeline Test Sample";
|
||||
|
||||
//
|
||||
// Function prototypes
|
||||
//
|
||||
int TimelineTest( );
|
||||
void Err(TCHAR *szErr);
|
||||
|
||||
|
||||
int APIENTRY WinMain(HINSTANCE hInstance,
|
||||
HINSTANCE hPrevInstance,
|
||||
LPSTR lpCmdLine,
|
||||
int nCmdShow)
|
||||
{
|
||||
// init the ole32 libraries
|
||||
//
|
||||
CoInitialize( NULL );
|
||||
|
||||
//
|
||||
// NOTE: There is no user interaction with this sample.
|
||||
// It will run to completion and exit.
|
||||
//
|
||||
TimelineTest();
|
||||
|
||||
CoUninitialize( );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void Err(TCHAR *szErr)
|
||||
{
|
||||
MessageBox(NULL, szErr, TEXT("Error"), MB_ICONEXCLAMATION);
|
||||
}
|
||||
|
||||
|
||||
int TimelineTest( )
|
||||
{
|
||||
USES_CONVERSION;
|
||||
HRESULT hr;
|
||||
|
||||
// use the ATL libraries to do automatic reference counting on pointers
|
||||
//
|
||||
CComPtr< IRenderEngine > pRenderEngine;
|
||||
CComPtr< IGraphBuilder > pGraph;
|
||||
CComPtr< IVideoWindow > pVidWindow;
|
||||
CComPtr< IMediaEvent > pEvent;
|
||||
CComPtr< IAMTimeline > pTimeline;
|
||||
CComPtr< IAMTimelineObj > pVideoGroupObj;
|
||||
CComPtr< IAMTimelineObj > pAudioGroupObj;
|
||||
CComPtr< IMediaControl > pControl;
|
||||
CComPtr< IMediaSeeking > pSeeking;
|
||||
|
||||
//--------------------------------------------
|
||||
// make the timeline
|
||||
//--------------------------------------------
|
||||
|
||||
hr = CoCreateInstance(
|
||||
CLSID_AMTimeline,
|
||||
NULL,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_IAMTimeline,
|
||||
(void**) &pTimeline
|
||||
);
|
||||
|
||||
if(FAILED( hr )) {
|
||||
Err(_T("Could not create timeline"));
|
||||
return hr;
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
||||
// make the root group/composition
|
||||
//--------------------------------------------
|
||||
|
||||
hr = pTimeline->CreateEmptyNode( &pVideoGroupObj, TIMELINE_MAJOR_TYPE_GROUP );
|
||||
if(FAILED( hr ))
|
||||
{
|
||||
Err(_T("Could not create empty node"));
|
||||
return hr;
|
||||
}
|
||||
|
||||
CComQIPtr< IAMTimelineGroup, &IID_IAMTimelineGroup > pVideoGroup( pVideoGroupObj );
|
||||
CMediaType VideoGroupType;
|
||||
|
||||
// all we set is the major type. The group will automatically use other defaults
|
||||
VideoGroupType.SetType( &MEDIATYPE_Video );
|
||||
hr = pVideoGroup->SetMediaType( &VideoGroupType );
|
||||
if(FAILED( hr ))
|
||||
{
|
||||
Err(_T("Could not set media type"));
|
||||
return hr;
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
||||
// add the group to the timeline
|
||||
//--------------------------------------------
|
||||
|
||||
hr = pTimeline->AddGroup( pVideoGroupObj );
|
||||
if(FAILED( hr ))
|
||||
{
|
||||
Err(_T("Could not add video group"));
|
||||
return hr;
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
||||
// make a track
|
||||
//--------------------------------------------
|
||||
|
||||
CComPtr< IAMTimelineObj > pTrack1Obj;
|
||||
hr = pTimeline->CreateEmptyNode( &pTrack1Obj, TIMELINE_MAJOR_TYPE_TRACK );
|
||||
if(FAILED( hr ))
|
||||
{
|
||||
Err(_T("Could not create empty track"));
|
||||
return hr;
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
||||
// tell the composition about the track
|
||||
//--------------------------------------------
|
||||
|
||||
CComQIPtr< IAMTimelineComp, &IID_IAMTimelineComp > pRootComp( pVideoGroupObj );
|
||||
hr = pRootComp->VTrackInsBefore( pTrack1Obj, -1 );
|
||||
if(FAILED( hr ))
|
||||
{
|
||||
Err(_T("Could not insert track"));
|
||||
return hr;
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
||||
// create a source from 0 to 8 seconds
|
||||
//--------------------------------------------
|
||||
|
||||
REFERENCE_TIME TLStart = 0 * UNITS;
|
||||
REFERENCE_TIME TLStop = 8 * UNITS;
|
||||
|
||||
// you can set these if you want to other numbers, and the video will
|
||||
// speed up or slow down if the duration isn't the same as the timeline's.
|
||||
REFERENCE_TIME MediaStart = 0 * UNITS;
|
||||
REFERENCE_TIME MediaStop = 8 * UNITS;
|
||||
WCHAR pClipname[256];
|
||||
TCHAR * tBasePath = (TCHAR *) DXUtil_GetDXSDKMediaPath( );
|
||||
wcscpy( pClipname, T2W( tBasePath ) );
|
||||
wcscat( pClipname, L"\\" );
|
||||
wcscat( pClipname, wszVideo1Name );
|
||||
|
||||
// create the timeline source
|
||||
//
|
||||
CComPtr<IAMTimelineObj> pSource1Obj;
|
||||
hr = pTimeline->CreateEmptyNode( &pSource1Obj, TIMELINE_MAJOR_TYPE_SOURCE );
|
||||
if(FAILED( hr ))
|
||||
{
|
||||
Err(_T("Could not create the timeline source"));
|
||||
return hr;
|
||||
}
|
||||
|
||||
// set up source right
|
||||
//
|
||||
hr = pSource1Obj->SetStartStop( TLStart, TLStop );
|
||||
CComQIPtr< IAMTimelineSrc, &IID_IAMTimelineSrc > pSource1Src( pSource1Obj );
|
||||
hr |= pSource1Src->SetMediaTimes( MediaStart, MediaStop );
|
||||
hr |= pSource1Src->SetMediaName( pClipname );
|
||||
if(FAILED( hr ))
|
||||
{
|
||||
Err(_T("Could not configure media source"));
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
||||
// tell the track about the source
|
||||
//--------------------------------------------
|
||||
|
||||
CComQIPtr< IAMTimelineTrack, &IID_IAMTimelineTrack > pTrack1( pTrack1Obj );
|
||||
hr = pTrack1->SrcAdd( pSource1Obj );
|
||||
if(FAILED( hr ))
|
||||
{
|
||||
Err(_T("Could not add source to track"));
|
||||
return hr;
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
||||
// make another track
|
||||
//--------------------------------------------
|
||||
|
||||
CComPtr< IAMTimelineObj > pTrack2Obj;
|
||||
hr = pTimeline->CreateEmptyNode( &pTrack2Obj, TIMELINE_MAJOR_TYPE_TRACK );
|
||||
if(FAILED( hr ))
|
||||
{
|
||||
Err(_T("Could not create second track"));
|
||||
return hr;
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
||||
// tell the composition about the track
|
||||
//--------------------------------------------
|
||||
|
||||
hr = pRootComp->VTrackInsBefore( pTrack2Obj, -1 );
|
||||
if(FAILED( hr ))
|
||||
{
|
||||
Err(_T("Could not insert second track"));
|
||||
return hr;
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
||||
// create a source for the 2nd track
|
||||
//--------------------------------------------
|
||||
|
||||
TLStart = 0 * UNITS;
|
||||
TLStop = 8 * UNITS;
|
||||
MediaStart = 0 * UNITS;
|
||||
MediaStop = 8 * UNITS;
|
||||
wcscpy( pClipname, T2W( tBasePath ) );
|
||||
wcscat( pClipname, L"\\" );
|
||||
wcscat( pClipname, wszVideo2Name );
|
||||
|
||||
// create the timeline source
|
||||
//
|
||||
CComPtr<IAMTimelineObj> pSource2Obj;
|
||||
hr = pTimeline->CreateEmptyNode( &pSource2Obj, TIMELINE_MAJOR_TYPE_SOURCE );
|
||||
if(FAILED( hr ))
|
||||
{
|
||||
Err(_T("Could not create the second timeline source"));
|
||||
return hr;
|
||||
}
|
||||
|
||||
// set up source right
|
||||
//
|
||||
hr = pSource2Obj->SetStartStop( TLStart, TLStop );
|
||||
CComQIPtr< IAMTimelineSrc, &IID_IAMTimelineSrc > pSource2Src( pSource2Obj );
|
||||
hr |= pSource2Src->SetMediaTimes( MediaStart, MediaStop );
|
||||
hr |= pSource2Src->SetMediaName( pClipname );
|
||||
if(FAILED( hr ))
|
||||
{
|
||||
Err(_T("Could not configure second media source"));
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
||||
// tell the track about the source
|
||||
//--------------------------------------------
|
||||
|
||||
CComQIPtr< IAMTimelineTrack, &IID_IAMTimelineTrack > pTrack2( pTrack2Obj );
|
||||
hr = pTrack2->SrcAdd( pSource2Obj );
|
||||
if(FAILED( hr ))
|
||||
{
|
||||
Err(_T("Could not add second track"));
|
||||
return hr;
|
||||
}
|
||||
|
||||
CComQIPtr< IAMTimelineTransable, &IID_IAMTimelineTransable > pTransable( pTrack2 );
|
||||
|
||||
|
||||
#ifdef DO_TRANSITION
|
||||
|
||||
//---------------------------------------------
|
||||
// create an transition on the track from A 2 B
|
||||
//---------------------------------------------
|
||||
|
||||
REFERENCE_TIME TransStart = 0 * UNITS;
|
||||
REFERENCE_TIME TransStop = 4 * UNITS;
|
||||
|
||||
// create the timeline effect
|
||||
//
|
||||
CComPtr<IAMTimelineObj> pTrackTransObj;
|
||||
hr = pTimeline->CreateEmptyNode(
|
||||
&pTrackTransObj,
|
||||
TIMELINE_MAJOR_TYPE_TRANSITION );
|
||||
if(FAILED( hr ))
|
||||
{
|
||||
Err(_T("Could not create transition effect"));
|
||||
return hr;
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
||||
// set up filter right
|
||||
//--------------------------------------------
|
||||
|
||||
// we set the CLSID of the DXT to use instead of a pointer to the
|
||||
// actual object. We let the DXT have it's default properties.
|
||||
//
|
||||
hr = pTrackTransObj->SetSubObjectGUID( CLSID_DxtJpeg );
|
||||
hr |= pTrackTransObj->SetStartStop( TransStart, TransStop );
|
||||
CComQIPtr< IAMTimelineTrans, &IID_IAMTimelineTrans > pTrackTrans( pTrackTransObj );
|
||||
hr |= pTransable->TransAdd( pTrackTransObj );
|
||||
if(FAILED( hr ))
|
||||
{
|
||||
Err(_T("Could not configure transition object"));
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
#ifdef CUTS_ONLY
|
||||
//---------------------------------------------
|
||||
// turn the transition into a cut by doing this
|
||||
//---------------------------------------------
|
||||
|
||||
hr = pTrackTrans->SetCutsOnly( TRUE );
|
||||
if(FAILED( hr ))
|
||||
{
|
||||
Err(_T("Could not SetCutsOnly to TRUE"));
|
||||
return hr;
|
||||
}
|
||||
|
||||
#endif // CUTS_ONLY
|
||||
|
||||
//---------------------------------------------
|
||||
// create an transition on the track from B 2 A
|
||||
//---------------------------------------------
|
||||
|
||||
TransStart = 4 * UNITS;
|
||||
TransStop = 8 * UNITS;
|
||||
|
||||
// create the timeline effect
|
||||
//
|
||||
pTrackTransObj.Release( );
|
||||
hr = pTimeline->CreateEmptyNode(
|
||||
&pTrackTransObj,
|
||||
TIMELINE_MAJOR_TYPE_TRANSITION );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
// set up filter right
|
||||
//
|
||||
hr = pTrackTransObj->SetSubObjectGUID( CLSID_DxtJpeg );
|
||||
hr |= pTrackTransObj->SetStartStop( TransStart, TransStop );
|
||||
pTrackTrans = pTrackTransObj;
|
||||
hr |= pTrackTrans->SetSwapInputs( TRUE );
|
||||
hr |= pTransable->TransAdd( pTrackTransObj );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//--------------------------------------------
|
||||
// set a property on the transition
|
||||
//--------------------------------------------
|
||||
|
||||
CComPtr< IPropertySetter > pTransSetter;
|
||||
pTransSetter.CoCreateInstance( CLSID_PropertySetter );
|
||||
DEXTER_PARAM Param;
|
||||
CComBSTR ParamName( "MaskNum" ); // the property name
|
||||
Param.Name = ParamName;
|
||||
Param.nValues = 1; // how many values we want to set
|
||||
DEXTER_VALUE Value;
|
||||
memset( &Value, 0, sizeof( Value ) );
|
||||
VariantClear( &Value.v );
|
||||
V_I4( &Value.v ) = 128; // mask number 128
|
||||
V_VT( &Value.v ) = VT_I4; // integer
|
||||
hr = pTransSetter->AddProp( Param, &Value );
|
||||
hr |= pTrackTransObj->SetPropertySetter( pTransSetter );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
// pTransSetter will be auto-freed by COM
|
||||
|
||||
#endif // DO_TRANSITION
|
||||
|
||||
#ifdef CUTS_ONLY
|
||||
//---------------------------------------------
|
||||
// turn the transition into a cut by doing this
|
||||
//---------------------------------------------
|
||||
|
||||
hr = pTrackTrans->SetCutsOnly( TRUE );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
#endif
|
||||
|
||||
//--------------------------------------------
|
||||
// make the root audio group/composition
|
||||
//--------------------------------------------
|
||||
|
||||
hr = pTimeline->CreateEmptyNode( &pAudioGroupObj, TIMELINE_MAJOR_TYPE_GROUP );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
CComQIPtr< IAMTimelineGroup, &IID_IAMTimelineGroup > pAudioGroup( pAudioGroupObj );
|
||||
CMediaType AudioGroupType;
|
||||
// all we set is the major type. The group will automatically use other defaults
|
||||
AudioGroupType.SetType( &MEDIATYPE_Audio );
|
||||
hr = pAudioGroup->SetMediaType( &AudioGroupType );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//--------------------------------------------
|
||||
// add the group to the timeline
|
||||
//--------------------------------------------
|
||||
|
||||
hr = pTimeline->AddGroup( pAudioGroupObj );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//--------------------------------------------
|
||||
// make a track
|
||||
//--------------------------------------------
|
||||
|
||||
CComPtr< IAMTimelineObj > pTrack3Obj;
|
||||
hr = pTimeline->CreateEmptyNode( &pTrack3Obj, TIMELINE_MAJOR_TYPE_TRACK );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//--------------------------------------------
|
||||
// tell the composition about the track
|
||||
//--------------------------------------------
|
||||
|
||||
CComQIPtr< IAMTimelineComp, &IID_IAMTimelineComp > pAudioComp( pAudioGroupObj );
|
||||
hr = pAudioComp->VTrackInsBefore( pTrack3Obj, -1 );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//--------------------------------------------
|
||||
// create a source
|
||||
//--------------------------------------------
|
||||
|
||||
TLStart = 0 * UNITS;
|
||||
TLStop = 6 * UNITS;
|
||||
// you can set these if you want to other numbers, the video will speed up
|
||||
// or slow down if the duration isn't the same at the timeline's.
|
||||
MediaStart = 0 * UNITS;
|
||||
MediaStop = 6 * UNITS;
|
||||
wcscpy( pClipname, T2W( tBasePath ) );
|
||||
wcscat( pClipname, L"\\" );
|
||||
wcscat( pClipname, wszAudio1Name );
|
||||
|
||||
// create the timeline source
|
||||
//
|
||||
CComPtr<IAMTimelineObj> pSource3Obj;
|
||||
hr = pTimeline->CreateEmptyNode( &pSource3Obj, TIMELINE_MAJOR_TYPE_SOURCE );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
// set up source right
|
||||
//
|
||||
hr = pSource3Obj->SetStartStop( TLStart, TLStop );
|
||||
CComQIPtr< IAMTimelineSrc, &IID_IAMTimelineSrc > pSource3Src( pSource3Obj );
|
||||
hr |= pSource3Src->SetMediaTimes( MediaStart, MediaStop );
|
||||
hr |= pSource3Src->SetMediaName( pClipname );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//--------------------------------------------
|
||||
// tell the track about the source
|
||||
//--------------------------------------------
|
||||
|
||||
CComQIPtr< IAMTimelineTrack, &IID_IAMTimelineTrack > pTrack3( pTrack3Obj );
|
||||
hr = pTrack3->SrcAdd( pSource3Obj );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
#ifdef DO_CROSSFADE
|
||||
//--------------------------------------------
|
||||
// put a volume effect on the source
|
||||
//--------------------------------------------
|
||||
|
||||
TLStart = 4 * UNITS;
|
||||
TLStop = 6 * UNITS;
|
||||
|
||||
CComPtr< IAMTimelineObj > pTrack3FxObj;
|
||||
hr = pTimeline->CreateEmptyNode( &pTrack3FxObj, TIMELINE_MAJOR_TYPE_EFFECT );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
// set up effect right
|
||||
//
|
||||
hr = pTrack3FxObj->SetStartStop( TLStart, TLStop );
|
||||
hr |= pTrack3FxObj->SetSubObjectGUID( CLSID_AudMixer );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
// add the effect
|
||||
//
|
||||
CComQIPtr< IAMTimelineEffectable , &IID_IAMTimelineEffectable > pTrack3Fable( pTrack3 );
|
||||
hr = pTrack3Fable->EffectInsBefore( pTrack3FxObj, -1 );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//------------------------------------------------
|
||||
// set the the volume envelope on the audio source
|
||||
//------------------------------------------------
|
||||
|
||||
CComPtr< IPropertySetter > pVolSetter;
|
||||
pVolSetter.CoCreateInstance( CLSID_PropertySetter );
|
||||
CComBSTR VolParamName( "Vol" ); // the property name
|
||||
Param.Name = VolParamName;
|
||||
Param.nValues = 2; // how many values we want to set
|
||||
|
||||
DEXTER_VALUE AudioValue[2];
|
||||
memset( &AudioValue[0], 0, sizeof( Value ) );
|
||||
VariantClear( &AudioValue[0].v );
|
||||
V_R8( &AudioValue[0].v ) = 1.0;
|
||||
V_VT( &AudioValue[0].v ) = VT_R8;
|
||||
AudioValue[0].rt = 0 * UNITS;
|
||||
memset( &AudioValue[1], 0, sizeof( Value ) );
|
||||
VariantClear( &AudioValue[1].v );
|
||||
V_R8( &AudioValue[1].v ) = 0.0;
|
||||
V_VT( &AudioValue[1].v ) = VT_R8;
|
||||
AudioValue[1].rt = 2 * UNITS;
|
||||
AudioValue[1].dwInterp = DEXTERF_INTERPOLATE;
|
||||
|
||||
hr = pVolSetter->AddProp( Param, AudioValue );
|
||||
hr |= pTrack3FxObj->SetPropertySetter( pVolSetter );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
pVolSetter.Release( );
|
||||
#endif // DO_CROSSFADE
|
||||
|
||||
//--------------------------------------------
|
||||
// make another track
|
||||
//--------------------------------------------
|
||||
|
||||
CComPtr< IAMTimelineObj > pTrack4Obj;
|
||||
hr = pTimeline->CreateEmptyNode( &pTrack4Obj, TIMELINE_MAJOR_TYPE_TRACK );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//--------------------------------------------
|
||||
// tell the composition about the track
|
||||
//--------------------------------------------
|
||||
|
||||
hr = pAudioComp->VTrackInsBefore( pTrack4Obj, -1 );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//--------------------------------------------
|
||||
// create a source for the 2nd track
|
||||
//--------------------------------------------
|
||||
|
||||
TLStart = 4 * UNITS;
|
||||
TLStop = 8 * UNITS;
|
||||
MediaStart = 0 * UNITS;
|
||||
MediaStop = 4 * UNITS;
|
||||
wcscpy( pClipname, T2W( tBasePath ) );
|
||||
wcscat( pClipname, L"\\" );
|
||||
wcscat( pClipname, wszAudio2Name );
|
||||
|
||||
// create the timeline source
|
||||
//
|
||||
CComPtr<IAMTimelineObj> pSource4Obj;
|
||||
hr = pTimeline->CreateEmptyNode( &pSource4Obj, TIMELINE_MAJOR_TYPE_SOURCE );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
// set up source right
|
||||
//
|
||||
hr = pSource4Obj->SetStartStop( TLStart, TLStop );
|
||||
CComQIPtr< IAMTimelineSrc, &IID_IAMTimelineSrc > pSource4Src( pSource4Obj );
|
||||
hr |= pSource4Src->SetMediaTimes( MediaStart, MediaStop );
|
||||
hr |= pSource4Src->SetMediaName( pClipname );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//--------------------------------------------
|
||||
// tell the track about the source
|
||||
//--------------------------------------------
|
||||
|
||||
CComQIPtr< IAMTimelineTrack, &IID_IAMTimelineTrack > pTrack4( pTrack4Obj );
|
||||
hr = pTrack4->SrcAdd( pSource4Obj );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
#ifdef DO_CROSSFADE
|
||||
//--------------------------------------------
|
||||
// put a volume effect on the source
|
||||
//--------------------------------------------
|
||||
|
||||
TLStart = 4 * UNITS;
|
||||
TLStop = 6 * UNITS;
|
||||
|
||||
CComPtr< IAMTimelineObj > pTrack4FxObj;
|
||||
hr = pTimeline->CreateEmptyNode( &pTrack4FxObj, TIMELINE_MAJOR_TYPE_EFFECT );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
// set up effect riht
|
||||
//
|
||||
hr = pTrack4FxObj->SetStartStop( TLStart, TLStop );
|
||||
hr |= pTrack4FxObj->SetSubObjectGUID( CLSID_AudMixer );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
// add the effect
|
||||
//
|
||||
CComQIPtr< IAMTimelineEffectable , &IID_IAMTimelineEffectable > pTrack4Fable( pTrack4 );
|
||||
hr = pTrack4Fable->EffectInsBefore( pTrack4FxObj, -1 );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//------------------------------------------------
|
||||
// set the the volume envelope on the audio source
|
||||
//------------------------------------------------
|
||||
|
||||
pVolSetter.CoCreateInstance( CLSID_PropertySetter );
|
||||
memset( &AudioValue[0], 0, sizeof( Value ) );
|
||||
VariantClear( &AudioValue[0].v );
|
||||
V_R8( &AudioValue[0].v ) = 0.0;
|
||||
V_VT( &AudioValue[0].v ) = VT_R8;
|
||||
AudioValue[0].rt = 0 * UNITS;
|
||||
memset( &AudioValue[1], 0, sizeof( Value ) );
|
||||
VariantClear( &AudioValue[1].v );
|
||||
V_R8( &AudioValue[1].v ) = 1.0;
|
||||
V_VT( &AudioValue[1].v ) = VT_R8;
|
||||
AudioValue[1].rt = 2 * UNITS;
|
||||
AudioValue[1].dwInterp = DEXTERF_INTERPOLATE;
|
||||
|
||||
hr = pVolSetter->AddProp( Param, AudioValue );
|
||||
hr |= pTrack4FxObj->SetPropertySetter( pVolSetter );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
// pVolSetter will be auto-freed by COM
|
||||
#endif // DO_CROSSFADE
|
||||
|
||||
//----------------------------------------------
|
||||
// make sure files are in their correct location
|
||||
//----------------------------------------------
|
||||
|
||||
hr = pTimeline->ValidateSourceNames(
|
||||
SFN_VALIDATEF_CHECK | SFN_VALIDATEF_POPUP | SFN_VALIDATEF_REPLACE,
|
||||
NULL,
|
||||
0 );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//--------------------------------------------
|
||||
// create the render engine
|
||||
//--------------------------------------------
|
||||
|
||||
hr = CoCreateInstance(
|
||||
CLSID_RenderEngine,
|
||||
NULL,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_IRenderEngine,
|
||||
(void**) &pRenderEngine );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
// tell the render engine about the timeline it should look at
|
||||
//
|
||||
hr = pRenderEngine->SetTimelineObject( pTimeline );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//--------------------------------------------
|
||||
// connect up the front end, then the back end
|
||||
//--------------------------------------------
|
||||
|
||||
hr = pRenderEngine->ConnectFrontEnd( );
|
||||
hr |= pRenderEngine->RenderOutputPins( );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//--------------------------------------------
|
||||
// get a bunch of pointers, then run the graph
|
||||
//--------------------------------------------
|
||||
|
||||
hr = pRenderEngine->GetFilterGraph( &pGraph );
|
||||
hr |= pGraph->QueryInterface( IID_IMediaEvent, (void**) &pEvent );
|
||||
hr |= pGraph->QueryInterface( IID_IMediaControl, (void**) &pControl );
|
||||
hr |= pGraph->QueryInterface( IID_IMediaSeeking, (void**) &pSeeking );
|
||||
hr |= pGraph->QueryInterface( IID_IVideoWindow, (void**) &pVidWindow );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//--------------------------------------------
|
||||
// give the main window a meaningful title
|
||||
//--------------------------------------------
|
||||
|
||||
BSTR bstrCaption;
|
||||
WriteBSTR(&bstrCaption, wszTitle);
|
||||
hr = pVidWindow->put_Caption(bstrCaption);
|
||||
FreeBSTR(&bstrCaption);
|
||||
|
||||
//--------------------------------------------
|
||||
// since no user interaction is allowed, remove
|
||||
// system menu and maximize/minimize buttons
|
||||
//--------------------------------------------
|
||||
long lStyle=0;
|
||||
hr = pVidWindow->get_WindowStyle(&lStyle);
|
||||
lStyle &= ~(WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU);
|
||||
hr = pVidWindow->put_WindowStyle(lStyle);
|
||||
|
||||
//--------------------------------------------
|
||||
// run it
|
||||
//--------------------------------------------
|
||||
|
||||
hr = pControl->Run( );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//--------------------------------------------
|
||||
// wait for it
|
||||
//--------------------------------------------
|
||||
|
||||
long EventCode = 0;
|
||||
hr = pEvent->WaitForCompletion( -1, &EventCode );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
REFERENCE_TIME Start = 0;
|
||||
|
||||
#ifdef DO_RENDERRANGE
|
||||
|
||||
// seek the timeline back to 0
|
||||
//
|
||||
hr = pSeeking->SetPositions( &Start, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
hr = pRenderEngine->SetRenderRange2( 2.0, 6.0 );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//------------------------------------------------------
|
||||
// connect up the front end, then the back end if needed
|
||||
//------------------------------------------------------
|
||||
|
||||
hr = pRenderEngine->ConnectFrontEnd( );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
if(hr == S_WARN_OUTPUTRESET) {
|
||||
hr |= pRenderEngine->RenderOutputPins( );
|
||||
}
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//--------------------------------------------
|
||||
// run it
|
||||
//--------------------------------------------
|
||||
|
||||
hr = pControl->Run( );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//--------------------------------------------
|
||||
// wait for it
|
||||
//--------------------------------------------
|
||||
|
||||
hr = pEvent->WaitForCompletion( -1, &EventCode );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
#endif // DO_RENDERRANGE
|
||||
|
||||
#ifdef DO_RECONNECT
|
||||
|
||||
//---------------------------------------------
|
||||
// make a change to the timeline, however small
|
||||
//---------------------------------------------
|
||||
|
||||
CComPtr< IAMTimelineObj > pTransObj;
|
||||
REFERENCE_TIME InOut = -1;
|
||||
pTransable->GetNextTrans( &pTransObj, &InOut );
|
||||
CComQIPtr< IAMTimelineTrans, &IID_IAMTimelineTrans > pTrans( pTransObj );
|
||||
pTrans->SetCutsOnly( TRUE );
|
||||
pTransObj.Release( );
|
||||
pTrans.Release( );
|
||||
hr = pTransable->GetNextTrans( &pTransObj, &InOut );
|
||||
pTrans = pTransObj;
|
||||
hr |= pTrans->SetCutsOnly( TRUE );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
// seek the timeline back to 0
|
||||
//
|
||||
hr = pSeeking->SetPositions( &Start, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//------------------------------------------------------
|
||||
// connect up the front end, then the back end if needed
|
||||
//------------------------------------------------------
|
||||
|
||||
hr = pRenderEngine->ConnectFrontEnd( );
|
||||
if(hr == S_WARN_OUTPUTRESET) {
|
||||
hr |= pRenderEngine->RenderOutputPins( );
|
||||
}
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//--------------------------------------------
|
||||
// run it
|
||||
//--------------------------------------------
|
||||
|
||||
hr = pControl->Run( );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
|
||||
//--------------------------------------------
|
||||
// wait for it
|
||||
//--------------------------------------------
|
||||
|
||||
hr = pEvent->WaitForCompletion( -1, &EventCode );
|
||||
ASSERT( !FAILED( hr ) );
|
||||
#endif // DO_RECONNECT
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user