Felix Arends | 8002aa7 | 2002-04-27 17:10:15 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
| 10 | * Copyright (C) 2002 by Felix Arends |
| 11 | * |
| 12 | * All files in this archive are subject to the GNU General Public License. |
| 13 | * See the file COPYING in the source tree root for full license agreement. |
| 14 | * |
| 15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 16 | * KIND, either express or implied. |
| 17 | * |
| 18 | ****************************************************************************/ |
| 19 | |
| 20 | #include <windows.h> |
| 21 | #include <process.h> |
| 22 | #include "uisw32.h" |
| 23 | #include "resource.h" |
Felix Arends | 664b2f7 | 2002-04-30 21:15:02 +0000 | [diff] [blame] | 24 | #include "button.h" |
Felix Arends | 0053ec0 | 2002-06-12 15:39:39 +0000 | [diff] [blame] | 25 | #include "thread.h" |
| 26 | #include "thread-win32.h" |
Felix Arends | 0707946 | 2002-06-15 10:58:14 +0000 | [diff] [blame] | 27 | #include "kernel.h" |
Felix Arends | 8002aa7 | 2002-04-27 17:10:15 +0000 | [diff] [blame] | 28 | |
Daniel Stenberg | 714d6ff | 2002-08-02 12:17:54 +0000 | [diff] [blame] | 29 | #ifndef LR_VGACOLOR /* Should be under MINGW32 builds? */ |
| 30 | #define LR_VGACOLOR LR_COLOR |
| 31 | #endif |
| 32 | |
Felix Arends | 8002aa7 | 2002-04-27 17:10:15 +0000 | [diff] [blame] | 33 | // extern functions |
Felix Arends | 664b2f7 | 2002-04-30 21:15:02 +0000 | [diff] [blame] | 34 | extern void app_main (void *); // mod entry point |
| 35 | extern void new_key(int key); |
Felix Arends | 8002aa7 | 2002-04-27 17:10:15 +0000 | [diff] [blame] | 36 | |
| 37 | // variables |
| 38 | HWND hGUIWnd; // the GUI window handle |
| 39 | unsigned int uThreadID; // id of mod thread |
| 40 | PBYTE lpKeys; |
Felix Arends | 647661c | 2002-06-01 20:56:38 +0000 | [diff] [blame] | 41 | bool bActive; // window active? |
Felix Arends | 0053ec0 | 2002-06-12 15:39:39 +0000 | [diff] [blame] | 42 | HANDLE hGUIThread; // thread for GUI |
Felix Arends | 8002aa7 | 2002-04-27 17:10:15 +0000 | [diff] [blame] | 43 | |
| 44 | // GUIWndProc |
| 45 | // window proc for GUI simulator |
| 46 | LRESULT GUIWndProc ( |
| 47 | HWND hWnd, |
| 48 | UINT uMsg, |
| 49 | WPARAM wParam, |
| 50 | LPARAM lParam |
| 51 | ) |
| 52 | { |
| 53 | static HBITMAP hBkgnd; |
Felix Arends | 8002aa7 | 2002-04-27 17:10:15 +0000 | [diff] [blame] | 54 | static HDC hMemDc; |
| 55 | |
| 56 | switch (uMsg) |
| 57 | { |
Felix Arends | 0707946 | 2002-06-15 10:58:14 +0000 | [diff] [blame] | 58 | case WM_TIMER: |
| 59 | current_tick++; |
| 60 | return TRUE; |
Felix Arends | 647661c | 2002-06-01 20:56:38 +0000 | [diff] [blame] | 61 | case WM_ACTIVATE: |
| 62 | if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE) |
| 63 | bActive = true; |
| 64 | else |
| 65 | bActive = false; |
| 66 | return TRUE; |
Felix Arends | 8002aa7 | 2002-04-27 17:10:15 +0000 | [diff] [blame] | 67 | case WM_CREATE: |
Felix Arends | 0707946 | 2002-06-15 10:58:14 +0000 | [diff] [blame] | 68 | SetTimer (hWnd, TIMER_EVENT, 50, NULL); |
Felix Arends | 8002aa7 | 2002-04-27 17:10:15 +0000 | [diff] [blame] | 69 | // load background image |
| 70 | hBkgnd = (HBITMAP)LoadImage (GetModuleHandle (NULL), MAKEINTRESOURCE(IDB_UI), |
Felix Arends | 175ac89 | 2002-05-29 16:34:40 +0000 | [diff] [blame] | 71 | IMAGE_BITMAP, 0, 0, LR_VGACOLOR); |
Felix Arends | 8002aa7 | 2002-04-27 17:10:15 +0000 | [diff] [blame] | 72 | hMemDc = CreateCompatibleDC (GetDC (hWnd)); |
| 73 | SelectObject (hMemDc, hBkgnd); |
| 74 | return TRUE; |
| 75 | case WM_SIZING: |
| 76 | { |
| 77 | LPRECT r = (LPRECT)lParam; |
| 78 | RECT r2; |
| 79 | char s[256]; |
| 80 | int v; |
| 81 | |
| 82 | switch (wParam) |
| 83 | { |
| 84 | case WMSZ_BOTTOM: |
| 85 | v = (r->bottom - r->top) / (UI_HEIGHT / 5); |
| 86 | r->bottom = r->top + v * UI_HEIGHT / 5; |
| 87 | r->right = r->left + v * UI_WIDTH / 5; |
| 88 | r->right += GetSystemMetrics (SM_CXSIZEFRAME) * 2; |
| 89 | r->bottom += GetSystemMetrics (SM_CYSIZEFRAME) * 2 + GetSystemMetrics (SM_CYSMCAPTION); |
| 90 | break; |
| 91 | case WMSZ_RIGHT: |
| 92 | v = (r->right - r->left) / (UI_WIDTH / 5); |
| 93 | r->bottom = r->top + v * UI_HEIGHT / 5; |
| 94 | r->right = r->left + v * UI_WIDTH / 5; |
| 95 | r->right += GetSystemMetrics (SM_CXSIZEFRAME) * 2; |
| 96 | r->bottom += GetSystemMetrics (SM_CYSIZEFRAME) * 2 + GetSystemMetrics (SM_CYSMCAPTION); |
| 97 | break; |
| 98 | case WMSZ_TOP: |
| 99 | v = (r->bottom - r->top) / (UI_HEIGHT / 5); |
| 100 | r->top = r->bottom - v * UI_HEIGHT / 5; |
| 101 | r->right = r->left + v * UI_WIDTH / 5; |
| 102 | r->right += GetSystemMetrics (SM_CXSIZEFRAME) * 2; |
| 103 | r->top -= GetSystemMetrics (SM_CYSIZEFRAME) * 2 + GetSystemMetrics (SM_CYSMCAPTION); |
| 104 | break; |
| 105 | case WMSZ_LEFT: |
| 106 | v = (r->right - r->left) / (UI_WIDTH / 5); |
| 107 | r->bottom = r->top + v * UI_HEIGHT / 5; |
| 108 | r->left = r->right - v * UI_WIDTH / 5; |
| 109 | r->left -= GetSystemMetrics (SM_CXSIZEFRAME) * 2; |
| 110 | r->bottom += GetSystemMetrics (SM_CYSIZEFRAME) * 2 + GetSystemMetrics (SM_CYSMCAPTION); |
| 111 | break; |
| 112 | case WMSZ_BOTTOMRIGHT: |
| 113 | GetWindowRect (hWnd, &r2); |
| 114 | if (abs(r2.right - r->right) > abs(r2.bottom - r->bottom)) |
| 115 | v = (r->right - r->left) / (UI_WIDTH / 5); |
| 116 | else |
| 117 | v = (r->bottom - r->top) / (UI_HEIGHT / 5); |
| 118 | r->bottom = r->top + v * UI_HEIGHT / 5; |
| 119 | r->right = r->left + v * UI_WIDTH / 5; |
| 120 | r->right += GetSystemMetrics (SM_CXSIZEFRAME) * 2; |
| 121 | r->bottom += GetSystemMetrics (SM_CYSIZEFRAME) * 2 + GetSystemMetrics (SM_CYSMCAPTION); |
| 122 | break; |
| 123 | case WMSZ_BOTTOMLEFT: |
| 124 | GetWindowRect (hWnd, &r2); |
| 125 | if (abs(r2.left - r->left) > abs(r2.bottom - r->bottom)) |
| 126 | v = (r->right - r->left) / (UI_WIDTH / 5); |
| 127 | else |
| 128 | v = (r->bottom - r->top) / (UI_HEIGHT / 5); |
| 129 | r->bottom = r->top + v * UI_HEIGHT / 5; |
| 130 | r->left = r->right - v * UI_WIDTH / 5; |
| 131 | r->left -= GetSystemMetrics (SM_CXSIZEFRAME) * 2; |
| 132 | r->bottom += GetSystemMetrics (SM_CYSIZEFRAME) * 2 + GetSystemMetrics (SM_CYSMCAPTION); |
| 133 | break; |
| 134 | case WMSZ_TOPRIGHT: |
| 135 | GetWindowRect (hWnd, &r2); |
| 136 | if (abs(r2.right - r->right) > abs(r2.top - r->top)) |
| 137 | v = (r->right - r->left) / (UI_WIDTH / 5); |
| 138 | else |
| 139 | v = (r->bottom - r->top) / (UI_HEIGHT / 5); |
| 140 | r->top = r->bottom - v * UI_HEIGHT / 5; |
| 141 | r->right = r->left + v * UI_WIDTH / 5; |
| 142 | r->right += GetSystemMetrics (SM_CXSIZEFRAME) * 2; |
| 143 | r->top -= GetSystemMetrics (SM_CYSIZEFRAME) * 2 + GetSystemMetrics (SM_CYSMCAPTION); |
| 144 | break; |
| 145 | case WMSZ_TOPLEFT: |
| 146 | GetWindowRect (hWnd, &r2); |
| 147 | if (abs(r2.left - r->left) > abs(r2.top - r->top)) |
| 148 | v = (r->right - r->left) / (UI_WIDTH / 5); |
| 149 | else |
| 150 | v = (r->bottom - r->top) / (UI_HEIGHT / 5); |
| 151 | r->top = r->bottom - v * UI_HEIGHT / 5; |
| 152 | r->left = r->right - v * UI_WIDTH / 5; |
| 153 | r->left -= GetSystemMetrics (SM_CXSIZEFRAME) * 2; |
| 154 | r->top -= GetSystemMetrics (SM_CYSIZEFRAME) * 2 + GetSystemMetrics (SM_CYSMCAPTION); |
| 155 | break; |
| 156 | } |
| 157 | |
| 158 | wsprintf (s, "RockBox Simulator @%d%%", |
| 159 | (r->right - r->left - GetSystemMetrics (SM_CXSIZEFRAME) * 2) |
| 160 | * 100 / UI_WIDTH); |
| 161 | SetWindowText (hWnd, s); |
| 162 | |
| 163 | return TRUE; |
| 164 | } |
| 165 | case WM_ERASEBKGND: |
| 166 | { |
| 167 | PAINTSTRUCT ps; |
| 168 | HDC hDc = BeginPaint (hWnd, &ps); |
| 169 | RECT r; |
| 170 | |
| 171 | GetClientRect (hWnd, &r); |
| 172 | // blit to screen |
| 173 | StretchBlt (hDc, 0, 0, r.right, r.bottom, |
| 174 | hMemDc, 0, 0, UI_WIDTH, UI_HEIGHT, SRCCOPY); |
| 175 | EndPaint (hWnd, &ps); |
| 176 | return TRUE; |
| 177 | } |
| 178 | case WM_PAINT: |
| 179 | { |
| 180 | PAINTSTRUCT ps; |
| 181 | RECT r; |
| 182 | HDC hDc = BeginPaint (hWnd, &ps); |
| 183 | |
| 184 | GetClientRect (hWnd, &r); |
| 185 | // draw lcd screen |
| 186 | StretchDIBits (hDc, |
| 187 | UI_LCD_POSX * r.right / UI_WIDTH, UI_LCD_POSY * r.bottom / UI_HEIGHT, |
| 188 | LCD_WIDTH * r.right / UI_WIDTH, LCD_HEIGHT * r.bottom / UI_HEIGHT, |
| 189 | 0, 0, LCD_WIDTH, LCD_HEIGHT, |
| 190 | bitmap, (BITMAPINFO *) &bmi, DIB_RGB_COLORS, SRCCOPY); |
| 191 | |
| 192 | EndPaint (hWnd, &ps); |
| 193 | return TRUE; |
| 194 | } |
| 195 | case WM_CLOSE: |
| 196 | // close simulator |
Felix Arends | 0707946 | 2002-06-15 10:58:14 +0000 | [diff] [blame] | 197 | KillTimer (hWnd, TIMER_EVENT); |
Felix Arends | 8002aa7 | 2002-04-27 17:10:15 +0000 | [diff] [blame] | 198 | hGUIWnd = NULL; |
| 199 | PostQuitMessage (0); |
| 200 | break; |
Felix Arends | 0053ec0 | 2002-06-12 15:39:39 +0000 | [diff] [blame] | 201 | case WM_DESTROY: |
| 202 | // close simulator |
| 203 | hGUIWnd = NULL; |
| 204 | PostQuitMessage (0); |
| 205 | break; |
Felix Arends | 8002aa7 | 2002-04-27 17:10:15 +0000 | [diff] [blame] | 206 | } |
| 207 | |
| 208 | return DefWindowProc (hWnd, uMsg, wParam, lParam); |
| 209 | } |
| 210 | |
| 211 | // GUIStartup |
| 212 | // register window class, show window, init GUI |
| 213 | BOOL GUIStartup () |
| 214 | { |
| 215 | WNDCLASS wc; |
| 216 | |
| 217 | // create window class |
| 218 | ZeroMemory (&wc, sizeof(wc)); |
| 219 | wc.hbrBackground = GetSysColorBrush (COLOR_WINDOW); |
| 220 | wc.hCursor = LoadCursor (NULL, IDC_ARROW); |
| 221 | wc.hInstance = GetModuleHandle (NULL); |
| 222 | wc.lpfnWndProc = (WNDPROC)GUIWndProc; |
| 223 | wc.lpszClassName = "RockBoxUISimulator"; |
| 224 | wc.style = CS_HREDRAW | CS_VREDRAW; |
| 225 | |
| 226 | if (RegisterClass (&wc) == 0) |
| 227 | return FALSE; |
| 228 | |
| 229 | // create window |
| 230 | hGUIWnd = CreateWindowEx ( |
| 231 | WS_EX_TOOLWINDOW | WS_EX_PALETTEWINDOW, |
| 232 | "RockBoxUISimulator", "ARCHOS JukeBox", |
| 233 | WS_VISIBLE | WS_SYSMENU | WS_OVERLAPPEDWINDOW, |
| 234 | CW_USEDEFAULT, CW_USEDEFAULT, |
| 235 | UI_WIDTH + GetSystemMetrics (SM_CXSIZEFRAME) * 2, |
| 236 | UI_HEIGHT + GetSystemMetrics (SM_CYSIZEFRAME) * 2 + GetSystemMetrics (SM_CYSMCAPTION), |
| 237 | NULL, NULL, GetModuleHandle (NULL), NULL); |
| 238 | |
| 239 | if (hGUIWnd == NULL) |
| 240 | return FALSE; |
| 241 | |
| 242 | return TRUE; |
| 243 | } |
| 244 | |
| 245 | // GUIDown |
| 246 | // destroy window, unregister window class |
| 247 | int GUIDown () |
| 248 | { |
Felix Arends | 0053ec0 | 2002-06-12 15:39:39 +0000 | [diff] [blame] | 249 | int i; |
| 250 | |
Felix Arends | 8002aa7 | 2002-04-27 17:10:15 +0000 | [diff] [blame] | 251 | DestroyWindow (hGUIWnd); |
Felix Arends | 0053ec0 | 2002-06-12 15:39:39 +0000 | [diff] [blame] | 252 | CloseHandle (hGUIThread); |
| 253 | for (i = 0; i < nThreads; i++) |
| 254 | { |
| 255 | ResumeThread (lpThreads[i]); |
| 256 | WaitForSingleObject (lpThreads[i], 1); |
| 257 | CloseHandle (lpThreads[i]); |
| 258 | } |
Felix Arends | 8002aa7 | 2002-04-27 17:10:15 +0000 | [diff] [blame] | 259 | return 0; |
| 260 | } |
| 261 | |
| 262 | // GUIMessageLoop |
| 263 | // standard message loop for GUI window |
| 264 | void GUIMessageLoop () |
| 265 | { |
| 266 | MSG msg; |
Felix Arends | 0053ec0 | 2002-06-12 15:39:39 +0000 | [diff] [blame] | 267 | while (GetMessage (&msg, NULL, 0, 0)) |
Felix Arends | 8002aa7 | 2002-04-27 17:10:15 +0000 | [diff] [blame] | 268 | { |
| 269 | TranslateMessage (&msg); |
| 270 | DispatchMessage (&msg); |
Felix Arends | 0053ec0 | 2002-06-12 15:39:39 +0000 | [diff] [blame] | 271 | if (msg.message == TM_YIELD) |
| 272 | { |
| 273 | SuspendThread (lpThreads[nPos]); |
| 274 | if (++nPos >= nThreads) |
| 275 | nPos = 0; |
| 276 | ResumeThread (lpThreads[nPos]); |
| 277 | } |
Felix Arends | 8002aa7 | 2002-04-27 17:10:15 +0000 | [diff] [blame] | 278 | } |
| 279 | } |
| 280 | |
| 281 | |
| 282 | // WinMain |
| 283 | // program entry point |
| 284 | int WINAPI WinMain ( |
| 285 | HINSTANCE hInstance, // current instance |
| 286 | HINSTANCE hPrevInstance, // previous instance |
| 287 | LPSTR lpCmd, // command line |
| 288 | int nShowCmd // show command |
| 289 | ) |
| 290 | { |
Felix Arends | 0053ec0 | 2002-06-12 15:39:39 +0000 | [diff] [blame] | 291 | DWORD dwThreadID; |
Daniel Stenberg | a32af77 | 2002-08-02 14:00:52 +0000 | [diff] [blame] | 292 | |
| 293 | (void)hInstance; |
| 294 | (void)hPrevInstance; |
| 295 | (void)lpCmd; |
| 296 | (void)nShowCmd; |
| 297 | |
Felix Arends | 8002aa7 | 2002-04-27 17:10:15 +0000 | [diff] [blame] | 298 | if (!GUIStartup ()) |
| 299 | return 0; |
| 300 | |
Felix Arends | 0053ec0 | 2002-06-12 15:39:39 +0000 | [diff] [blame] | 301 | hGUIThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)app_main, |
| 302 | NULL, 0, &dwThreadID); |
| 303 | |
| 304 | if (hGUIThread == NULL) |
| 305 | return MessageBox (NULL, "Error creating gui thread!", "Error", MB_OK); |
Felix Arends | 8002aa7 | 2002-04-27 17:10:15 +0000 | [diff] [blame] | 306 | |
| 307 | GUIMessageLoop (); |
| 308 | |
| 309 | return GUIDown (); |
Daniel Stenberg | 714d6ff | 2002-08-02 12:17:54 +0000 | [diff] [blame] | 310 | } |