fileview_filesystem.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. #include "main.h"
  2. #include "./fileview.h"
  3. #include "./fileview_internal.h"
  4. #include <vector>
  5. #include "../playlist/svc_playlisthandler.h"
  6. #include "../playlist/api_playlistmanager.h"
  7. #include <api/service/waservicefactorybase.h>
  8. #include <api/service/services.h>
  9. #include <shlwapi.h>
  10. #include <strsafe.h>
  11. #include <algorithm>
  12. #define FILEREC_ALLOCATION_STEP 1000
  13. #define FILETYPE_REREAD ((UINT)(0 - 1))
  14. typedef struct _FILETYPEREC
  15. {
  16. WCHAR szExtension[32];
  17. WCHAR szFamily[128];
  18. UINT Type;
  19. } FILETYPEREC;
  20. static std::vector<FILETYPEREC> supportedFilesList;
  21. //__inline static int __cdecl QSort_StrCmpI(const void *elem1, const void *elem2)
  22. //{
  23. // return (CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE, (LPCWSTR)elem1, -1, (LPCWSTR)elem2, -1) - 2);
  24. //}
  25. static BOOL FileView_GetPLExtensionName(LPCWSTR pszExt, LPWSTR pszDest, INT cchDest)
  26. {
  27. BOOL result(FALSE);
  28. DWORD lcid;
  29. int n(0);
  30. waServiceFactory *sf = 0;
  31. LPCWSTR ext;
  32. lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
  33. while (NULL != (sf = WASABI_API_SVC->service_enumService(WaSvc::PLAYLISTHANDLER, n++)))
  34. {
  35. svc_playlisthandler * handler = static_cast<svc_playlisthandler *>(sf->getInterface());
  36. if (handler)
  37. {
  38. int k(0);
  39. while (NULL != (ext = handler->EnumerateExtensions(k++)))
  40. {
  41. if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, pszExt, -1, ext, -1))
  42. {
  43. result = (S_OK == StringCchCopyW(pszDest, cchDest, handler->GetName()));
  44. if (result && CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, pszExt, -1, L"M3U8", -1)) // ugly...
  45. result = (S_OK == StringCchCatW(pszDest, cchDest, L" (Unicode)"));
  46. break;
  47. }
  48. }
  49. sf->releaseInterface(handler);
  50. }
  51. }
  52. return result;
  53. }
  54. static void FileView_ReadSupportedTypesInfo()
  55. {
  56. LPWSTR pszTypes, p;
  57. pszTypes = (LPWSTR)SendMessageW(plugin.hwndParent, WM_WA_IPC, 0, IPC_GET_EXTLISTW);
  58. if (pszTypes)
  59. {
  60. INT i;
  61. for(i = 0, p = pszTypes; *p != 0 && *(p+1) != 0; p += lstrlenW(p) + 1, i++)
  62. {
  63. FILETYPEREC ftr;
  64. if (S_OK == StringCchCopyW(ftr.szExtension, sizeof(ftr.szExtension) / sizeof(ftr.szExtension[0]), p))
  65. {
  66. ftr.Type = FILETYPE_REREAD;
  67. supportedFilesList.push_back(ftr);
  68. }
  69. }
  70. GlobalFree(pszTypes);
  71. }
  72. if (WASABI_API_SVC)
  73. {
  74. api_playlistmanager *plMngr = 0;
  75. waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(api_playlistmanagerGUID);
  76. if (factory) plMngr = (api_playlistmanager*) factory->getInterface();
  77. if (plMngr)
  78. {
  79. FILETYPEREC ftr;
  80. ftr.Type = FVFT_PLAYLIST;
  81. size_t playlistEnum=0;
  82. const wchar_t *playlistExt=0;
  83. while (NULL != (playlistExt = plMngr->EnumExtension(playlistEnum++)))
  84. {
  85. if (S_OK ==StringCchCopyW(ftr.szExtension, sizeof(ftr.szExtension) / sizeof(ftr.szExtension[0]), playlistExt))
  86. {
  87. FileView_GetPLExtensionName(ftr.szExtension, ftr.szFamily, sizeof(ftr.szFamily)/sizeof(ftr.szFamily[0]));
  88. supportedFilesList.push_back(ftr);
  89. }
  90. }
  91. factory->releaseInterface(plMngr);
  92. }
  93. }
  94. }
  95. static UINT FileView_GetFileType(LPCWSTR pszExtension)
  96. {
  97. FILETYPEREC *pftr = nullptr;
  98. if (!pszExtension) return FVFT_UNKNOWN;
  99. if ( 0 == supportedFilesList.size())
  100. {
  101. FileView_ReadSupportedTypesInfo();
  102. if (supportedFilesList.size()) {
  103. //qsort(supportedFilesList.begin(), supportedFilesList.size(), sizeof(FILETYPEREC), QSort_StrCmpI);
  104. std::sort(supportedFilesList.begin(), supportedFilesList.end(),
  105. [&](const FILETYPEREC &lhs, const FILETYPEREC &rhs) -> bool
  106. {
  107. return CSTR_LESS_THAN == CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE, (LPCWSTR)(&lhs), -1, (LPCWSTR)(&rhs), -1);
  108. }
  109. );
  110. }
  111. }
  112. //pftr = (FILETYPEREC*)bsearch(pszExtension, supportedFilesList.begin(), supportedFilesList.size(), sizeof(FILETYPEREC), QSort_StrCmpI);
  113. auto it = std::find_if(supportedFilesList.begin(), supportedFilesList.end(),
  114. [&](const FILETYPEREC& rec) -> bool
  115. {
  116. return CSTR_EQUAL == CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE, (LPCWSTR)(&rec), -1, (LPCWSTR)(pszExtension), -1);
  117. }
  118. );
  119. if (it != supportedFilesList.end())
  120. {
  121. pftr = &(*it);
  122. }
  123. if (pftr)
  124. {
  125. if (FILETYPE_REREAD == pftr->Type)
  126. {
  127. wchar_t szTest[MAX_PATH] = {0};
  128. pftr->Type = FVFT_UNKNOWN;
  129. if (S_OK == StringCchPrintfW(szTest, sizeof(szTest)/sizeof(wchar_t), L"test.%s", pftr->szExtension))
  130. {
  131. wchar_t szResult[MAX_PATH] = {0};
  132. extendedFileInfoStructW efis = { szTest, L"type", szResult, sizeof(szResult)/sizeof(szResult[0]), };
  133. if (SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)&efis, IPC_GET_EXTENDED_FILE_INFOW))
  134. {
  135. switch(szResult[0])
  136. {
  137. case L'0': pftr->Type = FVFT_AUDIO; break;
  138. case L'1': pftr->Type = FVFT_VIDEO; break;
  139. }
  140. pftr->szFamily[0] = L'\0';
  141. switch(pftr->Type)
  142. {
  143. case FVFT_AUDIO:
  144. case FVFT_VIDEO:
  145. extendedFileInfoStructW efis = { szTest, L"family", pftr->szFamily, sizeof(pftr->szFamily)/sizeof(pftr->szFamily[0]), };
  146. SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)&efis, IPC_GET_EXTENDED_FILE_INFOW);
  147. break;
  148. }
  149. }
  150. }
  151. }
  152. return pftr->Type;
  153. }
  154. return FVFT_UNKNOWN;
  155. }
  156. size_t FileView_ReadFileData(FILEDATA *pfd, LPCWSTR pszPath, UINT fStyle, FILESYSTEMINFO *pfsi)
  157. {
  158. HANDLE hFile;
  159. wchar_t szSearch[2 * MAX_PATH + 4] = {0};
  160. if (!pfd) return ((size_t)-1);
  161. size_t c = 0;
  162. pfd->count = 0;
  163. pfd->folderSize = 0;
  164. if (S_OK != StringCchPrintfW(szSearch, sizeof(szSearch)/sizeof(szSearch[0]), L"%s\\*", pszPath)) return ((size_t)-1);
  165. if (0 == pfd->allocated)
  166. {
  167. pfd->pRec = (FILERECORD*)calloc(FILEREC_ALLOCATION_STEP, sizeof(FILERECORD));
  168. if (!pfd->pRec)
  169. {
  170. return ((size_t)-1);
  171. }
  172. pfd->pSort = (size_t*)calloc(FILEREC_ALLOCATION_STEP, sizeof(size_t));
  173. if (!pfd->pSort)
  174. {
  175. if (pfd->pRec) free(pfd->pRec);
  176. ZeroMemory(&pfd, sizeof(FILEDATA));
  177. return ((size_t)-1);
  178. }
  179. pfd->allocated = FILEREC_ALLOCATION_STEP;
  180. }
  181. hFile = pfsi->fnFindFirstFile(szSearch, &pfd->pRec[c].Info);
  182. if (INVALID_HANDLE_VALUE != hFile)
  183. {
  184. do
  185. {
  186. if (0 == (FILE_ATTRIBUTE_DIRECTORY & pfd->pRec[c].Info.dwFileAttributes) &&
  187. (0 == (FVS_IGNOREHIDDEN & fStyle) || 0 == (FILE_ATTRIBUTE_HIDDEN & pfd->pRec[c].Info.dwFileAttributes)))
  188. {
  189. LPCWSTR pszExt = PathFindExtensionW(pfd->pRec[c].Info.cFileName);
  190. if (L'.' == *pszExt) pszExt++;
  191. else pszExt = NULL;
  192. pfd->pRec[c].extOffset = (pszExt && *pszExt) ? (pszExt - pfd->pRec[c].Info.cFileName) : 0;
  193. pfd->pRec[c].fileType = FileView_GetFileType(pszExt);
  194. pfd->pRec[c].pMeta = NULL;
  195. if ((FVFT_UNKNOWN == pfd->pRec[c].fileType && (FVS_SHOWUNKNOWN & fStyle)) ||
  196. (FVFT_AUDIO == pfd->pRec[c].fileType && (FVS_SHOWAUDIO & fStyle)) ||
  197. (FVFT_VIDEO == pfd->pRec[c].fileType && (FVS_SHOWVIDEO & fStyle)) ||
  198. (FVFT_PLAYLIST == pfd->pRec[c].fileType && (FVS_SHOWPLAYLIST & fStyle)))
  199. {
  200. if (NULL != pfd->pRec[c].extOffset && FVFT_UNKNOWN != pfd->pRec[c].fileType && (FVS_HIDEEXTENSION & fStyle))
  201. pfd->pRec[c].Info.cFileName[pfd->pRec[c].extOffset -1] = L'\0';
  202. pfd->pSort[c] = c;
  203. pfd->folderSize += (ULONGLONG)(((__int64)pfd->pRec[c].Info.nFileSizeHigh << 32) | pfd->pRec[c].Info.nFileSizeLow);
  204. c++;
  205. if (c == pfd->allocated)
  206. {
  207. void *pData;
  208. pData = realloc(pfd->pRec, sizeof(FILERECORD) * (pfd->allocated + FILEREC_ALLOCATION_STEP));
  209. if (!pData) { c = ((size_t)-1); break; }
  210. pfd->pRec = (FILERECORD*)pData;
  211. pData = realloc(pfd->pSort, sizeof(size_t) * (pfd->allocated + FILEREC_ALLOCATION_STEP));
  212. if (!pData) { c = ((size_t)-1); break; }
  213. pfd->pSort= (size_t*)pData;
  214. pfd->allocated += FILEREC_ALLOCATION_STEP;
  215. }
  216. }
  217. }
  218. } while (pfsi->fnFindNextFile(hFile, &pfd->pRec[c].Info));
  219. pfsi->fnFindClose(hFile);
  220. }
  221. else
  222. {
  223. DWORD e = GetLastError();
  224. if (0 != e) c = ((size_t)-1);
  225. }
  226. if (((size_t)-1) != c) pfd->count = c;
  227. return c;
  228. }
  229. LPCWSTR FileView_GetTypeFamily(LPCWSTR pszExtension)
  230. {
  231. if (!pszExtension || 0 == supportedFilesList.size())
  232. return NULL;
  233. //FILETYPEREC *pftr = (FILETYPEREC*)bsearch(pszExtension, supportedFilesList.begin(), supportedFilesList.size(), sizeof(FILETYPEREC), QSort_StrCmpI);
  234. FILETYPEREC* pftr = nullptr;
  235. auto it = std::find_if(supportedFilesList.begin(), supportedFilesList.end(),
  236. [&](const FILETYPEREC& rec) -> bool
  237. {
  238. return CSTR_EQUAL == CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE, (LPCWSTR)(&rec), -1, (LPCWSTR)(pszExtension), -1);
  239. }
  240. );
  241. if (it != supportedFilesList.end())
  242. {
  243. pftr = &(*it);
  244. }
  245. return (pftr) ? pftr->szFamily : NULL;
  246. }