VeritasPlay.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. #include "Main.h"
  2. #include <windows.h>
  3. #include "VeritasPlay.h"
  4. #include "CDDB.h"
  5. #include "workorder.h"
  6. #include "api.h"
  7. VeritasPlay::VeritasPlay(bool _ripping)
  8. : opened(false), ripping(_ripping),
  9. primo(0), padStart(false), padEnd(false)
  10. {
  11. submitHandle=0;
  12. hThread = NULL;
  13. overflowBuffer = NULL;
  14. overflow = 0;
  15. buffers = NULL;
  16. currentBuffer = 0;
  17. }
  18. VeritasPlay::~VeritasPlay()
  19. {
  20. if (opened)
  21. Abort();
  22. Close();
  23. DestroyBuffers();
  24. if (primo)
  25. {
  26. waServiceFactory *sf = (line.service ? line.service->service_getServiceByGuid(obj_primo::getServiceGuid()) : NULL);
  27. if (sf) sf->releaseInterface(primo);
  28. }
  29. primo = 0;
  30. if (submitHandle)
  31. {
  32. int x = workorder->CloseSig(submitHandle);
  33. submitHandle=0;
  34. }
  35. }
  36. void VeritasPlay::CreateBuffers()
  37. {
  38. if (buffers)
  39. return;
  40. if (ripping)
  41. {
  42. buf_size = config_rip_buffersize;
  43. nb_veritas_buf = config_rip_buffers;
  44. }
  45. else
  46. {
  47. buf_size = config_play_buffersize;
  48. nb_veritas_buf = config_play_buffers;
  49. }
  50. overflowBuffer = new BYTE[2352 * buf_size];
  51. overflow = 0;
  52. buffers = new VeritasBuffer[nb_veritas_buf];
  53. for (int i = 0;i < nb_veritas_buf;i++)
  54. {
  55. buffers[i].Create(buf_size);
  56. }
  57. }
  58. void VeritasPlay::DestroyBuffers()
  59. {
  60. if (buffers)
  61. {
  62. for (int i = 0;i < nb_veritas_buf;i++)
  63. {
  64. buffers[i].Destroy();
  65. }
  66. delete [] buffers;
  67. }
  68. buffers = 0;
  69. delete overflowBuffer;
  70. overflowBuffer = 0;
  71. }
  72. void VeritasPlay::setvolume(int a_v, int a_p)
  73. {
  74. line.outMod->SetVolume(a_v);
  75. line.outMod->SetPan(a_p);
  76. }
  77. void VeritasPlay::setoutputtime(int time_in_ms)
  78. {
  79. need_seek = time_in_ms;
  80. }
  81. void VeritasPlay::stop()
  82. {
  83. killswitch = 1;
  84. Close();
  85. if (hThread)
  86. {
  87. WaitForEvent(hThread, INFINITE);
  88. hThread=0;
  89. }
  90. line.outMod->Close();
  91. }
  92. void VeritasPlay::SeekAndFlush()
  93. {
  94. int destsector = start_sector + ((need_seek * 75) / 1000);
  95. Abort();
  96. openVeritasTrack(destsector, end_sector - destsector);
  97. decode_pos_ms = need_seek;
  98. // wait for a buffer before we flush
  99. DWORD cursec = 0, totsec = 0;
  100. while (true)
  101. {
  102. if (primo->RunningStatus(PRIMOSDK_GETSTATUS, &cursec, &totsec) != PRIMOSDK_RUNNING
  103. && primo->UnitStatus(&unit, NULL, NULL, NULL, NULL) == PRIMOSDK_UNITERROR)
  104. return;
  105. // check how far we've gone
  106. if (cursec < buffers[currentBuffer].sector)
  107. Sleep(1);
  108. else
  109. break;
  110. }
  111. overflow = 0;
  112. lastseek = destsector;
  113. line.outMod->Flush(need_seek);
  114. need_seek = -1;
  115. }
  116. void VeritasPlay::Seek()
  117. {
  118. int destsector = start_sector + ((need_seek * 75) / 1000);
  119. Abort();
  120. openVeritasTrack(destsector, end_sector - destsector);
  121. overflow = 0;
  122. decode_pos_ms = need_seek;
  123. need_seek = -1;
  124. lastseek = destsector;
  125. }
  126. void VeritasPlay::Abort()
  127. {
  128. AbortAsync();
  129. WaitForAbort(66);
  130. }
  131. void VeritasPlay::AbortAsync()
  132. {
  133. primo->RunningStatus(PRIMOSDK_ABORT, NULL, NULL);
  134. }
  135. void VeritasPlay::WaitForAbort(int time)
  136. {
  137. while (primo->RunningStatus(PRIMOSDK_GETSTATUS, NULL, NULL) == PRIMOSDK_RUNNING)
  138. Sleep(time);
  139. opened=false;
  140. }
  141. int VeritasPlay::openVeritasTrack(DWORD start, DWORD length)
  142. {
  143. int speedChoice = config_maxextractspeed;
  144. DWORD speed;
  145. if (ripping)
  146. {
  147. switch (speedChoice)
  148. {
  149. case 0: // 0.5x
  150. case 1: // 1x
  151. speed = 1; // can't do 0.5x in the SDK
  152. break;
  153. case 2: // 2x
  154. speed = 2;
  155. break;
  156. case 3: // 4x
  157. speed = 4;
  158. break;
  159. case 4: // 8x
  160. speed = 8;
  161. break;
  162. case 5: // 16x
  163. if (getRegVer() <= 0)
  164. speed = 8;
  165. else
  166. speed = 16;
  167. break;
  168. default:
  169. if (speedChoice < 0)
  170. speed = PRIMOSDK_MIN;
  171. else
  172. {
  173. if (getRegVer() <= 0)
  174. speed = 8;
  175. else
  176. speed = PRIMOSDK_MAX;
  177. }
  178. break;
  179. }
  180. }
  181. else
  182. speed = 4;//PRIMOSDK_MAX;
  183. if (primo->ExtractAudioToBuffer(&unit, start, length, speed, 0, 0, 0) != PRIMOSDK_OK)
  184. return 0;
  185. for (int i = 0;i < nb_veritas_buf;i++)
  186. {
  187. buffers[i].internal = buffers[i].buffer;
  188. if (i==0 && padStart)
  189. {
  190. buffers[i].offset = buf_size*2352 + config_offset*4;
  191. buffers[i].readSize = buf_size*2352;
  192. memset((char *)(buffers[i].internal)+buffers[i].offset, 0, buffers[i].readSize);
  193. buffers[i].sector=0;
  194. continue;
  195. }
  196. if (i==0 && ripping)
  197. buffers[i].offset = ((2352 + config_offset*4) % 2352);
  198. if (primo->NextExtractAudioBuffer(buffers[i].buffer, buf_size*2352, &buffers[i].readSize, &buffers[i].sector) != PRIMOSDK_OK)
  199. return 0;
  200. }
  201. currentBuffer = 0;
  202. opened = true;
  203. return 1;
  204. }
  205. int VeritasPlay::CopyOverflow(char *sample_buffer, int len)
  206. {
  207. if (overflow)
  208. {
  209. len = min(len, overflow);
  210. memset(sample_buffer, 0, len);
  211. memcpy(sample_buffer, overflowBuffer, len);
  212. overflow -= len;
  213. return len;
  214. }
  215. return 0;
  216. }
  217. void VeritasPlay::OutputOverflow()
  218. {
  219. while (overflow)
  220. {
  221. char sample_buffer[576*4*2] = {0};
  222. int bytes = 576 * 4;
  223. int len = min(bytes, overflow);
  224. memset(sample_buffer, 0, bytes);
  225. memcpy(sample_buffer, overflowBuffer, len);
  226. Output(sample_buffer, bytes);
  227. overflow -= len;
  228. }
  229. }
  230. #include <assert.h>
  231. void VeritasPlay::OutputBuffer(VeritasBuffer &buffer)
  232. {
  233. char sample_buffer[576*4*2] = {0};
  234. size_t bytes = 576 * 4;
  235. char *bufferPosition = sample_buffer;
  236. if (overflow)
  237. {
  238. assert(overflow < (long)bytes);
  239. memcpy(bufferPosition, overflowBuffer, overflow);
  240. bytes -= overflow;
  241. bufferPosition += overflow;
  242. overflow = 0;
  243. }
  244. BYTE *bufferInput = buffer.buffer;
  245. while (buffer.readSize)
  246. {
  247. if (buffer.readSize < bytes) // if we don't have enough left, save it to overflow
  248. {
  249. // if there was overflow last time, and the passed buffer didn't fill us up
  250. // then we'll have to save both
  251. BYTE *temp = overflowBuffer;
  252. int samplesLeft = 576 * 4 - bytes;
  253. if (samplesLeft)
  254. {
  255. memcpy(temp, sample_buffer, samplesLeft);
  256. temp += samplesLeft;
  257. overflow += samplesLeft;
  258. }
  259. // copy any leftovers of the passed buffer
  260. memcpy(temp, bufferInput, buffer.readSize);
  261. bufferInput += buffer.readSize;
  262. overflow += buffer.readSize;
  263. buffer.readSize = 0;
  264. return ;
  265. }
  266. else
  267. {
  268. memcpy(bufferPosition, bufferInput, bytes);
  269. bufferPosition = sample_buffer;
  270. bufferInput += bytes;
  271. buffer.readSize -= bytes;
  272. bytes = 576 * 4;
  273. Output(sample_buffer, 576*4);
  274. }
  275. }
  276. }
  277. size_t VeritasPlay::CopyBuffer(VeritasBuffer &buffer, char *&sample_buffer, int &bytes)
  278. {
  279. // since a buffer is only copied once, this is safe
  280. buffer.readSize -= buffer.offset;
  281. buffer.internal += buffer.offset;
  282. buffer.offset=0;
  283. size_t len = min((size_t)bytes, buffer.readSize);
  284. memcpy(sample_buffer, buffer.internal, len);
  285. buffer.internal += len;
  286. buffer.readSize -= len;
  287. sample_buffer += len;
  288. bytes -= len;
  289. return len;
  290. }
  291. void VeritasPlay::Output(char *buffer, int len)
  292. {
  293. line.VSAAddPCMData(buffer, g_nch, 16, line.outMod->GetWrittenTime() /*decode_pos_ms*/);
  294. line.SAAddPCMData(buffer, g_nch, 16, line.outMod->GetWrittenTime() /*decode_pos_ms*/);
  295. int bytes = len;
  296. if (line.dsp_isactive())
  297. bytes = line.dsp_dosamples((short *)buffer, len / g_nch / 2, 16, g_nch, 44100) * (g_nch * 2);
  298. while (line.outMod->CanWrite() < bytes && !killswitch) Sleep(10);
  299. line.outMod->Write(buffer, bytes);
  300. decode_pos_ms += ((len / g_nch / 2) * 1000) / 44100;
  301. }
  302. int VeritasPlay::read(char *dest, int len, int *killswitch) //called by winampGetExtendedRead_getData
  303. {
  304. bool noAbort=false;
  305. int bytesCopied = 0;
  306. speedLimiter.Limit(killswitch);
  307. while (!*killswitch)
  308. {
  309. DWORD cursec = 0, totsec = 0;
  310. int r = primo->RunningStatus(PRIMOSDK_GETSTATUS, &cursec, &totsec);
  311. switch(r)
  312. {
  313. case PRIMOSDK_RUNNING:
  314. break;
  315. case PRIMOSDK_OK:
  316. noAbort=true;
  317. break;
  318. default:
  319. goto readabort; // benski> Mr. Faulkner's high school BASIC class prepared me for the real world!
  320. }
  321. int a = primo->UnitStatus(&unit, NULL, NULL, NULL, NULL);
  322. switch(a)
  323. {
  324. case PRIMOSDK_OK:
  325. break;
  326. default: // todo is everything else really an error? maybe message box for testing purposes
  327. goto readabort;
  328. }
  329. // check how far we've gone
  330. if (cursec >= buffers[currentBuffer].sector)
  331. {
  332. char *olddest=dest;
  333. int bytes = CopyBuffer(buffers[currentBuffer], dest, len);
  334. if (submitHandle && bytes)
  335. {
  336. int res = workorder->WriteSigData(submitHandle, olddest, bytes);
  337. switch(res)
  338. {
  339. case S_OK:
  340. break;
  341. case SG_SignatureAcquired:
  342. default:
  343. workorder->CloseSig(submitHandle);
  344. submitHandle=0;
  345. break;
  346. }
  347. }
  348. speedLimiter.MoreBytesRead(bytes);
  349. bytesCopied += bytes;
  350. if (!len || end == 1)
  351. {
  352. return bytesCopied;
  353. }
  354. if ((buffers[currentBuffer].sector + lastseek) == end_sector) // are we done?
  355. {
  356. bytesCopied -= ((2352 - config_offset*4) % 2352);
  357. end = 1;
  358. return bytesCopied;
  359. }
  360. buffers[currentBuffer].internal = buffers[currentBuffer].buffer;
  361. buffers[currentBuffer].offset = 0;
  362. if (!noAbort)
  363. if (primo) primo->NextExtractAudioBuffer(buffers[currentBuffer].buffer, buf_size*2352, &buffers[currentBuffer].readSize, &buffers[currentBuffer].sector);
  364. currentBuffer = (currentBuffer + 1) % nb_veritas_buf;
  365. }
  366. else if (bytesCopied != 0)
  367. return bytesCopied;
  368. else
  369. Sleep(13*buf_size);
  370. }
  371. // TODO: we can only get here if killswitch got set or if there was an error
  372. readabort:
  373. if (submitHandle)
  374. {
  375. workorder->AbortSig(submitHandle);
  376. submitHandle=0;
  377. }
  378. AbortAsync();
  379. return -1;
  380. }
  381. int VeritasPlay::threadProc2()
  382. {
  383. bool noAbort=false;
  384. while (!killswitch)
  385. {
  386. if (need_seek != -1)
  387. SeekAndFlush();
  388. DWORD cursec = 0, totsec = 0;
  389. int r = primo->RunningStatus(PRIMOSDK_GETSTATUS, &cursec, &totsec);
  390. switch(r)
  391. {
  392. case PRIMOSDK_RUNNING:
  393. break;
  394. case PRIMOSDK_OK:
  395. noAbort=true;
  396. break;
  397. default:
  398. Abort();
  399. if (!killswitch) Sleep(200);
  400. if (!killswitch) PostMessage(line.hMainWindow, WM_WA_MPEG_EOF, 0, 0);
  401. return 0;
  402. }
  403. int a = primo->UnitStatus(&unit, NULL, NULL, NULL, NULL);
  404. switch(a)
  405. {
  406. case PRIMOSDK_OK:
  407. break;
  408. default: // todo is everything else really an error? maybe message box for testing purposes
  409. Abort();
  410. if (!killswitch) Sleep(200);
  411. if (!killswitch) PostMessage(line.hMainWindow, WM_WA_MPEG_EOF, 0, 0);
  412. return 0;
  413. }
  414. // check how far we've gone
  415. if (cursec >= buffers[currentBuffer].sector)
  416. {
  417. OutputBuffer(buffers[currentBuffer]);
  418. if ((buffers[currentBuffer].sector+lastseek)==end_sector) // are we done?
  419. break;
  420. buffers[currentBuffer].internal = buffers[currentBuffer].buffer;
  421. if (!noAbort)
  422. primo->NextExtractAudioBuffer(buffers[currentBuffer].buffer, buf_size*2352, &buffers[currentBuffer].readSize, &buffers[currentBuffer].sector);
  423. currentBuffer = (currentBuffer + 1) % nb_veritas_buf;
  424. }
  425. else
  426. Sleep(13*buf_size);
  427. }
  428. if (killswitch)
  429. {
  430. Abort();
  431. return 0;
  432. }
  433. if (!noAbort)
  434. AbortAsync();
  435. OutputOverflow();
  436. //wait for output to be finished
  437. line.outMod->Write(NULL, 0);
  438. if (!noAbort)
  439. WaitForAbort(10);
  440. while (!killswitch && line.outMod->IsPlaying()) Sleep(10);
  441. if (!killswitch)
  442. PostMessage(line.hMainWindow, WM_WA_MPEG_EOF, 0, 0);
  443. return 0;
  444. }
  445. #define VERITASPLAY_OPEN_FAIL 1
  446. #define VERITASPLAY_OPEN_NOPRIMO 2
  447. int VeritasPlay::open(char drive, int track) //called by winampGetExtendedRead
  448. {
  449. if ((ripping && !config_rip_veritas))
  450. return VERITASPLAY_OPEN_FAIL;
  451. need_seek = -1;
  452. driveLetter = drive;
  453. unit = drive;
  454. hThread = NULL;
  455. if (!primo)
  456. {
  457. waServiceFactory *sf = line.service->service_getServiceByGuid(obj_primo::getServiceGuid());
  458. if (sf) primo = reinterpret_cast<obj_primo *>(sf->getInterface());
  459. }
  460. if (!primo)
  461. return VERITASPLAY_OPEN_NOPRIMO;
  462. end = 0;
  463. speedLimiter.Reset();
  464. if (getRegVer() <= 0)
  465. speedLimiter.SetLimit(5);
  466. else
  467. speedLimiter.NoLimit();
  468. if (primo->DiscInfoEx(&unit,0, NULL, NULL, NULL, NULL, NULL, NULL) == PRIMOSDK_OK)
  469. {
  470. DWORD sesnum, tracktype, pregap;
  471. if (primo->TrackInfo(track, &sesnum, &tracktype, &pregap, &start_sector, &sec_length) == PRIMOSDK_OK)
  472. {
  473. if (ripping)
  474. {
  475. if (config_offset != 0)
  476. sec_length++; // TODO: some sort of logic for the last track
  477. if (config_offset<0)
  478. {
  479. if (track != 1 || config_read_leadin)
  480. start_sector--;
  481. else
  482. {
  483. sec_length--;
  484. padStart=true;
  485. }
  486. }
  487. }
  488. end_sector = start_sector + sec_length;
  489. #if 0 // TODO: add a config option to skip pregap (maybe separate config for burning and playback)
  490. start_sector+=pregap;
  491. sec_length-=pregap;
  492. #endif
  493. CreateBuffers();
  494. if (openVeritasTrack(start_sector, sec_length))
  495. {
  496. g_nch = 2; // TODO: maybe we should handle red book 4 channel audio?
  497. g_playlength = (sec_length / 75) * 1000;
  498. decode_pos_ms = 0;
  499. lastseek = start_sector;
  500. need_seek = -1;
  501. return 0;
  502. }
  503. }
  504. }
  505. Close();
  506. return VERITASPLAY_OPEN_FAIL;
  507. }
  508. int VeritasPlay::play(char drive, int track) //called by winamp2
  509. {
  510. if (!config_use_dae2 || !config_use_veritas)
  511. return 1;
  512. hThread=NULL;
  513. {
  514. g_playtrack = track;
  515. }
  516. switch(open(drive, track))
  517. {
  518. case VERITASPLAY_OPEN_FAIL:
  519. Sleep(200);
  520. // fall through
  521. case VERITASPLAY_OPEN_NOPRIMO:
  522. Close();
  523. return 1;
  524. }
  525. DWORD thread_id;
  526. hThread = CreateThread(NULL, NULL, &threadProc, (LPVOID)this, CREATE_SUSPENDED, &thread_id);
  527. SetThreadPriority(hThread, AGAVE_API_CONFIG->GetInt(playbackConfigGroupGUID, L"priority", THREAD_PRIORITY_HIGHEST));
  528. int maxlat = line.outMod->Open(44100, g_nch, 16, -1, -1);
  529. if (maxlat < 0)
  530. {
  531. Sleep(200);
  532. Close();
  533. CloseHandle(hThread);
  534. return 1;
  535. }
  536. killswitch = 0;
  537. line.SetInfo(1411, 44, g_nch, 1);
  538. line.SAVSAInit(maxlat, 44100);
  539. line.VSASetInfo(g_nch, 44100);
  540. line.is_seekable = 1;
  541. ResumeThread(hThread);
  542. return 0;
  543. }
  544. void VeritasPlay::Close()
  545. {
  546. driveLetter=0;
  547. }