Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code: - Client: Game client source (moved to Client/Client/) - Server: Game server source - GameTools: Development tools - CryptoSource: Encryption utilities - database: Database scripts - Script: Game scripts - rylCoder_16.02.2008_src: Legacy coder tools - GMFont, Game: Additional resources 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
763
GameTools/SoundLib/DMusic_OggLoader.cpp
Normal file
763
GameTools/SoundLib/DMusic_OggLoader.cpp
Normal file
@@ -0,0 +1,763 @@
|
||||
|
||||
#include "DMusic_OggLoader.h"
|
||||
|
||||
#include "OggFile.h"
|
||||
|
||||
#include <tchar.h>
|
||||
#include <atlbase.h>
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
#ifndef RELEASE
|
||||
#define RELEASE(x) { if(x) (x)->Release(); x = NULL; }
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
struct SWaveHeader
|
||||
{
|
||||
char ChunkID[4];
|
||||
DWORD ChunkSize;
|
||||
char Format[4];
|
||||
char SubChunk1ID[4];
|
||||
DWORD SubChunk1Size;
|
||||
WORD AudioFormat;
|
||||
WORD NumChannels;
|
||||
DWORD SampleRate;
|
||||
DWORD ByteRate;
|
||||
WORD BlockAlign;
|
||||
WORD BitsPerSample;
|
||||
char SubChunk2ID[4];
|
||||
DWORD SubChunk2Size;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
COggStream::COggStream()
|
||||
: m_cRef( 1 )
|
||||
, m_pLoader( NULL )
|
||||
, m_pOggFile( new COGGFile )
|
||||
|
||||
, m_pWaveHeader( new SWaveHeader )
|
||||
, m_TotalWaveBytes( 0 )
|
||||
, m_SeekPos( -sizeof( SWaveHeader ) )
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
COggStream::~COggStream()
|
||||
{
|
||||
Detach();
|
||||
|
||||
delete m_pOggFile;
|
||||
delete m_pWaveHeader;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
HRESULT COggStream::Attach( LPCTSTR tzFile, IDirectMusicLoader * pLoader )
|
||||
{
|
||||
Detach();
|
||||
|
||||
m_pOggFile->Create( tzFile );
|
||||
|
||||
m_pLoader = pLoader;
|
||||
pLoader->AddRef();
|
||||
|
||||
//Wave 헤더를 채워넣음.
|
||||
m_TotalWaveBytes = m_pOggFile->SeekWaveData( 0, ISoundFile::seek_end );
|
||||
m_pOggFile->SeekWaveData( 0, ISoundFile::seek_begin );
|
||||
|
||||
memcpy( m_pWaveHeader->ChunkID, "RIFF", 4 ); //null 문자를 넣지 않기 위해 strcpy 대신 memcpy로 복사함.
|
||||
m_pWaveHeader->ChunkSize = m_TotalWaveBytes + 36; //36 == sizeof( SWaveHeader ) - sizeof( m_pWaveHeader->m_ChunkID ) - sizeof( m_pWaveHeader->m_ChunkSize )
|
||||
memcpy( m_pWaveHeader->Format, "WAVE", 4 );
|
||||
memcpy( m_pWaveHeader->SubChunk1ID, "fmt ", 4 );
|
||||
m_pWaveHeader->SubChunk1Size = 16;
|
||||
m_pWaveHeader->AudioFormat = WAVE_FORMAT_PCM;
|
||||
m_pWaveHeader->NumChannels = m_pOggFile->GetChannelCount();
|
||||
m_pWaveHeader->SampleRate = m_pOggFile->GetSamplePerSec();
|
||||
m_pWaveHeader->BlockAlign = m_pOggFile->GetBitsPerSample() * m_pOggFile->GetChannelCount() / 8;
|
||||
m_pWaveHeader->ByteRate = m_pWaveHeader->BlockAlign * m_pWaveHeader->SampleRate;
|
||||
m_pWaveHeader->BitsPerSample = m_pOggFile->GetBitsPerSample();
|
||||
memcpy( m_pWaveHeader->SubChunk2ID, "data", 4 );
|
||||
m_pWaveHeader->SubChunk2Size = m_TotalWaveBytes;
|
||||
|
||||
m_SeekPos = -sizeof( SWaveHeader );
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
void COggStream::Detach()
|
||||
{
|
||||
m_pOggFile->Destroy();
|
||||
|
||||
RELEASE( m_pLoader );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
MUSIC_TIME COggStream::GetMusicTime()
|
||||
{
|
||||
DWORD cbSamples = m_TotalWaveBytes / ( m_pWaveHeader->NumChannels * ( m_pWaveHeader->BitsPerSample / 8 ) );
|
||||
|
||||
// At 120 bpm (2 beats per second) and 768 music-time ticks per beat,
|
||||
// we have 1536 ticks per second.
|
||||
//
|
||||
|
||||
return (cbSamples * 2 * DMUS_PPQ) / m_pWaveHeader->SampleRate;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
//IUnknown methods
|
||||
STDMETHODIMP COggStream::QueryInterface( REFIID iid, void ** ppv )
|
||||
{
|
||||
*ppv = NULL;
|
||||
|
||||
if (iid == IID_IUnknown || iid == IID_ISequentialStream)
|
||||
{
|
||||
// ISequentialStream is the base class for IStream, which
|
||||
// provides only sequential file I/O.
|
||||
//
|
||||
*ppv = (void*)static_cast<ISequentialStream*>(this);
|
||||
}
|
||||
else if (iid == IID_IStream)
|
||||
{
|
||||
// IStream adds the concept of a file pointer to the
|
||||
// sequential stream.
|
||||
//
|
||||
*ppv = (void*)static_cast<IStream*>(this);
|
||||
}
|
||||
else if (iid == IID_IDirectMusicGetLoader)
|
||||
{
|
||||
// This is a DirectMusic specific interface to get back
|
||||
// the loader that created this IStream.
|
||||
//
|
||||
*ppv = (void*)static_cast<IDirectMusicGetLoader*>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
STDMETHODIMP_(ULONG) COggStream::AddRef()
|
||||
{
|
||||
return InterlockedIncrement( &m_cRef );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
STDMETHODIMP_(ULONG) COggStream::Release()
|
||||
{
|
||||
if( InterlockedDecrement( &m_cRef ) == 0 )
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m_cRef;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
//IDirectMusicGetLoader
|
||||
STDMETHODIMP COggStream::GetLoader( IDirectMusicLoader ** ppLoader )
|
||||
{
|
||||
m_pLoader->AddRef();
|
||||
*ppLoader = m_pLoader;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
//IStream methods
|
||||
STDMETHODIMP COggStream::Read( void * pv, ULONG cb, ULONG * pcb )
|
||||
{
|
||||
if( m_pLoader == NULL )
|
||||
return E_FAIL;
|
||||
|
||||
if( m_SeekPos < 0 )
|
||||
{
|
||||
char * pWaveHeader = (char*)m_pWaveHeader;
|
||||
|
||||
if( m_SeekPos + long(cb) >= 0 )
|
||||
{
|
||||
//WaveHeader와 Ogg 데이터 사이에 m_SeekPos가 끼어 있으므로....
|
||||
//WaveHeader의 데이터를 먼저 복사...
|
||||
DWORD writeSize1 = -m_SeekPos;
|
||||
memcpy( pv, pWaveHeader + m_SeekPos + sizeof( SWaveHeader ), writeSize1 );
|
||||
pv = (char*)pv + writeSize1;
|
||||
|
||||
DWORD writeSize2 = cb - writeSize1;
|
||||
m_pOggFile->SeekWaveData( 0, ISoundFile::seek_begin );
|
||||
size_t BytesWritten2 = m_pOggFile->Read( pv, writeSize2 );
|
||||
|
||||
m_SeekPos += cb;
|
||||
|
||||
if( pcb )
|
||||
{
|
||||
*pcb = writeSize1 + BytesWritten2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy( pv, pWaveHeader + m_SeekPos + sizeof( SWaveHeader ), cb );
|
||||
m_SeekPos += cb;
|
||||
|
||||
if( pcb )
|
||||
{
|
||||
*pcb = cb;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t BytesWritten = m_pOggFile->Read( pv, cb );
|
||||
m_SeekPos += BytesWritten;
|
||||
|
||||
if( pcb )
|
||||
{
|
||||
*pcb = BytesWritten;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
STDMETHODIMP COggStream::Seek( LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER * plibNewPosition )
|
||||
{
|
||||
if( m_pLoader == NULL )
|
||||
return E_FAIL;
|
||||
|
||||
long offset = dlibMove.LowPart;
|
||||
|
||||
if( dwOrigin == FILE_BEGIN )
|
||||
{
|
||||
m_SeekPos = offset - sizeof( SWaveHeader );
|
||||
}
|
||||
else if( dwOrigin == FILE_END )
|
||||
{
|
||||
m_SeekPos = m_TotalWaveBytes + offset - sizeof( SWaveHeader );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_SeekPos += offset;
|
||||
}
|
||||
|
||||
if( m_SeekPos >= 0 )
|
||||
{
|
||||
m_pOggFile->SeekWaveData( m_SeekPos, ISoundFile::seek_begin );
|
||||
}
|
||||
|
||||
if( plibNewPosition )
|
||||
{
|
||||
plibNewPosition->HighPart = dlibMove.HighPart;
|
||||
plibNewPosition->LowPart = m_SeekPos + sizeof( SWaveHeader );
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
STDMETHODIMP COggStream::Clone( IStream ** ppstm )
|
||||
{
|
||||
COggStream * pOther = new COggStream;
|
||||
|
||||
if( pOther == NULL )
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
if( m_pOggFile )
|
||||
{
|
||||
HRESULT hr = pOther->Attach( m_pOggFile->GetFilename(), m_pLoader );
|
||||
|
||||
if( SUCCEEDED( hr ) )
|
||||
{
|
||||
LARGE_INTEGER liNewPosition;
|
||||
|
||||
liNewPosition.QuadPart = m_SeekPos + sizeof( SWaveHeader );
|
||||
|
||||
hr = pOther->Seek( liNewPosition, STREAM_SEEK_SET, NULL );
|
||||
}
|
||||
|
||||
if( FAILED( hr ) )
|
||||
{
|
||||
RELEASE( pOther );
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
*ppstm = static_cast<IStream*>( pOther );
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
struct SObjRef
|
||||
{
|
||||
wstring m_strFilename;
|
||||
GUID m_guidObject;
|
||||
IDirectMusicObject* m_pObject;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
CDMusic_OggLoader::CDMusic_OggLoader()
|
||||
: m_cRef( 1 )
|
||||
, m_pstrSearchPath( new std::wstring( L".\\" ) )
|
||||
, m_pObjList( new LIST_OBJREF )
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
CDMusic_OggLoader::~CDMusic_OggLoader()
|
||||
{
|
||||
delete m_pstrSearchPath;
|
||||
delete m_pObjList;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
HRESULT CDMusic_OggLoader::Init()
|
||||
{
|
||||
USES_CONVERSION;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
IDirectMusicLoader * pLoader;
|
||||
|
||||
hr = CoCreateInstance( CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC, IID_IDirectMusicLoader, (void**)&pLoader );
|
||||
if( SUCCEEDED( hr ) )
|
||||
{
|
||||
DMUS_OBJECTDESC ObjDesc;
|
||||
IDirectMusicObject * pGMSet = NULL;
|
||||
ObjDesc.guidClass = CLSID_DirectMusicCollection;
|
||||
ObjDesc.guidObject = GUID_DefaultGMCollection;
|
||||
ObjDesc.dwSize = sizeof( DMUS_OBJECTDESC );
|
||||
ObjDesc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_OBJECT;
|
||||
|
||||
hr = pLoader->GetObject( &ObjDesc, IID_IDirectMusicObject, (void**) &pGMSet );
|
||||
if( SUCCEEDED( hr ) )
|
||||
{
|
||||
SObjRef objRef;
|
||||
objRef.m_guidObject = GUID_DefaultGMCollection;
|
||||
objRef.m_pObject = pGMSet;
|
||||
|
||||
m_pObjList->push_back( objRef );
|
||||
|
||||
pGMSet->AddRef();
|
||||
|
||||
pGMSet->Release();
|
||||
}
|
||||
pLoader->Release();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
void CDMusic_OggLoader::UnInit()
|
||||
{
|
||||
LIST_OBJREF::iterator it, it_end;
|
||||
|
||||
it = m_pObjList->begin();
|
||||
it_end = m_pObjList->end();
|
||||
|
||||
for( ; it != it_end; it++ )
|
||||
{
|
||||
RELEASE( it->m_pObject );
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
//IUnknown methods
|
||||
STDMETHODIMP CDMusic_OggLoader::QueryInterface( REFIID iid, void ** ppv )
|
||||
{
|
||||
*ppv = NULL;
|
||||
|
||||
if( iid == IID_IUnknown || iid == IID_IDirectMusicLoader )
|
||||
{
|
||||
*ppv = (void*)static_cast<IDirectMusicLoader*>( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
STDMETHODIMP_(ULONG) CDMusic_OggLoader::AddRef()
|
||||
{
|
||||
return InterlockedIncrement( &m_cRef );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
STDMETHODIMP_(ULONG) CDMusic_OggLoader::Release()
|
||||
{
|
||||
LONG ulCount = InterlockedDecrement( &m_cRef );
|
||||
if( ulCount <= 0 )
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
return (ULONG) ulCount;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
STDMETHODIMP CDMusic_OggLoader::SetSearchDirectory( REFGUID rguidClass, WCHAR * pwzPath, BOOL fClear )
|
||||
{
|
||||
*m_pstrSearchPath = pwzPath;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
SObjRef * CDMusic_OggLoader::FindCacheObject( LPDMUS_OBJECTDESC pDesc )
|
||||
{
|
||||
LIST_OBJREF::iterator it, it_end;
|
||||
|
||||
it = m_pObjList->begin();
|
||||
it_end = m_pObjList->end();
|
||||
|
||||
if( pDesc->dwValidData & DMUS_OBJ_OBJECT ) //같은 GUID를 가진 것이 있는지 찾는다.
|
||||
{
|
||||
for( ; it != it_end; it++ )
|
||||
{
|
||||
if( it->m_guidObject == pDesc->guidObject )
|
||||
{
|
||||
return &(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( pDesc->dwValidData & DMUS_OBJ_FILENAME ) //같은 화일이름을 가진 것을 찾는다.
|
||||
{
|
||||
for( ; it != it_end; it++ )
|
||||
{
|
||||
if( it->m_strFilename == pDesc->wszFileName )
|
||||
{
|
||||
return &(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL; //못 찾으면 NULL 리턴
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
STDMETHODIMP CDMusic_OggLoader::CreateFromFile( IDirectMusicObject * pObject, WCHAR * wszFileName, MUSIC_TIME * pMusicTime )
|
||||
{
|
||||
USES_CONVERSION;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
//화일로부터 읽어들인다. 화일로부터 스트림을 만들고, 그것으로부터 읽어들인다.
|
||||
WCHAR wzFileName1[MAX_PATH];
|
||||
WCHAR wzExt[_MAX_EXT];
|
||||
|
||||
WCHAR wzDrive[_MAX_DRIVE] = L"";
|
||||
WCHAR wzDir[_MAX_DIR] = L"";
|
||||
_wsplitpath( wszFileName, wzDrive, wzDir, NULL, NULL );
|
||||
|
||||
//드라이브 문자가 있거나 Path가 \\로 시작할 대
|
||||
if( wzDrive[0] != L'\0' || wzDir[0] == L'\\' )
|
||||
{
|
||||
wcscpy( wzFileName1, wszFileName );
|
||||
}
|
||||
else
|
||||
{
|
||||
_wmakepath( wzFileName1, NULL, m_pstrSearchPath->c_str(), wszFileName, NULL );
|
||||
_wsplitpath( wzFileName1, NULL, NULL, NULL, wzExt );
|
||||
}
|
||||
|
||||
COggStream * pOggStream = new COggStream;
|
||||
if( pOggStream == NULL )
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
if( SUCCEEDED( hr ) )
|
||||
{
|
||||
hr = pOggStream->Attach( W2CT( wzFileName1 ), this );
|
||||
}
|
||||
|
||||
IPersistStream * pPersistStream = NULL;
|
||||
if( SUCCEEDED( hr ) )
|
||||
{
|
||||
hr = pObject->QueryInterface( IID_IPersistStream, (void**)&pPersistStream );
|
||||
}
|
||||
|
||||
if( SUCCEEDED( hr ) )
|
||||
{
|
||||
hr = pPersistStream->Load( pOggStream );
|
||||
}
|
||||
|
||||
if( pMusicTime )
|
||||
{
|
||||
*pMusicTime = pOggStream->GetMusicTime();
|
||||
}
|
||||
|
||||
RELEASE( pOggStream );
|
||||
RELEASE( pPersistStream );
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
STDMETHODIMP CDMusic_OggLoader::CreateFromStream( IDirectMusicObject * pObject, IStream * pStream )
|
||||
{
|
||||
IStream * pClonedStream = NULL;
|
||||
IPersistStream * pPersistStream = NULL;
|
||||
|
||||
HRESULT hr = pObject->QueryInterface( IID_IPersistStream, (void**)&pPersistStream );
|
||||
if( SUCCEEDED( hr ) )
|
||||
{
|
||||
hr = pStream->Clone( &pClonedStream );
|
||||
}
|
||||
|
||||
if( SUCCEEDED( hr ) )
|
||||
{
|
||||
hr = pPersistStream->Load( pClonedStream );
|
||||
}
|
||||
|
||||
RELEASE( pPersistStream );
|
||||
RELEASE( pClonedStream );
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
STDMETHODIMP CDMusic_OggLoader::AddToList( IDirectMusicObject * pObject, LPDMUS_OBJECTDESC pDesc )
|
||||
{
|
||||
DMUS_OBJECTDESC DESC;
|
||||
|
||||
memset( &DESC, 0, sizeof( DESC ) );
|
||||
DESC.dwSize = sizeof( DMUS_OBJECTDESC );
|
||||
pObject->GetDescriptor( &DESC );
|
||||
|
||||
if( ( DESC.dwValidData & DMUS_OBJ_OBJECT ) || ( pDesc->dwValidData & DMUS_OBJ_FILENAME ) )
|
||||
{
|
||||
SObjRef objRef;
|
||||
|
||||
objRef.m_guidObject = DESC.guidObject;
|
||||
|
||||
if( pDesc->dwValidData & DMUS_OBJ_FILENAME )
|
||||
{
|
||||
objRef.m_strFilename = pDesc->wszFileName;
|
||||
}
|
||||
|
||||
objRef.m_pObject = pObject;
|
||||
|
||||
m_pObjList->push_back( objRef );
|
||||
pObject->AddRef();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
//IDirectMusicLoader methods
|
||||
STDMETHODIMP CDMusic_OggLoader::GetObject( LPDMUS_OBJECTDESC pDesc, REFIID riid, LPVOID FAR * ppv )
|
||||
{
|
||||
USES_CONVERSION;
|
||||
|
||||
SObjRef * pFindedObj = FindCacheObject( pDesc );
|
||||
|
||||
//오브젝트를 찾았으면 그것이 요청한 인터페이스를 지원하는지 확인하고, 레퍼런스를 추가한다.
|
||||
if( pFindedObj )
|
||||
{
|
||||
IDirectMusicObject * pObject = pFindedObj->m_pObject;
|
||||
|
||||
if( pObject )
|
||||
{
|
||||
HRESULT hr = pObject->QueryInterface( riid, ppv );
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
else //찾지 못했으면 다시 만든다.
|
||||
{
|
||||
MUSIC_TIME musicTime = 0;
|
||||
|
||||
IDirectMusicObject * pObject = NULL;
|
||||
|
||||
//주어진 클래스는 IDirectMusicObject를 지원해서 생성 가능해야 한다.
|
||||
HRESULT hr = CoCreateInstance( pDesc->guidClass, NULL, CLSCTX_INPROC_SERVER, IID_IDirectMusicObject, (void**)&pObject );
|
||||
if( FAILED( hr ) )
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
if( pDesc->dwValidData & DMUS_OBJ_FILENAME )
|
||||
{
|
||||
hr = CreateFromFile( pObject, pDesc->wszFileName, &musicTime );
|
||||
}
|
||||
else if( pDesc->dwValidData & DMUS_OBJ_STREAM )
|
||||
{
|
||||
hr = CreateFromStream( pObject, pDesc->pStream );
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_FAIL;
|
||||
}
|
||||
|
||||
if( SUCCEEDED( hr ) )
|
||||
{
|
||||
//로딩에 성공했으면 AddRef를 하고 나중을 위해 GUID를 저장해 놓는다.
|
||||
AddToList( pObject, pDesc );
|
||||
|
||||
hr = pObject->QueryInterface( riid, ppv );
|
||||
}
|
||||
|
||||
if( SUCCEEDED( hr ) && riid == IID_IDirectMusicSegment8 && musicTime )
|
||||
{
|
||||
//Length 설정.. 대부분의 경우는 설정을 안해줘도 문제가 안 생기지만,
|
||||
//여러 종류의 MusicBuffer를 쓸 때는 문제가 생길 가능성이 있으므로
|
||||
//설정을 해줌.
|
||||
//현재는 템포 120 bpm을 기준으로 Music Time을 계산해서 설정하도록 했음.
|
||||
IDirectMusicSegment * pSegment = (IDirectMusicSegment8*)(*ppv);
|
||||
hr = pSegment->SetLength( musicTime );
|
||||
}
|
||||
|
||||
RELEASE( pObject );
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
STDMETHODIMP_(void) CDMusic_OggLoader::CollectGarbage()
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
STDMETHODIMP CDMusic_OggLoader::ReleaseObjectByUnknown( IUnknown * pObject )
|
||||
{
|
||||
LIST_OBJREF::iterator it, it_end;
|
||||
|
||||
it = m_pObjList->begin();
|
||||
it_end = m_pObjList->end();
|
||||
|
||||
for( ; it != it_end; it++ )
|
||||
{
|
||||
if( it->m_pObject == pObject )
|
||||
{
|
||||
if( it->m_pObject->Release() == 0 )
|
||||
{
|
||||
m_pObjList->erase( it );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
STDMETHODIMP CDMusic_OggLoader::LoadObjectFromFile( REFGUID rguidClassID,
|
||||
REFIID iidInterfaceID,
|
||||
WCHAR * pwzFilePath,
|
||||
void ** ppObject )
|
||||
{
|
||||
DMUS_OBJECTDESC dmod;
|
||||
|
||||
memset(&dmod, 0, sizeof(dmod));
|
||||
|
||||
dmod.dwSize = sizeof(dmod);
|
||||
dmod.dwValidData = DMUS_OBJ_FILENAME;
|
||||
dmod.guidClass = CLSID_DirectMusicSegment;
|
||||
wcscpy( dmod.wszFileName, pwzFilePath );
|
||||
|
||||
HRESULT hr = GetObject( &dmod, IID_IDirectMusicSegment8, ppObject );
|
||||
return hr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
Reference in New Issue
Block a user