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>
763 lines
16 KiB
C++
763 lines
16 KiB
C++
|
|
#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;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////
|