item.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. #include "./item.h"
  2. #include <strsafe.h>
  3. #define DECODEBUFFER_SIZE 4096*4
  4. DWORD BurnerItem::zeroMem[] = {0x00,};
  5. BurnerItem::BurnerItem(void)
  6. {
  7. fullname = NULL;
  8. title = NULL;
  9. length = 0;
  10. sizeBytes = 0;
  11. sizeSectors = 0;
  12. preGap = 0;
  13. fposition = 0;
  14. fhandle = NULL;
  15. heap = GetProcessHeap();
  16. ZeroMemory(ISRC, 12);
  17. itemStatus = BURNERITEM_READY;
  18. percentCompleted = 0;
  19. errorCode = BURNERITEM_SUCCESS;
  20. if (zeroMem[0] == 0x00) FillMemory(zeroMem, ZEROMEM_SIZE, 0xFFFFFFFF);
  21. }
  22. BurnerItem::~BurnerItem(void)
  23. {
  24. Destroy();
  25. }
  26. HRESULT BurnerItem::Create(const wchar_t* fullname, const wchar_t *title, int length)
  27. {
  28. if (this->fullname)
  29. {
  30. errorCode = BURNERITEM_ALREADYCREATED;
  31. return errorCode;
  32. }
  33. this->fullname = DuplicateString(heap, fullname, lstrlenW(fullname));
  34. this->title = DuplicateString(heap, title, lstrlenW(title));
  35. this->length = length;
  36. itemStatus = BURNERITEM_READY;
  37. errorCode = BURNERITEM_SUCCESS;
  38. return errorCode;
  39. }
  40. void BurnerItem::Destroy(void)
  41. {
  42. if (fullname)
  43. {
  44. HeapFree(heap, NULL, fullname);
  45. fullname = NULL;
  46. }
  47. if (title)
  48. {
  49. HeapFree(heap, NULL, title);
  50. title = NULL;
  51. }
  52. length = 0;
  53. sizeBytes = 0;
  54. sizeSectors = 0;
  55. preGap = 0;
  56. fposition = 0;
  57. fhandle = NULL;
  58. ZeroMemory(ISRC, 12);
  59. }
  60. HRESULT BurnerItem::Decode(BurnManager *manager, void *fileHandle, BURNERITEMCALLBACK notifyCB, void *userparam)
  61. {
  62. itemStatus = BURNERITEM_DECODING;
  63. if (notifyCB) notifyCB(this, userparam, BURNERITEM_DECODESTARTING, BURNERITEM_SUCCESS);
  64. if (!fullname)
  65. {
  66. errorCode = BURNERITEM_BADFILENAME;
  67. itemStatus = BURNERITEM_DECODED;
  68. if (notifyCB) notifyCB(this, userparam, BURNERITEM_DECODEFINISHED, errorCode);
  69. return errorCode;
  70. }
  71. ifc_audiostream *stream = manager->CreateDecoder(fullname);
  72. if (!stream)
  73. {
  74. errorCode = BURNERITEM_UNABLEOPENFILE;
  75. itemStatus = BURNERITEM_DECODED;
  76. if (notifyCB) notifyCB(this, userparam, BURNERITEM_DECODEFINISHED, errorCode);
  77. return errorCode;
  78. }
  79. fposition = 0;
  80. LONG fposLow(0), fposHigh(0);
  81. fposLow = SetFilePointer(fileHandle, 0, &fposHigh, FILE_CURRENT);
  82. fposition = (((__int64)fposHigh) << 32) | fposLow;
  83. DWORD decoded = 0;
  84. sizeBytes = 0;
  85. sizeSectors = 0;
  86. double percent = 0.0;
  87. int iopercent = -1;
  88. percentCompleted = 0;
  89. errorCode = BURNERITEM_DECODEPROGRESS;
  90. do
  91. {
  92. unsigned __int8 buffer[DECODEBUFFER_SIZE] = {0};
  93. int decode_killswitch=0, decode_error;
  94. decoded = (DWORD)stream->ReadAudio(buffer, DECODEBUFFER_SIZE, &decode_killswitch, &decode_error);
  95. if (decoded > 0)
  96. {
  97. DWORD written = 0;
  98. if (!WriteFile(fileHandle, buffer, decoded, &written, NULL))
  99. {
  100. errorCode = BURNERITEM_WRITEERROR;
  101. break;
  102. }
  103. sizeBytes += decoded;
  104. double step = ((double)decoded) / (((double)length) * 176.4f)*100.0f;
  105. percent += step;
  106. percentCompleted = (int)percent;
  107. if (iopercent != percentCompleted)
  108. {
  109. iopercent = percentCompleted;
  110. if (notifyCB)
  111. {
  112. if (BURNERITEM_CONTINUE != notifyCB(this, userparam, BURNERITEM_DECODEPROGRESS, percentCompleted))
  113. {
  114. errorCode = BURNERITEM_DECODECANCELING;
  115. break;
  116. }
  117. }
  118. }
  119. }
  120. } while(decoded);
  121. if (stream) manager->CloseDecoder(stream);
  122. itemStatus = BURNERITEM_DECODED;
  123. DWORD notifyCode = BURNERITEM_DECODEFINISHED;
  124. switch(errorCode)
  125. {
  126. case BURNERITEM_DECODECANCELING:
  127. errorCode = BURNERITEM_ABORTED;
  128. itemStatus = BURNERITEM_ABORTED;
  129. break;
  130. case BURNERITEM_DECODEPROGRESS:
  131. sizeSectors = (DWORD)(sizeBytes/2352 + ((sizeBytes%2352) ? 1 : 0));
  132. errorCode = BURNERITEM_SUCCESS;
  133. break;
  134. }
  135. if (notifyCB) notifyCB(this, userparam, notifyCode, errorCode);
  136. return errorCode;
  137. }
  138. HRESULT BurnerItem::AddStream(obj_primo *primoSDK, void *fileHandle)
  139. {
  140. fhandle = fileHandle;
  141. needSetFilePos = TRUE;
  142. streamedSize = 0;
  143. errorCode = primoSDK->AddAudioStream(StreamFiller, this, 0, GetSizeInSectors());
  144. return errorCode;
  145. }
  146. void BurnerItem::SetPreGap(unsigned int preGap)
  147. {
  148. this->preGap = preGap;
  149. }
  150. void BurnerItem::SetISRC(unsigned __int8 *ISRC)
  151. {
  152. CopyMemory(this->ISRC, ISRC, 12);
  153. }
  154. int BurnerItem::GetStatus(DWORD *retCode)
  155. {
  156. if(retCode)
  157. {
  158. switch(itemStatus)
  159. {
  160. case BURNERITEM_DECODING:
  161. case BURNERITEM_BURNING:
  162. *retCode = percentCompleted;
  163. break;
  164. default:
  165. *retCode = errorCode;
  166. }
  167. }
  168. return itemStatus;
  169. }
  170. DWORD BurnerItem::StreamFiller(PBYTE pBuffer, DWORD dwBytesRequested, PDWORD pdwBytesWritten, PVOID pContext)
  171. {
  172. BurnerItem *item = (BurnerItem*) pContext;
  173. if (item->needSetFilePos)
  174. {
  175. LONG fposLow = (LONG) item->fposition;
  176. LONG fposHigh = (LONG) (item->fposition >> 32);
  177. SetFilePointer(item->fhandle, fposLow, &fposHigh, FILE_BEGIN);
  178. item->streamedSize = 0;
  179. item->needSetFilePos = FALSE;
  180. }
  181. DWORD needToRead;
  182. item->streamedSize += dwBytesRequested;
  183. // check if we need to fill with zero
  184. if (item->streamedSize > item->sizeBytes)
  185. {
  186. needToRead = (DWORD)min(0, ((long)item->sizeBytes) - long(item->streamedSize - dwBytesRequested));
  187. }
  188. else
  189. {
  190. needToRead = dwBytesRequested;
  191. }
  192. // read from file
  193. if (needToRead)
  194. {
  195. *pdwBytesWritten = 0;
  196. if (!ReadFile(item->fhandle, pBuffer, needToRead, pdwBytesWritten, NULL))
  197. {
  198. DWORD le = GetLastError();
  199. item->itemStatus = BURNERITEM_BURNED;
  200. item->errorCode = BURNERITEM_READSTREAMERROR;
  201. }
  202. //else
  203. //{
  204. // LONG fposLow(0), fposHigh(0);
  205. // fposLow = SetFilePointer(item->fhandle, 0, &fposHigh, FILE_CURRENT);
  206. // SetFilePointer(item->fhandle, -((LONG)*pdwBytesWritten), NULL, FILE_CURRENT);
  207. // DWORD written(0);
  208. // long needToZerro(*pdwBytesWritten)l
  209. // while(needToZerro > 0)
  210. // {
  211. // DWORD write = min(ZEROMEM_SIZE*sizeof(DWORD), needToZerro);
  212. // if (!WriteFile(item->fhandle, &zeroMem, write, &written, NULL)) break;
  213. // needToZerro -= written;
  214. // }
  215. // SetFilePointer(item->fhandle, fposLow, &fposHigh, FILE_BEGIN);
  216. //}
  217. }
  218. else
  219. {
  220. *pdwBytesWritten = 0;
  221. }
  222. return (BURNERITEM_SUCCESS == item->errorCode) ? PRIMOSDK_OK : PRIMOSDK_ERROR;
  223. }
  224. wchar_t* BurnerItem::DuplicateString(void *heap, const wchar_t *source, unsigned int cchSource)
  225. {
  226. wchar_t *dest = (wchar_t*) HeapAlloc(heap, NULL, (cchSource + 1) * sizeof(wchar_t));
  227. CopyMemory(dest, source, cchSource * sizeof(wchar_t));
  228. dest[cchSource] = 0x0000;
  229. return dest;
  230. }