WavTgt.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /******************************************************************************
  2. |* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  3. |* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  4. |* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  5. |* PARTICULAR PURPOSE.
  6. |*
  7. |* Copyright 1995-2005 Nero AG. All Rights Reserved.
  8. |*-----------------------------------------------------------------------------
  9. |* PROJECT: Nero Plugin Manager Example
  10. |*
  11. |* FILE: WavTgt.cpp
  12. |*
  13. |* PURPOSE: Implementation of the wave target class
  14. ******************************************************************************/
  15. #include "stdafx.h"
  16. #include "WavTgt.h"
  17. // helper functions for file access
  18. #include "FileHelper.h"
  19. #include "NeroPluginUtil.h"
  20. // IAudioItem implementation
  21. // return the object that created the wave target
  22. bool CWavTgt::GetCreator(IAudioComponent** pCreator)
  23. {
  24. if(!pCreator)
  25. {
  26. ASSERT(FALSE);
  27. return false;
  28. }
  29. *pCreator = m_pCreator;
  30. (*pCreator)->AddRef();
  31. return true;
  32. }
  33. EAuxFlags CWavTgt::GetAuxFlags()
  34. {
  35. return m_flags;
  36. }
  37. void CWavTgt::SetAuxFlags(EAuxFlags flags)
  38. {
  39. m_flags = flags;
  40. }
  41. bool CWavTgt::SetURL(const char* szURL, IStatus** ppStatus)
  42. {
  43. // only local URLs are allowed for this target
  44. if(false == IsURLLocal(szURL))
  45. {
  46. RETURN_ERROR(AE_BadPathName);
  47. }
  48. m_csURL = szURL;
  49. return true;
  50. }
  51. const char * CWavTgt::GetURL()
  52. {
  53. return m_csURL;
  54. }
  55. EURLType CWavTgt::GetType()
  56. {
  57. return URL_LocalFile;
  58. }
  59. // IWavTgtSetDlgData implementation
  60. SWavFormat * CWavTgt::GetDlgData()
  61. {
  62. return &m_DlgData;
  63. }
  64. // IProcess implementation
  65. bool CWavTgt::Start(IStatus **ppStatus)
  66. {
  67. if(ppStatus)
  68. {
  69. *ppStatus = NULL;
  70. }
  71. m_hFile = CreateFile(m_csURL, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
  72. FILE_ATTRIBUTE_NORMAL, NULL);
  73. DWORD dwError = GetLastError();
  74. bool bRes = (m_hFile != INVALID_HANDLE_VALUE);
  75. if(false == bRes)
  76. {
  77. RETURN_ERROR(dwError);
  78. }
  79. int iSamplesPerSec = m_DlgData.m_iSamplesPerSecond;
  80. // Starting the target
  81. m_bEndProcess = FALSE;
  82. DWORD dwWritten = 0;
  83. // Starting header
  84. char* szHeader = "RIFF****WAVEfmt ";
  85. WriteFile(m_hFile, szHeader, strlen(szHeader), &dwWritten, NULL);
  86. // WAVE chunk size
  87. DWORD dw = 16;
  88. WriteFile(m_hFile, &dw, sizeof(DWORD), &dwWritten, NULL);
  89. // Sampling format
  90. PCMWAVEFORMAT format =
  91. {
  92. WAVE_FORMAT_PCM,
  93. m_DlgData.m_iChannels,
  94. iSamplesPerSec,
  95. (m_DlgData.m_iChannels * iSamplesPerSec *
  96. m_DlgData.m_iBitsPerSample) / BITS_PER_BYTE,
  97. (m_DlgData.m_iChannels * m_DlgData.m_iBitsPerSample) /
  98. BITS_PER_BYTE,
  99. m_DlgData.m_iBitsPerSample
  100. };
  101. WriteFile(m_hFile, &format, sizeof(PCMWAVEFORMAT), &dwWritten, NULL);
  102. // Data chunk header
  103. char *szData = "data****";
  104. WriteFile(m_hFile, szData, strlen(szData), &dwWritten, NULL);
  105. m_dwWrittenRAWSize = 0;
  106. // The remaining information will be saved as soon as RAW data is received
  107. // and the artist, copyright and other additional information will be
  108. // save in EndTarget, after the whole RAW chunk is ready.
  109. return bRes;
  110. }
  111. bool CWavTgt::End(IStatus** ppStatus)
  112. {
  113. ASSERT(m_hFile != INVALID_HANDLE_VALUE);
  114. if(ppStatus)
  115. {
  116. *ppStatus = NULL;
  117. }
  118. // align to the word size the RAW chunk
  119. if(m_dwWrittenRAWSize % 2)
  120. {
  121. WriteZeroByte(m_hFile);
  122. }
  123. // List chunk
  124. DWORD dwListChunkSizePos = 0,
  125. dwWritten = 0;
  126. CString *pcsCurField = &m_csArtist;
  127. BOOL bHeaderIsWritten = FALSE;
  128. DWORD dwListChunkSize = 0;
  129. char *szarListSubTitles[] =
  130. {
  131. "IART", // Artist
  132. "ICMT", // Comments
  133. "ICOP", // Copyright
  134. "ICRD", // Creation date
  135. "INAM" // Name (the title)
  136. };
  137. for(int i = 0; i < LIST_CHUNK_ITEMS; i++, pcsCurField++)
  138. {
  139. if(!pcsCurField->IsEmpty())
  140. {
  141. // the size of list item chunk size
  142. dwListChunkSize += 8;
  143. if (!bHeaderIsWritten)
  144. {
  145. // the INFO word
  146. dwListChunkSize += WAV_CHUNK_NAME_LEN;
  147. dwListChunkSizePos =
  148. GetFilePointer(m_hFile) + WAV_CHUNK_NAME_LEN;
  149. char *szListHeader = "LIST****INFO";
  150. WriteFile(m_hFile, szListHeader, strlen(szListHeader),
  151. &dwWritten, NULL);
  152. bHeaderIsWritten = TRUE;
  153. }
  154. // Subchunk title
  155. WriteFile(m_hFile, szarListSubTitles[i], WAV_CHUNK_NAME_LEN,
  156. &dwWritten, NULL);
  157. DWORD dwDataLen = pcsCurField->GetLength() + 1;
  158. dwListChunkSize += dwDataLen;
  159. // The size of this subchunk
  160. WriteFile(m_hFile, &dwDataLen, sizeof(DWORD),
  161. &dwWritten, NULL);
  162. // The subchunk content
  163. WriteFile(m_hFile, (LPCTSTR)(*pcsCurField), dwDataLen,
  164. &dwWritten, NULL);
  165. // align the chunk's size to the word size
  166. if(dwDataLen % 2)
  167. {
  168. WriteZeroByte(m_hFile);
  169. dwListChunkSize++;
  170. }
  171. }
  172. }
  173. // Fill the size field of the LIST chunk
  174. if(bHeaderIsWritten)
  175. {
  176. SetFilePointer(m_hFile, dwListChunkSizePos, 0, FILE_BEGIN);
  177. WriteFile(m_hFile, &dwListChunkSize, sizeof(DWORD),
  178. &dwWritten, NULL);
  179. // align the list chunk's size to the word size
  180. if(dwListChunkSize % 2)
  181. WriteZeroByte(m_hFile);
  182. }
  183. // Filling the RIFF chunk's size
  184. DWORD dwFileSize = GetFileSize(m_hFile, NULL);
  185. if (dwFileSize % 2)
  186. {
  187. // Going to the end of the file to align
  188. // the file's size to size of word
  189. SetFilePointer(m_hFile, 0, 0, FILE_END);
  190. WriteZeroByte(m_hFile);
  191. dwFileSize++;
  192. }
  193. SetFilePointer(m_hFile, WAV_CHUNK_NAME_LEN, 0, FILE_BEGIN);
  194. // The RIFF header size
  195. dwFileSize -= 8;
  196. WriteFile(m_hFile, &dwFileSize, sizeof(DWORD), &dwWritten, NULL);
  197. // Writing the "data" chunk's size
  198. SetFilePointer(m_hFile, 40, 0, FILE_BEGIN);
  199. WriteFile(m_hFile, &m_dwWrittenRAWSize, sizeof(DWORD), &dwWritten,
  200. NULL);
  201. CloseHandle(m_hFile);
  202. m_hFile = INVALID_HANDLE_VALUE;
  203. return true;
  204. }
  205. bool CWavTgt::IsInProcess()
  206. {
  207. return (m_hFile != INVALID_HANDLE_VALUE);
  208. }
  209. // IAudioTarget implementation
  210. bool CWavTgt::RawWrite(BYTE *pData, int iNumberOfBytesToWrite,
  211. EAudioRawState &state,
  212. IStatus **ppStatus)
  213. {
  214. if(false == (pData && iNumberOfBytesToWrite))
  215. {
  216. RETURN_ERROR(AE_InvalidParameter);
  217. }
  218. ASSERT(m_hFile != INVALID_HANDLE_VALUE);
  219. if(ppStatus)
  220. {
  221. *ppStatus = NULL;
  222. }
  223. DWORD dwWritten = 0;
  224. // WriteFile returns zero for failure
  225. int iRes = WriteFile(m_hFile, pData, iNumberOfBytesToWrite, &dwWritten, NULL);
  226. if(0 == iRes)
  227. {
  228. DWORD dwError = GetLastError();
  229. RETURN_ERROR(dwError);
  230. }
  231. m_dwWrittenRAWSize += iNumberOfBytesToWrite;
  232. return true;
  233. }
  234. SWavFormat CWavTgt::GetRawFormat()
  235. {
  236. return m_DlgData;
  237. }
  238. // IInfoWriter implementation
  239. void CWavTgt::SetTitle(const char *szTitle)
  240. {
  241. m_csTitle = szTitle;
  242. }
  243. void CWavTgt::SetArtist(const char *szArtist)
  244. {
  245. m_csArtist = szArtist;
  246. }
  247. void CWavTgt::SetAlbum(const char *szAlbum)
  248. {
  249. // not implemented
  250. }
  251. void CWavTgt::SetYear(const char *szYear)
  252. {
  253. // not implemented
  254. }
  255. void CWavTgt::SetGenre(const char *szGenre)
  256. {
  257. // not implemented
  258. }