playlist.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. #include "./playlist.h"
  2. #include "../Agave/DecodeFile/ifc_audiostream.h"
  3. #include <strsafe.h>
  4. #include "../winamp/wa_ipc.h"
  5. BurnerPlaylist::BurnerPlaylist()
  6. {
  7. evntCancel = NULL;
  8. }
  9. BurnerPlaylist::~BurnerPlaylist()
  10. {
  11. if (manager.GetDecodeAPI())
  12. {
  13. waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(decodeFileGUID);
  14. factory->releaseInterface(manager.GetDecodeAPI());
  15. manager.SetDecodeAPI(NULL);
  16. }
  17. clear();
  18. }
  19. HRESULT BurnerPlaylist::Load(const wchar_t *filename)
  20. {
  21. if (!WASABI_API_SVC) return PLAYLISTMANAGER_FAILED;
  22. waServiceFactory *plmFactory = WASABI_API_SVC->service_getServiceByGuid(api_playlistmanagerGUID);
  23. if (!plmFactory) return 0;
  24. api_playlistmanager *plManager = (api_playlistmanager*)plmFactory->getInterface();
  25. if (!plManager) return 0;
  26. length = 0;
  27. int retCode = plManager->Load(filename, this);
  28. return (PLAYLISTMANAGER_SUCCESS == retCode);
  29. }
  30. DWORD BurnerPlaylist::GetTotalSectors(void)
  31. {
  32. DWORD ts = 0;
  33. for(size_t i = 0; i < GetCount(); i++)
  34. {
  35. ts += BurnerVector::at(i)->GetSizeInSectors();
  36. }
  37. return ts;
  38. }
  39. DWORD BurnerPlaylist::GetStatus(DWORD *retCode)
  40. {
  41. if(retCode) *retCode = errorCode;
  42. return statusCode;
  43. }
  44. size_t BurnerPlaylist::GetStateCount(DWORD state, DWORD code)
  45. {
  46. size_t count = 0;
  47. for (size_t i = 0; i < GetCount(); i++)
  48. {
  49. if (BurnerVector::at(i)->itemStatus == state && BurnerVector::at(i)->errorCode == code) count++;
  50. }
  51. return count;
  52. }
  53. DWORD BurnerPlaylist::GetStateLengthMS(DWORD state, DWORD code)
  54. {
  55. DWORD len = 0;
  56. for (size_t i = 0; i < GetCount(); i++)
  57. {
  58. if (BurnerVector::at(i)->itemStatus == state && BurnerVector::at(i)->errorCode == code) len += BurnerVector::at(i)->GetLength();
  59. }
  60. return len;
  61. }
  62. DWORD BurnerPlaylist::GetStateSectors(DWORD state, DWORD code)
  63. {
  64. DWORD ts = 0;
  65. for(size_t i = 0; i < GetCount(); i++)
  66. {
  67. if (BurnerVector::at(i)->itemStatus == state && BurnerVector::at(i)->errorCode == code) ts += BurnerVector::at(i)->GetSizeInSectors();
  68. }
  69. return ts;
  70. }
  71. HRESULT BurnerPlaylist::CheckLicense(BURNERPLAYLISTCALLBACK notifyCB, void *userparam)
  72. {
  73. this->notifyCB = notifyCB;
  74. this->userparam = userparam;
  75. statusCode = BURNERPLAYLIST_LICENSINGSTARTING;
  76. errorCode = BURNERPLAYLIST_SUCCESS;
  77. OnNotify(statusCode, errorCode, 0);
  78. size_t count = BurnerVector::size();
  79. size_t realCount = 0;
  80. manager.CancelBurn(); // ha-ha
  81. wchar_t **filenames = (count) ? (wchar_t**)malloc(count*sizeof(wchar_t*)) : NULL;
  82. DWORD nc, ec;
  83. for (size_t i = 0; i < count; i++)
  84. {
  85. nc = BurnerVector::at(i)->GetStatus(&ec);
  86. if (nc == BURNERITEM_READY ||
  87. ((nc == BURNERITEM_LICENSED || nc == BURNERITEM_DECODED) && ec == BURNERITEM_SUCCESS))
  88. {
  89. filenames[realCount] = (wchar_t*)BurnerVector::at(i)->GetFullName();
  90. BurnerVector::at(i)->itemStatus = BURNERITEM_LICENSING;
  91. errorCode = BURNERPLAYLIST_ITEMADDED;
  92. realCount++;
  93. }
  94. else
  95. {
  96. BurnerVector::at(i)->itemStatus = BURNERITEM_SKIPPED;
  97. errorCode = BURNERPLAYLIST_ADDITEMSKIPPED;
  98. }
  99. OnNotify(statusCode, errorCode, i);
  100. }
  101. if (realCount == 0)
  102. {
  103. statusCode = BURNERPLAYLIST_LICENSINGFINISHED;
  104. errorCode = BURNERPLAYLIST_NOFILES;
  105. OnNotify(statusCode, errorCode, 0);
  106. if (filenames) free(filenames);
  107. return statusCode;
  108. }
  109. if (!manager.GetDecodeAPI())
  110. {
  111. api_decodefile *decoder = NULL;
  112. waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(decodeFileGUID);
  113. if (factory) decoder = (api_decodefile *)factory->getInterface();
  114. if (!factory || !decoder)
  115. {
  116. statusCode = BURNERPLAYLIST_LICENSINGFINISHED;
  117. errorCode = BURNERPLAYLIST_DECODESERVICEFAILED;
  118. OnNotify(statusCode, errorCode, 0);
  119. free(filenames);
  120. return statusCode;
  121. }
  122. manager.SetDecodeAPI(decoder);
  123. }
  124. manager.SetFiles(realCount, (const wchar_t**)filenames, this);
  125. free(filenames);
  126. return statusCode;
  127. }
  128. HRESULT BurnerPlaylist::Decode(void* hFile, BURNERPLAYLISTCALLBACK notifyCB, void *userparam, BOOL block)
  129. {
  130. this->notifyCB = notifyCB;
  131. this->userparam = userparam;
  132. this->hFile = hFile;
  133. hThread = NULL;
  134. statusCode = BURNERPLAYLIST_DECODESTARTING;
  135. errorCode = BURNERPLAYLIST_SUCCESS;
  136. OnNotify(statusCode, errorCode, 0);
  137. if (!manager.GetDecodeAPI())
  138. {
  139. api_decodefile *decoder = NULL;
  140. waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(decodeFileGUID);
  141. if (factory) decoder = (api_decodefile *)factory->getInterface();
  142. if (!factory || !decoder)
  143. {
  144. statusCode = BURNERPLAYLIST_DECODEFINISHED;
  145. errorCode = BURNERPLAYLIST_DECODESERVICEFAILED;
  146. OnNotify(statusCode, errorCode, 0);
  147. return statusCode;
  148. }
  149. manager.SetDecodeAPI(decoder);
  150. }
  151. if (block)
  152. {
  153. statusCode = DecodeWorker(this);
  154. OnNotify(statusCode, errorCode, 100);
  155. if (manager.GetDecodeAPI())
  156. {
  157. waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(decodeFileGUID);
  158. factory->releaseInterface(manager.GetDecodeAPI());
  159. manager.SetDecodeAPI(NULL);
  160. }
  161. }
  162. else
  163. {
  164. DWORD id;
  165. hThread = CreateThread(NULL, 0, DecodeWorker, this, 0, &id);
  166. if (NULL == hThread)
  167. {
  168. statusCode = BURNERPLAYLIST_DECODEFINISHED;
  169. errorCode = BURNERPLAYLIST_THREADCREATEFAILED;
  170. OnNotify(statusCode, errorCode, 0);
  171. }
  172. }
  173. return statusCode;
  174. }
  175. HRESULT BurnerPlaylist::Burn(obj_primo *primoSDK, DWORD drive, DWORD maxspeed, DWORD burnFlags, void* hFile,
  176. BURNERPLAYLISTCALLBACK notifyCB, void *userparam, BOOL block)
  177. {
  178. this->primoSDK = primoSDK;
  179. this->drive = drive;
  180. this->hFile = hFile;
  181. this->maxspeed = maxspeed;
  182. this->burnFlags = burnFlags;
  183. this->notifyCB = notifyCB;
  184. this->userparam = userparam;
  185. statusCode = BURNERPLAYLIST_BURNSTARTING;
  186. errorCode = BURNERPLAYLIST_SUCCESS;
  187. evntCancel = CreateEvent(NULL, FALSE, FALSE, NULL);
  188. OnNotify(statusCode, errorCode, 0); // here we go
  189. DWORD retCode;
  190. DWORD dwUnits[2];
  191. dwUnits[0] = drive;
  192. dwUnits[1] = 0xFFFFFFFF;
  193. retCode = primoSDK->NewAudio(dwUnits);
  194. if (PRIMOSDK_OK != retCode)
  195. {
  196. statusCode = BURNERPLAYLIST_BURNFINISHED;
  197. errorCode = BURNERPLAYLIST_NEWAUDIOFAILED;
  198. OnNotify(statusCode, errorCode, retCode);
  199. return statusCode;
  200. }
  201. if (BurnerVector::size() == 0)
  202. {
  203. statusCode = BURNERPLAYLIST_BURNFINISHED;
  204. errorCode = BURNERPLAYLIST_NOFILES;
  205. OnNotify(statusCode, errorCode, retCode);
  206. return statusCode;
  207. }
  208. size_t i;
  209. for(i = 0; i < BurnerVector::size(); i++)
  210. {
  211. DWORD ec;
  212. if (BURNERITEM_DECODED == BurnerVector::at(i)->GetStatus(&ec) && BURNERITEM_SUCCESS == ec)
  213. {
  214. BurnerVector::at(i)->itemStatus = BURNERITEM_READY;
  215. retCode = BurnerVector::at(i)->AddStream(primoSDK, hFile);
  216. if (PRIMOSDK_OK != retCode)
  217. {
  218. BurnerVector::at(i)->itemStatus = BURNERITEM_BURNED;
  219. BurnerVector::at(i)->errorCode = BURNERITEM_FAILED;
  220. errorCode = BURNERPLAYLIST_ADDITEMFAILED;
  221. break;
  222. }
  223. else errorCode = BURNERPLAYLIST_ITEMADDED;
  224. }
  225. else
  226. {
  227. errorCode = BURNERPLAYLIST_ADDITEMSKIPPED;
  228. BurnerVector::at(i)->itemStatus = BURNERITEM_SKIPPED;
  229. }
  230. OnNotify(statusCode, errorCode, i);
  231. }
  232. if (PRIMOSDK_OK != retCode || (WAIT_OBJECT_0 == WaitForSingleObject(evntCancel, 0)))
  233. {
  234. statusCode = (PRIMOSDK_OK == retCode) ? BURNERPLAYLIST_BURNCANCELING : BURNERPLAYLIST_BURNFINISHING;
  235. errorCode = (PRIMOSDK_OK == retCode) ? BURNERPLAYLIST_ABORTED : BURNERPLAYLIST_ADDITEMFAILED;
  236. BPLRUNSTATUS burnStatus;
  237. for(i = 0; i < BurnerVector::size(); i++)
  238. {
  239. burnStatus.iIndex = (int)i;
  240. if (BURNERITEM_SKIPPED == BurnerVector::at(burnStatus.iIndex)->itemStatus) continue;
  241. BurnerVector::at(burnStatus.iIndex)->itemStatus = (PRIMOSDK_OK == retCode) ? BURNERITEM_ABORTED : BURNERITEM_FAILED;
  242. OnNotify(statusCode, errorCode, (ULONG_PTR)&burnStatus);
  243. }
  244. CloseHandle(evntCancel);
  245. evntCancel = NULL;
  246. primoSDK->CloseAudio();
  247. statusCode = BURNERPLAYLIST_BURNFINISHED;
  248. OnNotify(statusCode, errorCode, i);
  249. return statusCode;
  250. }
  251. if (block)
  252. {
  253. DWORD notifyCode = BurnerWorker(this);
  254. OnNotify(BURNERPLAYLIST_BURNFINISHED, notifyCode, errorCode);
  255. }
  256. else
  257. {
  258. DWORD id;
  259. hThread = CreateThread(NULL, 0, BurnerWorker, this, 0, &id);
  260. if (NULL == hThread)
  261. {
  262. statusCode = BURNERPLAYLIST_BURNFINISHED;
  263. errorCode = BURNERPLAYLIST_THREADCREATEFAILED;
  264. OnNotify(statusCode, errorCode, i);
  265. }
  266. }
  267. return statusCode;
  268. }
  269. DWORD BurnerPlaylist::AddCompilationToCDDB(void)
  270. {
  271. wchar_t buf[64] = {0};
  272. wchar_t albumbuf[256]= L"Mix CD ";
  273. wchar_t dateString[128] = {0};
  274. GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, dateString, 128);
  275. StringCchCatW(albumbuf, 256, dateString);
  276. StringCchPrintfW(buf, 64, L"cda://%c.cda", (char)drive);
  277. extendedFileInfoStructW efis = { buf, L"album", albumbuf, 256, };
  278. if (SendMessageW(winampWnd, WM_WA_IPC, (WPARAM)&efis, IPC_SET_EXTENDED_FILE_INFOW))
  279. {
  280. efis.metadata = L"albumartist";
  281. efis.ret = L"Various Artists";
  282. SendMessageW(winampWnd, WM_WA_IPC, (WPARAM)&efis, IPC_SET_EXTENDED_FILE_INFOW);
  283. efis.metadata = L"genre";
  284. efis.ret = L"Mix";
  285. SendMessageW(winampWnd, WM_WA_IPC, (WPARAM)&efis, IPC_SET_EXTENDED_FILE_INFOW);
  286. SYSTEMTIME syst;
  287. GetLocalTime(&syst);
  288. if (syst.wYear)
  289. {
  290. wchar_t yearbuf[64] = {0};
  291. StringCchPrintfW(yearbuf, 64, L"%04d", syst.wYear);
  292. efis.metadata = L"year";
  293. efis.ret = yearbuf;
  294. SendMessageW(winampWnd, WM_WA_IPC, (WPARAM)&efis, IPC_SET_EXTENDED_FILE_INFOW);
  295. }
  296. wchar_t buf2[32] = {0};
  297. int index = 1;
  298. for (size_t i = 0;i < GetCount();i++)
  299. {
  300. DWORD is, ec;
  301. is = BurnerVector::at(i)->GetStatus(&ec);
  302. if (BURNERITEM_BURNED == is && BURNERITEM_SUCCESS == ec)
  303. {
  304. StringCchPrintfW(buf, 64, L"cda://%c,%d.cda", (char)drive, i);
  305. lstrcpynW(buf2, L"title", 32);
  306. efis.metadata = buf2;
  307. efis.ret = const_cast<wchar_t*>(BurnerVector::at(i)->GetTitle());
  308. SendMessageW(winampWnd, WM_WA_IPC, (WPARAM)&efis, IPC_SET_EXTENDED_FILE_INFOW);
  309. lstrcpynW(buf2, L"artist", 32);
  310. efis.ret=L"Various Artists"; // TODO: use actual track artist
  311. SendMessageW(winampWnd, WM_WA_IPC, (WPARAM)&efis, IPC_SET_EXTENDED_FILE_INFOW);
  312. index++;
  313. }
  314. }
  315. SendMessageW(winampWnd, WM_WA_IPC, (WPARAM)0, IPC_WRITE_EXTENDED_FILE_INFO);
  316. }
  317. return 1;
  318. }
  319. DWORD WINAPI BurnerPlaylist::DecodeWorker(void* param)
  320. {
  321. DWORD retCode;
  322. BurnerPlaylist *playlist = (BurnerPlaylist*)param;
  323. playlist->percentStep = (float)(1.f / ((double)playlist->GetCount()));
  324. playlist->activeDecode = NULL;
  325. DWORD itemError = BURNERITEM_SUCCESS;
  326. // for nice ui reason lets do it twice
  327. playlist->statusCode = BURNERPLAYLIST_DECODESTARTING;
  328. for(size_t i = 0; i < playlist->GetCount(); i++)
  329. {
  330. DWORD ec;
  331. if (BURNERITEM_LICENSED == playlist->at(i)->GetStatus(&ec) && BURN_OK == ec)
  332. {
  333. playlist->errorCode = BURNERPLAYLIST_ITEMADDED;
  334. playlist->at(i)->itemStatus = BURNERITEM_READY;
  335. }
  336. else
  337. {
  338. playlist->errorCode = BURNERPLAYLIST_ADDITEMSKIPPED;
  339. playlist->at(i)->itemStatus = BURNERITEM_SKIPPED;
  340. }
  341. playlist->OnNotify(playlist->statusCode, playlist->errorCode, i);
  342. }
  343. // actual work
  344. for(size_t i = 0; i < playlist->GetCount(); i++)
  345. {
  346. if (BURNERITEM_READY == playlist->at(i)->GetStatus(NULL))
  347. {
  348. BPLDECODEINFO info;
  349. info.iInstance = playlist->at(i);
  350. info.iIndex = (int)i;
  351. info.iNotifyCode = 0;
  352. info.iErrorCode = 0;
  353. info.percentCompleted = (playlist->activeDecode) ? playlist->percentStep*i*100.0f : 0;
  354. playlist->activeDecode = &info;
  355. playlist->statusCode = BURNERPLAYLIST_DECODEPROGRESS;
  356. playlist->errorCode = BURNERPLAYLIST_DECODENEXTITEM;
  357. playlist->OnNotify(playlist->statusCode, playlist->errorCode, (ULONG_PTR)playlist->activeDecode);
  358. retCode = playlist->at(i)->Decode(&playlist->manager, playlist->hFile, OnItemDecode, playlist);
  359. if (BURNERITEM_SUCCESS != retCode)
  360. {
  361. itemError = retCode;
  362. }
  363. if (BURNERITEM_ABORTED == retCode)
  364. {
  365. playlist->statusCode = BURNERPLAYLIST_DECODECANCELING;
  366. playlist->errorCode = BURNERPLAYLIST_ABORTED;
  367. DWORD notifyCode = BURNERITEM_DECODEFINISHED;
  368. for(size_t k = i; k < playlist->GetCount(); k++)
  369. {
  370. info.iIndex = (int)k;
  371. info.iInstance = playlist->at(k);
  372. info.iInstance->errorCode = BURNERITEM_ABORTED;
  373. info.iInstance->itemStatus = BURNERITEM_ABORTED;
  374. OnItemDecode(info.iInstance, playlist, notifyCode, info.iInstance->errorCode);
  375. }
  376. break;
  377. }
  378. }
  379. }
  380. // release decoderAPI
  381. waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(decodeFileGUID);
  382. factory->releaseInterface(playlist->manager.GetDecodeAPI());
  383. playlist->manager.SetDecodeAPI(NULL);
  384. if (playlist->hThread)
  385. {
  386. CloseHandle(playlist->hThread);
  387. playlist->hThread = NULL;
  388. }
  389. playlist->statusCode = BURNERPLAYLIST_DECODEFINISHED;
  390. if (playlist->GetCount() == 0) playlist->errorCode = BURNERPLAYLIST_NOFILES;
  391. else if (BURNERITEM_ABORTED == itemError) playlist->errorCode = BURNERPLAYLIST_ABORTED;
  392. else if (BURNERITEM_SUCCESS == itemError) playlist->errorCode = BURNERPLAYLIST_SUCCESS;
  393. else playlist->errorCode = BURNERPLAYLIST_FAILED;
  394. playlist->OnNotify(playlist->statusCode , playlist->errorCode, (ULONG_PTR)playlist->activeDecode);
  395. playlist->activeDecode = NULL;
  396. return playlist->statusCode;
  397. }
  398. DWORD WINAPI BurnerPlaylist::BurnerWorker(void* param)
  399. {
  400. DWORD primoCode;
  401. BurnerPlaylist *playlist = (BurnerPlaylist*)param;
  402. WABURNSTRUCT bs;
  403. playlist->statusCode = BURNERPLAYLIST_BURNSTARTING;
  404. playlist->errorCode = BURNERPLAYLIST_BEGINBURN;
  405. playlist->OnNotify(playlist->statusCode, playlist->errorCode, 0);
  406. primoCode = BeginBurn(playlist->primoSDK, playlist->drive, &bs);
  407. bs.eject = TRUE;
  408. DWORD leadin = 0;
  409. BPLRUNSTATUS burnStatus;
  410. ZeroMemory(&burnStatus, sizeof(BPLRUNSTATUS));
  411. burnStatus.iIndex = -1;
  412. BOOL canceled = FALSE;
  413. DWORD itemSector = 0;
  414. BOOL cp1 = FALSE;
  415. if (PRIMOSDK_OK != primoCode)
  416. {
  417. playlist->errorCode = BURNERPLAYLIST_BEGINBURNFAILED;
  418. }
  419. else
  420. {
  421. playlist->statusCode = BURNERPLAYLIST_BURNPROGRESS;
  422. primoCode = playlist->primoSDK->WriteAudioEx(playlist->burnFlags, playlist->maxspeed, 0x00);
  423. if (PRIMOSDK_OK == primoCode)
  424. {
  425. DWORD waitResult;
  426. while(BURNERPLAYLIST_BURNPROGRESS == playlist->statusCode && WAIT_TIMEOUT == (waitResult = WaitForSingleObject(playlist->evntCancel, 500)))
  427. {
  428. primoCode = playlist->primoSDK->RunningStatus(PRIMOSDK_GETSTATUS, &burnStatus.sCurrent, &burnStatus.sTotal);
  429. if (PRIMOSDK_RUNNING == primoCode)
  430. {
  431. playlist->statusCode = BURNERPLAYLIST_BURNPROGRESS;
  432. if (burnStatus.sCurrent == 0)
  433. {
  434. if (cp1) continue; // do not send anymore
  435. playlist->errorCode = BURNERPLAYLIST_WRITELEADIN; //BURNERPLAYLIST_DISCOPEN
  436. cp1 = TRUE;
  437. }
  438. else if (burnStatus.sCurrent > 0 && (!leadin || leadin == burnStatus.sCurrent))
  439. {
  440. if (!leadin)
  441. {
  442. leadin = burnStatus.sCurrent;
  443. playlist->errorCode = BURNERPLAYLIST_WRITELEADIN; // unreachable :)
  444. }
  445. continue;
  446. }
  447. else if (burnStatus.sCurrent == burnStatus.sTotal)
  448. {
  449. if (burnStatus.iIndex >= 0 && BURNERITEM_BURNING == playlist->at(burnStatus.iIndex)->itemStatus)
  450. {
  451. playlist->at(burnStatus.iIndex)->itemStatus = BURNERITEM_BURNED;
  452. playlist->at(burnStatus.iIndex)->errorCode = BURNERITEM_SUCCESS;
  453. playlist->at(burnStatus.iIndex)->percentCompleted = 100;
  454. playlist->OnNotify(playlist->statusCode, BURNERPLAYLIST_WRITEITEMEND, (ULONG_PTR)&burnStatus);
  455. }
  456. if (burnStatus.iIndex == -1) continue;
  457. playlist->errorCode = BURNERPLAYLIST_WRITELEADOUT;
  458. burnStatus.iIndex = -1;
  459. burnStatus.iInstance = NULL;
  460. }
  461. else
  462. {
  463. playlist->errorCode = BURNERPLAYLIST_WRITEDATA;
  464. while (itemSector < burnStatus.sCurrent && burnStatus.iIndex < (int)playlist->size())
  465. { if (burnStatus.iIndex >= 0 && BURNERITEM_BURNING == playlist->at(burnStatus.iIndex)->itemStatus)
  466. {
  467. playlist->at(burnStatus.iIndex)->itemStatus = BURNERITEM_BURNED;
  468. playlist->at(burnStatus.iIndex)->errorCode = BURNERITEM_SUCCESS;
  469. playlist->at(burnStatus.iIndex)->percentCompleted = 100;
  470. playlist->OnNotify(playlist->statusCode, BURNERPLAYLIST_WRITEITEMEND, (ULONG_PTR)&burnStatus);
  471. }
  472. while (++burnStatus.iIndex < (int)playlist->size() && BURNERITEM_READY != playlist->at(burnStatus.iIndex)->itemStatus);
  473. if (burnStatus.iIndex < (int)playlist->size()) itemSector += playlist->at(burnStatus.iIndex)->GetSizeInSectors();
  474. }
  475. if ( burnStatus.iIndex >= 0 && burnStatus.iIndex < (int)playlist->size())
  476. {
  477. BurnerItem *bi = playlist->at(burnStatus.iIndex);
  478. burnStatus.iInstance = bi;
  479. if (BURNERITEM_READY == bi->itemStatus)
  480. {
  481. bi->itemStatus = BURNERITEM_BURNING;
  482. bi->percentCompleted = 0;
  483. playlist->OnNotify(playlist->statusCode, BURNERPLAYLIST_WRITEITEMBEGIN, (ULONG_PTR)&burnStatus);
  484. }
  485. if (BURNERITEM_SUCCESS == bi->errorCode)
  486. {
  487. DWORD is = bi->GetSizeInSectors();
  488. bi->itemStatus = BURNERITEM_BURNING;
  489. bi->percentCompleted = (is - (itemSector - burnStatus.sCurrent))*100 / is;
  490. }
  491. else
  492. {
  493. bi->itemStatus = BURNERITEM_BURNED;
  494. bi->errorCode = BURNERITEM_SUCCESS;
  495. bi->percentCompleted = 100;
  496. }
  497. }
  498. }
  499. playlist->OnNotify(playlist->statusCode, playlist->errorCode, (ULONG_PTR)&burnStatus);
  500. }
  501. else
  502. {
  503. playlist->errorCode = BURNERPLAYLIST_WRITEAUDIOFAILED;
  504. break;
  505. }
  506. }
  507. if (WAIT_OBJECT_0 == waitResult)
  508. { // aborting
  509. canceled = TRUE;
  510. playlist->statusCode = BURNERPLAYLIST_BURNCANCELING;
  511. playlist->errorCode = BURNERPLAYLIST_ABORTED;
  512. playlist->at(burnStatus.iIndex)->itemStatus = BURNERITEM_CANCELING;
  513. playlist->OnNotify(playlist->statusCode, playlist->errorCode, (ULONG_PTR)&burnStatus);
  514. DWORD test = playlist->primoSDK->RunningStatus(PRIMOSDK_ABORT, &burnStatus.sCurrent, &burnStatus.sTotal);
  515. do
  516. {
  517. Sleep(1000);
  518. primoCode = playlist->primoSDK->RunningStatus(PRIMOSDK_GETSTATUS, &burnStatus.sCurrent, &burnStatus.sTotal);
  519. }while(PRIMOSDK_RUNNING == primoCode);
  520. for (size_t i = 0; i < playlist->GetCount(); i++)
  521. {
  522. burnStatus.iIndex = (int)i;
  523. DWORD cs = playlist->at(burnStatus.iIndex)->itemStatus;
  524. if (BURNERITEM_BURNING != cs && BURNERITEM_READY != cs && BURNERITEM_CANCELING != cs) continue;
  525. playlist->at(burnStatus.iIndex)->itemStatus = BURNERITEM_ABORTED;
  526. playlist->OnNotify(playlist->statusCode, playlist->errorCode, (ULONG_PTR)&burnStatus);
  527. }
  528. }
  529. }
  530. else
  531. {
  532. playlist->errorCode = BURNERPLAYLIST_WRITEAUDIOFAILED;
  533. }
  534. }
  535. if (PRIMOSDK_USERABORT == primoCode) playlist->errorCode = BURNERPLAYLIST_ABORTED;
  536. else if (PRIMOSDK_OK == primoCode) playlist->errorCode = BURNERPLAYLIST_SUCCESS;
  537. playlist->statusCode = BURNERPLAYLIST_BURNFINISHING;
  538. playlist->OnNotify(playlist->statusCode, playlist->errorCode, 0);
  539. // check unit status and notify later
  540. DWORD statCode, cmd(0), sense(0), asc(0), ascq(0);
  541. statCode = playlist->primoSDK->UnitStatus(&bs.drive, &cmd, &sense, &asc, &ascq);
  542. bs.eject = playlist->ejectDone;
  543. primoCode = EndBurn(&bs);
  544. if (PRIMOSDK_OK != primoCode) playlist->errorCode = BURNERPLAYLIST_ENDBURNFAILED;
  545. playlist->primoSDK->CloseAudio();
  546. if (playlist->hThread)
  547. {
  548. CloseHandle(playlist->hThread);
  549. playlist->hThread = NULL;
  550. }
  551. primoCode = (0xFF000000 & (statCode << 24)) | (0x00FF0000 & (sense << 16)) | (0x0000FF00 & (asc << 8)) | (0x000000FF & ascq);
  552. if (BURNERPLAYLIST_SUCCESS == playlist->errorCode && statCode != PRIMOSDK_OK) playlist->errorCode = BURNERPLAYLIST_FAILED;
  553. if (BURNERPLAYLIST_SUCCESS == playlist->errorCode && (PRIMOSDK_WRITE == (playlist->burnFlags&PRIMOSDK_WRITE)))
  554. {
  555. playlist->manager.BurnFinished();
  556. }
  557. else
  558. {
  559. playlist->manager.CancelBurn();
  560. }
  561. playlist->statusCode = BURNERPLAYLIST_BURNFINISHED;
  562. playlist->OnNotify(playlist->statusCode, playlist->errorCode, primoCode);
  563. return playlist->statusCode;
  564. }
  565. DWORD BurnerPlaylist::OnNotify(DWORD notifyCode, DWORD errorCode, ULONG_PTR param)
  566. {
  567. DWORD retCode = (notifyCB) ? notifyCB(this, userparam, notifyCode, errorCode, param) : BURNERPLAYLIST_CONTINUE;
  568. if ( BURNERPLAYLIST_STOP == retCode && evntCancel) SetEvent(evntCancel);
  569. return retCode;
  570. }
  571. void BurnerPlaylist::OnFile(const wchar_t *filename, const wchar_t *title, int lengthInMS, ifc_plentryinfo *info)
  572. {
  573. if (NULL == filename) return;
  574. BurnerItem *item = new BurnerItem();
  575. item->Create(filename,title, lengthInMS);
  576. length += lengthInMS;
  577. push_back(item);
  578. }
  579. DWORD WINAPI BurnerPlaylist::OnItemDecode(void* sender, void *param, DWORD notifyCode, DWORD errorCode)
  580. {
  581. BurnerPlaylist *pl = (BurnerPlaylist*)param;
  582. pl->activeDecode->iNotifyCode = notifyCode;
  583. pl->activeDecode->iErrorCode = errorCode;
  584. pl->activeDecode->percentCompleted += pl->percentStep;
  585. pl->statusCode = BURNERPLAYLIST_DECODEPROGRESS;
  586. pl->errorCode = BURNERPLAYLIST_DECODEITEM;
  587. DWORD retCode = pl->OnNotify(pl->statusCode , pl->errorCode , (ULONG_PTR)pl->activeDecode);
  588. return (BURNERPLAYLIST_STOP == retCode) ? BURNERITEM_STOP : BURNERITEM_CONTINUE;
  589. }
  590. void BurnerPlaylist::OnLicenseCallback(size_t numFiles, WRESULT *results)
  591. {
  592. statusCode = BURNERPLAYLIST_LICENSINGPROGRESS;
  593. DWORD errorCode = BURNERPLAYLIST_SUCCESS;
  594. size_t realCount = 0;
  595. size_t allowed = 0;
  596. for (size_t i = 0; i < BurnerVector::size(); i++)
  597. {
  598. if (BURNERITEM_LICENSING == BurnerVector::at(i)->itemStatus)
  599. {
  600. if (realCount == numFiles)
  601. {
  602. statusCode = BURNERPLAYLIST_LICENSINGFINISHED;
  603. errorCode = BURNERPLAYLIST_WRONGFILECOUNT;
  604. break;
  605. }
  606. BurnerVector::at(i)->itemStatus = BURNERITEM_LICENSED;
  607. BurnerVector::at(i)->errorCode = results[realCount];
  608. OnNotify(statusCode, results[realCount], (LPARAM)i);
  609. if (BURN_OK != results[realCount]) errorCode = BURNERPLAYLIST_FILENOTLICENSED;
  610. else allowed++;
  611. realCount++;
  612. }
  613. }
  614. statusCode = BURNERPLAYLIST_LICENSINGFINISHED;
  615. OnNotify(statusCode, errorCode, allowed);
  616. }
  617. #define CBCLASS BurnerPlaylist
  618. START_DISPATCH;
  619. VCB(IFC_PLAYLISTLOADERCALLBACK_ONFILE, OnFile)
  620. END_DISPATCH;
  621. #undef CBCLASS