Configure needs AS to be set for the Makefiles.
[mplayer/glamo.git] / gui / win32 / gui.c
blobd9d86f58a3c19f0beea985c025bd8a848fde2e0c
1 /*
2 * MPlayer GUI for Win32
3 * Copyright (C) 2003 Sascha Sommer <saschasommer@freenet.de>
4 * Copyright (C) 2006 Erik Augustson <erik_27can@yahoo.com>
5 * Copyright (C) 2006 Gianluigi Tiesi <sherpya@netfarm.it>
7 * This file is part of MPlayer.
9 * MPlayer is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * MPlayer is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <ctype.h>
27 #include <fcntl.h>
28 #include <windows.h>
29 #include <windowsx.h>
30 #include <shlobj.h>
32 #include "version.h"
33 #include "mplayer.h"
34 #include "mp_fifo.h"
35 #include "mp_msg.h"
36 #include "help_mp.h"
37 #include "input/input.h"
38 #include "input/mouse.h"
39 #include "osdep/keycodes.h"
40 #include "stream/stream.h"
41 #include "libvo/video_out.h"
42 #include "gui/interface.h"
43 #include "gui.h"
44 #include "dialogs.h"
46 // HACK around bug in old mingw
47 #undef INVALID_FILE_ATTRIBUTES
48 #define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
50 #ifndef WM_XBUTTONDOWN
51 # define WM_XBUTTONDOWN 0x020B
52 # define WM_XBUTTONUP 0x020C
53 # define WM_XBUTTONDBLCLK 0x020D
54 #endif
56 /* Globals / Externs */
57 void renderinfobox(skin_t *skin, window_priv_t *priv);
58 void renderwidget(skin_t *skin, image *dest, widget *item, int state);
59 void print_version(void);
60 float sub_aspect;
62 DWORD oldtime;
63 NOTIFYICONDATA nid;
64 int console_state = 0;
65 play_tree_t *playtree = NULL;
67 static HBRUSH colorbrush = NULL; //Handle to colorkey brush
68 static COLORREF windowcolor = RGB(255,0,255); //Windowcolor == colorkey
70 void console_toggle(void)
72 if (console_state)
74 FreeConsole();
75 console = 0;
76 console_state = 0;
78 else
80 /* This code comes from: http://dslweb.nwnexus.com/~ast/dload/guicon.htm */
81 CONSOLE_SCREEN_BUFFER_INFO coninfo;
82 FILE *fp;
83 HWND hwnd = NULL;
84 console = 1;
85 AllocConsole();
86 SetConsoleTitle(MP_TITLE);
88 /* disable the close button for now */
89 while (!hwnd)
91 hwnd = FindWindow(NULL, MP_TITLE);
92 Sleep(100);
94 DeleteMenu(GetSystemMenu(hwnd, 0), SC_CLOSE, MF_BYCOMMAND);
96 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
97 coninfo.dwSize.Y = 1000;
98 SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
99 fp = freopen("con", "w", stdout);
100 *stdout = *fp;
101 setvbuf(stdout, NULL, _IONBF, 0);
102 fp = freopen("con", "r", stdin);
103 *stdin = *fp;
104 setvbuf(stdin, NULL, _IONBF, 0);
105 fp = freopen("con", "w", stdout);
106 *stderr = *fp;
107 setvbuf(stderr, NULL, _IONBF, 0);
108 print_version();
109 console_state = 1;
113 void capitalize(char *filename)
115 unsigned int i;
116 BOOL cap = TRUE;
117 for (i=0; i < strlen(filename); i++)
119 if (cap)
121 cap = FALSE;
122 filename[i] = toupper(filename[i]);
124 else if (filename[i] == ' ')
125 cap = TRUE;
126 else
127 filename[i] = tolower(filename[i]);
131 static image *get_drawground(HWND hwnd)
133 gui_t * gui = (gui_t *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
134 unsigned int i;
135 if(!gui) return NULL;
136 for(i=0; i<gui->window_priv_count; i++)
137 if(gui->window_priv[i]->hwnd==hwnd)
138 return &gui->window_priv[i]->img;
139 return NULL;
142 static HBITMAP get_bitmap(HWND hwnd)
144 gui_t *gui = (gui_t *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
145 unsigned int i;
146 if(!gui) return NULL;
147 for(i=0; i<gui->window_priv_count; i++)
148 if(gui->window_priv[i]->hwnd == hwnd)
149 return gui->window_priv[i]->bitmap;
150 return NULL;
153 static int get_windowtype(HWND hwnd)
155 gui_t *gui = (gui_t *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
156 unsigned int i;
157 if(!gui) return -1;
158 for(i=0; i<gui->window_priv_count; i++)
159 if(gui->window_priv[i]->hwnd == hwnd)
160 return gui->window_priv[i]->type;
161 return -1;
164 static void uninit(gui_t *gui)
166 if(gui->skin) destroy_window(gui);
167 if(gui->playlist) gui->playlist->free_playlist(gui->playlist);
168 gui->playlist = NULL;
172 the gui message handler
173 tries to handle the incoming messages
174 and passes them to the player's message handler if it can't handle them
176 static void handlemsg(HWND hWnd, int msg)
178 gui_t *gui = (gui_t *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
179 if(msg == evNone) return;
181 switch(msg)
183 case evLoadPlay:
184 case evLoad:
185 if(display_openfilewindow(gui, 0) && (msg == evLoadPlay))
186 handlemsg(hWnd, evDropFile);
187 return;
188 case evLoadSubtitle:
189 display_opensubtitlewindow(gui);
190 break;
191 case evPreferences:
192 display_prefswindow(gui);
193 return;
194 case evPlayList:
195 display_playlistwindow(gui);
196 return;
197 case evSkinBrowser:
198 display_skinbrowser(gui);
199 break;
200 case evEqualizer:
201 display_eqwindow(gui);
202 break;
203 case evAbout:
204 MessageBox(hWnd, COPYRIGHT, "About", MB_OK);
205 break;
206 case evIconify:
207 ShowWindow(hWnd, SW_MINIMIZE);
208 break;
209 case evIncVolume:
210 mplayer_put_key(KEY_VOLUME_UP);
211 break;
212 case evDecVolume:
213 mplayer_put_key(KEY_VOLUME_DOWN);
214 break;
215 default:
216 mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] received msg %s (%i)\n", gui->skin->geteventname(msg), msg);
217 break;
219 gui->playercontrol(msg);
222 static widget *clickedinsidewidget(gui_t *gui, int window, int x, int y)
224 unsigned int i;
225 widget *item;
226 for(i=0; i<gui->skin->widgetcount; i++)
228 item = gui->skin->widgets[i];
229 if((item->window == window) && (item->x <= x) && (item->x + item->width >= x) &&
230 (item->y <= y) && (item->y + item->height >= y))
231 return item;
233 return NULL;
236 /* updates sliders and the display */
237 static void updatedisplay(gui_t *gui, HWND hwnd)
239 unsigned int i;
240 window_priv_t *priv = NULL;
241 DWORD time = timeGetTime();
243 if(!hwnd) return;
245 /* load all potmeters hpotmeters */
246 for(i=0; i<gui->skin->widgetcount; i++)
248 if(gui->skin->widgets[i]->type == tyHpotmeter || gui->skin->widgets[i]->type == tyPotmeter)
250 if(gui->skin->widgets[i]->msg == evSetVolume)
251 gui->skin->widgets[i]->value = guiIntfStruct.Volume;
252 else if(gui->skin->widgets[i]->msg == evSetMoviePosition)
253 gui->skin->widgets[i]->value = guiIntfStruct.Position;
254 else if(gui->skin->widgets[i]->msg == evSetBalance)
255 gui->skin->widgets[i]->value = guiIntfStruct.Balance;
256 if(gui->skin->widgets[i]->window == get_windowtype(hwnd))
257 renderwidget(gui->skin, get_drawground(hwnd), gui->skin->widgets[i],
258 gui->skin->widgets[i]->pressed ? 0 : 1);
260 /* update some buttons */
261 if(gui->skin->widgets[i]->type == tyButton && gui->skin->widgets[i]->window == get_windowtype(hwnd))
263 if(gui->skin->widgets[i]->msg == evPlaySwitchToPause)
265 gui->skin->widgets[i]->value = guiIntfStruct.Playing;
266 renderwidget(gui->skin, get_drawground(hwnd), gui->skin->widgets[i],
267 guiIntfStruct.Playing == 1 ? 0 : 1);
269 if(gui->skin->widgets[i]->msg == evMute)
271 gui->skin->widgets[i]->value = guiIntfStruct.Volume;
272 renderwidget(gui->skin, get_drawground(hwnd), gui->skin->widgets[i],
273 guiIntfStruct.Volume == 0.0f ? 0 : 1);
278 /* updating the display once a 100.second is enough imo */
279 if((time - oldtime) < 100) return;
280 oldtime=time;
282 /* suppress directx's fullscreen window when using the sub window */
283 if(sub_window && &video_driver_list[0] && strstr("directx", video_driver_list[0]))
285 HWND hWndFS = NULL; //handle to directx's fullscreen window
286 if(hWndFS == NULL)
288 hWndFS = FindWindow(NULL, "MPlayer Fullscreen");
289 if(hWndFS != NULL) DestroyWindow(hWndFS); //sub window handles fullscreen
293 for (i=0; i<gui->window_priv_count; i++)
295 if(gui->window_priv[i]->hwnd == hwnd)
296 priv=gui->window_priv[i];
297 }// Sherpya
298 /* display the status msgs */
299 renderinfobox(gui->skin, priv);
300 RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE);
303 static LRESULT CALLBACK SubProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
305 gui_t *gui = (gui_t *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
306 if (gui && (gui->subwindow != hWnd)) return FALSE;
308 switch (message)
310 case WM_CLOSE:
311 handlemsg(hWnd, evExit);
312 return 0;
313 case WM_DESTROY:
314 PostQuitMessage(0);
315 return 0;
316 case WM_KEYDOWN:
318 switch(wParam)
320 case VK_LEFT:
321 mplayer_put_key(KEY_LEFT);
322 break;
323 case VK_UP:
324 mplayer_put_key(KEY_UP);
325 break;
326 case VK_RIGHT:
327 mplayer_put_key(KEY_RIGHT);
328 break;
329 case VK_DOWN:
330 mplayer_put_key(KEY_DOWN);
331 break;
332 case VK_TAB:
333 mplayer_put_key(KEY_TAB);
334 break;
335 case VK_BACK:
336 mplayer_put_key(KEY_BS);
337 break;
338 case VK_DELETE:
339 mplayer_put_key(KEY_DELETE);
340 break;
341 case VK_INSERT:
342 mplayer_put_key(KEY_INSERT);
343 break;
344 case VK_HOME:
345 mplayer_put_key(KEY_HOME);
346 break;
347 case VK_END:
348 mplayer_put_key(KEY_END);
349 break;
350 case VK_PRIOR:
351 mplayer_put_key(KEY_PAGE_UP);
352 break;
353 case VK_NEXT:
354 mplayer_put_key(KEY_PAGE_DOWN);
355 break;
356 case VK_ESCAPE:
357 mplayer_put_key(KEY_ESC);
358 break;
360 break;
362 case WM_COMMAND:
364 switch(LOWORD(wParam))
366 case IDEXIT:
367 PostQuitMessage(0);
368 handlemsg(hWnd, evExit);
369 break;
370 case IDFILE_OPEN:
371 handlemsg(hWnd, evLoadPlay);
372 break;
373 case IDURL_OPEN:
374 display_openurlwindow(gui, 0);
375 break;
376 case IDDIR_OPEN:
378 static char path[MAX_PATH];
379 BROWSEINFO bi;
380 LPITEMIDLIST pidl;
381 memset(&bi, 0, sizeof(BROWSEINFO));
382 bi.lpszTitle = "Choose a Directory...";
383 pidl = SHBrowseForFolder(&bi);
384 if (SHGetPathFromIDList(pidl, path))
386 gui->playlist->clear_playlist(gui->playlist);
387 adddirtoplaylist(gui->playlist, path, TRUE);
388 gui->startplay(gui);
390 break;
392 case ID_PTRACK:
393 handlemsg(hWnd, evPrev);
394 break;
395 case ID_SEEKB:
396 handlemsg(hWnd, evBackward10sec);
397 break;
398 case ID_PLAY:
399 handlemsg(hWnd, evPlaySwitchToPause);
400 break;
401 case ID_STOP:
402 handlemsg(hWnd, evStop);
403 break;
404 case ID_SEEKF:
405 handlemsg(hWnd, evForward10sec);
406 break;
407 case ID_NTRACK:
408 handlemsg(hWnd, evNext);
409 break;
410 #ifdef CONFIG_DVDREAD
411 case ID_CHAPTERSEL:
412 display_chapterselwindow(gui);
413 break;
414 #endif
415 case ID_FULLSCREEN:
416 mp_input_queue_cmd(mp_input_parse_cmd("vo_fullscreen"));
417 break;
418 case ID_MUTE:
419 mp_input_queue_cmd(mp_input_parse_cmd("mute"));
420 break;
421 case ID_ASPECT1:
422 mp_input_queue_cmd(mp_input_parse_cmd("switch_ratio 1.777777"));
423 break;
424 case ID_ASPECT2:
425 mp_input_queue_cmd(mp_input_parse_cmd("switch_ratio 1.333333"));
426 break;
427 case ID_ASPECT3:
428 mp_input_queue_cmd(mp_input_parse_cmd("switch_ratio 2.35"));
429 break;
430 case ID_ASPECT4:
431 mp_input_queue_cmd(mp_input_parse_cmd("switch_ratio 0"));
432 break;
433 case IDSUB_TOGGLE:
434 mp_input_queue_cmd(mp_input_parse_cmd("sub_visibility"));
435 break;
436 case IDSUB_CYCLE:
437 mp_input_queue_cmd(mp_input_parse_cmd("sub_select"));
438 break;
440 return 0;
442 case WM_CHAR:
443 mplayer_put_key(wParam);
444 break;
445 case WM_DROPFILES:
447 if(!lParam)
449 char file[MAX_PATH];
450 int filecount = DragQueryFile((HDROP) wParam, -1, file, MAX_PATH);
451 int i;
452 for(i=0; i<filecount; i++)
454 DragQueryFile((HDROP) wParam, i, file, MAX_PATH);
455 mplSetFileName(NULL, file, STREAMTYPE_FILE);
456 if(!parse_filename(file, playtree, mconfig, 1))
457 gui->playlist->add_track(gui->playlist, file, NULL, NULL, 0);
459 DragFinish((HDROP) wParam);
460 handlemsg(hWnd, evDropFile);
462 else
464 gui->playlist->clear_playlist(gui->playlist);
465 gui->playlist->add_track(gui->playlist, (const char *) wParam, NULL, NULL, 0);
466 handlemsg(hWnd, evDropFile);
468 SetForegroundWindow(gui->subwindow);
469 return 0;
471 case WM_LBUTTONDOWN:
473 if(!vo_nomouse_input)
474 mplayer_put_key(MOUSE_BTN0);
475 break;
477 case WM_MBUTTONDOWN:
479 if(!vo_nomouse_input)
480 mplayer_put_key(MOUSE_BTN1);
481 break;
483 case WM_RBUTTONDOWN:
485 POINT point;
486 point.x = GET_X_LPARAM(lParam);
487 point.y = GET_Y_LPARAM(lParam);
488 ClientToScreen(hWnd, &point);
489 if(guiIntfStruct.StreamType == STREAMTYPE_DVD)
490 EnableMenuItem(gui->dvdmenu, ID_CHAPTERSEL, MF_BYCOMMAND | MF_ENABLED);
491 TrackPopupMenu(gui->submenu, 0, point.x, point.y, 0, hWnd, NULL);
492 return 0;
494 case WM_LBUTTONDBLCLK:
496 if(!vo_nomouse_input)
497 mplayer_put_key(MOUSE_BTN0_DBL);
498 break;
500 case WM_MBUTTONDBLCLK:
502 if(!vo_nomouse_input)
503 mplayer_put_key(MOUSE_BTN1_DBL);
504 break;
506 case WM_RBUTTONDBLCLK:
508 if(!vo_nomouse_input)
509 mplayer_put_key(MOUSE_BTN2_DBL);
510 break;
512 case WM_MOUSEWHEEL:
514 int x = GET_WHEEL_DELTA_WPARAM(wParam);
515 if(vo_nomouse_input)
516 break;
517 if (x > 0)
518 mplayer_put_key(MOUSE_BTN3);
519 else
520 mplayer_put_key(MOUSE_BTN4);
521 break;
523 case WM_XBUTTONDOWN:
525 if(vo_nomouse_input)
526 break;
527 if(HIWORD(wParam) == 1)
528 mplayer_put_key(MOUSE_BTN5);
529 else
530 mplayer_put_key(MOUSE_BTN6);
531 break;
533 case WM_XBUTTONDBLCLK:
535 if(vo_nomouse_input)
536 break;
537 if(HIWORD(wParam) == 1)
538 mplayer_put_key(MOUSE_BTN5_DBL);
539 else
540 mplayer_put_key(MOUSE_BTN6_DBL);
541 break;
543 case WM_TIMER:
545 if(fullscreen) while(ShowCursor(FALSE) >= 0){}
546 KillTimer(hWnd, ID_TIMER);
547 return 0;
549 case WM_MOUSEMOVE:
551 ShowCursor(TRUE);
552 SetTimer(hWnd, ID_TIMER, 3000, (TIMERPROC) NULL);
553 break;
555 case WM_WINDOWPOSCHANGED:
557 int tmpheight=0;
558 static uint32_t rect_width;
559 static uint32_t rect_height;
560 RECT rd;
561 POINT pt;
562 pt.x = 0;
563 pt.y = 0;
564 GetClientRect(hWnd, &rd);
565 ClientToScreen(hWnd, &pt);
567 rect_width = rd.right - rd.left;
568 rect_height = rd.bottom - rd.top;
570 /* maintain our aspect ratio */
571 tmpheight = ((float)rect_width/sub_aspect);
572 tmpheight += tmpheight % 2;
573 if(tmpheight > rect_height)
575 rect_width = ((float)rect_height*sub_aspect);
576 rect_width += rect_width % 2;
578 else rect_height = tmpheight;
580 rd.right = rd.left + rect_width;
581 rd.bottom = rd.top + rect_height;
583 AdjustWindowRect(&rd, WS_OVERLAPPEDWINDOW | WS_SIZEBOX, 0);
584 SetWindowPos(hWnd, 0, fullscreen?0:pt.x+rd.left, fullscreen?0:pt.y+rd.top,
585 fullscreen?vo_screenwidth:rd.right-rd.left, fullscreen?vo_screenheight:rd.bottom-rd.top, SWP_NOOWNERZORDER);
586 SetForegroundWindow(hWnd);
587 return 0;
589 case WM_SYSCOMMAND:
591 switch(wParam)
593 case SC_SCREENSAVE:
594 case SC_MONITORPOWER:
595 mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>killing screensaver\n" );
596 return 0;
598 break;
600 case WM_PAINT:
602 PAINTSTRUCT ps;
603 RECT rect;
604 HDC hdc = BeginPaint(hWnd, &ps);
605 HDC hMemDC = CreateCompatibleDC(hdc);
606 HBRUSH blackbrush = (HBRUSH)GetStockObject(BLACK_BRUSH);
607 int width, height;
608 GetClientRect(hWnd, &rect);
609 width = rect.right - rect.left;
610 height = rect.bottom - rect.top;
611 if(guiIntfStruct.Playing == 0)
613 int i;
614 window *desc = NULL;
616 for (i=0; i<gui->skin->windowcount; i++)
617 if(gui->skin->windows[i]->type == wiSub)
618 desc = gui->skin->windows[i];
620 SelectObject(hMemDC, get_bitmap(hWnd));
621 StretchBlt(hdc, 0, 0, width, height, hMemDC, 0, 0, desc->base->bitmap[0]->width,
622 desc->base->bitmap[0]->height, SRCCOPY);
623 } else {
624 FillRect(GetDC(hWnd), &rect, fullscreen?blackbrush:colorbrush);
626 DeleteDC(hMemDC);
627 EndPaint(hWnd, &ps);
628 return 0;
631 return DefWindowProc(hWnd, message, wParam, lParam);
634 /* Window Proc for the gui Window */
635 static LRESULT CALLBACK EventProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
637 gui_t *gui = (gui_t *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
639 /* Avoid processing when then window doesn't match gui mainwindow */
640 if (gui && (gui->mainwindow != hWnd)) return FALSE;
642 switch (message)
644 case WM_CLOSE:
645 handlemsg(hWnd, evExit);
646 return 0;
647 case WM_DESTROY:
648 PostQuitMessage(0);
649 return 0;
650 case WM_SYSTRAY:
652 switch(lParam)
654 POINT cursor;
655 case WM_RBUTTONDOWN:
657 GetCursorPos(&cursor);
658 SetForegroundWindow(hWnd);
659 TrackPopupMenu(gui->traymenu, 0, cursor.x, cursor.y, 0, hWnd, NULL);
660 break;
662 case WM_MBUTTONDBLCLK:
663 case WM_LBUTTONDBLCLK:
665 if(IsWindowVisible(hWnd)) ShowWindow(hWnd, SW_HIDE);
666 else { ShowWindow(hWnd, SW_SHOW); SetForegroundWindow(hWnd); }
667 break;
670 break;
672 case WM_KEYDOWN:
674 switch(wParam)
676 case VK_LEFT:
677 mplayer_put_key(KEY_LEFT);
678 break;
679 case VK_UP:
680 mplayer_put_key(KEY_UP);
681 break;
682 case VK_RIGHT:
683 mplayer_put_key(KEY_RIGHT);
684 break;
685 case VK_DOWN:
686 mplayer_put_key(KEY_DOWN);
687 break;
688 case VK_TAB:
689 mplayer_put_key(KEY_TAB);
690 break;
691 case VK_BACK:
692 mplayer_put_key(KEY_BS);
693 break;
694 case VK_DELETE:
695 mplayer_put_key(KEY_DELETE);
696 break;
697 case VK_INSERT:
698 mplayer_put_key(KEY_INSERT);
699 break;
700 case VK_HOME:
701 mplayer_put_key(KEY_HOME);
702 break;
703 case VK_END:
704 mplayer_put_key(KEY_END);
705 break;
706 case VK_PRIOR:
707 mplayer_put_key(KEY_PAGE_UP);
708 break;
709 case VK_NEXT:
710 mplayer_put_key(KEY_PAGE_DOWN);
711 break;
712 case VK_ESCAPE:
713 mplayer_put_key(KEY_ESC);
714 break;
716 break;
718 case WM_CHAR:
719 mplayer_put_key(wParam);
720 break;
721 case WM_COPYDATA:
723 if(lParam)
725 PCOPYDATASTRUCT cdData;
726 cdData = (PCOPYDATASTRUCT) lParam;
727 mplSetFileName(NULL, cdData->lpData, STREAMTYPE_FILE);
728 if(!parse_filename(cdData->lpData, playtree, mconfig, 1))
729 gui->playlist->add_track(gui->playlist, cdData->lpData, NULL, NULL, 0);
730 gui->startplay(gui);
732 break;
734 case WM_DROPFILES:
736 if(!lParam)
738 char file[MAX_PATH];
739 int filecount = DragQueryFile((HDROP) wParam, -1, file, MAX_PATH);
740 int i;
741 for(i=0; i<filecount; i++)
743 DragQueryFile((HDROP) wParam, i, file, MAX_PATH);
744 mplSetFileName(NULL, file, STREAMTYPE_FILE);
745 if(!parse_filename(file, playtree, mconfig, 1))
746 gui->playlist->add_track(gui->playlist, file, NULL, NULL, 0);
748 DragFinish((HDROP) wParam);
749 handlemsg(hWnd, evDropFile);
751 else
753 gui->playlist->clear_playlist(gui->playlist);
754 gui->playlist->add_track(gui->playlist, (const char *) wParam, NULL, NULL, 0);
755 handlemsg(hWnd, evDropFile);
757 SetForegroundWindow(gui->mainwindow);
758 return 0;
760 case WM_LBUTTONDOWN:
762 SetCapture(hWnd);
763 gui->mousex = GET_X_LPARAM(lParam);
764 gui->mousey = GET_Y_LPARAM(lParam);
765 /* inside a widget */
766 gui->activewidget = clickedinsidewidget(gui, get_windowtype(hWnd), gui->mousex, gui->mousey);
767 if(gui->activewidget)
769 gui->activewidget->pressed = 1;
770 gui->mousewx = gui->mousex - gui->activewidget->x;
771 gui->mousewy = gui->mousey - gui->activewidget->y;
772 renderwidget(gui->skin, get_drawground(hWnd), gui->activewidget, 0);
773 RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE);
774 handlemsg(hWnd, gui->activewidget->msg);
776 break;
778 case WM_CAPTURECHANGED:
780 if(gui->activewidget)
782 gui->activewidget->pressed = 0;
783 renderwidget(gui->skin, get_drawground(hWnd), gui->activewidget, 1);
784 RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE);
785 gui->activewidget = NULL;
787 break;
789 case WM_LBUTTONUP:
791 ReleaseCapture();
792 if(gui->activewidget)
794 gui->activewidget->pressed = 0;
795 renderwidget(gui->skin, get_drawground(hWnd), gui->activewidget, 1);
796 RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE);
797 gui->activewidget = NULL;
799 break;
801 case WM_RBUTTONDOWN:
803 POINT point;
804 char device[MAX_PATH];
805 char searchpath[MAX_PATH];
806 char searchpath2[MAX_PATH];
807 #ifdef CONFIG_LIBCDIO
808 char searchpath3[MAX_PATH];
809 #endif
810 int len, pos = 0, cdromdrive = 0;
811 UINT errmode;
812 point.x = GET_X_LPARAM(lParam);
813 point.y = GET_Y_LPARAM(lParam);
814 ClientToScreen(hWnd, &point);
815 errmode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
816 while (GetMenuItemCount(gui->diskmenu) > 0)
817 DeleteMenu(gui->diskmenu, 0, MF_BYPOSITION);
818 len = GetLogicalDriveStrings(MAX_PATH, device);
819 while(pos < len)
821 if(GetDriveType(device + pos) == DRIVE_CDROM)
823 char volname[MAX_PATH];
824 char menuitem[MAX_PATH];
825 int flags = MF_STRING;
826 mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] checking %s for CD/VCD/SVCD/DVDs\n", device + pos);
827 sprintf(searchpath, "%sVIDEO_TS", device + pos);
828 sprintf(searchpath2, "%sMpegav", device + pos);
829 #ifdef CONFIG_LIBCDIO
830 sprintf(searchpath3, "%sTrack01.cda", device + pos);
831 #endif
832 if(GetFileAttributes(searchpath) != INVALID_FILE_ATTRIBUTES)
833 flags |= MF_ENABLED;
834 else if(GetFileAttributes(searchpath2) != INVALID_FILE_ATTRIBUTES)
835 flags |= MF_ENABLED;
836 #ifdef CONFIG_LIBCDIO
837 else if(GetFileAttributes(searchpath3) != INVALID_FILE_ATTRIBUTES)
838 flags |= MF_ENABLED;
839 #endif
840 else
841 flags |= MF_GRAYED;
842 volname[0] = 0;
843 strcpy(menuitem, device + pos);
844 menuitem[strlen(menuitem) - 1]=0;
845 GetVolumeInformation(device + pos, volname, MAX_PATH, NULL, NULL, NULL, NULL, 0);
846 if (strlen(volname))
848 capitalize(volname);
849 strcat(menuitem, " - ");
850 strcat(menuitem, volname);
852 AppendMenu(gui->diskmenu, flags, IDPLAYDISK + cdromdrive, menuitem);
853 cdromdrive++;
855 pos += strlen(device + pos) + 1;
857 SetErrorMode(errmode);
858 TrackPopupMenu(gui->menu, 0, point.x, point.y, 0, hWnd, NULL);
859 return 0;
861 case WM_MOUSEMOVE:
863 if(wParam & MK_LBUTTON)
865 POINT point;
866 RECT rect;
867 if(gui->activewidget)
869 widget *item = gui->activewidget;
871 if(item->type == tyHpotmeter)
873 item->x = GET_X_LPARAM(lParam) - gui->mousewx;
874 item->value = (float)((float)((item->x - item->wx) * 100.0f) / (float)(item->wwidth - item->width));
876 if(item->type == tyPotmeter)
878 gui->mousewx = GET_X_LPARAM(lParam) - gui->activewidget->x;
879 item->value = (float) (gui->mousewx * 100.0f) / (float) item->wwidth;
882 if((item->type == tyPotmeter) || (item->type == tyHpotmeter) || (item->type == tyVpotmeter))
884 /* Bound checks */
885 if(item->value > 100.0f)
886 item->value = 100.0f;
887 else if(item->value < 0.0f)
888 item->value = 0.0f;
890 if(item->msg == evSetVolume)
891 guiIntfStruct.Volume = (float) item->value;
892 else if(item->msg == evSetMoviePosition)
893 guiIntfStruct.Position = (float) item->value;
894 else if(item->msg == evSetBalance)
896 /* make the range for 50% a bit bigger, because the sliders for balance usually suck */
897 if((item->value - 50.0f < 1.5f) && (item->value - 50.0f > -1.5f))
898 item->value = 50.0f;
899 guiIntfStruct.Balance = (float) item->value;
901 updatedisplay(gui, hWnd);
902 handlemsg(hWnd, item->msg);
904 break;
906 point.x = GET_X_LPARAM(lParam);
907 point.y = GET_Y_LPARAM(lParam);
908 ClientToScreen(hWnd, &point);
909 GetWindowRect(hWnd, &rect);
910 MoveWindow(hWnd, point.x - gui->mousex, point.y - gui->mousey,
911 rect.right-rect.left,rect.bottom-rect.top,TRUE);
912 break;
914 break;
916 case WM_COMMAND:
918 switch(LOWORD(wParam))
920 case IDEXIT:
921 PostQuitMessage(0);
922 handlemsg(hWnd, evExit);
923 break;
924 case IDFILE_OPEN:
925 handlemsg(hWnd, evLoadPlay);
926 break;
927 case IDDIR_OPEN:
929 static char path[MAX_PATH];
930 BROWSEINFO bi;
931 LPITEMIDLIST pidl;
932 memset(&bi, 0, sizeof(BROWSEINFO));
933 bi.lpszTitle = "Choose a Directory...";
934 pidl = SHBrowseForFolder(&bi);
935 if (SHGetPathFromIDList(pidl, path))
937 gui->playlist->clear_playlist(gui->playlist);
938 adddirtoplaylist(gui->playlist, path, TRUE);
939 gui->startplay(gui);
941 break;
943 case ID_SKINBROWSER:
944 handlemsg(hWnd, evSkinBrowser);
945 break;
946 case IDURL_OPEN:
947 display_openurlwindow(gui, 0);
948 break;
949 case ID_MUTE:
950 mp_input_queue_cmd(mp_input_parse_cmd("mute"));
951 break;
952 case IDSUBTITLE_OPEN:
953 display_opensubtitlewindow(gui);
954 break;
955 case ID_PTRACK:
956 handlemsg(hWnd, evPrev);
957 break;
958 case ID_SEEKB:
959 handlemsg(hWnd, evBackward10sec);
960 break;
961 case ID_PLAY:
962 handlemsg(hWnd, evPlaySwitchToPause);
963 break;
964 case ID_STOP:
965 handlemsg(hWnd, evStop);
966 break;
967 case ID_SEEKF:
968 handlemsg(hWnd, evForward10sec);
969 break;
970 case ID_NTRACK:
971 handlemsg(hWnd, evNext);
972 break;
973 case ID_SHOWHIDE:
975 if(IsWindowVisible(hWnd)) ShowWindow(hWnd, SW_HIDE);
976 else ShowWindow(hWnd, SW_SHOW);
977 break;
979 case ID_PLAYLIST:
980 handlemsg(hWnd, evPlayList);
981 break;
982 case ID_PREFS:
983 handlemsg(hWnd, evPreferences);
984 break;
985 case ID_CONSOLE:
986 console_toggle();
987 break;
988 case ID_ONLINEHELP:
989 ShellExecute(NULL, "open", ONLINE_HELP_URL, NULL, NULL, SW_SHOWNORMAL);
990 break;
992 if((IDPLAYDISK <= LOWORD(wParam)) && (LOWORD(wParam) < (IDPLAYDISK + 100)))
994 char device[MAX_PATH];
995 char searchpath[MAX_PATH];
996 char filename[MAX_PATH];
997 int len, pos = 0, cdromdrive = 0;
998 len = GetLogicalDriveStrings(MAX_PATH, device);
999 while(pos < len)
1001 if(GetDriveType(device + pos)==DRIVE_CDROM)
1003 if(LOWORD(wParam) - IDPLAYDISK == cdromdrive)
1005 sprintf(searchpath, "%sVIDEO_TS", device + pos);
1006 if(GetFileAttributes(searchpath) != INVALID_FILE_ATTRIBUTES)
1008 #ifdef CONFIG_DVDREAD
1009 if (dvd_device) free(dvd_device);
1010 dvd_device = strdup(device + pos);
1011 dvd_title = dvd_chapter = dvd_angle = 1;
1012 handlemsg(hWnd, evPlayDVD);
1013 #endif
1015 sprintf(searchpath, "%sTrack01.cda", device + pos);
1016 if(GetFileAttributes(searchpath) != INVALID_FILE_ATTRIBUTES)
1018 #ifdef CONFIG_LIBCDIO
1019 if (cdrom_device) free(cdrom_device);
1020 cdrom_device = strdup(device + pos);
1021 /* mplayer doesn't seem to like the trailing \ after the device name */
1022 cdrom_device[2]=0;
1023 handlemsg(hWnd, evPlayCD);
1024 #endif
1025 } else {
1026 HANDLE searchhndl;
1027 WIN32_FIND_DATA finddata;
1028 sprintf(searchpath, "%smpegav\\*.dat", device + pos);
1029 if((searchhndl=FindFirstFile(searchpath, &finddata)) != INVALID_HANDLE_VALUE)
1031 mp_msg(MSGT_GPLAYER,MSGL_V, "Opening VCD/SVCD\n");
1032 gui->playlist->clear_playlist(gui->playlist);
1035 sprintf(filename, "%smpegav\\%s", device + pos, finddata.cFileName);
1036 gui->playlist->add_track(gui->playlist, filename, NULL, NULL, 0);
1038 while(FindNextFile(searchhndl, &finddata));
1039 FindClose(searchhndl);
1041 gui->startplay(gui);
1044 cdromdrive++;
1046 pos += strlen(device + pos) + 1;
1049 break;
1051 case WM_PAINT:
1053 PAINTSTRUCT ps;
1054 RECT rd;
1055 HDC hdc = BeginPaint(hWnd, &ps);
1056 HDC hMemDC = CreateCompatibleDC(hdc);
1057 int width, height;
1058 GetClientRect(hWnd, &rd);
1059 width = rd.right - rd.left;
1060 height = rd.bottom - rd.top;
1061 SelectObject(hMemDC, get_bitmap(hWnd));
1062 BitBlt(hdc, 0, 0, width, height, hMemDC, 0, 0, SRCCOPY);
1063 DeleteDC(hMemDC);
1064 EndPaint(hWnd, &ps);
1065 return 0;
1067 return 0;
1069 return DefWindowProc(hWnd, message, wParam, lParam);
1072 static void startplay(gui_t *gui)
1074 handlemsg(gui->mainwindow, evDropFile);
1077 /* returns the bits per pixel of the desktop */
1078 /* the format is always in BGR byte order */
1079 static int GetDesktopBitsPerPixel(void)
1081 HWND desktop=GetDesktopWindow();
1082 HDC dc=GetDC(desktop);
1083 int bpp=GetDeviceCaps(dc, BITSPIXEL);
1084 ReleaseDC(desktop, dc);
1085 return bpp;
1088 /* unloads a skin and destroys its windows */
1089 int destroy_window(gui_t *gui)
1091 RECT rd;
1092 unsigned int i;
1094 /* Save position: MSDN says don't pass workspace coordinates
1095 * to CreateWindow() or SetWindowPos(), as both of which expect
1096 * screen coordinates; resulting in the window appearing in the
1097 * wrong location.
1098 * -Erik
1101 /* main window position */
1102 if(IsIconic(gui->mainwindow))
1103 ShowWindow(gui->mainwindow, SW_SHOWNORMAL);
1104 GetWindowRect(gui->mainwindow, &rd);
1105 gui_main_pos_x = rd.left;
1106 gui_main_pos_y = rd.top;
1108 /* sub window position */
1109 if(IsIconic(gui->subwindow))
1110 ShowWindow(gui->subwindow, SW_SHOWNORMAL);
1111 GetWindowRect(gui->subwindow, &rd);
1112 gui_sub_pos_x = rd.left;
1113 gui_sub_pos_y = rd.top;
1115 for(i=0; i<gui->window_priv_count; i++)
1117 if(gui->window_priv[i]->bitmap)
1118 DeleteObject(gui->window_priv[i]->bitmap);
1119 free(gui->window_priv[i]);
1121 free(gui->window_priv);
1122 gui->window_priv = NULL;
1123 gui->window_priv_count = 0;
1125 /* destroy the main window */
1126 if(gui->mainwindow)
1127 DestroyWindow(gui->mainwindow);
1128 gui->mainwindow = NULL;
1130 /* destroy the sub window */
1131 if(gui->subwindow)
1132 DestroyWindow(gui->subwindow);
1133 gui->subwindow = NULL;
1135 UnregisterClass(gui->classname, 0);
1136 DestroyIcon(gui->icon);
1138 gui->skin->freeskin(gui->skin);
1139 gui->skin = NULL;
1140 return 0;
1143 static void create_menu(gui_t *gui)
1145 gui->diskmenu = CreatePopupMenu();
1146 gui->menu=CreatePopupMenu();
1147 gui->trayplaymenu = CreatePopupMenu();
1148 AppendMenu(gui->menu, MF_STRING | MF_POPUP, (UINT) gui->trayplaymenu, "Open...");
1149 AppendMenu(gui->trayplaymenu, MF_STRING, IDFILE_OPEN, "File...");
1150 AppendMenu(gui->trayplaymenu, MF_STRING, IDURL_OPEN, "Url...");
1151 AppendMenu(gui->trayplaymenu, MF_STRING, IDDIR_OPEN, "Directory...");
1152 AppendMenu(gui->menu, MF_SEPARATOR, 0, 0);
1153 AppendMenu(gui->menu, MF_STRING | MF_POPUP, (UINT) gui->diskmenu, "Play &CD/DVD/VCD/SVCD");
1154 AppendMenu(gui->menu, MF_SEPARATOR, 0, 0);
1155 AppendMenu(gui->menu, MF_STRING, IDSUBTITLE_OPEN, "Open Subtitle");
1156 AppendMenu(gui->menu, MF_STRING, ID_SKINBROWSER, "Skin Browser");
1157 AppendMenu(gui->menu, MF_SEPARATOR, 0, 0);
1158 AppendMenu(gui->menu, MF_STRING, ID_PREFS, "Preferences");
1159 AppendMenu(gui->menu, MF_STRING, ID_CONSOLE, "Debug Console");
1160 AppendMenu(gui->menu, MF_STRING, ID_ONLINEHELP, "Online Help");
1161 AppendMenu(gui->menu, MF_SEPARATOR, 0, 0);
1162 AppendMenu(gui->menu, MF_STRING, IDEXIT, "&Exit");
1165 static void create_traymenu(gui_t *gui)
1167 gui->traymenu = CreatePopupMenu();
1168 gui->trayplaybackmenu = CreatePopupMenu();
1169 AppendMenu(gui->traymenu, MF_STRING | MF_POPUP, (UINT) gui->trayplaymenu, "Open...");
1170 AppendMenu(gui->traymenu, MF_SEPARATOR, 0, 0);
1171 AppendMenu(gui->traymenu, MF_STRING | MF_POPUP, (UINT) gui->trayplaybackmenu, "Playback");
1172 AppendMenu(gui->trayplaybackmenu, MF_STRING, ID_SEEKB, "Seek Backwards");
1173 AppendMenu(gui->trayplaybackmenu, MF_STRING, ID_PTRACK, "Previous Track");
1174 AppendMenu(gui->trayplaybackmenu, MF_STRING, ID_PLAY, "Play/Pause");
1175 AppendMenu(gui->trayplaybackmenu, MF_STRING, ID_STOP, "Stop");
1176 AppendMenu(gui->trayplaybackmenu, MF_STRING, ID_NTRACK, "Next Track");
1177 AppendMenu(gui->trayplaybackmenu, MF_STRING, ID_SEEKF, "Seek Forwards");
1178 AppendMenu(gui->traymenu, MF_SEPARATOR, 0, 0);
1179 AppendMenu(gui->traymenu, MF_STRING, ID_MUTE, "Toggle Mute");
1180 AppendMenu(gui->traymenu, MF_SEPARATOR, 0, 0);
1181 AppendMenu(gui->traymenu, MF_STRING, IDSUBTITLE_OPEN, "Open Subtitle");
1182 AppendMenu(gui->traymenu, MF_STRING, ID_PLAYLIST, "Playlist");
1183 AppendMenu(gui->traymenu, MF_SEPARATOR, 0, 0);
1184 AppendMenu(gui->traymenu, MF_STRING, ID_SHOWHIDE, "Show/Hide");
1185 AppendMenu(gui->traymenu, MF_SEPARATOR, 0, 0);
1186 AppendMenu(gui->traymenu, MF_STRING, ID_PREFS, "Preferences");
1187 AppendMenu(gui->traymenu, MF_STRING, ID_CONSOLE, "Debug Console");
1188 AppendMenu(gui->traymenu, MF_STRING, ID_ONLINEHELP, "Online Help");
1189 AppendMenu(gui->traymenu, MF_SEPARATOR, 0, 0);
1190 AppendMenu(gui->traymenu, MF_STRING, IDEXIT, "&Exit");
1193 static void create_submenu(gui_t *gui)
1195 gui->submenu = CreatePopupMenu();
1196 gui->dvdmenu = CreatePopupMenu();
1197 gui->aspectmenu = CreatePopupMenu();
1198 gui->subtitlemenu = CreatePopupMenu();
1199 AppendMenu(gui->submenu, MF_STRING | MF_POPUP, (UINT) gui->trayplaymenu, "Open...");
1200 AppendMenu(gui->submenu, MF_SEPARATOR, 0, 0);
1201 AppendMenu(gui->submenu, MF_STRING, ID_SEEKB, "Seek Backwards");
1202 AppendMenu(gui->submenu, MF_STRING, ID_PTRACK, "Previous Track");
1203 AppendMenu(gui->submenu, MF_STRING, ID_PLAY, "Play/Pause");
1204 AppendMenu(gui->submenu, MF_STRING, ID_STOP, "Stop");
1205 AppendMenu(gui->submenu, MF_STRING, ID_NTRACK, "Next Track");
1206 AppendMenu(gui->submenu, MF_STRING, ID_SEEKF, "Seek Forwards");
1207 AppendMenu(gui->submenu, MF_SEPARATOR, 0, 0);
1208 AppendMenu(gui->submenu, MF_STRING, ID_FULLSCREEN, "Toggle Fullscreen");
1209 AppendMenu(gui->submenu, MF_STRING, ID_MUTE, "Toggle Mute");
1210 AppendMenu(gui->submenu, MF_SEPARATOR, 0, 0);
1211 AppendMenu(gui->submenu, MF_STRING | MF_POPUP, (UINT) gui->aspectmenu, "Aspect Ratio");
1212 AppendMenu(gui->submenu, MF_STRING | MF_POPUP, (UINT) gui->subtitlemenu, "Subtitle Options");
1213 AppendMenu(gui->submenu, MF_STRING | MF_POPUP, (UINT) gui->dvdmenu, "DVD Options");
1214 #ifdef CONFIG_DVDREAD
1215 AppendMenu(gui->dvdmenu, MF_STRING | MF_GRAYED, ID_CHAPTERSEL, "Select Title/Chapter...");
1216 #endif
1217 AppendMenu(gui->subtitlemenu, MF_STRING, IDSUB_TOGGLE, "Subtitle Visibility On/Off");
1218 AppendMenu(gui->subtitlemenu, MF_STRING, IDSUB_CYCLE, "Cycle Subtitle Languages");
1219 AppendMenu(gui->aspectmenu, MF_STRING, ID_ASPECT1, "Set 16:9");
1220 AppendMenu(gui->aspectmenu, MF_STRING, ID_ASPECT2, "Set 4:3");
1221 AppendMenu(gui->aspectmenu, MF_STRING, ID_ASPECT3, "Set 2.35");
1222 AppendMenu(gui->aspectmenu, MF_SEPARATOR, 0, 0);
1223 AppendMenu(gui->aspectmenu, MF_STRING, ID_ASPECT4, "Original Aspect");
1224 AppendMenu(gui->submenu, MF_SEPARATOR, 0, 0);
1225 AppendMenu(gui->submenu, MF_STRING, IDEXIT, "&Exit");
1228 static void maketransparent(HWND hwnd, COLORREF crTransparent)
1230 HDC mdc = GetDC(hwnd);
1231 RECT rd;
1232 HRGN crRgnres, crRgn, crRgnTmp;
1233 int iX = 0, iY = 0, iLeftX = 0;
1234 int width, height;
1235 GetWindowRect(hwnd, &rd);
1236 width = rd.right - rd.left;
1237 height = rd.bottom - rd.top;
1239 /* create an empty region */
1240 crRgn = CreateRectRgn(0, 0, 0, 0);
1242 /* Create a region from a bitmap with transparency colour of Purple */
1243 for (iY = -1; iY < height; iY++)
1247 /* skip over transparent pixels at start of lines */
1248 while (iX <= width && GetPixel(mdc,iX, iY) == crTransparent) iX++;
1250 /* remember this pixel */
1251 iLeftX = iX;
1253 /* now find first non transparent pixel */
1254 while (iX <= width && GetPixel(mdc,iX, iY) != crTransparent) ++iX;
1256 /* create a temp region on this info */
1257 crRgnTmp = CreateRectRgn(iLeftX, iY, iX, iY+1);
1259 /* combine into main region */
1260 crRgnres = crRgn;
1261 CombineRgn(crRgnres, crRgn, crRgnTmp, RGN_OR);
1262 crRgn = crRgnres;
1264 /* delete the temp region for next pass (otherwise you'll get an ASSERT) */
1265 DeleteObject(crRgnTmp);
1266 } while (iX < width);
1267 iX = 0;
1269 SetWindowRgn(hwnd, crRgn, TRUE);
1270 DeleteObject(crRgn);
1271 ReleaseDC(hwnd,mdc);
1274 static int window_render(gui_t *gui, HWND hWnd, HDC hdc, window_priv_t *priv, window *desc, BITMAPINFO binfo)
1276 int i;
1277 SetWindowLongPtr(hWnd, GWLP_USERDATA, (DWORD) gui);
1278 (gui->window_priv_count)++;
1279 gui->window_priv = realloc(gui->window_priv, sizeof(window_priv_t *) * gui->window_priv_count);
1280 priv = gui->window_priv[gui->window_priv_count - 1] = calloc(1, sizeof(window_priv_t));
1281 priv->hwnd = hWnd;
1282 priv->type = desc->type;
1283 priv->background = desc->base->bitmap[0];
1284 memcpy(&priv->img, desc->base->bitmap[0], sizeof(image));
1285 hdc = GetDC(hWnd);
1286 binfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1287 binfo.bmiHeader.biWidth = priv->img.width;
1288 binfo.bmiHeader.biHeight = -priv->img.height;
1289 binfo.bmiHeader.biPlanes = 1;
1290 binfo.bmiHeader.biSizeImage = priv->img.width * priv->img.height * (gui->screenbpp / 8);
1291 binfo.bmiHeader.biXPelsPerMeter = 0;
1292 binfo.bmiHeader.biYPelsPerMeter = 0;
1293 binfo.bmiHeader.biClrUsed = 0;
1294 binfo.bmiHeader.biClrImportant = 0;
1295 binfo.bmiHeader.biBitCount = gui->screenbpp;
1296 binfo.bmiHeader.biCompression = BI_RGB;
1297 priv->bitmap = CreateDIBSection(hdc, &binfo, DIB_RGB_COLORS, (void **) &priv->img.data, NULL, 0);
1298 if(!priv->bitmap)
1300 mp_msg(MSGT_GPLAYER, MSGL_FATAL, "[GUI] unable to create bitmap for skinned window\n");
1301 return 0;
1303 memcpy(priv->img.data, desc->base->bitmap[0]->data, binfo.bmiHeader.biSizeImage);
1304 ReleaseDC(hWnd,hdc);
1306 for (i=0; i<gui->skin->widgetcount; i++)
1307 if(gui->skin->widgets[i]->window == desc->type)
1308 renderwidget(gui->skin, &priv->img, gui->skin->widgets[i], 1);
1310 return 0;
1313 /* creates the sub (AKA video) window,*/
1314 int create_subwindow(gui_t *gui, char *skindir)
1316 HINSTANCE instance = GetModuleHandle(NULL);
1317 WNDCLASS wc;
1318 RECT rect;
1319 HWND hWnd;
1320 DWORD style = 0;
1321 HDC hdc = NULL;
1322 BITMAPINFO binfo;
1323 window_priv_t *priv = NULL;
1324 window *desc = NULL;
1325 int i, x = -1, y = -1;
1326 vo_colorkey = 0xff00ff;
1328 for (i=0; i<gui->skin->windowcount; i++)
1329 if(gui->skin->windows[i]->type == wiSub)
1330 desc = gui->skin->windows[i];
1332 if(!desc)
1334 mp_msg(MSGT_GPLAYER, MSGL_FATAL, "[GUI] Invalid skin description\n");
1335 return 1;
1338 windowcolor = vo_colorkey;
1339 colorbrush = CreateSolidBrush(windowcolor);
1340 wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
1341 wc.lpfnWndProc = SubProc;
1342 wc.cbClsExtra = 0;
1343 wc.cbWndExtra = 0;
1344 wc.hInstance = instance;
1345 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
1346 wc.hIcon = gui->icon;
1347 wc.hbrBackground = NULL; //WM_PAINT will handle background color switching;
1348 wc.lpszClassName = "MPlayer Sub for Windows";
1349 wc.lpszMenuName = NULL;
1350 RegisterClass(&wc);
1352 /* create the sub window menu */
1353 create_submenu(gui);
1355 rect.top = rect.left = 100;
1356 rect.bottom = rect.top+desc->base->bitmap[0]->height;
1357 rect.right = rect.left+desc->base->bitmap[0]->width;
1359 /* our window aspect */
1360 sub_aspect = (float)(rect.right-rect.left)/(rect.bottom-rect.top);
1362 style = fullscreen?WS_VISIBLE | WS_POPUP:WS_OVERLAPPEDWINDOW | WS_SYSMENU | WS_MINIMIZEBOX;
1363 AdjustWindowRect(&rect, style, 0);
1365 if (gui_sub_pos_x >= 0)
1366 x = gui_sub_pos_x;
1367 if (gui_sub_pos_y >= 0)
1368 y = gui_sub_pos_y;
1370 /* out of bounds check */
1371 if (x <= -1 || (x+(rect.right-rect.left) > GetSystemMetrics(SM_CXSCREEN)))
1372 x = CW_USEDEFAULT;
1373 if (y <= -1 || (y+(rect.bottom-rect.top) > GetSystemMetrics(SM_CYSCREEN)))
1374 y = x;
1376 hWnd = CreateWindowEx(0, "MPlayer Sub for Windows", "MPlayer for Windows", style,
1377 x, y, rect.right-rect.left, rect.bottom-rect.top,
1378 gui->subwindow, NULL, instance, NULL);
1380 /* load all the window images */
1381 window_render(gui, hWnd, hdc, priv, desc, binfo);
1383 /* enable drag and drop support */
1384 DragAcceptFiles(hWnd, TRUE);
1386 gui->subwindow = hWnd;
1387 if(sub_window)
1388 WinID = gui->subwindow;
1389 ShowWindow(gui->subwindow, SW_SHOW);
1390 UpdateWindow(gui->subwindow);
1391 return 0;
1394 /* loads/updates a skin and creates windows for it */
1395 int create_window(gui_t *gui, char *skindir)
1397 HINSTANCE instance = GetModuleHandle(NULL);
1398 WNDCLASS wc;
1399 RECT rect;
1400 DWORD style = 0;
1401 HWND hwnd;
1402 HDC hdc = NULL;
1403 BITMAPINFO binfo;
1404 window_priv_t *priv = NULL;
1405 window *desc = NULL;
1406 char dir[MAX_PATH];
1407 unsigned int i;
1408 int x = -1, y = -1;
1410 /* destroy the current main window */
1411 if(gui->skin) destroy_window(gui);
1413 /* get screenproperties */
1414 gui->screenbpp = GetDesktopBitsPerPixel();
1415 gui->screenw = GetSystemMetrics(SM_CXSCREEN);
1416 gui->screenh = GetSystemMetrics(SM_CYSCREEN);
1418 /* load the new skin */
1419 gui->skin = loadskin(skindir, gui->screenbpp);
1420 if(!gui->skin)
1422 mp_msg(MSGT_GPLAYER, MSGL_FATAL, "[GUI] fatal error during skinload\n");
1423 /* Set default Skin */
1424 if (skinName) free(skinName);
1425 skinName = strdup("Blue");
1426 /* then force write conf */
1427 cfg_write();
1428 return 1;
1431 /* find the description of the mainwindow */
1432 for (i=0; i<gui->skin->windowcount; i++)
1433 if(gui->skin->windows[i]->type == wiMain)
1434 desc = gui->skin->windows[i];
1436 if(!desc)
1438 mp_msg(MSGT_GPLAYER, MSGL_FATAL, "[GUI] Invalid skin description\n");
1439 return 1;
1442 /* load the icon from the executable */
1443 GetModuleFileName(NULL, dir, MAX_PATH);
1444 gui->icon = ExtractIcon(instance, dir, 0);
1446 /* create the window class */
1447 wc.style = CS_HREDRAW | CS_VREDRAW;
1448 wc.lpfnWndProc = EventProc;
1449 wc.cbClsExtra = 0;
1450 wc.cbWndExtra = 0;
1451 wc.hInstance = instance;
1452 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
1453 wc.hIcon = gui->icon;
1454 wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
1455 wc.lpszClassName = gui->classname = "MPlayer GUI for Windows";
1456 wc.lpszMenuName = NULL;
1457 RegisterClass(&wc);
1459 /* create a context menu */
1460 create_menu(gui);
1461 /* create the systray menu */
1462 create_traymenu(gui);
1464 /* create the mainwindow */
1465 /* TODO implement aligning as described in skin.html */
1466 rect.top = rect.left = 100;
1467 rect.bottom = rect.top+desc->base->bitmap[0]->height;
1468 rect.right = rect.left+desc->base->bitmap[0]->width;
1469 if(desc->decoration) style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
1470 else style = WS_POPUP | WS_SYSMENU;
1472 AdjustWindowRect(&rect, style, 0);
1474 /* Check if out of screen */
1475 if (gui_main_pos_x >= 0)
1476 x = gui_main_pos_x;
1477 if (gui_main_pos_y >= 0)
1478 y = gui_main_pos_y;
1480 if (x <= -1 || (x+(rect.right-rect.left) > GetSystemMetrics(SM_CXFULLSCREEN)))
1482 x = (GetSystemMetrics(SM_CXSCREEN) / 2) - ((rect.right-rect.left) / 2);
1483 gui_main_pos_x = x;
1485 if (y <= -1 || (y+(rect.bottom-rect.top) > GetSystemMetrics(SM_CYFULLSCREEN)))
1487 y = ((GetSystemMetrics(SM_CYSCREEN)-40) - (rect.bottom-rect.top));
1488 gui_main_pos_y = y;
1491 hwnd = CreateWindowEx(0, gui->classname, "MPlayer for Windows", style,
1492 x, y, rect.right-rect.left, rect.bottom-rect.top,
1493 gui->mainwindow, NULL, instance, NULL);
1495 /* set the systray icon properties */
1496 nid.cbSize = sizeof(NOTIFYICONDATA);
1497 nid.hWnd = hwnd;
1498 nid.uID = 1;
1499 nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
1500 nid.uCallbackMessage = WM_SYSTRAY;
1501 nid.hIcon = gui->icon;
1502 strcpy(nid.szTip, "MPlayer for Windows");
1504 /* register the systray icon */
1505 Shell_NotifyIcon(NIM_ADD, &nid);
1507 /* load all the window images */
1508 window_render(gui, hwnd, hdc, priv, desc, binfo);
1510 /* enable drag and drop support */
1511 DragAcceptFiles(hwnd, TRUE);
1513 updatedisplay(gui, hwnd);
1514 gui->mainwindow = hwnd;
1516 /* display */
1517 ShowWindow(gui->mainwindow, SW_SHOW);
1518 UpdateWindow(gui->mainwindow);
1519 maketransparent(gui->mainwindow, RGB(255, 0, 255));
1520 return 0;
1523 gui_t *create_gui(char *skindir, char *skinName, void (*playercontrol)(int event))
1525 gui_t *gui = calloc(1, sizeof(gui_t));
1526 char temp[MAX_PATH];
1527 HWND runningmplayer = FindWindow("MPlayer GUI for Windows", "MPlayer for Windows");
1529 if(runningmplayer)
1531 free(gui);
1532 return NULL;
1535 gui->startplay = startplay;
1536 gui->playercontrol = playercontrol;
1537 gui->uninit = uninit;
1538 gui->updatedisplay = updatedisplay;
1540 /* create playlist */
1541 gui->playlist = create_playlist();
1543 if(!skinName) skinName = strdup("Blue");
1544 sprintf(temp, "%s\\%s", skindir, skinName);
1545 if(create_window(gui, temp)) return NULL;
1546 if(create_subwindow(gui, temp)) return NULL;
1547 if(console) console_toggle();
1548 return gui;