1
0

ReIndexUI.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. #include "Main.h"
  2. #include "ml_local.h"
  3. #include "resource.h"
  4. static INT_PTR CALLBACK CompactWndProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  5. {
  6. switch (msg)
  7. {
  8. case WM_INITDIALOG:
  9. {
  10. SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
  11. SendDlgItemMessage(hwndDlg, IDC_PROGRESS1, PBM_SETRANGE, 0, MAKELPARAM(0, 400));
  12. SendDlgItemMessage(hwndDlg, IDC_PROGRESS1, PBM_SETPOS, 0, 0);
  13. int *progress = (int *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
  14. if (progress[1] == -102)
  15. {
  16. progress[1] = -101;
  17. SetWindowTextW(hwndDlg, WASABI_API_LNGSTRINGW(IDS_REFRESH_FILESIZE_DATEADDED));
  18. }
  19. SetTimer(hwndDlg, 666, 500, 0);
  20. break;
  21. }
  22. case WM_TIMER:
  23. if (wParam == 666)
  24. {
  25. int *progress = (int *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
  26. if (progress[0] == 666)
  27. {
  28. KillTimer(hwndDlg, 666);
  29. EndDialog(hwndDlg, 0);
  30. }
  31. else if (progress[1] != -101)
  32. {
  33. SendDlgItemMessage(hwndDlg, IDC_PROGRESS1, PBM_SETPOS, progress[1] + 300, 0);
  34. }
  35. else
  36. {
  37. SendDlgItemMessage(hwndDlg, IDC_PROGRESS1, PBM_SETPOS, progress[0] + 100, 0);
  38. }
  39. }
  40. break;
  41. }
  42. return 0;
  43. }
  44. static DWORD CALLBACK CompactThread(LPVOID param)
  45. {
  46. WASABI_API_DIALOGBOXPARAMW(IDD_REINDEX, NULL, CompactWndProc, (LPARAM)param);
  47. return 0;
  48. }
  49. static int sortFunc(const void *a, const void *b)
  50. {
  51. const wchar_t **fn1 = (const wchar_t **)a;
  52. const wchar_t **fn2 = (const wchar_t **)b;
  53. return _wcsicmp(*fn1, *fn2);
  54. }
  55. void RetypeFilename(nde_table_t table)
  56. {
  57. int totalRecords = NDE_Table_GetRecordsCount(g_table);
  58. if (totalRecords == 0) // bail out early so we don't flash a dialog
  59. return;
  60. int progress[2] = {-100, -101};
  61. DWORD threadId = 0;
  62. HANDLE compactThread = 0;
  63. nde_scanner_t pruneScanner = NDE_Table_CreateScanner(table);
  64. if (pruneScanner)
  65. {
  66. bool first=true;
  67. int recordNum = 0;
  68. NDE_Scanner_First(pruneScanner);
  69. while (!NDE_Scanner_EOF(pruneScanner))
  70. {
  71. progress[0] = MulDiv(recordNum, 100, totalRecords)-100;
  72. nde_field_t f = NDE_Scanner_GetFieldByID(pruneScanner, MAINTABLE_ID_FILENAME);
  73. if (f && NDE_Field_GetType(f) == FIELD_STRING)
  74. {
  75. wchar_t *s = NDE_StringField_GetString(f);
  76. ndestring_retain(s);
  77. NDE_Scanner_DeleteField(pruneScanner, f);
  78. nde_field_t new_f = NDE_Scanner_NewFieldByID(pruneScanner, MAINTABLE_ID_FILENAME);
  79. NDE_StringField_SetString(new_f, s);
  80. ndestring_release(s);
  81. NDE_Scanner_Post(pruneScanner);
  82. }
  83. else if (f)
  84. {
  85. first = false; // skips creating the thread
  86. break;
  87. }
  88. recordNum++;
  89. NDE_Scanner_Next(pruneScanner);
  90. if (first)
  91. {
  92. compactThread = CreateThread(0, 0, CompactThread, progress, 0, &threadId);
  93. DumpArtCache(); // go ahead and dump the album art cache if we had to rebuild this table. ideally we could perform the same logic but this is easier and it's 1 in the morning and i don't feel like doing it :)
  94. }
  95. first=false;
  96. }
  97. NDE_Table_DestroyScanner(table, pruneScanner);
  98. if (compactThread)
  99. NDE_Table_Sync(table);
  100. }
  101. progress[0] = 666;
  102. if (compactThread)
  103. {
  104. WaitForSingleObject(compactThread, INFINITE);
  105. CloseHandle(compactThread);
  106. }
  107. }
  108. void RefreshFileSizeAndDateAddedTable(nde_table_t table)
  109. {
  110. int totalRecords = NDE_Table_GetRecordsCount(g_table);
  111. if (totalRecords == 0) // bail out early so we don't flash a dialog
  112. return;
  113. int progress[2] = {-100, -102};
  114. DWORD threadId = 0;
  115. HANDLE compactThread = 0;
  116. nde_scanner_t scanner = NDE_Table_CreateScanner(table);
  117. if (scanner)
  118. {
  119. bool first=true;
  120. int recordNum = 0;
  121. NDE_Scanner_First(scanner);
  122. while (!NDE_Scanner_EOF(scanner))
  123. {
  124. progress[0] = MulDiv(recordNum, 400, totalRecords);
  125. // converts filesize from a int and kb scaled value to the actual filesize as a int64
  126. nde_field_t f = NDE_Scanner_GetFieldByID(scanner, MAINTABLE_ID_FILESIZE);
  127. if (f && NDE_Field_GetType(f) == FIELD_INTEGER)
  128. {
  129. __int64 size = NDE_IntegerField_GetValue(f);
  130. if (size) size *= 1024;
  131. NDE_Scanner_DeleteField(scanner, f);
  132. nde_field_t new_f = NDE_Scanner_NewFieldByType(scanner, FIELD_INT64, MAINTABLE_ID_FILESIZE);
  133. NDE_Int64Field_SetValue(new_f, size);
  134. NDE_Scanner_Post(scanner);
  135. }
  136. // takes the lastupd value and applies it to dateadded so we've got something to use
  137. f = NDE_Scanner_GetFieldByID(scanner, MAINTABLE_ID_LASTUPDTIME);
  138. if (f && NDE_Field_GetType(f) == FIELD_DATETIME)
  139. {
  140. int lastupd = NDE_IntegerField_GetValue(f);
  141. nde_field_t new_f = NDE_Scanner_NewFieldByID(scanner, MAINTABLE_ID_DATEADDED);
  142. NDE_IntegerField_SetValue(new_f, lastupd);
  143. NDE_Scanner_Post(scanner);
  144. }
  145. NDE_Scanner_Next(scanner);
  146. recordNum++;
  147. if (first)
  148. {
  149. compactThread = CreateThread(0, 0, CompactThread, progress, 0, &threadId);
  150. }
  151. first=false;
  152. }
  153. NDE_Table_DestroyScanner(table, scanner);
  154. if (compactThread)
  155. NDE_Table_Sync(table);
  156. }
  157. progress[0] = 666;
  158. if (compactThread)
  159. {
  160. WaitForSingleObject(compactThread, INFINITE);
  161. CloseHandle(compactThread);
  162. }
  163. }
  164. void ReindexTable(nde_table_t table)
  165. {
  166. int totalRecords = NDE_Table_GetRecordsCount(g_table);
  167. if (totalRecords == 0) // bail out early so we don't flash a dialog
  168. return;
  169. int progress[2] = {-100, -101};
  170. DWORD threadId;
  171. HANDLE compactThread = CreateThread(0, 0, CompactThread, progress, 0, &threadId);
  172. nde_scanner_t pruneScanner = NDE_Table_CreateScanner(table);
  173. if (pruneScanner)
  174. {
  175. int recordNum = 0;
  176. NDE_Scanner_First(pruneScanner);
  177. while (!NDE_Scanner_EOF(pruneScanner))
  178. {
  179. int total = MulDiv(recordNum, 100, totalRecords);
  180. progress[0] = total - 100;
  181. #ifndef elementsof
  182. #define elementsof(x) (sizeof(x)/sizeof(*x))
  183. #endif
  184. unsigned char STR_IDS[] = {MAINTABLE_ID_TITLE, MAINTABLE_ID_ARTIST, MAINTABLE_ID_ALBUM, MAINTABLE_ID_GENRE,
  185. MAINTABLE_ID_COMMENT, MAINTABLE_ID_GRACENOTE_ID, MAINTABLE_ID_ALBUMARTIST,
  186. MAINTABLE_ID_TRACKGAIN, MAINTABLE_ID_PUBLISHER, MAINTABLE_ID_COMPOSER,
  187. MAINTABLE_ID_PODCASTCHANNEL, MAINTABLE_ID_GRACENOTEFILEID, MAINTABLE_ID_GRACENOTEEXTDATA,
  188. MAINTABLE_ID_CATEGORY, MAINTABLE_ID_CODEC, MAINTABLE_ID_DIRECTOR, MAINTABLE_ID_PRODUCER
  189. };
  190. for (size_t i = 0;i != elementsof(STR_IDS);i++)
  191. {
  192. nde_field_t f = NDE_Scanner_GetFieldByID(pruneScanner, STR_IDS[i]);
  193. if (f)
  194. {
  195. const wchar_t *s = NDE_StringField_GetString(f);
  196. if (!s || !*s)
  197. {
  198. NDE_Scanner_DeleteField(pruneScanner, f);
  199. NDE_Scanner_Post(pruneScanner);
  200. }
  201. }
  202. }
  203. unsigned char INT_IDS_ZEROOK[] = {MAINTABLE_ID_LENGTH, MAINTABLE_ID_PLAYCOUNT, MAINTABLE_ID_FILESIZE,
  204. MAINTABLE_ID_TYPE, MAINTABLE_ID_ISPODCAST, MAINTABLE_ID_LOSSLESS
  205. };
  206. for (size_t i = 0;i != elementsof(INT_IDS_ZEROOK);i++)
  207. {
  208. nde_field_t f = NDE_Scanner_GetFieldByID(pruneScanner, INT_IDS_ZEROOK[i]);
  209. if (f)
  210. {
  211. int s = NDE_IntegerField_GetValue(f);
  212. if (s < 0)
  213. {
  214. NDE_Scanner_DeleteField(pruneScanner, f);
  215. NDE_Scanner_Post(pruneScanner);
  216. }
  217. }
  218. }
  219. unsigned char INT_IDS[] = {MAINTABLE_ID_TRACKNB, MAINTABLE_ID_LASTUPDTIME, MAINTABLE_ID_LASTPLAY, MAINTABLE_ID_RATING,
  220. MAINTABLE_ID_FILETIME, MAINTABLE_ID_BITRATE, MAINTABLE_ID_DISC, MAINTABLE_ID_BPM, MAINTABLE_ID_DISCS,
  221. MAINTABLE_ID_TRACKS, MAINTABLE_ID_PODCASTPUBDATE, MAINTABLE_ID_FILESIZE, MAINTABLE_ID_DATEADDED
  222. };
  223. for (size_t i = 0;i != elementsof(INT_IDS);i++)
  224. {
  225. nde_field_t f = NDE_Scanner_GetFieldByID(pruneScanner, INT_IDS[i]);
  226. if (f)
  227. {
  228. int s = NDE_IntegerField_GetValue(f);
  229. if (s <= 0)
  230. {
  231. NDE_Scanner_DeleteField(pruneScanner, f);
  232. NDE_Scanner_Post(pruneScanner);
  233. }
  234. }
  235. }
  236. NDE_Scanner_Next(pruneScanner);
  237. recordNum++;
  238. }
  239. NDE_Table_DestroyScanner(table, pruneScanner);
  240. NDE_Table_Sync(table);
  241. }
  242. NDE_Table_Compact(table, &progress[0]);
  243. assert(((Table *)table)->CheckIndexing());
  244. // now remove duplicates
  245. nde_scanner_t dupscanner = NDE_Table_CreateScanner(table);
  246. if (dupscanner)
  247. {
  248. int count = NDE_Scanner_GetRecordsCount(dupscanner);
  249. wchar_t **filenames = new wchar_t *[count];
  250. int i = 0;
  251. for (NDE_Scanner_First(dupscanner);!NDE_Scanner_EOF(dupscanner);NDE_Scanner_Next(dupscanner))
  252. {
  253. nde_field_t fileName = NDE_Scanner_GetFieldByID(dupscanner, MAINTABLE_ID_FILENAME);
  254. if (fileName)
  255. {
  256. filenames[i] = NDE_StringField_GetString(fileName);
  257. ndestring_retain(filenames[i]);
  258. i++;
  259. }
  260. }
  261. count = i;
  262. if (count)
  263. {
  264. qsort(filenames, count, sizeof(wchar_t *), sortFunc);
  265. for (int x = 0;x < (count - 1);x++)
  266. {
  267. int total = MulDiv(x, 100, count);
  268. progress[1] = total - 100;
  269. if (!_wcsicmp(filenames[x], filenames[x+1]))
  270. {
  271. wchar_t query[1024] = {0};
  272. wnsprintfW(query, 1024, L"filename == \"%s\"", filenames[x]);
  273. nde_scanner_t scanner = NDE_Table_CreateScanner(table);
  274. NDE_Scanner_Query(scanner, query);
  275. NDE_Scanner_First(scanner);
  276. NDE_Scanner_Next(scanner);
  277. while (!NDE_Scanner_EOF(scanner))
  278. {
  279. NDE_Scanner_Delete(scanner);
  280. NDE_Scanner_Post(scanner);
  281. NDE_Scanner_Next(scanner);
  282. }
  283. NDE_Table_DestroyScanner(table, scanner);
  284. }
  285. ndestring_release(filenames[x]);
  286. filenames[x]=0;
  287. }
  288. }
  289. delete[] filenames;
  290. }
  291. NDE_Table_DestroyScanner(table, dupscanner);
  292. NDE_Table_Sync(table);
  293. NDE_Table_Compact(table, &progress[1]);
  294. progress[0] = 666;
  295. WaitForSingleObject(compactThread, INFINITE);
  296. CloseHandle(compactThread);
  297. }