ml_lib.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. /*
  2. ** Copyright © 2003-2014 Winamp SA
  3. **
  4. ** This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held
  5. ** liable for any damages arising from the use of this software.
  6. **
  7. ** Permission is granted to anyone to use this software for any purpose, including commercial applications, and to
  8. ** alter it and redistribute it freely, subject to the following restrictions:
  9. **
  10. ** 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
  11. ** If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
  12. **
  13. ** 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  14. **
  15. ** 3. This notice may not be removed or altered from any source distribution.
  16. **
  17. */
  18. #include <windows.h>
  19. #include "ml.h"
  20. void freeRecord(itemRecord *p)
  21. {
  22. if (p)
  23. {
  24. free(p->title);
  25. free( p->artist );
  26. free( p->ext );
  27. free(p->comment);
  28. free(p->album);
  29. free(p->genre);
  30. free(p->filename);
  31. if (p->extended_info)
  32. {
  33. for (int x = 0; p->extended_info[x]; x ++)
  34. free(p->extended_info[x]);
  35. free(p->extended_info);
  36. p->extended_info = 0;
  37. }
  38. }
  39. }
  40. void freeRecordList(itemRecordList *obj)
  41. {
  42. if (obj)
  43. {
  44. emptyRecordList(obj);
  45. free(obj->Items);
  46. obj->Items=0;
  47. obj->Alloc=obj->Size=0;
  48. }
  49. }
  50. void emptyRecordList(itemRecordList *obj)
  51. {
  52. if (obj)
  53. {
  54. itemRecord *p=obj->Items;
  55. while (obj->Size-->0)
  56. {
  57. freeRecord(p);
  58. p++;
  59. }
  60. obj->Size=0;
  61. }
  62. }
  63. void allocRecordList(itemRecordList *obj, int newsize, int granularity)
  64. {
  65. if (newsize < obj->Alloc || newsize < obj->Size) return;
  66. int old_Alloc = obj->Alloc;
  67. obj->Alloc=newsize+granularity;
  68. itemRecord *data = (itemRecord*)realloc(obj->Items, sizeof(itemRecord) * obj->Alloc);
  69. if (!data)
  70. {
  71. data = (itemRecord*)malloc(sizeof(itemRecord) * obj->Alloc);
  72. if (data)
  73. {
  74. memcpy(data, obj->Items, sizeof(itemRecord) * old_Alloc);
  75. free(obj->Items);
  76. obj->Items = data;
  77. }
  78. else
  79. obj->Alloc = old_Alloc;
  80. }
  81. else
  82. obj->Items = data;
  83. if (!old_Alloc) memset(data, 0, sizeof(itemRecordW) * obj->Alloc);
  84. if (!obj->Items) obj->Alloc = 0;
  85. }
  86. void compactRecordList(itemRecordListW *obj)
  87. {
  88. if (obj->Size && obj->Size < obj->Alloc - 1024)
  89. {
  90. size_t old_Alloc = obj->Size;
  91. obj->Alloc = obj->Size;
  92. itemRecordW *data = (itemRecordW *)realloc(obj->Items, sizeof(itemRecordW) * obj->Alloc);
  93. if (!data)
  94. {
  95. data = (itemRecordW *)malloc(sizeof(itemRecordW) * obj->Alloc);
  96. if (data)
  97. {
  98. memcpy(data, obj->Items, sizeof(itemRecordW) * old_Alloc);
  99. free(obj->Items);
  100. obj->Items = data;
  101. }
  102. else
  103. obj->Alloc = (int)old_Alloc;
  104. }
  105. else
  106. obj->Items = data;
  107. }
  108. }
  109. void copyRecord(itemRecord *out, const itemRecord *in)
  110. {
  111. #define COPYSTR(FOO) out->FOO = in->FOO ? _strdup(in->FOO) : 0;
  112. COPYSTR(filename)
  113. COPYSTR( title )
  114. COPYSTR( ext )
  115. COPYSTR(album)
  116. COPYSTR(artist)
  117. COPYSTR(comment)
  118. COPYSTR(genre)
  119. out->year=in->year;
  120. out->track=in->track;
  121. out->length=in->length;
  122. #undef COPYSTR
  123. out->extended_info=0;
  124. if (in->extended_info)
  125. {
  126. for (int y = 0; in->extended_info[y]; y ++)
  127. {
  128. char *p=in->extended_info[y];
  129. if (*p) setRecordExtendedItem(out,p,p+strlen(p)+1);
  130. }
  131. }
  132. }
  133. void copyRecordList(itemRecordList *out, const itemRecordList *in)
  134. {
  135. allocRecordList(out,out->Size+in->Size,0);
  136. if (!out->Items) return;
  137. for (int x = 0; x < in->Size; x ++)
  138. {
  139. copyRecord(&out->Items[out->Size++],&in->Items[x]);
  140. }
  141. }
  142. char *getRecordExtendedItem(const itemRecord *item, const char *name)
  143. {
  144. if (item->extended_info)
  145. {
  146. for (int x = 0; item->extended_info[x]; x ++)
  147. {
  148. if (!_stricmp(item->extended_info[x],name))
  149. return item->extended_info[x]+strlen(name)+1;
  150. }
  151. }
  152. return NULL;
  153. }
  154. void setRecordExtendedItem(itemRecord *item, const char *name, char *value)
  155. {
  156. int x=0;
  157. if (item->extended_info)
  158. {
  159. for (x = 0; item->extended_info[x]; x ++)
  160. {
  161. if (!_stricmp(item->extended_info[x],name))
  162. {
  163. size_t name_len = strlen(name), value_len = strlen(value);
  164. if (value_len>strlen(item->extended_info[x]+name_len+1))
  165. {
  166. free(item->extended_info[x]);
  167. item->extended_info[x]=(char*)malloc(name_len+value_len+2);
  168. }
  169. strncpy(item->extended_info[x], name, name_len);
  170. strncpy(item->extended_info[x]+strlen(name)+1, value, value_len);
  171. return;
  172. }
  173. }
  174. }
  175. // x=number of valid items.
  176. char **data = (char**)realloc(item->extended_info,sizeof(char*) * (x+2));
  177. if (data)
  178. {
  179. // if we could allocate then add, otherwise we'll have to skip
  180. item->extended_info = data;
  181. size_t name_len = strlen(name), value_len = strlen(value);
  182. item->extended_info[x]=(char*)malloc(name_len+value_len+2);
  183. strncpy(item->extended_info[x], name, name_len);
  184. strncpy(item->extended_info[x]+name_len+1, value, value_len);
  185. item->extended_info[x+1]=0;
  186. }
  187. else
  188. {
  189. data=(char**)_aligned_malloc(sizeof(char*) * (x+2), 16);
  190. if (data)
  191. {
  192. memcpy(data, item->extended_info, sizeof(char*) * x);
  193. free(item->extended_info);
  194. // if we could allocate then add, otherwise we'll have to skip
  195. item->extended_info = data;
  196. size_t name_len = strlen(name), value_len = strlen(value);
  197. item->extended_info[x]=(char*)malloc(name_len+value_len+2);
  198. strncpy(item->extended_info[x], name, name_len);
  199. strncpy(item->extended_info[x]+name_len+1, value, value_len);
  200. item->extended_info[x+1]=0;
  201. }
  202. }
  203. }
  204. /*
  205. ----------------------------------
  206. wide version starts here
  207. ----------------------------------
  208. */
  209. void freeRecord(itemRecordW *p)
  210. {
  211. if (p)
  212. {
  213. free(p->title);
  214. free(p->artist);
  215. free(p->comment);
  216. free(p->album);
  217. free(p->genre);
  218. free(p->filename);
  219. free(p->albumartist);
  220. free(p->replaygain_album_gain);
  221. free(p->replaygain_track_gain);
  222. free(p->publisher);
  223. free(p->composer);
  224. if (p->extended_info)
  225. {
  226. for (int x = 0; p->extended_info[x].key; x ++)
  227. {
  228. free(p->extended_info[x].key);
  229. free(p->extended_info[x].value);
  230. }
  231. free(p->extended_info);
  232. p->extended_info = 0;
  233. }
  234. }
  235. }
  236. void freeRecordList(itemRecordListW *obj)
  237. {
  238. if (obj)
  239. {
  240. emptyRecordList(obj);
  241. free(obj->Items);
  242. obj->Items=0;
  243. obj->Alloc=obj->Size=0;
  244. }
  245. }
  246. void emptyRecordList(itemRecordListW *obj)
  247. {
  248. if (obj)
  249. {
  250. itemRecordW *p=obj->Items;
  251. while (obj->Size-->0)
  252. {
  253. freeRecord(p);
  254. p++;
  255. }
  256. obj->Size=0;
  257. }
  258. }
  259. void allocRecordList(itemRecordListW *obj, int newsize, int granularity)
  260. {
  261. if (newsize < obj->Alloc || newsize < obj->Size) return;
  262. int old_Alloc = obj->Alloc;
  263. obj->Alloc=newsize+granularity;
  264. itemRecordW *data = (itemRecordW*)realloc(obj->Items,sizeof(itemRecordW)*obj->Alloc);
  265. if (!data)
  266. {
  267. data = (itemRecordW*)malloc(sizeof(itemRecordW) * obj->Alloc);
  268. if (data)
  269. {
  270. memcpy(data, obj->Items, sizeof(itemRecordW) * obj->Alloc);
  271. free(obj->Items);
  272. obj->Items = data;
  273. }
  274. else
  275. obj->Alloc = old_Alloc;
  276. }
  277. else
  278. obj->Items = data;
  279. if (!old_Alloc) memset(data, 0, sizeof(itemRecordW) * obj->Alloc);
  280. if (!obj->Items) obj->Alloc = 0;
  281. }
  282. void copyRecord(itemRecordW *out, const itemRecordW *in)
  283. {
  284. #define COPYSTR(FOO) out->FOO = in->FOO ? _wcsdup(in->FOO) : 0;
  285. #define COPY(FOO) out->FOO = in->FOO;
  286. COPYSTR(filename);
  287. COPYSTR(title);
  288. COPYSTR(album);
  289. COPYSTR(artist);
  290. COPYSTR(comment);
  291. COPYSTR(genre);
  292. COPYSTR(albumartist);
  293. COPYSTR(replaygain_album_gain);
  294. COPYSTR(replaygain_track_gain);
  295. COPYSTR(publisher);
  296. COPYSTR(composer);
  297. COPY(year);
  298. COPY(track);
  299. COPY(tracks);
  300. COPY(length);
  301. COPY(rating);
  302. COPY(playcount);
  303. COPY(lastplay);
  304. COPY(lastupd);
  305. COPY(filetime);
  306. COPY(filesize);
  307. COPY(bitrate);
  308. COPY(type);
  309. COPY(disc);
  310. COPY(discs);
  311. COPY(bpm);
  312. COPYSTR(category);
  313. #undef COPYSTR
  314. out->extended_info=0;
  315. if (in->extended_info)
  316. {
  317. for (int y = 0; in->extended_info[y].key; y ++)
  318. {
  319. setRecordExtendedItem(out,in->extended_info[y].key,in->extended_info[y].value);
  320. }
  321. }
  322. }
  323. void copyRecordList(itemRecordListW *out, const itemRecordListW *in)
  324. {
  325. allocRecordList(out,out->Size+in->Size,0);
  326. if (!out->Items) return;
  327. for (int x = 0; x < in->Size; x ++)
  328. {
  329. copyRecord(&out->Items[out->Size++],&in->Items[x]);
  330. }
  331. }
  332. wchar_t *getRecordExtendedItem(const itemRecordW *item, const wchar_t *name)
  333. {
  334. if (item->extended_info)
  335. {
  336. for (size_t x = 0; item->extended_info[x].key; x ++)
  337. {
  338. if (!_wcsicmp(item->extended_info[x].key,name))
  339. return item->extended_info[x].value;
  340. }
  341. }
  342. return NULL;
  343. }
  344. wchar_t *getRecordExtendedItem_fast(const itemRecordW *item, const wchar_t *name)
  345. {
  346. if (item->extended_info)
  347. {
  348. for (size_t x = 0; item->extended_info[x].key; x ++)
  349. {
  350. if (item->extended_info[x].key == name)
  351. return item->extended_info[x].value;
  352. }
  353. }
  354. return NULL;
  355. }
  356. void setRecordExtendedItem(itemRecordW *item, const wchar_t *name, const wchar_t *value)
  357. {
  358. size_t x=0;
  359. if (item->extended_info) for (x = 0; item->extended_info[x].key; x ++)
  360. {
  361. if (!_wcsicmp(item->extended_info[x].key,name))
  362. {
  363. free(item->extended_info[x].value);
  364. item->extended_info[x].value = _wcsdup(value);
  365. return;
  366. }
  367. }
  368. // x=number of valid items.
  369. extendedInfoW *data = (extendedInfoW *)realloc(item->extended_info, sizeof(extendedInfoW) * (x+2));
  370. if (data)
  371. {
  372. item->extended_info = data;
  373. item->extended_info[x].key = _wcsdup(name);
  374. item->extended_info[x].value = _wcsdup(value);
  375. item->extended_info[x+1].key=0;
  376. item->extended_info[x+1].value=0;
  377. }
  378. else
  379. {
  380. data=(extendedInfoW *)_aligned_malloc(sizeof(extendedInfoW) * (x+2), 16);
  381. if (data)
  382. {
  383. item->extended_info=data;
  384. item->extended_info[x].key = _wcsdup(name);
  385. item->extended_info[x].value = _wcsdup(value);
  386. item->extended_info[x+1].key=0;
  387. item->extended_info[x+1].value=0;
  388. }
  389. }
  390. }
  391. // this version assumes that the 'name' won't already be in the itemRecord
  392. void setRecordExtendedItem_fast(itemRecordW *item, const wchar_t *name, const wchar_t *value)
  393. {
  394. int x=0;
  395. if (item->extended_info)
  396. {
  397. for (x = 0; item->extended_info[x].key; x ++)
  398. {
  399. }
  400. }
  401. // x=number of valid items.
  402. extendedInfoW *data=(extendedInfoW *)_aligned_realloc(item->extended_info,sizeof(extendedInfoW) * (x+2), 16);
  403. if (data)
  404. {
  405. item->extended_info=data;
  406. item->extended_info[x].key = _wcsdup(name);
  407. item->extended_info[x].value = _wcsdup(value);
  408. item->extended_info[x+1].key=0;
  409. item->extended_info[x+1].value=0;
  410. }
  411. else
  412. {
  413. data=(extendedInfoW *)_aligned_malloc(sizeof(extendedInfoW) * (x+2), 16);
  414. if (data)
  415. {
  416. item->extended_info=data;
  417. item->extended_info[x].key = _wcsdup(name);
  418. item->extended_info[x].value = _wcsdup(value);
  419. item->extended_info[x+1].key=0;
  420. item->extended_info[x+1].value=0;
  421. }
  422. }
  423. }
  424. // TODO: redo this without AutoChar
  425. #include "../nu/AutoChar.h"
  426. #define COPY_EXTENDED_STR(field) if (input-> ## field && input-> ## field ## [0]) setRecordExtendedItem(output, #field, AutoChar(input-> ## field));
  427. #define COPY_EXTENDED_INT(field) if (input->##field > 0) { char temp[64] = {0}; _itoa(input->##field, temp, 10); setRecordExtendedItem(output, #field, temp); }
  428. #define COPY_EXTENDED_INT64(field) if (input->##field > 0) { char temp[64] = {0}; _i64toa(input->##field, temp, 10); setRecordExtendedItem(output, #field, temp); }
  429. #define COPY_EXTENDED_INT0(field) if (input->##field >= 0) { char temp[64] = {0}; _itoa(input->##field, temp, 10); setRecordExtendedItem(output, #field, temp); }
  430. void convertRecord(itemRecord *output, const itemRecordW *input)
  431. {
  432. output->filename=AutoCharDup(input->filename);
  433. output->title = AutoCharDup( input->title );
  434. output->ext = AutoCharDup( input->ext );
  435. output->album=AutoCharDup(input->album);
  436. output->artist=AutoCharDup(input->artist);
  437. output->comment=AutoCharDup(input->comment);
  438. output->genre=AutoCharDup(input->genre);
  439. output->year=input->year;
  440. output->track=input->track;
  441. output->length=input->length;
  442. output->extended_info=0;
  443. COPY_EXTENDED_STR(albumartist);
  444. COPY_EXTENDED_STR(replaygain_album_gain);
  445. COPY_EXTENDED_STR(replaygain_track_gain);
  446. COPY_EXTENDED_STR(publisher);
  447. COPY_EXTENDED_STR(composer);
  448. COPY_EXTENDED_INT(tracks);
  449. COPY_EXTENDED_INT(rating);
  450. COPY_EXTENDED_INT(playcount);
  451. COPY_EXTENDED_INT64(lastplay);
  452. COPY_EXTENDED_INT64(lastupd);
  453. COPY_EXTENDED_INT64(filetime);
  454. COPY_EXTENDED_INT(filesize);
  455. COPY_EXTENDED_INT(bitrate);
  456. COPY_EXTENDED_INT0(type);
  457. COPY_EXTENDED_INT(disc);
  458. COPY_EXTENDED_INT(discs);
  459. COPY_EXTENDED_INT(bpm);
  460. COPY_EXTENDED_STR(category);
  461. if (input->extended_info)
  462. {
  463. for (int y = 0; input->extended_info[y].key; y ++)
  464. {
  465. setRecordExtendedItem(output, AutoChar(input->extended_info[y].key), AutoChar(input->extended_info[y].value));
  466. }
  467. }
  468. }
  469. #undef COPY_EXTENDED_STR
  470. #undef COPY_EXTENDED_INT
  471. #undef COPY_EXTENDED_INT0
  472. #include "../nu/AutoWide.h"
  473. #define COPY_EXTENDED_STR(field) output->##field = AutoWideDup(getRecordExtendedItem(input, #field));
  474. #define COPY_EXTENDED_INT(field) { char *x = getRecordExtendedItem(input, #field); output->##field=x?atoi(x):-1; }
  475. void convertRecord(itemRecordW *output, const itemRecord *input)
  476. {
  477. output->filename=AutoWideDup(input->filename);
  478. output->title=AutoWideDup(input->title);
  479. output->ext = AutoWideDup( input->ext );
  480. output->album=AutoWideDup(input->album);
  481. output->artist=AutoWideDup(input->artist);
  482. output->comment=AutoWideDup(input->comment);
  483. output->genre=AutoWideDup(input->genre);
  484. output->year=input->year;
  485. output->track=input->track;
  486. output->length=input->length;
  487. output->extended_info=0;
  488. COPY_EXTENDED_STR(albumartist);
  489. COPY_EXTENDED_STR(replaygain_album_gain);
  490. COPY_EXTENDED_STR(replaygain_track_gain);
  491. COPY_EXTENDED_STR(publisher);
  492. COPY_EXTENDED_STR(composer);
  493. COPY_EXTENDED_INT(tracks);
  494. COPY_EXTENDED_INT(rating);
  495. COPY_EXTENDED_INT(playcount);
  496. COPY_EXTENDED_INT(lastplay);
  497. COPY_EXTENDED_INT(lastupd);
  498. COPY_EXTENDED_INT(filetime);
  499. COPY_EXTENDED_INT(filesize);
  500. COPY_EXTENDED_INT(type);
  501. COPY_EXTENDED_INT(disc);
  502. COPY_EXTENDED_INT(discs);
  503. COPY_EXTENDED_INT(bpm);
  504. COPY_EXTENDED_INT(bitrate);
  505. COPY_EXTENDED_STR(composer);
  506. COPY_EXTENDED_STR(category);
  507. // TODO: copy input's extended fields
  508. }
  509. #undef COPY_EXTENDED_STR
  510. #undef COPY_EXTENDED_INT
  511. void convertRecordList(itemRecordList *output, const itemRecordListW *input)
  512. {
  513. output->Alloc = output->Size = input->Size;
  514. output->Items = (itemRecord*)calloc(sizeof(itemRecord),input->Size);
  515. if (output->Items)
  516. {
  517. for(int i=0; i < input->Size; i++)
  518. {
  519. convertRecord(&output->Items[i],&input->Items[i]);
  520. }
  521. }
  522. else
  523. output->Alloc = output->Size = 0;
  524. }
  525. void convertRecordList(itemRecordListW *output, const itemRecordList *input)
  526. {
  527. output->Alloc = output->Size = input->Size;
  528. output->Items = (itemRecordW*)calloc(sizeof(itemRecordW),input->Size);
  529. if (output->Items)
  530. {
  531. for(int i=0; i < input->Size; i++)
  532. {
  533. convertRecord(&output->Items[i],&input->Items[i]);
  534. }
  535. }
  536. }