123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940 |
- #include "main.h"
- #include "resource.h"
- #include "api_mldb.h"
- #include "../Winamp/strutil.h"
- enum {
- STATUS_SEARCHING,
- STATUS_GETINFO,
- STATUS_DONE,
- };
- extern HWND g_bgrescan_status_hwnd;
- extern nde_scanner_t m_media_scanner;
- #define MAX_RECURSE_DEPTH 32
- /* Event handles */
- static HANDLE scan_killswitch=0;
- static HANDLE scan_cancel=0;
- static HANDLE scan_cancel_complete=0;
- /* Thread handle */
- static HANDLE scan_thread=0;
- /* extension list */
- static wchar_t *scan_extlist=0;
- static void SyncTable()
- {
- EnterCriticalSection(&g_db_cs);
- NDE_Table_Sync(g_table);
- g_table_dirty=0;
- LeaveCriticalSection(&g_db_cs);
- }
- static bool ScanCancelled(HANDLE *events, int count)
- {
- // make sure no one cancelled us
- DWORD eventFired=WaitForMultipleObjectsEx(count, events, FALSE, 0, TRUE);
- if (eventFired >= WAIT_OBJECT_0 && eventFired < (WAIT_OBJECT_0+count))
- return true;
- return false;
- }
- static bool SupportedType(const wchar_t *ext)
- {
- if (!scan_extlist)
- scan_extlist=(wchar_t*)SendMessage(plugin.hwndWinampParent,WM_WA_IPC,0,IPC_GET_EXTLISTW);
- // dunno how this would happen but should verify
- if (!scan_extlist || scan_extlist == (wchar_t *)1)
- return false;
- const wchar_t *a = scan_extlist;
- while (a && *a)
- {
- if (CompareStringW(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), NORM_IGNORECASE, a, -1, ext, -1) == CSTR_EQUAL)
- {
- return true;
- }
- a+=wcslen(a)+1;
- }
- return false;
- }
- static void CountFolder(const wchar_t *folder, int recurse, HANDLE cancelswitch, volatile int *found)
- {
- wchar_t filespec[MAX_PATH] = {0};
- PathCombineW(filespec, folder, L"*.*");
- WIN32_FIND_DATAW findData = {0};
- HANDLE h = FindFirstFileW(filespec, &findData);
- if (h != INVALID_HANDLE_VALUE)
- {
- if (IsWindow(g_bgrescan_status_hwnd))
- {
- wchar_t status[150+MAX_PATH] = {0};
- WASABI_API_LNGSTRINGW_BUF(IDS_SCANNING_DIR, status, 150);
- const wchar_t *p=folder+wcslen(folder);
- while (p > folder && *p != '\\') p--;
- p--;
- while (p >= folder && *p != '\\') p--;
- StringCbCatW(status, sizeof(status), ++p);
- SetWindowTextW(g_bgrescan_status_hwnd,status);
- }
- HANDLE events[2] = { scan_killswitch, cancelswitch};
- do
- {
- // make sure no one cancelled us
- if (ScanCancelled(events, 2))
- break;
- /* if it's a directory (And not either of the two special dirs */
- if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- && lstrcmpiW(findData.cFileName, L".")
- && lstrcmpiW(findData.cFileName, L".."))
- {
- if (recurse && recurse < MAX_RECURSE_DEPTH)
- {
- PathCombineW(filespec, folder, findData.cFileName);
- CountFolder(filespec, recurse+1, cancelswitch, found); // add 1 so we can verify recurse depth
- }
- }
- if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
- {
- wchar_t *ext=extensionW(findData.cFileName);
- if (ext && ext[0] && SupportedType(ext))
- {
- PathCombineW(filespec, folder, findData.cFileName);
- if (IsWindow(g_bgrescan_status_hwnd))
- {
- wchar_t b[150+MAX_PATH] = {0};
- WASABI_API_LNGSTRINGW_BUF(IDS_SCANNING_FILE, b, 150);
- StringCbCatW(b, sizeof(b), filespec);
- SetWindowTextW(g_bgrescan_status_hwnd,b);
- }
- if (found)
- (*found)++;
- }
- }
- } while (FindNextFileW(h, &findData));
- FindClose(h);
- }
- else if (!(GetFileAttributesW(folder) & FILE_ATTRIBUTE_DIRECTORY))
- {
- if (IsWindow(g_bgrescan_status_hwnd))
- {
- wchar_t b[150+MAX_PATH] = {0};
- WASABI_API_LNGSTRINGW_BUF(IDS_SCANNING_FILE, b, 150);
- StringCbCatW(b, sizeof(b), folder);
- SetWindowTextW(g_bgrescan_status_hwnd,b);
- }
- if (found)
- (*found)++;
- }
- }
- static void ScanFolder(const wchar_t *folder, int recurse, int metadata, int guessmode, HANDLE cancelswitch, volatile int *scanned)
- {
- if ((unsigned long)folder < 65536) return;
- wchar_t filespec[MAX_PATH] = {0};
- wchar_t status[150+MAX_PATH] = {0};
- PathCombineW(filespec, folder, L"*.*");
- WIN32_FIND_DATAW findData = {0};
- HANDLE h = FindFirstFileW(filespec, &findData);
- if (h != INVALID_HANDLE_VALUE)
- {
- if (IsWindow(g_bgrescan_status_hwnd))
- {
- WASABI_API_LNGSTRINGW_BUF(IDS_SCANNING_DIR, status, 150);
- const wchar_t *p=folder+wcslen(folder);
- while (p > folder && *p != '\\') p--;
- p--;
- while (p >= folder && *p != '\\') p--;
- StringCbCatW(status, sizeof(status), ++p);
- SetWindowTextW(g_bgrescan_status_hwnd,status);
- }
- HANDLE events[2] = { scan_killswitch, cancelswitch};
- do
- {
- // make sure no one cancelled us
- if (ScanCancelled(events, 2))
- break;
- /* if it's a directory (And not either of the two special dirs */
- if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- && lstrcmpiW(findData.cFileName, L".")
- && lstrcmpiW(findData.cFileName, L".."))
- {
- if (recurse && recurse < MAX_RECURSE_DEPTH)
- {
- PathCombineW(filespec, folder, findData.cFileName);
- ScanFolder(filespec, recurse+1, metadata, guessmode, cancelswitch, scanned); // add 1 so we can verify recurse depth
- }
- }
- if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
- {
- wchar_t *ext=extensionW(findData.cFileName);
- if (ext && ext[0] && SupportedType(ext))
- {
- PathCombineW(filespec, folder, findData.cFileName);
- if (IsWindow(g_bgrescan_status_hwnd))
- {
- WASABI_API_LNGSTRINGW_BUF(IDS_SCANNING_FILE, status, 150);
- StringCbCatW(status, sizeof(status), filespec);
- SetWindowTextW(g_bgrescan_status_hwnd,status);
- }
- addFileToDb(filespec, 0, metadata, guessmode);
- if (scanned)
- (*scanned)++;
- }
- }
- } while (FindNextFileW(h, &findData));
- FindClose(h);
- }
- else if (!(GetFileAttributesW(folder) & FILE_ATTRIBUTE_DIRECTORY))
- {
- if (IsWindow(g_bgrescan_status_hwnd))
- {
- WASABI_API_LNGSTRINGW_BUF(IDS_SCANNING_FILE, status, 150);
- StringCbCatW(status, sizeof(status), folder);
- SetWindowTextW(g_bgrescan_status_hwnd,status);
- }
- addFileToDb(folder, 0, metadata, guessmode);
- if (scanned)
- (*scanned)++;
- }
- }
- static DWORD CALLBACK ScanThreadProc(LPVOID param)
- {
- /* sit and run APCs until we get signalled to die */
- HANDLE events[2] = { scan_killswitch, scan_cancel};
- int eventFired;
- do
- {
- eventFired=WaitForMultipleObjectsEx(2, events, FALSE, INFINITE, TRUE);
- switch(eventFired)
- {
- case WAIT_OBJECT_0+1: // cancel event
- ResetEvent(scan_cancel);
- SetEvent(scan_cancel_complete);
- break;
- }
- }
- while (eventFired != WAIT_OBJECT_0);
- if (scan_extlist && scan_extlist != (wchar_t *)1)
- GlobalFree((HGLOBAL)scan_extlist);
- scan_extlist=0;
- return 0;
- }
- static bool ScanCreateThread()
- {
- if (!scan_thread)
- {
- /* create events */
- scan_killswitch = CreateEvent(NULL, TRUE, FALSE, NULL);
- scan_cancel = CreateEvent(NULL, TRUE, FALSE, NULL);
- scan_cancel_complete = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset event
- /* start thread */
- scan_thread = CreateThread(NULL, 0, ScanThreadProc, 0, 0, 0);
- }
- return !!scan_thread;
- }
- void Scan_Cancel()
- {
- HWND old = g_bgrescan_status_hwnd; // clear g_bgrescan_status_hwnd so that we don't deadlock when the BG thread calls SetWindowText
- g_bgrescan_status_hwnd = 0;
- if (scan_cancel)
- SignalObjectAndWait(scan_cancel, scan_cancel_complete, INFINITE, FALSE);
- g_bgrescan_status_hwnd = old;
- }
- void Scan_Kill()
- {
- HWND old = g_bgrescan_status_hwnd; // clear g_bgrescan_status_hwnd so that we don't deadlock when the BG thread calls SetWindowText
- g_bgrescan_status_hwnd = 0;
- if (scan_thread)
- SignalObjectAndWait(scan_killswitch, scan_thread, INFINITE, FALSE);
- g_bgrescan_status_hwnd = old;
- }
- /* ---------------
- * Scan_ScanFolder
- * ---------------
- */
- struct ScanFolderParams
- {
- ScanFolderParams(const wchar_t *_path, int _guess, int _meta, int _recurse)
- {
- path = _wcsdup(_path);
- guess = _guess >= 0 ? _guess : g_config->ReadInt(L"guessmode",0);;
- meta = _meta >= 0 ? _meta : g_config->ReadInt(L"usemetadata",1);
- recurse = _recurse;
- }
- ~ScanFolderParams()
- {
- free(path);
- }
- wchar_t *path;
- int guess;
- int meta;
- int recurse;
- };
- static VOID CALLBACK ScanFolderAPC(ULONG_PTR param)
- {
- // clear extension list to get latest config
- if (scan_extlist && scan_extlist != (wchar_t *)1)
- GlobalFree((HGLOBAL)scan_extlist);
- scan_extlist = 0;
- ScanFolderParams *params = (ScanFolderParams *)param;
- ScanFolder(params->path, params->recurse, params->meta, params->guess, scan_cancel, 0);
- SyncTable();
- delete params;
- }
- void Scan_ScanFolderBackground(const wchar_t *path, int guess, int meta, int recurse)
- {
- if (ScanCreateThread())
- {
- ScanFolderParams *params = new ScanFolderParams(path, guess, meta, recurse);
- if (QueueUserAPC(ScanFolderAPC, scan_thread, (ULONG_PTR)params) == 0)
- delete params;
- }
- }
- /* ---------------
- * Scan_ScanFolders
- * ---------------
- */
- struct ScanFoldersParams
- {
- ScanFoldersParams(wchar_t **_path, size_t _count, int *_guess, int *_meta, int *_recurse)
- {
- path = _path;
- count = _count;
- guess = _guess;
- meta = _meta;
- recurse = _recurse;
- found = 0;
- scanned = 0;
- cancel_switch = CreateEvent(NULL, TRUE, FALSE, NULL);
- status = STATUS_SEARCHING;
- ui = 0;
- in_timer = 0;
- }
- ~ScanFoldersParams()
- {
- for (size_t i=0;i!=count;i++)
- free(path[i]);
- free(path);
- free(guess);
- free(meta);
- free(recurse);
- CloseHandle(cancel_switch);
- }
- wchar_t **path;
- size_t count;
- int *guess;
- int *meta;
- int *recurse;
- volatile int found;
- volatile int scanned;
- volatile int status;
- int in_timer;
- HANDLE cancel_switch;
- HWND ui;
- };
- static VOID CALLBACK ScanFoldersAPC(ULONG_PTR param)
- {
- // clear extension list to get latest config
- if (scan_extlist && scan_extlist != (wchar_t *)1)
- GlobalFree((HGLOBAL)scan_extlist);
- scan_extlist = 0;
- ScanFoldersParams *params = (ScanFoldersParams *)param;
- HANDLE events[2] = { scan_killswitch, params->cancel_switch};
- for (size_t i=0;i!=params->count;i++)
- {
- if (ScanCancelled(events, 2))
- break;
- CountFolder(params->path[i], params->recurse[i], params->cancel_switch, ¶ms->found);
- }
- params->status = STATUS_GETINFO;
- for (size_t i=0;i!=params->count;i++)
- {
- if (ScanCancelled(events, 2))
- break;
- int guess = params->guess[i] >= 0 ? params->guess[i] : g_config->ReadInt(L"guessmode",0);;
- int meta = params->meta[i] >= 0 ? params->meta[i] : g_config->ReadInt(L"usemetadata",1);
- ScanFolder(params->path[i], params->recurse[i], meta, guess, params->cancel_switch, ¶ms->scanned);
- }
- params->status = STATUS_DONE;
- PostMessage(params->ui, WM_APP, 0, 0);
- }
- static INT_PTR CALLBACK ScanFileUI(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
- {
- switch(uMsg)
- {
- case WM_INITDIALOG:
- {
- SetDlgItemTextW(hwndDlg,IDC_STATUS,WASABI_API_LNGSTRINGW(IDS_INITIALIZING));
- ScanFoldersParams *params = (ScanFoldersParams *)lParam;
- params->ui = hwndDlg;
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
- if (QueueUserAPC(ScanFoldersAPC, scan_thread, (ULONG_PTR)lParam) == 0)
- EndDialog(hwndDlg, 0);
- else
- {
- SendDlgItemMessage(hwndDlg,IDC_PROGRESS1,PBM_SETRANGE,0,MAKELPARAM(0, 100));
- SetTimer(hwndDlg,0x123,300,NULL);
- }
- // show window and restore last position as applicable
- POINT pt = {g_config->ReadInt(L"scan_x", -1), g_config->ReadInt(L"scan_y", -1)};
- if (!windowOffScreen(hwndDlg, pt))
- SetWindowPos(hwndDlg, HWND_TOP, pt.x, pt.y, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOSENDCHANGING);
- }
- break;
- case WM_TIMER:
- {
- ScanFoldersParams *params = (ScanFoldersParams *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
- if (params->in_timer) break;
- params->in_timer++;
- if(params->status==STATUS_SEARCHING)
- {
- wchar_t tmp[512] = {0};
- StringCchPrintfW(tmp, 512, WASABI_API_LNGSTRINGW(IDS_SEARCHING_X_FILES_FOUND), params->found);
- SetDlgItemTextW(hwndDlg,IDC_STATUS,tmp);
- }
- else if(params->status==STATUS_GETINFO)
- {
- wchar_t tmp[512] = {0};
- int perc=params->found?(params->scanned*100/params->found):0;
- StringCchPrintfW(tmp, 512, WASABI_API_LNGSTRINGW(IDS_GETTING_INFO_FROM_FILES_PERCENT),perc);
- SetDlgItemTextW(hwndDlg,IDC_STATUS,tmp);
- SendDlgItemMessage(hwndDlg,IDC_PROGRESS1,PBM_SETPOS,perc,0);
- }
- params->in_timer--;
- }
- break;
- case WM_APP:
- {
- KillTimer(hwndDlg,0x123);
- SyncTable();
- EndDialog(hwndDlg,0);
- }
- break;
- case WM_COMMAND:
- if (LOWORD(wParam)==IDCANCEL)
- {
- ScanFoldersParams *params = (ScanFoldersParams *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
- SetEvent(params->cancel_switch);
- }
- break;
- case WM_DESTROY:
- {
- RECT scan_rect = {0};
- GetWindowRect(hwndDlg, &scan_rect);
- g_config->WriteInt(L"scan_x", scan_rect.left);
- g_config->WriteInt(L"scan_y", scan_rect.top);
- KillTimer(hwndDlg,0x123);
- ScanFoldersParams *params = (ScanFoldersParams *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
- delete params;
- return FALSE;
- }
- }
- return FALSE;
- }
- /* When you call this function, it will own the memory and release it with free() */
- void Scan_ScanFolders(HWND parent, size_t count, wchar_t **paths, int *guess, int *meta, int *recurse)
- {
- openDb();
- if (g_table && ScanCreateThread())
- {
- ScanFoldersParams *params = new ScanFoldersParams(paths, count, guess, meta, recurse);
- WASABI_API_LNG->LDialogBoxParamW(WASABI_API_LNG->FindDllHandleByGUID(WinampLangGUID),
- GetModuleHandleW(L"winamp.exe"), IDD_ADDSTUFF,
- parent, (DLGPROC)ScanFileUI, (LPARAM)params);
- PostMessage(plugin.hwndWinampParent,WM_WA_IPC,NDE_Table_GetRecordsCount(g_table),IPC_STATS_LIBRARY_ITEMCNT);
- }
- else
- {
- for (size_t i=0;i!=count;i++)
- free(paths[i]);
- free(paths);
- }
- }
- void Scan_ScanFolder(HWND parent, const wchar_t *path, int guess, int meta, int recurse)
- {
- // kind of a hack ...
- if (ScanCreateThread())
- {
- wchar_t **paths = (wchar_t **)calloc(1, sizeof(wchar_t*));
- int *guesses = (int *)calloc(1, sizeof(int));
- int *metas = (int *)calloc(1, sizeof(int));
- int *recs = (int *)calloc(1, sizeof(int));
- *guesses = guess;
- *metas = meta;
- *recs = recurse;
- paths[0] = _wcsdup(path);
- Scan_ScanFolders(parent, 1, paths, guesses, metas, recs);
- }
- }
- static VOID CALLBACK BackgroundScanAPC(ULONG_PTR param)
- {
- openDb();
- if (!g_table)
- return;
- HANDLE events[2] = { scan_killswitch, scan_cancel};
- // clear extension list to get latest config
- if (scan_extlist && scan_extlist != (wchar_t *)1)
- GlobalFree((HGLOBAL)scan_extlist);
- scan_extlist = 0;
- // read list from config
- UINT codePage = CP_ACP;
- char scandirlist[65536] = {0};
- if (!g_config->ReadString("scandirlist", 0, scandirlist, 65536))
- {
- g_config->ReadString("scandirlist_utf8","", scandirlist, 65536);
- codePage = CP_UTF8;
- }
- AutoWide s1(scandirlist, codePage);
- size_t len = wcslen(s1)+2;
- wchar_t *s =(wchar_t*)calloc(len, sizeof(wchar_t));
- if (s)
- {
- lstrcpynW(s, s1, len);
- s[wcslen(s)+1]=0;
- wchar_t *p=s;
- while (p && *p == L'|') p++;
- while ((p=wcsstr(p,L"|")))
- {
- *p++=0;
- while (p && *p == L'|') p++;
- }
- p=s;
- // iterate through list
- while (p && *p && !ScanCancelled(events, 2))
- {
- while (p && *p == L'|') p++;
- int use_metadata=g_config->ReadInt(L"usemetadata",1);
- int guess_mode=g_config->ReadInt(L"guessmode",0);
- int recurse=1;
- if (*p == L'<' && wcsstr(p,L">"))
- {
- p++;
- while (p && *p != L'>')
- {
- // <MmSs>can prefix directory
- // M=metadata use override
- // m=no metadata
- // S=smart guessing
- // s=stupid guessing
- if (*p == L'M') use_metadata=1;
- else if (*p == L'm') use_metadata=0;
- else if (*p == L'S') guess_mode=0;
- else if (*p == L's') guess_mode=1;
- else if (*p == L'r') recurse=0;
- else if (*p == L'g') guess_mode=2;
- p++;
- }
- p++;
- }
- ScanFolder(p, recurse, use_metadata, guess_mode, scan_cancel, 0);
- p+=wcslen(p)+1;
- }
- free(s);
- }
- /* Remove missing files */
- if (!ScanCancelled(events, 2) && g_config->ReadInt(L"bgrescan_compact",1))
- {
- EnterCriticalSection(&g_db_cs);
- nde_scanner_t scanner = NDE_Table_CreateScanner(g_table);
- NDE_Scanner_Query(scanner, L"");
- NDE_Scanner_First(scanner);
- again:
- nde_field_t f=NDE_Scanner_GetFieldByID(scanner, MAINTABLE_ID_FILENAME);
- wchar_t *gs=0;
- if (f)
- {
- gs = NDE_StringField_GetString(f);
- ndestring_retain(gs);
- if (GetFileAttributesW(gs) != INVALID_FILE_ATTRIBUTES)
- {
- NDE_Scanner_Next(scanner);
- }
- else
- {
- // Issue wasabi callback for pre removal
- WASABI_API_SYSCB->syscb_issueCallback(api_mldb::SYSCALLBACK, api_mldb::MLDB_FILE_REMOVED_PRE, (size_t)gs, 0);
-
- NDE_Scanner_Delete(scanner);
- NDE_Scanner_Post(scanner);
- // Issue wasabi callback for pre removal
- WASABI_API_SYSCB->syscb_issueCallback(api_mldb::SYSCALLBACK, api_mldb::MLDB_FILE_REMOVED_POST, (size_t)gs, 0);
- }
- }
- LeaveCriticalSection(&g_db_cs);
- if (f) // done checking for unused files
- {
- if (IsWindow(g_bgrescan_status_hwnd))
- {
- wchar_t b[150+MAX_PATH] = {0};
- WASABI_API_LNGSTRINGW_BUF(IDS_CHECKING_FOR_FILE, b, 150);
- StringCbCatW(b, sizeof(b), PathFindFileNameW(gs));
- SetWindowTextW(g_bgrescan_status_hwnd,b);
- }
- ndestring_release(gs);
- gs=0;
- if (!ScanCancelled(events, 2))
- {
- EnterCriticalSection(&g_db_cs);
- goto again;
- }
- }
- EnterCriticalSection(&g_db_cs);
- NDE_Table_DestroyScanner(g_table, scanner);
- LeaveCriticalSection(&g_db_cs);
- if (IsWindow(g_bgrescan_status_hwnd))
- {
- wchar_t b[150] = {0};
- WASABI_API_LNGSTRINGW_BUF(IDS_COMPACTING, b, 150);
- SetWindowTextW(g_bgrescan_status_hwnd,b);
- }
- }
- // TODO: hmmm, safe to do on separate thread?
- EnterCriticalSection(&g_db_cs);
- if (!ScanCancelled(events, 2))
- {
- wchar_t *last_query = NULL;
- if (m_media_scanner)
- {
- const wchar_t *lq = NDE_Scanner_GetLastQuery(m_media_scanner);
- if (lq) last_query = _wcsdup(lq);
- NDE_Table_DestroyScanner(g_table, m_media_scanner);
- }
- NDE_Table_Sync(g_table); // this is currently b0rk3d -- fucko :)
- NDE_Table_Compact(g_table);
- g_table_dirty=0;
- if (m_media_scanner)
- {
- m_media_scanner=NDE_Table_CreateScanner(g_table);
- if (last_query != NULL)
- {
- NDE_Scanner_Query(m_media_scanner, last_query);
- free(last_query);
- }
- }
- PostMessage(plugin.hwndWinampParent,WM_WA_IPC,NDE_Table_GetRecordsCount(g_table),IPC_STATS_LIBRARY_ITEMCNT);
- }
- else
- {
- NDE_Table_Sync(g_table); // this is currently b0rk3d -- fucko :)
- g_table_dirty=0;
- }
- LeaveCriticalSection(&g_db_cs);
- if (IsWindow(g_bgrescan_status_hwnd))
- SetWindowTextW(g_bgrescan_status_hwnd,L"");
- g_bgscan_last_rescan = time(NULL);
- g_bgscan_scanning = 0;
- }
- void Scan_BackgroundScan()
- {
- if (ScanCreateThread())
- {
- g_bgrescan_force = 0;
- g_bgscan_last_rescan = time(NULL);
- g_bgscan_scanning = 1;
- QueueUserAPC(BackgroundScanAPC, scan_thread, (ULONG_PTR)0);
- }
- }
- static void RemoveFiles(HANDLE cancelswitch, volatile int *found, volatile int *count, volatile int *scanned)
- {
- // TODO: benski> we might need to keep the database lock the whole time. need to think it thru
- EnterCriticalSection(&g_db_cs);
- nde_scanner_t myscanner=NDE_Table_CreateScanner(g_table);
- NDE_Scanner_Query(myscanner, L"");
- NDE_Scanner_First(myscanner);
- *found=0;
- *scanned=0;
- *count=NDE_Table_GetRecordsCount(g_table);
- LeaveCriticalSection(&g_db_cs);
- HANDLE events[2] = { scan_killswitch, cancelswitch};
- bool fileRemoved = false;
- wchar_t *filename;
- while (!ScanCancelled(events, 2))
- {
- EnterCriticalSection(&g_db_cs);
- if (!NDE_Scanner_BOF(myscanner) && !NDE_Scanner_EOF(myscanner))
- {
- nde_field_t f= NDE_Scanner_GetFieldByID(myscanner, MAINTABLE_ID_FILENAME);
- if (f)
- {
- (*scanned)++;
- filename = (NDE_StringField_GetString(f));
- if (GetFileAttributesW(NDE_StringField_GetString(f)) != INVALID_FILE_ATTRIBUTES)
- {
- NDE_Scanner_Next(myscanner);
- }
- else
- {
- // Issue wasabi callback for pre removal
- WASABI_API_SYSCB->syscb_issueCallback(api_mldb::SYSCALLBACK, api_mldb::MLDB_FILE_REMOVED_PRE, (size_t)filename, 0);
- //remove file
- NDE_Scanner_Delete(myscanner);
- NDE_Scanner_Post(myscanner);
- (*found)++;
- fileRemoved = true;
- }
- }
- else
- {
- //remove file
- NDE_Scanner_Delete(myscanner);
- NDE_Scanner_Post(myscanner);
- (*found)++;
- fileRemoved = false;
- }
- }
- else // last file
- {
- LeaveCriticalSection(&g_db_cs);
- break;
- }
- LeaveCriticalSection(&g_db_cs);
- if (fileRemoved)
- {
- // Issue wasabi callback for pre removal
- WASABI_API_SYSCB->syscb_issueCallback(api_mldb::SYSCALLBACK, api_mldb::MLDB_FILE_REMOVED_POST, (size_t)filename, 0);
- fileRemoved = false;
- }
- }
- EnterCriticalSection(&g_db_cs);
- NDE_Table_DestroyScanner(g_table, myscanner); // important that we delete the scanner BEFORE
- myscanner=0;
- wchar_t *last_query = NULL;
- if (m_media_scanner)
- {
- const wchar_t *lq = NDE_Scanner_GetLastQuery(m_media_scanner);
- if (lq) last_query = _wcsdup(lq);
- NDE_Table_DestroyScanner(g_table, m_media_scanner);
- }
- NDE_Table_Sync(g_table); // this is currently b0rk3d -- fucko :)
- NDE_Table_Compact(g_table);
- g_table_dirty=0;
- if (m_media_scanner)
- {
- m_media_scanner=NDE_Table_CreateScanner(g_table);
- if (last_query != NULL)
- {
- NDE_Scanner_Query(m_media_scanner, last_query);
- free(last_query);
- }
- }
- LeaveCriticalSection(&g_db_cs);
- }
- struct RemoveFilesParams
- {
- RemoveFilesParams()
- {
- found = 0;
- scanned = 0;
- total = 0;
- cancel_switch = CreateEvent(NULL, TRUE, FALSE, NULL);
- ui = 0;
- in_timer = 0;
- }
- ~RemoveFilesParams()
- {
- CloseHandle(cancel_switch);
- }
- volatile int found;
- volatile int scanned;
- volatile int total;
- int in_timer;
- HANDLE cancel_switch;
- HWND ui;
- };
- static VOID CALLBACK RemoveFilesAPC(ULONG_PTR param)
- {
- RemoveFilesParams *params = (RemoveFilesParams *)param;
- RemoveFiles(params->cancel_switch, ¶ms->found, ¶ms->total, ¶ms->scanned);
- PostMessage(params->ui, WM_APP, 0, 0);
- }
- static INT_PTR CALLBACK RemoveFilesUI(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
- {
- switch(uMsg)
- {
- case WM_INITDIALOG:
- {
- SetWindowTextW(hwndDlg,WASABI_API_LNGSTRINGW(IDS_REMOVING_FILES_NOT_EXISTING));
- SetDlgItemTextW(hwndDlg,IDC_STATUS,WASABI_API_LNGSTRINGW(IDS_INITIALIZING));
- RemoveFilesParams *params = (RemoveFilesParams *)lParam;
- params->ui = hwndDlg;
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
- if (QueueUserAPC(RemoveFilesAPC, scan_thread, (ULONG_PTR)lParam) == 0)
- EndDialog(hwndDlg, 0);
- else
- {
- SendDlgItemMessage(hwndDlg,IDC_PROGRESS1,PBM_SETRANGE,0,MAKELPARAM(0, 100));
- SetTimer(hwndDlg,0x123,300,NULL);
- }
- // show window and restore last position as applicable
- POINT pt = {g_config->ReadInt(L"scan_x", -1), g_config->ReadInt(L"scan_y", -1)};
- if (!windowOffScreen(hwndDlg, pt))
- SetWindowPos(hwndDlg, HWND_TOP, pt.x, pt.y, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOSENDCHANGING);
- }
- break;
- case WM_TIMER:
- {
- RemoveFilesParams *params = (RemoveFilesParams *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
- if (params->in_timer) break;
- params->in_timer++;
- if(params->total)
- {
- wchar_t tmp[512] = {0};
- int perc=(params->scanned*100/(params->total?params->total:1));
- StringCchPrintfW(tmp, 512, WASABI_API_LNGSTRINGW(IDS_SCANNING_X_OF_X_X_REMOVED),params->scanned,params->total,params->found);
- SetDlgItemTextW(hwndDlg,IDC_STATUS,tmp);
- SendDlgItemMessage(hwndDlg,IDC_PROGRESS1,PBM_SETPOS,perc,0);
- }
- params->in_timer--;
- }
- break;
- case WM_APP:
- {
- RemoveFilesParams *params = (RemoveFilesParams *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
- KillTimer(hwndDlg,0x123);
- wchar_t tmp[512] = {0};
- int perc=(params->scanned*100/(params->total?params->total:1));
- StringCchPrintfW(tmp, 512, WASABI_API_LNGSTRINGW(IDS_SCANNED_X_FILES_X_REMOVED),params->total,params->found);
- SetDlgItemTextW(hwndDlg,IDC_STATUS,tmp);
- SendDlgItemMessage(hwndDlg,IDC_PROGRESS1,PBM_SETPOS,perc,0);
- SyncTable();
- EndDialog(hwndDlg,0);
- }
- break;
- case WM_COMMAND:
- if (LOWORD(wParam)==IDCANCEL)
- {
- RemoveFilesParams *params = (RemoveFilesParams *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
- SetEvent(params->cancel_switch);
- }
- break;
-
- case WM_DESTROY:
- {
- RECT scan_rect = {0};
- GetWindowRect(hwndDlg, &scan_rect);
- g_config->WriteInt(L"scan_x", scan_rect.left);
- g_config->WriteInt(L"scan_y", scan_rect.top);
- KillTimer(hwndDlg,0x123);
- RemoveFilesParams *params = (RemoveFilesParams *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
- delete params;
- }
- return FALSE;
- }
- return FALSE;
- }
- void Scan_RemoveFiles(HWND parent)
- {
- openDb();
- if (g_table && ScanCreateThread())
- {
- RemoveFilesParams *params = new RemoveFilesParams();
- WASABI_API_LNG->LDialogBoxParamW(WASABI_API_LNG->FindDllHandleByGUID(WinampLangGUID),
- GetModuleHandleW(L"winamp.exe"), IDD_ADDSTUFF,
- parent, (DLGPROC)RemoveFilesUI, (LPARAM)params);
- PostMessage(plugin.hwndWinampParent,WM_WA_IPC,NDE_Table_GetRecordsCount(g_table),IPC_STATS_LIBRARY_ITEMCNT);
- }
- }
|