AsyncReader.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:5k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2005 Gabest
  3.  * http://www.gabest.org
  4.  *
  5.  *  This Program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2, or (at your option)
  8.  *  any later version.
  9.  *   
  10.  *  This Program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  *  GNU General Public License for more details.
  14.  *   
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21. #include "StdAfx.h"
  22. #include "AsyncReader.h"
  23. #include <afxsock.h>
  24. #include <afxinet.h>
  25. #include "......DSUtilDSUtil.h"
  26. //
  27. // CAsyncFileReader
  28. //
  29. CAsyncFileReader::CAsyncFileReader(CString fn, HRESULT& hr) 
  30. : CUnknown(NAME("CAsyncFileReader"), NULL, &hr)
  31. , m_len(-1)
  32. , m_hBreakEvent(NULL)
  33. , m_lOsError(0)
  34. {
  35. hr = Open(fn, modeRead|shareDenyWrite|typeBinary|osSequentialScan) ? S_OK : E_FAIL;
  36. if(SUCCEEDED(hr)) m_len = GetLength();
  37. }
  38. STDMETHODIMP CAsyncFileReader::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  39. {
  40. CheckPointer(ppv, E_POINTER);
  41. return 
  42. QI(IAsyncReader)
  43. QI(ISyncReader)
  44. QI(IFileHandle)
  45. __super::NonDelegatingQueryInterface(riid, ppv);
  46. }
  47. // IAsyncReader
  48. STDMETHODIMP CAsyncFileReader::SyncRead(LONGLONG llPosition, LONG lLength, BYTE* pBuffer)
  49. {
  50. do
  51. {
  52. try
  53. {
  54. if(llPosition+lLength > GetLength()) return E_FAIL; // strange, but the Seek below can return llPosition even if the file is not that big (?)
  55. if(llPosition != Seek(llPosition, begin)) return E_FAIL;
  56. if((UINT)lLength < Read(pBuffer, lLength)) return E_FAIL;
  57. #ifdef DEBUG
  58. static __int64 s_total = 0, s_laststoppos = 0;
  59. s_total += lLength;
  60. if(s_laststoppos > llPosition)
  61. TRACE(_T("[%I64d - %I64d] %d (%I64d)n"), llPosition, llPosition + lLength, lLength, s_total);
  62. s_laststoppos = llPosition + lLength;
  63. #endif
  64. return S_OK;
  65. }
  66. catch(CFileException* e)
  67. {
  68. m_lOsError = e->m_lOsError;
  69. e->Delete();
  70. Sleep(1);
  71. CString fn = m_strFileName;
  72. try {Close();} catch(CFileException* e) {e->Delete();}
  73. try {Open(fn, modeRead|shareDenyWrite|typeBinary|osSequentialScan);} catch(CFileException* e) {e->Delete();}
  74. m_strFileName = fn;
  75. }
  76. }
  77. while(m_hBreakEvent && WaitForSingleObject(m_hBreakEvent, 0) == WAIT_TIMEOUT);
  78. return E_FAIL;
  79. }
  80. STDMETHODIMP CAsyncFileReader::Length(LONGLONG* pTotal, LONGLONG* pAvailable)
  81. {
  82. LONGLONG len = m_len >= 0 ? m_len : GetLength();
  83. if(pTotal) *pTotal = len;
  84. if(pAvailable) *pAvailable = len;
  85. return S_OK;
  86. }
  87. // IFileHandle
  88. STDMETHODIMP_(HANDLE) CAsyncFileReader::GetFileHandle()
  89. {
  90. return m_hFile;
  91. }
  92. //
  93. // CAsyncUrlReader
  94. //
  95. CAsyncUrlReader::CAsyncUrlReader(CString url, HRESULT& hr) 
  96. : CAsyncFileReader(url, hr)
  97. {
  98. if(SUCCEEDED(hr)) return;
  99. m_url = url;
  100. if(CAMThread::Create())
  101. CallWorker(CMD_INIT);
  102. hr = Open(m_fn, modeRead|shareDenyRead|typeBinary|osSequentialScan) ? S_OK : E_FAIL;
  103. m_len = -1; // force GetLength() return actual length always
  104. }
  105. CAsyncUrlReader::~CAsyncUrlReader()
  106. {
  107. if(ThreadExists())
  108. CallWorker(CMD_EXIT);
  109. if(!m_fn.IsEmpty())
  110. {
  111. CFile::Close();
  112. DeleteFile(m_fn);
  113. }
  114. }
  115. // IAsyncReader
  116. STDMETHODIMP CAsyncUrlReader::Length(LONGLONG* pTotal, LONGLONG* pAvailable)
  117. {
  118. if(pTotal) *pTotal = 0;
  119. return __super::Length(NULL, pAvailable);
  120. }
  121. // CAMThread
  122. DWORD CAsyncUrlReader::ThreadProc()
  123. {
  124. AfxSocketInit(NULL);
  125. DWORD cmd = GetRequest();
  126. if(cmd != CMD_INIT) {Reply(E_FAIL); return E_FAIL;}
  127. try
  128. {
  129. CInternetSession is;
  130. CAutoPtr<CStdioFile> fin(is.OpenURL(m_url, 1, INTERNET_FLAG_TRANSFER_BINARY|INTERNET_FLAG_EXISTING_CONNECT|INTERNET_FLAG_NO_CACHE_WRITE));
  131. TCHAR path[MAX_PATH], fn[MAX_PATH];
  132. CFile fout;
  133. if(GetTempPath(MAX_PATH, path) && GetTempFileName(path, _T("mpc_http"), 0, fn)
  134. && fout.Open(fn, modeCreate|modeWrite|shareDenyWrite|typeBinary))
  135. {
  136. m_fn = fn;
  137. char buff[1024];
  138. int len = fin->Read(buff, sizeof(buff));
  139. if(len > 0) fout.Write(buff, len);
  140. Reply(S_OK);
  141. while(!CheckRequest(&cmd))
  142. {
  143. int len = fin->Read(buff, sizeof(buff));
  144. if(len > 0) fout.Write(buff, len);
  145. }
  146. }
  147. else
  148. {
  149. Reply(E_FAIL);
  150. }
  151. fin->Close(); // must close it because the destructor doesn't seem to do it and we will get an exception when "is" is destroying
  152. }
  153. catch(CInternetException* ie)
  154. {
  155. ie->Delete();
  156. Reply(E_FAIL);
  157. }
  158. //
  159. cmd = GetRequest();
  160. ASSERT(cmd == CMD_EXIT);
  161. Reply(S_OK);
  162. //
  163. m_hThread = NULL;
  164. return S_OK;
  165. }