Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

365 lines
10 KiB

  1. // cdread.cpp
  2. //
  3. #include <windows.h>
  4. #include <windowsx.h>
  5. #include <TCHAR.H>
  6. #include <mmsystem.h>
  7. #include "cdread.h"
  8. #include "cddata.h"
  9. #include "..\main\resource.h"
  10. #include "..\main\sink.h"
  11. #include "mmreg.h"
  12. #include "msacm.h"
  13. HANDLE hFile = NULL;
  14. LPCDDATA pData = NULL;
  15. TIMEDMETER tm;
  16. DWORD dwTotalBytes = 0;
  17. WAVEFORMATEX wfxPCM1, wfxPCM2;
  18. DWORD cbOutBytes[3];
  19. HACMSTREAM acmStream[3];
  20. ACMSTREAMHEADER acmHeader[3];
  21. BYTE sSample[CDDA_SECTOR_SIZE * SECTORS_PER_READ];
  22. BYTE sCompBuffer[CDDA_SECTOR_SIZE * SECTORS_PER_READ];
  23. // Write a WAV header for the selected format
  24. BOOL writeHeader(int iSize, LPWAVEFORMATEX lpwfx)
  25. {
  26. DWORD dwBytesWritten = 0;
  27. unsigned data, formatdata;
  28. WORD wData;
  29. WriteFile(hFile,"RIFF",4,&dwBytesWritten,NULL);
  30. formatdata = 16;
  31. if ((lpwfx->wFormatTag != WAVE_FORMAT_PCM) && (lpwfx->cbSize > 0))
  32. {
  33. formatdata += sizeof(WORD); //to write cdSize out
  34. formatdata += lpwfx->cbSize;
  35. }
  36. data = 0x24 + iSize + (formatdata-16);
  37. WriteFile(hFile,&data,sizeof(unsigned),&dwBytesWritten,NULL);
  38. WriteFile(hFile,"WAVE",4,&dwBytesWritten,NULL);
  39. WriteFile(hFile,"fmt ",4,&dwBytesWritten,NULL);
  40. WriteFile(hFile,&formatdata,sizeof(unsigned),&dwBytesWritten,NULL);
  41. WriteFile(hFile,lpwfx,formatdata,&dwBytesWritten,NULL);
  42. /*
  43. wData = lpwfx->wFormatTag;
  44. WriteFile(hFile,&wData,sizeof(WORD),&dwBytesWritten,NULL);
  45. wData = lpwfx->nChannels;
  46. WriteFile(hFile,&wData,sizeof(WORD),&dwBytesWritten,NULL);
  47. data = lpwfx->nSamplesPerSec;
  48. WriteFile(hFile,&data,sizeof(unsigned),&dwBytesWritten,NULL);
  49. data = lpwfx->nAvgBytesPerSec;
  50. WriteFile(hFile,&data,sizeof(unsigned),&dwBytesWritten,NULL);
  51. wData = lpwfx->nBlockAlign;
  52. WriteFile(hFile,&wData,sizeof(WORD),&dwBytesWritten,NULL);
  53. wData = lpwfx->wBitsPerSample;
  54. WriteFile(hFile,&wData,sizeof(WORD),&dwBytesWritten,NULL);
  55. if ((lpwfx->wFormatTag != WAVE_FORMAT_PCM) && (lpwfx->cbSize > 0))
  56. {
  57. wData = lpwfx->cbSize;
  58. WriteFile(hFile,&wData,sizeof(WORD),&dwBytesWritten,NULL);
  59. pData = (BYTE*)(&(lpwfx->cbSize) + sizeof(WORD));
  60. WriteFile(hFile,pData,lpwfx->cbSize,&dwBytesWritten,NULL);
  61. }
  62. */
  63. WriteFile(hFile,"data",4,&dwBytesWritten,NULL);
  64. data = iSize;
  65. WriteFile(hFile,&data,sizeof(unsigned),&dwBytesWritten,NULL);
  66. return TRUE;
  67. }
  68. BOOL readTOC( HANDLE hDevice, PCDROM_TOC pToc )
  69. {
  70. DWORD dwTocSize = sizeof(CDROM_TOC);
  71. DWORD dwBytesReturned = 0;
  72. DWORD dwNumTracks = 0;
  73. if( !DeviceIoControl( hDevice,
  74. IOCTL_CDROM_READ_TOC,
  75. pToc, // pointer to inputbuffer
  76. dwTocSize, // sizeof inputbuffer
  77. pToc, // pointer to outputbuffer
  78. dwTocSize, // sizeof outputbuffer
  79. &dwBytesReturned, // pointer to number of bytes returned
  80. FALSE
  81. )
  82. )
  83. {
  84. return FALSE;
  85. }
  86. dwNumTracks = pToc->LastTrack - pToc->FirstTrack;
  87. //
  88. // number of tracks plus zero-based plus leadout track
  89. //
  90. if ( (dwNumTracks+2) * sizeof(TRACK_DATA) != dwBytesReturned - 4 )
  91. {
  92. dwNumTracks = (dwBytesReturned - 4) / sizeof(TRACK_DATA);
  93. }
  94. // parse and print the information
  95. PTRACK_DATA pTrack = (PTRACK_DATA) &(pToc->TrackData[0]);
  96. return TRUE;
  97. }
  98. BOOL skipRead( BYTE* buffer, DWORD dwSize, int iPercent )
  99. {
  100. return TRUE;
  101. }
  102. BOOL writeRead( BYTE* buffer, DWORD dwSize, int iPercent )
  103. {
  104. DWORD dwBytesWritten = 0;
  105. if (pData)
  106. {
  107. pData->UpdateMeter(&tm);
  108. }
  109. acmStreamConvert(acmStream[0],&acmHeader[0],0);
  110. acmStreamConvert(acmStream[1],&acmHeader[1],0);
  111. acmStreamConvert(acmStream[2],&acmHeader[2],0);
  112. WriteFile(hFile,sCompBuffer,acmHeader[2].cbDstLengthUsed,&dwBytesWritten,NULL);
  113. dwTotalBytes += dwBytesWritten;
  114. return TRUE;
  115. }
  116. BOOL rawReadTrack(HANDLE device, PCDROM_TOC pTOC, int iTrack, LPREADFUNC lpReadFunc )
  117. {
  118. RAW_READ_INFO info; // fill in for the read request
  119. DWORD dwBytesRead; // bytes returned
  120. DWORD dwStartingLBA;
  121. DWORD dwNumLBA;
  122. DWORD dwEndingLBA;
  123. DWORD dwSectorsToRead;
  124. DWORD dwError;
  125. PTRACK_DATA pTrack = (PTRACK_DATA) &(pTOC->TrackData[0]);
  126. PTRACK_DATA pTrack2;
  127. // Use VirtualAlloc so we get a page-aligned region since we're doing
  128. // non-cached IO
  129. /*
  130. sSample = (BYTE*)VirtualAlloc(NULL, PAGE_VAL, MEM_COMMIT, PAGE_READWRITE );
  131. if( !sSample )
  132. {
  133. //MessageBox( NULL, "Error allocating memory block.", "Error", MB_OK );
  134. return FALSE;
  135. }
  136. */
  137. pTrack += (iTrack-1);
  138. pTrack2 = pTrack + 1;
  139. dwStartingLBA = MSF_TO_LBA( pTrack->Address[1], pTrack->Address[2], pTrack->Address[3] );
  140. dwEndingLBA = MSF_TO_LBA( pTrack2->Address[1], pTrack2->Address[2], pTrack2->Address[3] );
  141. dwNumLBA = dwEndingLBA-dwStartingLBA;
  142. //
  143. // round up the num sectors to read
  144. //
  145. dwSectorsToRead = ((dwNumLBA - 1) / SECTORS_PER_READ + 1) * SECTORS_PER_READ;
  146. dwEndingLBA = dwStartingLBA + dwSectorsToRead;
  147. // start the read loop
  148. for ( DWORD i = dwStartingLBA; i < dwEndingLBA; i += SECTORS_PER_READ )
  149. {
  150. int iPercent;
  151. info.DiskOffset.QuadPart = (unsigned __int64)(i*2048);
  152. info.SectorCount = SECTORS_PER_READ;
  153. info.TrackMode = CDDA;
  154. if( !DeviceIoControl( device,
  155. IOCTL_CDROM_RAW_READ,
  156. &info, // pointer to inputbuffer
  157. sizeof(RAW_READ_INFO), // sizeof inputbuffer
  158. sSample, // pointer to outputbuffer
  159. CDDA_SECTOR_SIZE * SECTORS_PER_READ, // sizeof outputbuffer
  160. &dwBytesRead, // pointer to number of bytes returned
  161. FALSE // ???
  162. )
  163. )
  164. {
  165. goto fail;
  166. }
  167. iPercent = (i-dwStartingLBA)/(dwEndingLBA-dwStartingLBA);
  168. if( !((*lpReadFunc)(sSample, dwBytesRead, iPercent) ) )
  169. {
  170. goto fail;
  171. }
  172. }
  173. //VirtualFree( sSample, PAGE_VAL, MEM_DECOMMIT );
  174. return TRUE;
  175. fail:
  176. VirtualFree( sSample, PAGE_VAL, MEM_DECOMMIT );
  177. return FALSE;
  178. }
  179. // Find the byte size of a track
  180. int getTrackSize( PCDROM_TOC pTOC, int iTrack )
  181. {
  182. PTRACK_DATA pTrack = &(pTOC->TrackData[0]);
  183. DWORD dwLBA1, dwLBA2;
  184. pTrack += (iTrack-1);
  185. dwLBA1 = MSF_TO_LBA( pTrack->Address[1], pTrack->Address[2], pTrack->Address[3] );
  186. pTrack++;
  187. dwLBA2 = MSF_TO_LBA( pTrack->Address[1], pTrack->Address[2], pTrack->Address[3] );
  188. return (dwLBA2-dwLBA1) * CDDA_SECTOR_SIZE;
  189. }
  190. BOOL StoreTrack(HWND hwndMain, TCHAR chDrive, int nTrack, TCHAR* pszFilename, LPWAVEFORMATEX lpwfxDest)
  191. {
  192. HANDLE hDevice;
  193. TCHAR szDeviceName[MAX_PATH];
  194. CDROM_TOC sTOC;
  195. wsprintf( szDeviceName, TEXT("\\\\.\\%c:"), chDrive );
  196. hDevice = CreateFile( szDeviceName, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
  197. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
  198. if( INVALID_HANDLE_VALUE == hDevice )
  199. {
  200. return FALSE;
  201. }
  202. readTOC( hDevice, &sTOC );
  203. int iSize = getTrackSize( &sTOC, nTrack );
  204. dwTotalBytes = 0;
  205. WAVEFORMATEX waveFormat;
  206. waveFormat.wFormatTag = WAVE_FORMAT_PCM;
  207. waveFormat.nChannels = 2;
  208. waveFormat.nSamplesPerSec = 44100;
  209. waveFormat.nAvgBytesPerSec = 176400;
  210. waveFormat.nBlockAlign = 4;
  211. waveFormat.wBitsPerSample = 16;
  212. waveFormat.cbSize = sizeof(waveFormat);
  213. wfxPCM1.wFormatTag = WAVE_FORMAT_PCM;
  214. acmFormatSuggest(NULL, &waveFormat, &wfxPCM1, sizeof(WAVEFORMATEX),
  215. ACM_FORMATSUGGESTF_WFORMATTAG);
  216. wfxPCM2.wFormatTag = WAVE_FORMAT_PCM;
  217. acmFormatSuggest(NULL, lpwfxDest, &wfxPCM2, sizeof(WAVEFORMATEX),
  218. ACM_FORMATSUGGESTF_WFORMATTAG);
  219. acmStreamOpen(&acmStream[0],NULL,&waveFormat,&wfxPCM1,NULL,NULL,0,ACM_STREAMOPENF_NONREALTIME);
  220. acmStreamOpen(&acmStream[1],NULL,&wfxPCM1,&wfxPCM2,NULL,NULL,0,ACM_STREAMOPENF_NONREALTIME);
  221. acmStreamOpen(&acmStream[2],NULL,&wfxPCM2,lpwfxDest,NULL,NULL,0,ACM_STREAMOPENF_NONREALTIME);
  222. acmStreamSize(acmStream[0],CDDA_SECTOR_SIZE * SECTORS_PER_READ,&cbOutBytes[0],ACM_STREAMSIZEF_SOURCE);
  223. acmStreamSize(acmStream[1],CDDA_SECTOR_SIZE * SECTORS_PER_READ,&cbOutBytes[1],ACM_STREAMSIZEF_SOURCE);
  224. acmStreamSize(acmStream[2],CDDA_SECTOR_SIZE * SECTORS_PER_READ,&cbOutBytes[2],ACM_STREAMSIZEF_SOURCE);
  225. acmHeader[0].cbStruct = sizeof(acmHeader);
  226. acmHeader[0].fdwStatus = 0;
  227. acmHeader[0].dwUser = 0;
  228. acmHeader[0].pbSrc = sSample;
  229. acmHeader[0].cbSrcLength = CDDA_SECTOR_SIZE * SECTORS_PER_READ;
  230. acmHeader[0].pbDst = sCompBuffer;
  231. acmHeader[0].cbDstLength = cbOutBytes[0];
  232. acmHeader[0].dwDstUser = 0;
  233. acmHeader[1].cbStruct = sizeof(acmHeader);
  234. acmHeader[1].fdwStatus = 0;
  235. acmHeader[1].dwUser = 0;
  236. acmHeader[1].pbSrc = sCompBuffer;
  237. acmHeader[1].cbSrcLength = cbOutBytes[0];
  238. acmHeader[1].pbDst = sSample;
  239. acmHeader[1].cbDstLength = cbOutBytes[1];
  240. acmHeader[1].dwDstUser = 0;
  241. acmHeader[2].cbStruct = sizeof(acmHeader);
  242. acmHeader[2].fdwStatus = 0;
  243. acmHeader[2].dwUser = 0;
  244. acmHeader[2].pbSrc = sSample;
  245. acmHeader[2].cbSrcLength = cbOutBytes[1];
  246. acmHeader[2].pbDst = sCompBuffer;
  247. acmHeader[2].cbDstLength = cbOutBytes[2];
  248. acmHeader[2].dwDstUser = 0;
  249. acmStreamPrepareHeader(acmStream[0],&acmHeader[0],0);
  250. acmStreamPrepareHeader(acmStream[1],&acmHeader[1],0);
  251. acmStreamPrepareHeader(acmStream[2],&acmHeader[2],0);
  252. hFile = CreateFile(pszFilename,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
  253. //write a temp header. we'll need to write a new one later when we know the right file size
  254. if( !writeHeader( iSize, lpwfxDest ) )
  255. {
  256. CloseHandle( hFile );
  257. return FALSE;
  258. }
  259. pData = GetCDData();
  260. if (pData)
  261. {
  262. pData->CreateMeter(&tm,hwndMain,(iSize / (CDDA_SECTOR_SIZE * SECTORS_PER_READ)),5,IDS_RIPPING_CD);
  263. }
  264. rawReadTrack( hDevice, &sTOC, nTrack, writeRead );
  265. if (pData)
  266. {
  267. pData->DestroyMeter(&tm);
  268. }
  269. acmStreamUnprepareHeader(acmStream[0],&acmHeader[0],0);
  270. acmStreamUnprepareHeader(acmStream[1],&acmHeader[1],0);
  271. acmStreamUnprepareHeader(acmStream[2],&acmHeader[2],0);
  272. acmStreamClose(acmStream[0],0);
  273. acmStreamClose(acmStream[1],0);
  274. acmStreamClose(acmStream[2],0);
  275. CloseHandle( hDevice );
  276. SetFilePointer(hFile,0,NULL,FILE_BEGIN);
  277. if( !writeHeader( dwTotalBytes, lpwfxDest ) )
  278. {
  279. CloseHandle( hFile );
  280. return FALSE;
  281. }
  282. CloseHandle( hFile );
  283. return TRUE;
  284. }