home *** CD-ROM | disk | FTP | other *** search
/ Game Audio Programming / GameAudioProgramming.iso / Game_Audio / audio_sdk / src / AudioLib / FileStream.cpp < prev    next >
C/C++ Source or Header  |  2002-09-09  |  8KB  |  327 lines

  1. /***********************************************************\
  2. Copyright (C) James Boer, 2002. 
  3. All rights reserved worldwide.
  4.  
  5. This software is provided "as is" without express or implied
  6. warranties. You may freely copy and compile this source into
  7. applications you distribute provided that the copyright text
  8. below is included in the resulting source code, for example:
  9. "Portions Copyright (C) James Boer, 2002"
  10. \***********************************************************/
  11.  
  12. #include "FileStream.h"
  13. #include "AudioMgr.h"
  14.  
  15. using namespace std;
  16. using namespace Audio;
  17.  
  18.  
  19.  
  20. IMPLEMENT_POOL(FileStream);
  21.  
  22. //------------------------------------------------------------------------//
  23. FileStream::FileStream()
  24. {
  25.     Clear();
  26. }
  27.  
  28. //------------------------------------------------------------------------//
  29. FileStream::~FileStream()
  30. {
  31.     assert(m_iRefCount == 0);
  32. }
  33.  
  34. //------------------------------------------------------------------------//
  35. void FileStream::Clear()
  36. {
  37.     m_iRefCount = 0;
  38.     m_pFile = 0;
  39.     m_nSize = 0;
  40.     m_sFileName.erase();
  41.  
  42.     m_pBuffer = 0;
  43.     m_nReadPtr = 0;
  44.     m_bBuffered = false;
  45. }
  46.  
  47.  
  48. //------------------------------------------------------------------------//
  49. HRESULT FileStream::Open(std::string sFileName)
  50. {
  51.     if(m_pFile)
  52.         return E_FAIL;
  53.  
  54.     m_sFileName = sFileName;
  55.     m_pFile = fopen(sFileName.c_str(), "rb");
  56.     if(!m_pFile)
  57.     {
  58.  
  59.         _getcwd(DXAudioMgr()->GetCurrentWorkingPath(), MAX_PATH);
  60.         chdir(DXAudioMgr()->GetAudioSystemPath());
  61.         m_pFile = fopen(sFileName.c_str(), "rb");
  62.         chdir(DXAudioMgr()->GetCurrentWorkingPath());
  63.         if(!m_pFile)
  64.             return E_FAIL;
  65.     }
  66.  
  67.  
  68.     fseek(m_pFile, 0, SEEK_END);
  69.     m_nSize = ftell(m_pFile);
  70.     fseek(m_pFile, 0, SEEK_SET);
  71.  
  72.     // Cache the entire file in memory if it is relatively small
  73.     // 44100 * 2 * 2 (2 second 16-bit buffer at 44.1KHz)
  74.     if(m_nSize <= 176400 && DXAudioMgr()->GetInit()->m_bAutoStream)
  75.         m_pBuffer = new uint8[m_nSize];
  76.  
  77.     return S_OK;
  78. }
  79.  
  80.  
  81. //------------------------------------------------------------------------//
  82. void FileStream::Close()
  83. {
  84.     SAFE_DELETE_ARRAY(m_pBuffer);
  85.     if(m_pFile)
  86.     {
  87.         fclose(m_pFile);
  88.         m_pFile = 0;
  89.     }
  90.     Clear();
  91. }
  92.  
  93.  
  94.  
  95. //------------------------------------------------------------------------//
  96. HRESULT FileStream::QueryInterface(
  97.     const struct _GUID& guid, 
  98.     void** ppInterface)
  99. {
  100.     if (guid == IID_IStream)
  101.         *ppInterface = (IStream*)this;
  102.     else if (guid == IID_ISequentialStream)
  103.         *ppInterface = (ISequentialStream*)this;
  104.     else if (guid == IID_IUnknown)
  105.         *ppInterface = (IUnknown*)this;
  106.     else
  107.         return E_NOTIMPL;
  108.     ((IUnknown*)*ppInterface)->AddRef();
  109.     return S_OK;
  110. }
  111.  
  112. //------------------------------------------------------------------------//
  113. ULONG FileStream::AddRef()
  114. {
  115.     InterlockedIncrement(&m_iRefCount);
  116.     return m_iRefCount;
  117. }
  118.  
  119. //------------------------------------------------------------------------//
  120. ULONG FileStream::Release()
  121. {
  122.     int32 iPrev = InterlockedDecrement(&m_iRefCount);
  123.     if(iPrev == 0)
  124.     {
  125.         Close();
  126.         FileStream::DestroyObject(this);
  127.     }
  128.     assert(m_iRefCount >= 0);
  129.     return m_iRefCount;
  130. }
  131.  
  132.  
  133.  
  134. // ISequentialStream Interface
  135. //------------------------------------------------------------------------//
  136. HRESULT FileStream::Read( 
  137.     /* [length_is][size_is][out] */ void *pv,
  138.     /* [in] */ ULONG cb,
  139.     /* [out] */ ULONG *pcbRead)
  140. {
  141.     if(!m_pFile)
  142.         return E_FAIL;
  143.  
  144.     uint32 nRead;
  145.     if(m_pBuffer)
  146.     {
  147.         if(!m_bBuffered)
  148.         {
  149.             uint32 nFullRead = fread((uint8*)m_pBuffer, 1, m_nSize, m_pFile);
  150.             if(nFullRead != m_nSize)
  151.                 return E_FAIL;
  152.             m_bBuffered = true;
  153.         }
  154.  
  155.         nRead = ClampMax(cb, m_nSize - m_nReadPtr);
  156.         memcpy(pv, m_pBuffer + m_nReadPtr, nRead);
  157.         m_nReadPtr += cb;
  158.     }
  159.     else
  160.     {
  161.         nRead = fread((uint8*)pv, 1, cb, m_pFile);
  162.     }
  163.  
  164.     if(pcbRead)
  165.         *pcbRead = nRead;
  166.  
  167.     return S_OK;
  168. }
  169.  
  170. //------------------------------------------------------------------------//
  171. HRESULT FileStream::Write( 
  172.     /* [size_is][in] */ const void *pv,
  173.     /* [in] */ ULONG cb,
  174.     /* [out] */ ULONG *pcbWritten)
  175. {
  176.     return E_NOTIMPL;
  177. }
  178.  
  179.  
  180. // IStream Interface
  181. //------------------------------------------------------------------------//
  182. HRESULT FileStream::Seek( 
  183.     /* [in] */ LARGE_INTEGER dlibMove,
  184.     /* [in] */ DWORD dwOrigin,
  185.     /* [out] */ ULARGE_INTEGER *plibNewPosition)
  186. {
  187.  
  188.     if(!m_pFile)
  189.         return E_FAIL;
  190.  
  191.     uint32 nSeek = (uint32)dlibMove.QuadPart;
  192.     if(m_pBuffer)
  193.     {
  194.         switch(dwOrigin)
  195.         {
  196.             case SEEK_SET:
  197.                 m_nReadPtr = dlibMove.QuadPart;
  198.                 break;
  199.             case SEEK_CUR:
  200.                 m_nReadPtr += dlibMove.QuadPart;
  201.                 break;
  202.             case SEEK_END:
  203.                 m_nReadPtr = m_nSize - dlibMove.QuadPart;
  204.                 break;
  205.         };
  206.         if(plibNewPosition)
  207.             plibNewPosition->QuadPart = m_nReadPtr;
  208.     }
  209.     else
  210.     {
  211.         if(fseek(m_pFile, nSeek, dwOrigin))
  212.             return E_FAIL;
  213.         if(plibNewPosition)
  214.             plibNewPosition->QuadPart = ftell(m_pFile);
  215.     }
  216.  
  217.     return S_OK;
  218. }
  219.  
  220.     
  221. //------------------------------------------------------------------------//
  222. HRESULT FileStream::SetSize( 
  223.     /* [in] */ ULARGE_INTEGER libNewSize)
  224. {
  225.     return E_NOTIMPL;
  226. }
  227.  
  228.     
  229. //------------------------------------------------------------------------//
  230. HRESULT FileStream::CopyTo( 
  231.     /* [unique][in] */ IStream *pstm,
  232.     /* [in] */ ULARGE_INTEGER cb,
  233.     /* [out] */ ULARGE_INTEGER *pcbRead,
  234.     /* [out] */ ULARGE_INTEGER *pcbWritten)
  235. {
  236.     return E_NOTIMPL;
  237. }
  238.  
  239.     
  240. //------------------------------------------------------------------------//
  241. HRESULT FileStream::Commit( 
  242.     /* [in] */ DWORD grfCommitFlags)
  243. {
  244.     return E_NOTIMPL;
  245. }
  246.  
  247.     
  248. //------------------------------------------------------------------------//
  249. HRESULT FileStream::Revert(void)
  250. {
  251.     return E_NOTIMPL;
  252. }
  253.  
  254.     
  255. //------------------------------------------------------------------------//
  256. HRESULT FileStream::LockRegion( 
  257.     /* [in] */ ULARGE_INTEGER libOffset,
  258.     /* [in] */ ULARGE_INTEGER cb,
  259.     /* [in] */ DWORD dwLockType)
  260. {
  261.     return E_NOTIMPL;
  262. }
  263.  
  264.     
  265. //------------------------------------------------------------------------//
  266. HRESULT FileStream::UnlockRegion( 
  267.     /* [in] */ ULARGE_INTEGER libOffset,
  268.     /* [in] */ ULARGE_INTEGER cb,
  269.     /* [in] */ DWORD dwLockType)
  270. {
  271.     return E_NOTIMPL;
  272. }
  273.  
  274.     
  275. //------------------------------------------------------------------------//
  276. HRESULT FileStream::Stat( 
  277.     /* [out] */ STATSTG *pstatstg,
  278.     /* [in] */ DWORD grfStatFlag)
  279. {
  280.     if(!pstatstg)
  281.         return E_INVALIDARG;
  282.  
  283.     pstatstg->pwcsName = 0;
  284.     if(grfStatFlag == 1)
  285.     {
  286.         pstatstg->pwcsName = (WCHAR*)CoTaskMemAlloc(MAX_PATH * sizeof(WCHAR));
  287.         ConvertAnsiStringToWide(pstatstg->pwcsName, m_sFileName.c_str());
  288.     }
  289.     else
  290.         pstatstg->pwcsName = 0;
  291.     pstatstg->type = STGTY_STREAM;
  292.     pstatstg->cbSize.QuadPart = m_nSize;
  293.     pstatstg->atime.dwHighDateTime = 0;
  294.     pstatstg->atime.dwLowDateTime = 0;
  295.     pstatstg->ctime.dwHighDateTime = 0;
  296.     pstatstg->ctime.dwLowDateTime = 0;
  297.     pstatstg->mtime.dwHighDateTime = 0;
  298.     pstatstg->mtime.dwLowDateTime = 0;
  299.     pstatstg->grfLocksSupported = 0;
  300.  
  301.     return S_OK;
  302. }
  303.  
  304.     
  305. //------------------------------------------------------------------------//
  306. HRESULT FileStream::Clone( 
  307.     /* [out] */ IStream **ppstm)
  308. {
  309.     IAudioStream* pStream;
  310.     if(!AudioMgr()->CreateAudioStream(pStream))
  311.         return E_FAIL;
  312.     if(FAILED(pStream->Open(m_sFileName)))
  313.     {
  314.         pStream->Release();
  315.         return E_FAIL;
  316.     }
  317.     LARGE_INTEGER liPos;
  318.     if(m_pBuffer)
  319.         liPos.QuadPart = m_nReadPtr;
  320.     else
  321.         liPos.QuadPart = ftell(m_pFile);
  322.     pStream->Seek(liPos, SEEK_SET, 0);
  323.     *ppstm = (IStream*)pStream;
  324.     return S_OK;
  325. }
  326.  
  327.