/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2002 by Felix Arends * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include #include #include #include #include "uisw32.h" #include "resource.h" #include "button.h" #include "thread.h" #include "thread-win32.h" #include "kernel.h" #ifndef LR_VGACOLOR /* Should be under MINGW32 builds? */ #define LR_VGACOLOR LR_COLOR #endif // extern functions extern void app_main (void *); // mod entry point extern void new_key(int key); void button_event(int key, bool pressed); // variables HWND hGUIWnd; // the GUI window handle unsigned int uThreadID; // id of mod thread PBYTE lpKeys; bool bActive; // window active? HANDLE hGUIThread; // thread for GUI bool lcd_display_redraw=true; // Used for player simulator char having_new_lcd=true; // Used for player simulator // GUIWndProc // window proc for GUI simulator LRESULT CALLBACK GUIWndProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { static HBITMAP hBkgnd; static HDC hMemDc; switch (uMsg) { case WM_TIMER: current_tick++; return TRUE; case WM_ACTIVATE: if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE) bActive = true; else bActive = false; return TRUE; case WM_CREATE: SetTimer (hWnd, TIMER_EVENT, 50, NULL); // load background image hBkgnd = (HBITMAP)LoadImage (GetModuleHandle (NULL), MAKEINTRESOURCE(IDB_UI), IMAGE_BITMAP, 0, 0, LR_VGACOLOR); hMemDc = CreateCompatibleDC (GetDC (hWnd)); SelectObject (hMemDc, hBkgnd); return TRUE; case WM_SIZING: { LPRECT r = (LPRECT)lParam; RECT r2; char s[256]; int v; switch (wParam) { case WMSZ_BOTTOM: v = (r->bottom - r->top) / (UI_HEIGHT / 5); r->bottom = r->top + v * UI_HEIGHT / 5; r->right = r->left + v * UI_WIDTH / 5; r->right += GetSystemMetrics (SM_CXSIZEFRAME) * 2; r->bottom += GetSystemMetrics (SM_CYSIZEFRAME) * 2 + GetSystemMetrics (SM_CYSMCAPTION); break; case WMSZ_RIGHT: v = (r->right - r->left) / (UI_WIDTH / 5); r->bottom = r->top + v * UI_HEIGHT / 5; r->right = r->left + v * UI_WIDTH / 5; r->right += GetSystemMetrics (SM_CXSIZEFRAME) * 2; r->bottom += GetSystemMetrics (SM_CYSIZEFRAME) * 2 + GetSystemMetrics (SM_CYSMCAPTION); break; case WMSZ_TOP: v = (r->bottom - r->top) / (UI_HEIGHT / 5); r->top = r->bottom - v * UI_HEIGHT / 5; r->right = r->left + v * UI_WIDTH / 5; r->right += GetSystemMetrics (SM_CXSIZEFRAME) * 2; r->top -= GetSystemMetrics (SM_CYSIZEFRAME) * 2 + GetSystemMetrics (SM_CYSMCAPTION); break; case WMSZ_LEFT: v = (r->right - r->left) / (UI_WIDTH / 5); r->bottom = r->top + v * UI_HEIGHT / 5; r->left = r->right - v * UI_WIDTH / 5; r->left -= GetSystemMetrics (SM_CXSIZEFRAME) * 2; r->bottom += GetSystemMetrics (SM_CYSIZEFRAME) * 2 + GetSystemMetrics (SM_CYSMCAPTION); break; case WMSZ_BOTTOMRIGHT: GetWindowRect (hWnd, &r2); if (abs(r2.right - r->right) > abs(r2.bottom - r->bottom)) v = (r->right - r->left) / (UI_WIDTH / 5); else v = (r->bottom - r->top) / (UI_HEIGHT / 5); r->bottom = r->top + v * UI_HEIGHT / 5; r->right = r->left + v * UI_WIDTH / 5; r->right += GetSystemMetrics (SM_CXSIZEFRAME) * 2; r->bottom += GetSystemMetrics (SM_CYSIZEFRAME) * 2 + GetSystemMetrics (SM_CYSMCAPTION); break; case WMSZ_BOTTOMLEFT: GetWindowRect (hWnd, &r2); if (abs(r2.left - r->left) > abs(r2.bottom - r->bottom)) v = (r->right - r->left) / (UI_WIDTH / 5); else v = (r->bottom - r->top) / (UI_HEIGHT / 5); r->bottom = r->top + v * UI_HEIGHT / 5; r->left = r->right - v * UI_WIDTH / 5; r->left -= GetSystemMetrics (SM_CXSIZEFRAME) * 2; r->bottom += GetSystemMetrics (SM_CYSIZEFRAME) * 2 + GetSystemMetrics (SM_CYSMCAPTION); break; case WMSZ_TOPRIGHT: GetWindowRect (hWnd, &r2); if (abs(r2.right - r->right) > abs(r2.top - r->top)) v = (r->right - r->left) / (UI_WIDTH / 5); else v = (r->bottom - r->top) / (UI_HEIGHT / 5); r->top = r->bottom - v * UI_HEIGHT / 5; r->right = r->left + v * UI_WIDTH / 5; r->right += GetSystemMetrics (SM_CXSIZEFRAME) * 2; r->top -= GetSystemMetrics (SM_CYSIZEFRAME) * 2 + GetSystemMetrics (SM_CYSMCAPTION); break; case WMSZ_TOPLEFT: GetWindowRect (hWnd, &r2); if (abs(r2.left - r->left) > abs(r2.top - r->top)) v = (r->right - r->left) / (UI_WIDTH / 5); else v = (r->bottom - r->top) / (UI_HEIGHT / 5); r->top = r->bottom - v * UI_HEIGHT / 5; r->left = r->right - v * UI_WIDTH / 5; r->left -= GetSystemMetrics (SM_CXSIZEFRAME) * 2; r->top -= GetSystemMetrics (SM_CYSIZEFRAME) * 2 + GetSystemMetrics (SM_CYSMCAPTION); break; } wsprintf (s, "RockBox Simulator @%d%%", (r->right - r->left - GetSystemMetrics (SM_CXSIZEFRAME) * 2) * 100 / UI_WIDTH); SetWindowText (hWnd, s); return TRUE; } case WM_ERASEBKGND: { PAINTSTRUCT ps; HDC hDc = BeginPaint (hWnd, &ps); RECT r; GetClientRect (hWnd, &r); // blit background image to screen StretchBlt (hDc, 0, 0, r.right, r.bottom, hMemDc, 0, 0, UI_WIDTH, UI_HEIGHT, SRCCOPY); EndPaint (hWnd, &ps); return TRUE; } case WM_PAINT: { PAINTSTRUCT ps; RECT r; HDC hDc = BeginPaint (hWnd, &ps); GetClientRect (hWnd, &r); // draw lcd screen StretchDIBits (hDc, UI_LCD_POSX * r.right / UI_WIDTH, UI_LCD_POSY * r.bottom / UI_HEIGHT, UI_LCD_WIDTH * r.right / UI_WIDTH, UI_LCD_HEIGHT * r.bottom / UI_HEIGHT, 0, 0, LCD_WIDTH, LCD_HEIGHT, bitmap, (BITMAPINFO *) &bmi, DIB_RGB_COLORS, SRCCOPY); EndPaint (hWnd, &ps); return TRUE; } case WM_CLOSE: // close simulator KillTimer (hWnd, TIMER_EVENT); hGUIWnd = NULL; PostQuitMessage (0); break; case WM_DESTROY: // close simulator hGUIWnd = NULL; PostQuitMessage (0); break; case WM_KEYDOWN: button_event(wParam, true); break; case WM_KEYUP: button_event(wParam, false); break; } return DefWindowProc (hWnd, uMsg, wParam, lParam); } // GUIStartup // register window class, show window, init GUI BOOL GUIStartup () { WNDCLASS wc; // create window class ZeroMemory (&wc, sizeof(wc)); wc.hbrBackground = GetSysColorBrush (COLOR_WINDOW); wc.hCursor = LoadCursor (NULL, IDC_ARROW); wc.hInstance = GetModuleHandle (NULL); wc.lpfnWndProc = GUIWndProc; wc.lpszClassName = "RockBoxUISimulator"; wc.style = CS_HREDRAW | CS_VREDRAW; if (RegisterClass (&wc) == 0) return FALSE; // create window hGUIWnd = CreateWindowEx ( WS_EX_TOOLWINDOW | WS_EX_OVERLAPPEDWINDOW, "RockBoxUISimulator", "ARCHOS JukeBox", WS_VISIBLE | WS_SYSMENU | WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, UI_WIDTH + GetSystemMetrics (SM_CXSIZEFRAME) * 2, UI_HEIGHT + GetSystemMetrics (SM_CYSIZEFRAME) * 2 + GetSystemMetrics (SM_CYSMCAPTION), NULL, NULL, GetModuleHandle (NULL), NULL); if (hGUIWnd == NULL) return FALSE; return TRUE; } // GUIDown // destroy window, unregister window class int GUIDown () { int i; DestroyWindow (hGUIWnd); CloseHandle (hGUIThread); for (i = 0; i < nThreads; i++) { ResumeThread (lpThreads[i]); WaitForSingleObject (lpThreads[i], 1); CloseHandle (lpThreads[i]); } return 0; } // GUIMessageLoop // standard message loop for GUI window void GUIMessageLoop () { MSG msg; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg); DispatchMessage (&msg); if (msg.message == TM_YIELD) { SuspendThread (lpThreads[nPos]); if (++nPos >= nThreads) nPos = 0; ResumeThread (lpThreads[nPos]); } } } // WinMain // program entry point int WINAPI WinMain ( HINSTANCE hInstance, // current instance HINSTANCE hPrevInstance, // previous instance LPSTR lpCmd, // command line int nShowCmd // show command ) { DWORD dwThreadID; (void)hInstance; (void)hPrevInstance; (void)lpCmd; (void)nShowCmd; /* default file mode should be O_BINARY to be consistent with rockbox */ _fmode = _O_BINARY; if (!GUIStartup ()) return 0; hGUIThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)app_main, NULL, 0, &dwThreadID); if (hGUIThread == NULL) return MessageBox (NULL, "Error creating gui thread!", "Error", MB_OK); GUIMessageLoop (); return GUIDown (); }