CDText.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. #include "main.h"
  2. #include "cddb.h"
  3. #include "api__in_cdda.h"
  4. #ifndef IGNORE_API_GRACENOTE
  5. #include "../primo/obj_primo.h"
  6. #endif
  7. //#include "CDPlay.h"
  8. #include "DAEPlay.h"
  9. #include "../nu/ns_wc.h"
  10. #include "../nde/ndestring.h"
  11. #ifndef IGNORE_API_GRACENOTE
  12. const char *ReadLine(const char *input, char *output, size_t size, int codepage)
  13. {
  14. size--; // leave room for null terminator
  15. while (input && *input && *input != '\r' && size)
  16. {
  17. char *next = CharNextExA(codepage, input, 0);
  18. while (input != next)
  19. {
  20. if (size)
  21. {
  22. *output = *input;
  23. output++;
  24. *output = 0; // safe because we left room for the null terminator
  25. size--;
  26. }
  27. input++;
  28. }
  29. }
  30. if (*input == '\r')
  31. input++;
  32. if (*input == '\n')
  33. input++;
  34. return input;
  35. }
  36. static bool CDText_Process(DINFO *ps, const char *title, const char *performers, const char *composers, int codepage)
  37. {
  38. char thisTitle[1024] = {0};
  39. const char *titles = title;
  40. // first, get disc title
  41. thisTitle[0] = 0;
  42. titles = ReadLine(titles, thisTitle, 1024, codepage);
  43. if (thisTitle[0])
  44. {
  45. ndestring_release(ps->title);
  46. int count = MultiByteToWideChar(codepage, 0, thisTitle, -1, 0, 0);
  47. ps->title = ndestring_malloc(count*sizeof(wchar_t));
  48. MultiByteToWideChar(codepage, 0, thisTitle, -1, ps->title, count);
  49. }
  50. // now get track titles
  51. int trackNum = 0;
  52. while (titles && *titles)
  53. {
  54. if (trackNum == ps->ntracks)
  55. break;
  56. TRACKINFO &trackInfo = ps->tracks[trackNum];
  57. thisTitle[0] = 0;
  58. titles = ReadLine(titles, thisTitle, 1024, codepage);
  59. if (thisTitle[0])
  60. {
  61. ndestring_release(trackInfo.title);
  62. int count = MultiByteToWideChar(codepage, 0, thisTitle, -1, 0, 0);
  63. trackInfo.title = ndestring_malloc(count*sizeof(wchar_t));
  64. MultiByteToWideChar(codepage, 0, thisTitle, -1, trackInfo.title, count);
  65. }
  66. trackNum++;
  67. }
  68. titles = performers;
  69. // now get disc artist
  70. thisTitle[0] = 0;
  71. titles = ReadLine(titles, thisTitle, 1024, codepage);
  72. if (thisTitle[0])
  73. {
  74. ndestring_release(ps->artist);
  75. int count = MultiByteToWideChar(codepage, 0, thisTitle, -1, 0, 0);
  76. ps->artist = ndestring_malloc(count*sizeof(wchar_t));
  77. MultiByteToWideChar(codepage, 0, thisTitle, -1, ps->artist, count);
  78. }
  79. // now get track artists
  80. trackNum = 0;
  81. while (titles && *titles)
  82. {
  83. if (trackNum == ps->ntracks)
  84. break;
  85. TRACKINFO &trackInfo = ps->tracks[trackNum];
  86. thisTitle[0] = 0;
  87. titles = ReadLine(titles, thisTitle, 1024, codepage);
  88. if (thisTitle[0])
  89. {
  90. ndestring_release(trackInfo.artist);
  91. int count = MultiByteToWideChar(codepage, 0, thisTitle, -1, 0, 0);
  92. trackInfo.artist = ndestring_malloc(count*sizeof(wchar_t));
  93. MultiByteToWideChar(codepage, 0, thisTitle, -1, trackInfo.artist, count);
  94. }
  95. trackNum++;
  96. }
  97. titles = composers;
  98. // now get disc composer
  99. thisTitle[0] = 0;
  100. titles = ReadLine(titles, thisTitle, 1024, codepage);
  101. if (thisTitle[0])
  102. {
  103. ndestring_release(ps->composer);
  104. int count = MultiByteToWideChar(codepage, 0, thisTitle, -1, 0, 0);
  105. ps->composer = ndestring_malloc(count*sizeof(wchar_t));
  106. MultiByteToWideChar(codepage, 0, thisTitle, -1, ps->composer, count);
  107. }
  108. // now get track composers
  109. trackNum = 0;
  110. while (titles && *titles)
  111. {
  112. if (trackNum == ps->ntracks)
  113. break;
  114. TRACKINFO &trackInfo = ps->tracks[trackNum];
  115. thisTitle[0] = 0;
  116. titles = ReadLine(titles, thisTitle, 1024, codepage);
  117. if (thisTitle[0])
  118. {
  119. ndestring_release(trackInfo.composer);
  120. int count = MultiByteToWideChar(codepage, 0, thisTitle, -1, 0, 0);
  121. trackInfo.composer = ndestring_malloc(count*sizeof(wchar_t));
  122. MultiByteToWideChar(codepage, 0, thisTitle, -1, trackInfo.composer, count);
  123. }
  124. trackNum++;
  125. }
  126. ps->populated = true;
  127. return true;
  128. }
  129. bool DoCDText(DINFO *ps, char device)
  130. {
  131. if (!device)
  132. return false;
  133. if (config_use_veritas)
  134. {
  135. obj_primo *primo=0;
  136. waServiceFactory *sf = line.service->service_getServiceByGuid(obj_primo::getServiceGuid());
  137. if (sf) primo = reinterpret_cast<obj_primo *>(sf->getInterface());
  138. if (!primo)
  139. return false;
  140. DWORD unit = device;
  141. DWORD tracks;
  142. if (primo->DiscInfoEx(&unit, 0, NULL, NULL, NULL, &tracks, NULL, NULL) != PRIMOSDK_OK) // CDTextInfoEJ suggest that this needs to be called first
  143. {
  144. sf->releaseInterface(primo);
  145. return false;
  146. }
  147. if (ps->ntracks == 0) // go ahead and set if it's not set yet
  148. ps->ntracks = tracks;
  149. char titleE[8192] = "", performerE[8192] = "", composerE[8192] = "", titleJ[2000] = "", performerJ[2000] = "", composerJ[2000] = "";
  150. if (primo->CDTextInfoEJ(&unit, (PBYTE)titleE, (PBYTE)performerE, (PBYTE)composerE, (PBYTE)titleJ, (PBYTE)performerJ, (PBYTE)composerJ) == PRIMOSDK_OK)
  151. {
  152. sf->releaseInterface(primo);
  153. // read titles
  154. if (titleE[0])
  155. return CDText_Process(ps, titleE, performerE, composerE, 28591);
  156. else
  157. return CDText_Process(ps, titleJ, performerJ, composerJ, 932);
  158. }
  159. }
  160. return false;
  161. }
  162. #else
  163. bool DoCDText(DINFO *ps, wchar_t device)
  164. {
  165. if (!device)
  166. return false;
  167. DAEPlay *dae = (g_cdplay && g_cdplay == daePlayer && g_cdplay->g_drive == device ? daePlayer : new DAEPlay);
  168. if (dae)
  169. {
  170. if (dae != daePlayer)
  171. {
  172. if (dae->open(device, 1))
  173. {
  174. delete(dae);
  175. return false;
  176. }
  177. }
  178. DAEPlay::CDTextArray* cd_text = dae->getCDText();
  179. if ((int)cd_text > 0)
  180. {
  181. if (ps)
  182. {
  183. ps->ntracks = cd_text->size() - 1;
  184. ndestring_release(ps->title);
  185. ps->title = ndestring_wcsdup(cd_text[DAEPlay::CD_TEXT_TITLE][0]);
  186. ndestring_release(ps->artist);
  187. ps->artist = ndestring_wcsdup(cd_text[DAEPlay::CD_TEXT_PERFORMER][0]);
  188. // TODO match this to the supported list of genres...
  189. /*ndestring_release(ps->genre);
  190. ps->genre = ndestring_wcsdup(cd_text[DAEPlay::CD_TEXT_GENRE][0]);*/
  191. ndestring_release(ps->composer);
  192. ps->composer = ndestring_wcsdup(cd_text[DAEPlay::CD_TEXT_COMPOSER][0]);
  193. for (size_t i = 1; i < cd_text->size(); i++)
  194. {
  195. if (i == ps->ntracks + 1)
  196. break;
  197. TRACKINFO &trackInfo = ps->tracks[i-1];
  198. // TODO improve error handling
  199. ndestring_release(trackInfo.artist);
  200. trackInfo.artist = ndestring_wcsdup(cd_text[DAEPlay::CD_TEXT_PERFORMER][i]);
  201. //free(cd_text[DAEPlay::CD_TEXT_PERFORMER][i]);
  202. ndestring_release(trackInfo.title);
  203. trackInfo.title = ndestring_wcsdup(cd_text[DAEPlay::CD_TEXT_TITLE][i]);
  204. //free(cd_text[DAEPlay::CD_TEXT_TITLE][i]);
  205. ndestring_release(trackInfo.genre);
  206. trackInfo.genre = ndestring_wcsdup(cd_text[DAEPlay::CD_TEXT_GENRE][i]);
  207. //free(cd_text[DAEPlay::CD_TEXT_GENRE][i]);
  208. ndestring_release(trackInfo.composer);
  209. trackInfo.composer = ndestring_wcsdup(cd_text[DAEPlay::CD_TEXT_COMPOSER][i]);
  210. //free(cd_text[DAEPlay::CD_TEXT_COMPOSER][i]);
  211. }
  212. ps->populated = true;
  213. }
  214. if (dae != daePlayer) delete(dae);
  215. return true;
  216. }
  217. if (dae != daePlayer) delete(dae);
  218. }
  219. return false;
  220. }
  221. #endif