diff options
Diffstat (limited to 'Src/Plugins/Library/ml_rg/Progress.cpp')
-rw-r--r-- | Src/Plugins/Library/ml_rg/Progress.cpp | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/Src/Plugins/Library/ml_rg/Progress.cpp b/Src/Plugins/Library/ml_rg/Progress.cpp new file mode 100644 index 00000000..18c26031 --- /dev/null +++ b/Src/Plugins/Library/ml_rg/Progress.cpp @@ -0,0 +1,261 @@ +#include "main.h" +#include "resource.h" +#include"api__ml_rg.h" +#include <strsafe.h> + +struct Progress +{ + Progress() + { + processedFiles = 0; + currentBytes = 0; + totalBytes = 0; + activeHWND = 0; + threadHandle = 0; + openDialogs = 0; + done = false; + killSwitch = 0; + } + + size_t processedFiles; + uint64_t currentBytes; + uint32_t totalBytes; + WorkQueue activeQueue; + HWND activeHWND; + HANDLE threadHandle; + size_t openDialogs; + bool done; + int killSwitch; +}; + +DWORD WINAPI ThreadProc(void *param) +{ + Progress *progress = (Progress *)param; + ProgressCallback callback(progress->activeHWND); + progress->activeQueue.Calculate(&callback, &progress->killSwitch); + PostMessage(progress->activeHWND, WM_USER + 2, 0, 0); + + return 0; +} + +void getViewport(RECT *r, HWND wnd, int full, RECT *sr) +{ + POINT *p = NULL; + + if (p || sr || wnd) + { + HMONITOR hm = NULL; + + if (sr) + hm = MonitorFromRect(sr, MONITOR_DEFAULTTONEAREST); + else if (wnd) + hm = MonitorFromWindow(wnd, MONITOR_DEFAULTTONEAREST); + else if (p) + hm = MonitorFromPoint(*p, MONITOR_DEFAULTTONEAREST); + + if (hm) + { + MONITORINFOEXW mi; + memset(&mi, 0, sizeof(mi)); + mi.cbSize = sizeof(mi); + + if (GetMonitorInfoW(hm, &mi)) + { + if (!full) + *r = mi.rcWork; + else + *r = mi.rcMonitor; + + return ; + } + } + } + if (full) + { // this might be borked =) + r->top = r->left = 0; + r->right = GetSystemMetrics(SM_CXSCREEN); + r->bottom = GetSystemMetrics(SM_CYSCREEN); + } + else + { + SystemParametersInfoW(SPI_GETWORKAREA, 0, r, 0); + } +} + +BOOL windowOffScreen(HWND hwnd, POINT pt) +{ + RECT r = {0}, wnd = {0}, sr = {0}; + GetWindowRect(hwnd, &wnd); + sr.left = pt.x; + sr.top = pt.y; + sr.right = sr.left + (wnd.right - wnd.left); + sr.bottom = sr.top + (wnd.bottom - wnd.top); + getViewport(&r, hwnd, 0, &sr); + return !PtInRect(&r, pt); +} + +void SaveWindowPos(HWND hwnd) +{ + RECT rect = {0}; + GetWindowRect(hwnd, &rect); + char buf[16] = {0}; + StringCchPrintfA(buf, 16, "%d", rect.left); + WritePrivateProfileStringA("ml_rg", "prog_x", buf, iniFile); + StringCchPrintfA(buf, 16, "%d", rect.top); + WritePrivateProfileStringA("ml_rg", "prog_y", buf, iniFile); +} + +INT_PTR WINAPI ReplayGainProgressProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_INITDIALOG: + { + Progress *progress = (Progress *)lParam; + progress->killSwitch = 0; + progress->done = false; + progress->openDialogs = 0; + progress->processedFiles = 0; + progress->activeHWND = hwndDlg; + + wchar_t dummy[64] = {0}; + StringCchPrintfW(dummy, 64, WASABI_API_LNGSTRINGW(IDS_1_OF_X_FILES), progress->activeQueue.totalFiles); + SetDlgItemTextW(hwndDlg, IDC_PROGRESS_FILES, dummy); + + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)progress); + DWORD threadId; + progress->threadHandle = CreateThread(NULL, 0, ThreadProc, (void *)progress, CREATE_SUSPENDED, &threadId); + SetThreadPriority(progress->threadHandle, THREAD_PRIORITY_IDLE); + ResumeThread(progress->threadHandle); + + POINT pt = {(LONG)GetPrivateProfileIntA("ml_rg", "prog_x", -1, iniFile), + (LONG)GetPrivateProfileIntA("ml_rg", "prog_y", -1, iniFile)}; + if (!windowOffScreen(hwndDlg, pt)) + SetWindowPos(hwndDlg, HWND_TOP, pt.x, pt.y, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOSENDCHANGING); + else + ShowWindow(hwndDlg, SW_SHOW); + } + break; + case WM_DESTROY: + { + SaveWindowPos(hwndDlg); + Progress *progress = (Progress *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + CloseHandle(progress->threadHandle); + progress->activeHWND = 0; + delete progress; + } + break; + case WM_USER: // file finished + { + Progress *progress = (Progress *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + progress->processedFiles++; + + if (progress->processedFiles + 1 > progress->activeQueue.totalFiles) + SetDlgItemTextW(hwndDlg, IDC_PROGRESS_FILES, WASABI_API_LNGSTRINGW(IDS_FINISHED)); + else + { + wchar_t dummy[64] = {0}; + StringCchPrintfW(dummy, 64, + WASABI_API_LNGSTRINGW(IDS_X_OF_X_FILES), + progress->processedFiles + 1, progress->activeQueue.totalFiles); + SetDlgItemTextW(hwndDlg, IDC_PROGRESS_FILES, dummy); + } + } + break; + case WM_USER + 1: // album done + { + Progress *progress = (Progress *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + WorkQueue::RGWorkQueue *queue = (WorkQueue::RGWorkQueue *)lParam; + SaveWindowPos(hwndDlg); + if (config_ask && config_ask_each_album) + { + progress->openDialogs++; + DoResults(*queue); + progress->openDialogs--; + if (!progress->openDialogs && progress->done) + DestroyWindow(hwndDlg); + } + else if (config_ask == 0) + { + WriteAlbum(*queue); + } + } + break; + case WM_USER + 2: // all tracks done + { + Progress *progress = (Progress *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + ShowWindow(hwndDlg, SW_HIDE); + SaveWindowPos(hwndDlg); + if (config_ask && config_ask_each_album == 0) + { + DoResults(progress->activeQueue); + } + progress->killSwitch = 1; + WaitForSingleObject(progress->threadHandle, INFINITE); + progress->done = true; + if (!progress->openDialogs) + DestroyWindow(hwndDlg); + } + break; + case WM_USER + 3: // total bytes of current file + { + Progress *progress = (Progress *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + progress->currentBytes = 0; + progress->totalBytes = (uint32_t)lParam; + if (progress->totalBytes == 0) + { + SetDlgItemTextW(hwndDlg, IDC_FILE_PROGRESS, WASABI_API_LNGSTRINGW(IDS_PROCESSING)); + } + else + { + wchar_t dummy[64] = {0}; + StringCchPrintfW(dummy, 64, L"%u%%", (progress->currentBytes * 100) / progress->totalBytes); + SetDlgItemTextW(hwndDlg, IDC_FILE_PROGRESS, dummy); + } + } + break; + case WM_USER + 4: // more bytes read + { + Progress *progress = (Progress *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + progress->currentBytes += lParam; + if (progress->totalBytes == 0) + { + SetDlgItemTextW(hwndDlg, IDC_FILE_PROGRESS, WASABI_API_LNGSTRINGW(IDS_PROCESSING)); + } + else + { + wchar_t dummy[64] = {0}; + StringCchPrintfW(dummy, 64, L"%u%%", (progress->currentBytes * 100) / progress->totalBytes); + SetDlgItemTextW(hwndDlg, IDC_FILE_PROGRESS, dummy); + } + } + break; + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDCANCEL: + { + Progress *progress = (Progress *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + progress->killSwitch = 1; + break; + } + } + break; + } + return 0; +} + +void DoProgress(WorkQueue &workQueue) +{ + Progress *progress = new Progress; + progress->activeQueue = workQueue; // this is a huge slow copy, but I don't care at the moment + WASABI_API_CREATEDIALOGPARAMW(IDD_PROGRESS, GetDialogBoxParent(), ReplayGainProgressProc, (LPARAM)progress); +} + +HWND GetDialogBoxParent() +{ + HWND parent = (HWND)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_GETDIALOGBOXPARENT); + if (!parent || parent == (HWND)1) + return plugin.hwndWinampParent; + return parent; +}
\ No newline at end of file |