aboutsummaryrefslogtreecommitdiffhomepage
path: root/Gui/win32/gui.c
diff options
context:
space:
mode:
Diffstat (limited to 'Gui/win32/gui.c')
-rw-r--r--Gui/win32/gui.c1555
1 files changed, 1555 insertions, 0 deletions
diff --git a/Gui/win32/gui.c b/Gui/win32/gui.c
new file mode 100644
index 0000000000..a1cbfab4ab
--- /dev/null
+++ b/Gui/win32/gui.c
@@ -0,0 +1,1555 @@
+/*
+ MPlayer Gui for win32
+ Copyright (c) 2003 Sascha Sommer <saschasommer@freenet.de>
+ Copyright (c) 2006 Erik Augustson <erik_27can@yahoo.com>
+ Copyright (c) 2006 Gianluigi Tiesi <sherpya@netfarm.it>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <windows.h>
+#include <windowsx.h>
+#include <shlobj.h>
+#include <version.h>
+#include <mplayer.h>
+#include <mp_msg.h>
+#include <help_mp.h>
+#include <cpudetect.h>
+#include <input/input.h>
+#include <input/mouse.h>
+#include <osdep/keycodes.h>
+#include <libmpdemux/stream.h>
+#include <libvo/video_out.h>
+#include <interface.h>
+#include "gui.h"
+#include "wincfg.h"
+#include "dialogs.h"
+
+#ifndef WM_XBUTTONDOWN
+# define WM_XBUTTONDOWN 0x020B
+# define WM_XBUTTONUP 0x020C
+# define WM_XBUTTONDBLCLK 0x020D
+#endif
+
+#define MP_TITLE "MPlayer " VERSION " (C) 2000-2006 MPlayer Team"
+
+/* Globals / Externs */
+extern void renderinfobox(skin_t *skin, window_priv_t *priv);
+extern void renderwidget(skin_t *skin, image *dest, widget *item, int state);
+extern void mplayer_put_key(int code);
+extern int WinID;
+float sub_aspect;
+
+DWORD oldtime;
+NOTIFYICONDATA nid;
+int console_state = 0;
+
+/* Sub window stuff */
+static HBRUSH colorbrush = NULL; //Handle to colorkey brush
+static COLORREF windowcolor = RGB(0,0,16); //Windowcolor == colorkey
+
+/* vo_gl includes vo_init in w32_common.c, without gl this file is not included */
+#if !defined(GL_WIN32) && !defined(HAVE_GL)
+int vo_init(void)
+{
+ mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] dummy vo_init()\n");
+ return 1;
+}
+#endif
+
+void console_toggle(void)
+{
+ if (console_state)
+ {
+ FreeConsole();
+ console = 0;
+ console_state = 0;
+ }
+ else
+ {
+ /* This code comes from: http://dslweb.nwnexus.com/~ast/dload/guicon.htm */
+ CONSOLE_SCREEN_BUFFER_INFO coninfo;
+ FILE *fp;
+ HWND hwnd = NULL;
+ console = 1;
+ AllocConsole();
+ SetConsoleTitle(MP_TITLE);
+
+ /* disable the close button for now */
+ while (!hwnd)
+ {
+ hwnd = FindWindow(NULL, MP_TITLE);
+ Sleep(100);
+ }
+ DeleteMenu(GetSystemMenu(hwnd, 0), SC_CLOSE, MF_BYCOMMAND);
+
+ GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
+ coninfo.dwSize.Y = 1000;
+ SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
+ fp = freopen("con", "w", stdout);
+ *stdout = *fp;
+ setvbuf(stdout, NULL, _IONBF, 0);
+ fp = freopen("con", "r", stdin);
+ *stdin = *fp;
+ setvbuf(stdin, NULL, _IONBF, 0);
+ fp = freopen("con", "w", stdout);
+ *stderr = *fp;
+ setvbuf(stderr, NULL, _IONBF, 0);
+ mp_msg(MSGT_CPLAYER, MSGL_INFO, "%s\n", MP_TITLE);
+ GetCpuCaps(&gCpuCaps);
+#if defined(ARCH_X86) || defined(ARCH_X86_64)
+ mp_msg(MSGT_CPLAYER,MSGL_INFO,"CPUflags: MMX: %d MMX2: %d 3DNow: %d 3DNow2: %d SSE: %d SSE2: %d\n",
+ gCpuCaps.hasMMX, gCpuCaps.hasMMX2,
+ gCpuCaps.has3DNow, gCpuCaps.has3DNowExt,
+ gCpuCaps.hasSSE, gCpuCaps.hasSSE2);
+#ifdef RUNTIME_CPUDETECT
+ mp_msg(MSGT_CPLAYER,MSGL_INFO, MSGTR_CompiledWithRuntimeDetection);
+#else
+ mp_msg(MSGT_CPLAYER,MSGL_INFO, MSGTR_CompiledWithCPUExtensions);
+#ifdef HAVE_MMX
+ mp_msg(MSGT_CPLAYER,MSGL_INFO," MMX");
+#endif
+#ifdef HAVE_MMX2
+ mp_msg(MSGT_CPLAYER,MSGL_INFO," MMX2");
+#endif
+#ifdef HAVE_3DNOW
+ mp_msg(MSGT_CPLAYER,MSGL_INFO," 3DNow");
+#endif
+#ifdef HAVE_3DNOWEX
+ mp_msg(MSGT_CPLAYER,MSGL_INFO," 3DNowEx");
+#endif
+#ifdef HAVE_SSE
+ mp_msg(MSGT_CPLAYER,MSGL_INFO," SSE");
+#endif
+#ifdef HAVE_SSE2
+ mp_msg(MSGT_CPLAYER,MSGL_INFO," SSE2");
+#endif
+ mp_msg(MSGT_CPLAYER,MSGL_INFO,"\n\n");
+#endif
+#endif
+ console_state = 1;
+ }
+}
+
+void capitalize(char *filename)
+{
+ unsigned int i;
+ BOOL cap = TRUE;
+ for (i=0; i < strlen(filename); i++)
+ {
+ if (cap)
+ {
+ cap = FALSE;
+ filename[i] = toupper(filename[i]);
+ }
+ else if (filename[i] == ' ')
+ cap = TRUE;
+ else
+ filename[i] = tolower(filename[i]);
+ }
+}
+
+static image *get_drawground(HWND hwnd)
+{
+ gui_t * gui = (gui_t *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ unsigned int i;
+ if(!gui) return NULL;
+ for(i=0; i<gui->window_priv_count; i++)
+ if(gui->window_priv[i]->hwnd==hwnd)
+ return &gui->window_priv[i]->img;
+ return NULL;
+}
+
+static HBITMAP get_bitmap(HWND hwnd)
+{
+ gui_t *gui = (gui_t *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ unsigned int i;
+ if(!gui) return NULL;
+ for(i=0; i<gui->window_priv_count; i++)
+ if(gui->window_priv[i]->hwnd == hwnd)
+ return gui->window_priv[i]->bitmap;
+ return NULL;
+}
+
+static int get_windowtype(HWND hwnd)
+{
+ gui_t *gui = (gui_t *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ unsigned int i;
+ if(!gui) return -1;
+ for(i=0; i<gui->window_priv_count; i++)
+ if(gui->window_priv[i]->hwnd == hwnd)
+ return gui->window_priv[i]->type;
+ return -1;
+}
+
+static void uninit(gui_t *gui)
+{
+ if(gui->skin) destroy_window(gui);
+ if(gui->playlist) gui->playlist->free_playlist(gui->playlist);
+ gui->playlist = NULL;
+}
+
+/*
+ the gui message handler
+ tries to handle the incoming messages
+ and passes them to the player's message handler if it can't handle them
+*/
+static void handlemsg(HWND hWnd, int msg)
+{
+ gui_t *gui = (gui_t *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
+ if(msg == evNone) return;
+
+ switch(msg)
+ {
+ case evLoadPlay:
+ case evLoad:
+ if(display_openfilewindow(gui, 0) && (msg == evLoadPlay))
+ handlemsg(hWnd, evDropFile);
+ return;
+#ifdef USE_SUB
+ case evLoadSubtitle:
+ display_opensubtitlewindow(gui);
+ break;
+#endif
+ case evPreferences:
+ display_prefswindow(gui);
+ return;
+ case evPlayList:
+ display_playlistwindow(gui);
+ return;
+ case evSkinBrowser:
+ display_skinbrowser(gui);
+ break;
+ case evEqualizer:
+ display_eqwindow(gui);
+ break;
+ case evAbout:
+ MessageBox(hWnd, COPYRIGHT, "About", MB_OK);
+ break;
+ case evIconify:
+ ShowWindow(hWnd, SW_MINIMIZE);
+ break;
+ case evIncVolume:
+ mplayer_put_key(KEY_VOLUME_UP);
+ break;
+ case evDecVolume:
+ mplayer_put_key(KEY_VOLUME_DOWN);
+ break;
+ default:
+ mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] received msg %s (%i)\n", gui->skin->geteventname(msg), msg);
+ break;
+ }
+ gui->playercontrol(msg);
+}
+
+static widget *clickedinsidewidget(gui_t *gui, int window, int x, int y)
+{
+ unsigned int i;
+ widget *item;
+ for(i=0; i<gui->skin->widgetcount; i++)
+ {
+ item = gui->skin->widgets[i];
+ if((item->window == window) && (item->x <= x) && (item->x + item->width >= x) &&
+ (item->y <= y) && (item->y + item->height >= y))
+ return item;
+ }
+ return NULL;
+}
+
+/* updates sliders and the display */
+static void updatedisplay(gui_t *gui, HWND hwnd)
+{
+ if(!hwnd) return;
+
+ unsigned int i;
+ window_priv_t *priv = NULL;
+
+ /* load all potmeters hpotmeters */
+ for(i=0; i<gui->skin->widgetcount; i++)
+ {
+ if(gui->skin->widgets[i]->type == tyHpotmeter || gui->skin->widgets[i]->type == tyPotmeter)
+ {
+ if(gui->skin->widgets[i]->msg == evSetVolume)
+ gui->skin->widgets[i]->value = guiIntfStruct.Volume;
+ else if(gui->skin->widgets[i]->msg == evSetMoviePosition)
+ gui->skin->widgets[i]->value = guiIntfStruct.Position;
+ else if(gui->skin->widgets[i]->msg == evSetBalance)
+ gui->skin->widgets[i]->value = guiIntfStruct.Balance;
+ if(gui->skin->widgets[i]->window == get_windowtype(hwnd))
+ renderwidget(gui->skin, get_drawground(hwnd), gui->skin->widgets[i],
+ gui->skin->widgets[i]->pressed ? 0 : 1);
+ }
+ /* update some buttons */
+ if(gui->skin->widgets[i]->type == tyButton && gui->skin->widgets[i]->window == get_windowtype(hwnd))
+ {
+ if(gui->skin->widgets[i]->msg == evPlaySwitchToPause)
+ {
+ gui->skin->widgets[i]->value = guiIntfStruct.Playing;
+ renderwidget(gui->skin, get_drawground(hwnd), gui->skin->widgets[i],
+ guiIntfStruct.Playing == 1 ? 0 : 1);
+ }
+ if(gui->skin->widgets[i]->msg == evMute)
+ {
+ gui->skin->widgets[i]->value = guiIntfStruct.Volume;
+ renderwidget(gui->skin, get_drawground(hwnd), gui->skin->widgets[i],
+ guiIntfStruct.Volume == 0.0f ? 0 : 1);
+ }
+ }
+ }
+
+ /* updating the display once a 100.second is enough imo */
+ DWORD time = timeGetTime();
+ if((time - oldtime) < 100) return;
+ oldtime=time;
+
+ for (i=0; i<gui->window_priv_count; i++)
+ {
+ if(gui->window_priv[i]->hwnd == hwnd)
+ priv=gui->window_priv[i];
+ }// Sherpya
+ /* display the status msgs */
+ renderinfobox(gui->skin, priv);
+ RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE);
+}
+
+static LRESULT CALLBACK SubProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ gui_t *gui = (gui_t *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
+ if (gui && (gui->subwindow != hWnd)) return FALSE;
+
+ switch (message)
+ {
+ case WM_CLOSE:
+ handlemsg(hWnd, evExit);
+ return 0;
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ return 0;
+ case WM_KEYDOWN:
+ {
+ switch(wParam)
+ {
+ case VK_LEFT:
+ mplayer_put_key(KEY_LEFT);
+ break;
+ case VK_UP:
+ mplayer_put_key(KEY_UP);
+ break;
+ case VK_RIGHT:
+ mplayer_put_key(KEY_RIGHT);
+ break;
+ case VK_DOWN:
+ mplayer_put_key(KEY_DOWN);
+ break;
+ case VK_TAB:
+ mplayer_put_key(KEY_TAB);
+ break;
+ case VK_BACK:
+ mplayer_put_key(KEY_BS);
+ break;
+ case VK_DELETE:
+ mplayer_put_key(KEY_DELETE);
+ break;
+ case VK_INSERT:
+ mplayer_put_key(KEY_INSERT);
+ break;
+ case VK_HOME:
+ mplayer_put_key(KEY_HOME);
+ break;
+ case VK_END:
+ mplayer_put_key(KEY_END);
+ break;
+ case VK_PRIOR:
+ mplayer_put_key(KEY_PAGE_UP);
+ break;
+ case VK_NEXT:
+ mplayer_put_key(KEY_PAGE_DOWN);
+ break;
+ case VK_ESCAPE:
+ mplayer_put_key(KEY_ESC);
+ break;
+ }
+ break;
+ }
+ case WM_COMMAND:
+ {
+ switch(LOWORD(wParam))
+ {
+ case IDEXIT:
+ PostQuitMessage(0);
+ handlemsg(hWnd, evExit);
+ break;
+ case IDFILE_OPEN:
+ handlemsg(hWnd, evLoadPlay);
+ break;
+ case IDURL_OPEN:
+ display_openurlwindow(gui, 0);
+ break;
+ case IDDIR_OPEN:
+ {
+ static char path[MAX_PATH];
+ BROWSEINFO bi;
+ memset(&bi, 0, sizeof(BROWSEINFO));
+ bi.lpszTitle = "Choose a Directory...";
+ LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
+ if (SHGetPathFromIDList(pidl, path))
+ {
+ gui->playlist->clear_playlist(gui->playlist);
+ adddirtoplaylist(gui->playlist, path, TRUE);
+ gui->startplay(gui);
+ }
+ break;
+ }
+ case ID_PTRACK:
+ handlemsg(hWnd, evPrev);
+ break;
+ case ID_SEEKB:
+ handlemsg(hWnd, evBackward10sec);
+ break;
+ case ID_PLAY:
+ handlemsg(hWnd, evPlaySwitchToPause);
+ break;
+ case ID_STOP:
+ handlemsg(hWnd, evStop);
+ break;
+ case ID_SEEKF:
+ handlemsg(hWnd, evForward10sec);
+ break;
+ case ID_NTRACK:
+ handlemsg(hWnd, evNext);
+ break;
+#ifdef USE_DVDREAD
+ case ID_CHAPTERSEL:
+ display_chapterselwindow(gui);
+ break;
+#endif
+ case ID_ASPECT1:
+ mp_input_queue_cmd(mp_input_parse_cmd("switch_ratio 1.777777"));
+ break;
+ case ID_ASPECT2:
+ mp_input_queue_cmd(mp_input_parse_cmd("switch_ratio 1.333333"));
+ break;
+ case ID_ASPECT3:
+ mp_input_queue_cmd(mp_input_parse_cmd("switch_ratio 2.35"));
+ break;
+ case ID_ASPECT4:
+ mp_input_queue_cmd(mp_input_parse_cmd("switch_ratio 0"));
+ break;
+ case IDSUB_TOGGLE:
+ mp_input_queue_cmd(mp_input_parse_cmd("sub_visibility"));
+ break;
+ case IDSUB_CYCLE:
+ mp_input_queue_cmd(mp_input_parse_cmd("sub_select"));
+ break;
+ }
+ return 0;
+ }
+ case WM_CHAR:
+ mplayer_put_key(wParam);
+ break;
+ case WM_DROPFILES:
+ {
+ if(!lParam)
+ {
+ char file[MAX_PATH];
+ int filecount = DragQueryFile((HDROP) wParam, -1, file, MAX_PATH);
+ int i;
+ for(i=0; i<filecount; i++)
+ {
+ DragQueryFile((HDROP) wParam, i, file, MAX_PATH);
+ if(!parse_filename(file, playtree, mconfig, 1))
+ gui->playlist->add_track(gui->playlist, file, NULL, NULL, 0);
+ }
+ DragFinish((HDROP) wParam);
+ handlemsg(hWnd, evDropFile);
+ }
+ else
+ {
+ gui->playlist->clear_playlist(gui->playlist);
+ gui->playlist->add_track(gui->playlist, (const char *) wParam, NULL, NULL, 0);
+ handlemsg(hWnd, evDropFile);
+ }
+ SetForegroundWindow(gui->subwindow);
+ return 0;
+ }
+ case WM_LBUTTONDOWN:
+ {
+ if(!vo_nomouse_input)
+ mplayer_put_key(MOUSE_BTN0);
+ break;
+ }
+ case WM_MBUTTONDOWN:
+ {
+ if(!vo_nomouse_input)
+ mplayer_put_key(MOUSE_BTN1);
+ break;
+ }
+ case WM_RBUTTONDOWN:
+ {
+ POINT point;
+ point.x = GET_X_LPARAM(lParam);
+ point.y = GET_Y_LPARAM(lParam);
+ ClientToScreen(hWnd, &point);
+ if(guiIntfStruct.StreamType == STREAMTYPE_DVD)
+ EnableMenuItem(gui->dvdmenu, ID_CHAPTERSEL, MF_BYCOMMAND | MF_ENABLED);
+ TrackPopupMenu(gui->submenu, 0, point.x, point.y, 0, hWnd, NULL);
+ return 0;
+ }
+ case WM_LBUTTONDBLCLK:
+ {
+ if(!vo_nomouse_input)
+ mplayer_put_key(MOUSE_BTN0_DBL);
+ break;
+ }
+ case WM_MBUTTONDBLCLK:
+ {
+ if(!vo_nomouse_input)
+ mplayer_put_key(MOUSE_BTN1_DBL);
+ break;
+ }
+ case WM_RBUTTONDBLCLK:
+ {
+ if(!vo_nomouse_input)
+ mplayer_put_key(MOUSE_BTN2_DBL);
+ break;
+ }
+ case WM_MOUSEWHEEL:
+ {
+ if(vo_nomouse_input)
+ break;
+ int x = GET_WHEEL_DELTA_WPARAM(wParam);
+ if (x > 0)
+ mplayer_put_key(MOUSE_BTN3);
+ else
+ mplayer_put_key(MOUSE_BTN4);
+ break;
+ }
+ case WM_XBUTTONDOWN:
+ {
+ if(vo_nomouse_input)
+ break;
+ if(HIWORD(wParam) == 1)
+ mplayer_put_key(MOUSE_BTN5);
+ else
+ mplayer_put_key(MOUSE_BTN6);
+ break;
+ }
+ case WM_XBUTTONDBLCLK:
+ {
+ if(vo_nomouse_input)
+ break;
+ if(HIWORD(wParam) == 1)
+ mplayer_put_key(MOUSE_BTN5_DBL);
+ else
+ mplayer_put_key(MOUSE_BTN6_DBL);
+ break;
+ }
+ case WM_WINDOWPOSCHANGED:
+ {
+ int tmpheight=0;
+ static uint32_t rect_width;
+ static uint32_t rect_height;
+ RECT rd;
+ POINT pt;
+ while(ShowCursor(TRUE) <= 0){}
+ pt.x = 0;
+ pt.y = 0;
+ GetClientRect(hWnd, &rd);
+ ClientToScreen(hWnd, &pt);
+
+ rect_width = rd.right - rd.left;
+ rect_height = rd.bottom - rd.top;
+
+ /* maintain our aspect ratio */
+ tmpheight = ((float)rect_width/sub_aspect);
+ tmpheight += tmpheight % 2;
+ if(tmpheight > rect_height)
+ {
+ rect_width = ((float)rect_height*sub_aspect);
+ rect_width += rect_width % 2;
+ }
+ else rect_height = tmpheight;
+
+ rd.right = rd.left + rect_width;
+ rd.bottom = rd.top + rect_height;
+
+ AdjustWindowRect(&rd, WS_OVERLAPPEDWINDOW | WS_SIZEBOX, 0);
+ SetWindowPos(hWnd, HWND_NOTOPMOST, pt.x+rd.left, pt.y+rd.top,
+ rd.right-rd.left, rd.bottom-rd.top, SWP_NOOWNERZORDER);
+ return 0;
+ }
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ RECT rect;
+ HDC hdc = BeginPaint(hWnd, &ps);
+ HDC hMemDC = CreateCompatibleDC(hdc);
+ int width, height;
+ GetClientRect(hWnd, &rect);
+ width = rect.right - rect.left;
+ height = rect.bottom - rect.top;
+ if(guiIntfStruct.Playing == 0)
+ {
+ int i;
+ window *desc = NULL;
+
+ for (i=0; i<gui->skin->windowcount; i++)
+ if(gui->skin->windows[i]->type == wiSub)
+ desc = gui->skin->windows[i];
+
+ SelectObject(hMemDC, get_bitmap(hWnd));
+ StretchBlt(hdc, 0, 0, width, height, hMemDC, 0, 0, desc->base->bitmap[0]->width,
+ desc->base->bitmap[0]->height, SRCCOPY);
+ }
+ DeleteDC(hMemDC);
+ EndPaint(hWnd, &ps);
+ return 0;
+ }
+ }
+ return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+/* Window Proc for the gui Window */
+static LRESULT CALLBACK EventProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ gui_t *gui = (gui_t *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
+
+ /* Avoid processing when then window doesn't match gui mainwindow */
+ if (gui && (gui->mainwindow != hWnd)) return FALSE;
+
+ switch (message)
+ {
+ case WM_CLOSE:
+ handlemsg(hWnd, evExit);
+ return 0;
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ return 0;
+ case WM_SYSTRAY:
+ {
+ switch(lParam)
+ {
+ POINT cursor;
+ case WM_RBUTTONDOWN:
+ {
+ GetCursorPos(&cursor);
+ SetForegroundWindow(hWnd);
+ TrackPopupMenu(gui->traymenu, 0, cursor.x, cursor.y, 0, hWnd, NULL);
+ break;
+ }
+ case WM_MBUTTONDBLCLK:
+ case WM_LBUTTONDBLCLK:
+ {
+ if(IsWindowVisible(hWnd)) ShowWindow(hWnd, SW_HIDE);
+ else { ShowWindow(hWnd, SW_SHOW); SetForegroundWindow(hWnd); }
+ break;
+ }
+ }
+ break;
+ }
+ case WM_KEYDOWN:
+ {
+ switch(wParam)
+ {
+ case VK_LEFT:
+ mplayer_put_key(KEY_LEFT);
+ break;
+ case VK_UP:
+ mplayer_put_key(KEY_UP);
+ break;
+ case VK_RIGHT:
+ mplayer_put_key(KEY_RIGHT);
+ break;
+ case VK_DOWN:
+ mplayer_put_key(KEY_DOWN);
+ break;
+ case VK_TAB:
+ mplayer_put_key(KEY_TAB);
+ break;
+ case VK_BACK:
+ mplayer_put_key(KEY_BS);
+ break;
+ case VK_DELETE:
+ mplayer_put_key(KEY_DELETE);
+ break;
+ case VK_INSERT:
+ mplayer_put_key(KEY_INSERT);
+ break;
+ case VK_HOME:
+ mplayer_put_key(KEY_HOME);
+ break;
+ case VK_END:
+ mplayer_put_key(KEY_END);
+ break;
+ case VK_PRIOR:
+ mplayer_put_key(KEY_PAGE_UP);
+ break;
+ case VK_NEXT:
+ mplayer_put_key(KEY_PAGE_DOWN);
+ break;
+ case VK_ESCAPE:
+ mplayer_put_key(KEY_ESC);
+ break;
+ }
+ break;
+ }
+ case WM_CHAR:
+ mplayer_put_key(wParam);
+ break;
+ case WM_SYSCOMMAND:
+ {
+ switch(wParam)
+ {
+ case SC_SCREENSAVE:
+ case SC_MONITORPOWER:
+ mp_msg(MSGT_VO, MSGL_V ,"<vo_directx><INFO>killing screensaver\n" );
+ return 0;
+ }
+ break;
+ }
+ case WM_COPYDATA:
+ {
+ if(lParam)
+ {
+ PCOPYDATASTRUCT cdData;
+ cdData = (PCOPYDATASTRUCT) lParam;
+ if(!parse_filename(cdData->lpData, playtree, mconfig, 1))
+ gui->playlist->add_track(gui->playlist, cdData->lpData, NULL, NULL, 0);
+ gui->startplay(gui);
+ }
+ break;
+ }
+ case WM_DROPFILES:
+ {
+ if(!lParam)
+ {
+ char file[MAX_PATH];
+ int filecount = DragQueryFile((HDROP) wParam, -1, file, MAX_PATH);
+ int i;
+ for(i=0; i<filecount; i++)
+ {
+ DragQueryFile((HDROP) wParam, i, file, MAX_PATH);
+ if(!parse_filename(file, playtree, mconfig, 1))
+ gui->playlist->add_track(gui->playlist, file, NULL, NULL, 0);
+ }
+ DragFinish((HDROP) wParam);
+ handlemsg(hWnd, evDropFile);
+ }
+ else
+ {
+ gui->playlist->clear_playlist(gui->playlist);
+ gui->playlist->add_track(gui->playlist, (const char *) wParam, NULL, NULL, 0);
+ handlemsg(hWnd, evDropFile);
+ }
+ SetForegroundWindow(gui->mainwindow);
+ return 0;
+ }
+ case WM_LBUTTONDOWN:
+ {
+ SetCapture(hWnd);
+ gui->mousex = GET_X_LPARAM(lParam);
+ gui->mousey = GET_Y_LPARAM(lParam);
+ /* inside a widget */
+ gui->activewidget = clickedinsidewidget(gui, get_windowtype(hWnd), gui->mousex, gui->mousey);
+ if(gui->activewidget)
+ {
+ gui->activewidget->pressed = 1;
+ gui->mousewx = gui->mousex - gui->activewidget->x;
+ gui->mousewy = gui->mousey - gui->activewidget->y;
+ renderwidget(gui->skin, get_drawground(hWnd), gui->activewidget, 0);
+ RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE);
+ handlemsg(hWnd, gui->activewidget->msg);
+ }
+ break;
+ }
+ case WM_CAPTURECHANGED:
+ {
+ if(gui->activewidget)
+ {
+ gui->activewidget->pressed = 0;
+ renderwidget(gui->skin, get_drawground(hWnd), gui->activewidget, 1);
+ RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE);
+ gui->activewidget = NULL;
+ }
+ break;
+ }
+ case WM_LBUTTONUP:
+ {
+ ReleaseCapture();
+ if(gui->activewidget)
+ {
+ gui->activewidget->pressed = 0;
+ renderwidget(gui->skin, get_drawground(hWnd), gui->activewidget, 1);
+ RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE);
+ gui->activewidget = NULL;
+ }
+ break;
+ }
+ case WM_RBUTTONDOWN:
+ {
+ POINT point;
+ char device[MAX_PATH];
+ char searchpath[MAX_PATH];
+ char searchpath2[MAX_PATH];
+#ifdef HAVE_LIBCDIO
+ char searchpath3[MAX_PATH];
+#endif
+ int len, pos = 0, cdromdrive = 0;
+ point.x = GET_X_LPARAM(lParam);
+ point.y = GET_Y_LPARAM(lParam);
+ ClientToScreen(hWnd, &point);
+ len = GetLogicalDriveStrings(MAX_PATH, device);
+ while(pos < len)
+ {
+ if(GetDriveType(device + pos) == DRIVE_CDROM)
+ {
+ mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] checking %s for CD/VCD/SVCD/DVDs\n", device + pos);
+ sprintf(searchpath, "%sVIDEO_TS", device + pos);
+ sprintf(searchpath2, "%sMpegav", device + pos);
+#ifdef HAVE_LIBCDIO
+ sprintf(searchpath3, "%sTrack01.cda", device + pos);
+#endif
+ if(GetFileAttributes(searchpath) != INVALID_FILE_ATTRIBUTES)
+ EnableMenuItem(gui->diskmenu, IDPLAYDISK + cdromdrive, MF_BYCOMMAND | MF_ENABLED);
+ else if(GetFileAttributes(searchpath2) != INVALID_FILE_ATTRIBUTES)
+ EnableMenuItem(gui->diskmenu, IDPLAYDISK + cdromdrive, MF_BYCOMMAND | MF_ENABLED);
+#ifdef HAVE_LIBCDIO
+ else if(GetFileAttributes(searchpath3) != INVALID_FILE_ATTRIBUTES)
+ EnableMenuItem(gui->diskmenu, IDPLAYDISK + cdromdrive, MF_BYCOMMAND | MF_ENABLED);
+#endif
+ else EnableMenuItem(gui->diskmenu, IDPLAYDISK + cdromdrive, MF_BYCOMMAND | MF_GRAYED);
+ cdromdrive++;
+ }
+ pos += strlen(device + pos) + 1;
+ }
+ TrackPopupMenu(gui->menu, 0, point.x, point.y, 0, hWnd, NULL);
+ return 0;
+ }
+ case WM_MOUSEMOVE:
+ {
+ if(wParam & MK_LBUTTON)
+ {
+ POINT point;
+ RECT rect;
+ if(gui->activewidget)
+ {
+ widget *item = gui->activewidget;
+
+ if(item->type == tyHpotmeter)
+ {
+ item->x = GET_X_LPARAM(lParam) - gui->mousewx;
+ item->value = (float)((float)((item->x - item->wx) * 100.0f) / (float)(item->wwidth - item->width));
+ }
+ if(item->type == tyPotmeter)
+ {
+ gui->mousewx = GET_X_LPARAM(lParam) - gui->activewidget->x;
+ item->value = (float) (gui->mousewx * 100.0f) / (float) item->wwidth;
+ }
+
+ if((item->type == tyPotmeter) || (item->type == tyHpotmeter) || (item->type == tyVpotmeter))
+ {
+ /* Bound checks */
+ if(item->value > 100.0f)
+ item->value = 100.0f;
+ else if(item->value < 0.0f)
+ item->value = 0.0f;
+
+ if(item->msg == evSetVolume)
+ guiIntfStruct.Volume = (float) item->value;
+ else if(item->msg == evSetMoviePosition)
+ guiIntfStruct.Position = (float) item->value;
+ else if(item->msg == evSetBalance)
+ {
+ /* make the range for 50% a bit bigger, because the sliders for balance usually suck */
+ if((item->value - 50.0f < 1.5f) && (item->value - 50.0f > -1.5f))
+ item->value = 50.0f;
+ guiIntfStruct.Balance = (float) item->value;
+ }
+ updatedisplay(gui, hWnd);
+ handlemsg(hWnd, item->msg);
+ }
+ break;
+ }
+ point.x = GET_X_LPARAM(lParam);
+ point.y = GET_Y_LPARAM(lParam);
+ ClientToScreen(hWnd, &point);
+ GetWindowRect(hWnd, &rect);
+ MoveWindow(hWnd, point.x - gui->mousex, point.y - gui->mousey,
+ rect.right-rect.left,rect.bottom-rect.top,TRUE);
+ break;
+ }
+ break;
+ }
+ case WM_COMMAND:
+ {
+ switch(LOWORD(wParam))
+ {
+ case IDEXIT:
+ PostQuitMessage(0);
+ handlemsg(hWnd, evExit);
+ break;
+ case IDFILE_OPEN:
+ handlemsg(hWnd, evLoadPlay);
+ break;
+ case IDDIR_OPEN:
+ {
+ static char path[MAX_PATH];
+ BROWSEINFO bi;
+ memset(&bi, 0, sizeof(BROWSEINFO));
+ bi.lpszTitle = "Choose a Directory...";
+ LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
+ if (SHGetPathFromIDList(pidl, path))
+ {
+ gui->playlist->clear_playlist(gui->playlist);
+ adddirtoplaylist(gui->playlist, path, TRUE);
+ gui->startplay(gui);
+ }
+ break;
+ }
+ case ID_SKINBROWSER:
+ handlemsg(hWnd, evSkinBrowser);
+ break;
+ case IDURL_OPEN:
+ display_openurlwindow(gui, 0);
+ break;
+#ifdef USE_SUB
+ case IDSUBTITLE_OPEN:
+ display_opensubtitlewindow(gui);
+ break;
+#endif
+ case ID_PTRACK:
+ handlemsg(hWnd, evPrev);
+ break;
+ case ID_SEEKB:
+ handlemsg(hWnd, evBackward10sec);
+ break;
+ case ID_PLAY:
+ handlemsg(hWnd, evPlaySwitchToPause);
+ break;
+ case ID_STOP:
+ handlemsg(hWnd, evStop);
+ break;
+ case ID_SEEKF:
+ handlemsg(hWnd, evForward10sec);
+ break;
+ case ID_NTRACK:
+ handlemsg(hWnd, evNext);
+ break;
+ case ID_SHOWHIDE:
+ {
+ if(IsWindowVisible(hWnd)) ShowWindow(hWnd, SW_HIDE);
+ else ShowWindow(hWnd, SW_SHOW);
+ break;
+ }
+ case ID_PLAYLIST:
+ handlemsg(hWnd, evPlayList);
+ break;
+ case ID_PREFS:
+ handlemsg(hWnd, evPreferences);
+ break;
+ case ID_CONSOLE:
+ console_toggle();
+ break;
+ case ID_ONLINEHELP:
+ ShellExecute(NULL, "open", ONLINE_HELP_URL, NULL, NULL, SW_SHOWNORMAL);
+ break;
+ }
+ if((IDPLAYDISK <= LOWORD(wParam)) && (LOWORD(wParam) < (IDPLAYDISK + 100)))
+ {
+ char device[MAX_PATH];
+ char searchpath[MAX_PATH];
+ char filename[MAX_PATH];
+ int len, pos = 0, cdromdrive = 0;
+ len = GetLogicalDriveStrings(MAX_PATH, device);
+ while(pos < len)
+ {
+ if(GetDriveType(device + pos)==DRIVE_CDROM)
+ {
+ if(LOWORD(wParam) - IDPLAYDISK == cdromdrive)
+ {
+#ifdef USE_DVDREAD
+ sprintf(searchpath, "%sVIDEO_TS", device + pos);
+ if(GetFileAttributes(searchpath) != INVALID_FILE_ATTRIBUTES)
+ {
+ if (dvd_device) free(dvd_device);
+ dvd_device = strdup(device + pos);
+ dvd_title = dvd_chapter = dvd_angle = 1;
+ handlemsg(hWnd, evPlayDVD);
+ }
+#endif
+#ifdef HAVE_LIBCDIO
+ sprintf(searchpath, "%sTrack01.cda", device + pos);
+ if(GetFileAttributes(searchpath) != INVALID_FILE_ATTRIBUTES)
+ {
+ if (cdrom_device) free(cdrom_device);
+ cdrom_device = strdup(device + pos);
+ /* mplayer doesn't seem to like the trailing \ after the device name */
+ cdrom_device[2]=0;
+ handlemsg(hWnd, evPlayCD);
+ }
+#endif
+ else
+ {
+ HANDLE searchhndl;
+ WIN32_FIND_DATA finddata;
+ sprintf(searchpath, "%smpegav\\*.dat", device + pos);
+ if((searchhndl=FindFirstFile(searchpath, &finddata)) != INVALID_HANDLE_VALUE)
+ {
+ mp_msg(MSGT_GPLAYER,MSGL_V, "Opening VCD/SVCD\n");
+ gui->playlist->clear_playlist(gui->playlist);
+ do
+ {
+ sprintf(filename, "%smpegav\\%s", device + pos, finddata.cFileName);
+ gui->playlist->add_track(gui->playlist, filename, NULL, NULL, 0);
+ }
+ while(FindNextFile(searchhndl, &finddata));
+ FindClose(searchhndl);
+ }
+ gui->startplay(gui);
+ }
+ }
+ cdromdrive++;
+ }
+ pos += strlen(device + pos) + 1;
+ }
+ }
+ break;
+ }
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ RECT rd;
+ HDC hdc = BeginPaint(hWnd, &ps);
+ HDC hMemDC = CreateCompatibleDC(hdc);
+ int width, height;
+ GetClientRect(hWnd, &rd);
+ width = rd.right - rd.left;
+ height = rd.bottom - rd.top;
+ SelectObject(hMemDC, get_bitmap(hWnd));
+ BitBlt(hdc, 0, 0, width, height, hMemDC, 0, 0, SRCCOPY);
+ DeleteDC(hMemDC);
+ EndPaint(hWnd, &ps);
+ return 0;
+ }
+ return 0;
+ }
+ return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+inline void startplay(gui_t *gui)
+{
+ handlemsg(gui->mainwindow, evDropFile);
+}
+
+/* returns the bits per pixel of the desktop */
+/* the format is always in BGR byte order */
+static int GetDesktopBitsPerPixel(void)
+{
+ HWND desktop=GetDesktopWindow();
+ HDC dc=GetDC(desktop);
+ int bpp=GetDeviceCaps(dc, BITSPIXEL);
+ ReleaseDC(desktop, dc);
+ return bpp;
+}
+
+/* unloads a skin and destroys its windows */
+extern int destroy_window(gui_t *gui)
+{
+ RECT rd;
+ unsigned int i;
+
+ /* Save position: MSDN says don't pass workspace coordinates
+ * to CreateWindow() or SetWindowPos(), as both of which expect
+ * screen coordinates; resulting in the window appearing in the
+ * wrong location.
+ * -Erik
+ */
+
+ /* main window position */
+ if(IsIconic(gui->mainwindow))
+ ShowWindow(gui->mainwindow, SW_SHOWNORMAL);
+ GetWindowRect(gui->mainwindow, &rd);
+ gui_main_pos_x = rd.left;
+ gui_main_pos_y = rd.top;
+
+ /* sub window position */
+ if(IsIconic(gui->subwindow))
+ ShowWindow(gui->subwindow, SW_SHOWNORMAL);
+ GetWindowRect(gui->subwindow, &rd);
+ gui_sub_pos_x = rd.left;
+ gui_sub_pos_y = rd.top;
+
+ for(i=0; i<gui->window_priv_count; i++)
+ {
+ if(gui->window_priv[i]->bitmap)
+ DeleteObject(gui->window_priv[i]->bitmap);
+ free(gui->window_priv[i]);
+ }
+ free(gui->window_priv);
+ gui->window_priv = NULL;
+ gui->window_priv_count = 0;
+
+ /* destroy the main window */
+ if(gui->mainwindow)
+ DestroyWindow(gui->mainwindow);
+ gui->mainwindow = NULL;
+
+ /* destroy the sub window */
+ if(gui->subwindow)
+ DestroyWindow(gui->subwindow);
+ gui->subwindow = NULL;
+
+ UnregisterClass(gui->classname, 0);
+ DestroyIcon(gui->icon);
+
+ gui->skin->freeskin(gui->skin);
+ gui->skin = NULL;
+ return 0;
+}
+
+static void create_menu(gui_t *gui)
+{
+ char device[MAX_PATH];
+ char volname[MAX_PATH];
+ char menuitem[MAX_PATH];
+ int len, pos = 0, cdromdrive = 0;
+ gui->diskmenu = CreatePopupMenu();
+ len = GetLogicalDriveStrings(MAX_PATH, device);
+ while(pos < len)
+ {
+ if(GetDriveType(device + pos) == DRIVE_CDROM)
+ {
+ volname[0] = 0;
+ menuitem[0] = 0;
+ strcat(menuitem, device + pos);
+ menuitem[strlen(menuitem) - 1]=0;
+ GetVolumeInformation(device + pos, volname, MAX_PATH, NULL, NULL, NULL, NULL, 0);
+ if (strlen(volname))
+ {
+ capitalize(volname);
+ strcat(menuitem, " - ");
+ strcat(menuitem, volname);
+ }
+ AppendMenu(gui->diskmenu, MF_STRING, IDPLAYDISK + cdromdrive, menuitem);
+ cdromdrive++;
+ }
+ pos += strlen(device + pos) + 1;
+ }
+ gui->menu=CreatePopupMenu();
+ gui->trayplaymenu = CreatePopupMenu();
+ AppendMenu(gui->menu, MF_STRING | MF_POPUP, (UINT) gui->trayplaymenu, "Open...");
+ AppendMenu(gui->trayplaymenu, MF_STRING, IDFILE_OPEN, "File...");
+ AppendMenu(gui->trayplaymenu, MF_STRING, IDURL_OPEN, "Url...");
+ AppendMenu(gui->trayplaymenu, MF_STRING, IDDIR_OPEN, "Directory...");
+ AppendMenu(gui->menu, MF_SEPARATOR, 0, 0);
+ AppendMenu(gui->menu, MF_STRING | MF_POPUP, (UINT) gui->diskmenu, "Play &CD/DVD/VCD/SVCD");
+ AppendMenu(gui->menu, MF_SEPARATOR, 0, 0);
+#ifdef USE_SUB
+ AppendMenu(gui->menu, MF_STRING, IDSUBTITLE_OPEN, "Open Subtitle");
+#endif
+ AppendMenu(gui->menu, MF_STRING, ID_SKINBROWSER, "Skin Browser");
+ AppendMenu(gui->menu, MF_SEPARATOR, 0, 0);
+ AppendMenu(gui->menu, MF_STRING, ID_PREFS, "Preferences");
+ AppendMenu(gui->menu, MF_STRING, ID_CONSOLE, "Debug Console");
+ AppendMenu(gui->menu, MF_STRING, ID_ONLINEHELP, "Online Help");
+ AppendMenu(gui->menu, MF_SEPARATOR, 0, 0);
+ AppendMenu(gui->menu, MF_STRING, IDEXIT, "&Exit");
+}
+
+static void create_traymenu(gui_t *gui)
+{
+ gui->traymenu = CreatePopupMenu();
+ gui->trayplaybackmenu = CreatePopupMenu();
+ AppendMenu(gui->traymenu, MF_STRING | MF_POPUP, (UINT) gui->trayplaymenu, "Open...");
+ AppendMenu(gui->traymenu, MF_SEPARATOR, 0, 0);
+ AppendMenu(gui->traymenu, MF_STRING | MF_POPUP, (UINT) gui->trayplaybackmenu, "Playback");
+ AppendMenu(gui->trayplaybackmenu, MF_STRING, ID_SEEKB, "Seek Backwards");
+ AppendMenu(gui->trayplaybackmenu, MF_STRING, ID_PTRACK, "Previous Track");
+ AppendMenu(gui->trayplaybackmenu, MF_STRING, ID_PLAY, "Play/Pause");
+ AppendMenu(gui->trayplaybackmenu, MF_STRING, ID_STOP, "Stop");
+ AppendMenu(gui->trayplaybackmenu, MF_STRING, ID_NTRACK, "Next Track");
+ AppendMenu(gui->trayplaybackmenu, MF_STRING, ID_SEEKF, "Seek Forwards");
+ AppendMenu(gui->traymenu, MF_SEPARATOR, 0, 0);
+#ifdef USE_SUB
+ AppendMenu(gui->traymenu, MF_STRING, IDSUBTITLE_OPEN, "Open Subtitle");
+#endif
+ AppendMenu(gui->traymenu, MF_STRING, ID_PLAYLIST, "Playlist");
+ AppendMenu(gui->traymenu, MF_SEPARATOR, 0, 0);
+ AppendMenu(gui->traymenu, MF_STRING, ID_SHOWHIDE, "Show/Hide");
+ AppendMenu(gui->traymenu, MF_SEPARATOR, 0, 0);
+ AppendMenu(gui->traymenu, MF_STRING, ID_PREFS, "Preferences");
+ AppendMenu(gui->traymenu, MF_STRING, ID_CONSOLE, "Debug Console");
+ AppendMenu(gui->traymenu, MF_STRING, ID_ONLINEHELP, "Online Help");
+ AppendMenu(gui->traymenu, MF_SEPARATOR, 0, 0);
+ AppendMenu(gui->traymenu, MF_STRING, IDEXIT, "&Exit");
+}
+
+static void create_submenu(gui_t *gui)
+{
+ gui->submenu = CreatePopupMenu();
+ gui->dvdmenu = CreatePopupMenu();
+ gui->aspectmenu = CreatePopupMenu();
+ gui->subtitlemenu = CreatePopupMenu();
+ AppendMenu(gui->submenu, MF_STRING | MF_POPUP, (UINT) gui->trayplaymenu, "Open...");
+ AppendMenu(gui->submenu, MF_SEPARATOR, 0, 0);
+ AppendMenu(gui->submenu, MF_STRING, ID_SEEKB, "Seek Backwards");
+ AppendMenu(gui->submenu, MF_STRING, ID_PTRACK, "Previous Track");
+ AppendMenu(gui->submenu, MF_STRING, ID_PLAY, "Play/Pause");
+ AppendMenu(gui->submenu, MF_STRING, ID_STOP, "Stop");
+ AppendMenu(gui->submenu, MF_STRING, ID_NTRACK, "Next Track");
+ AppendMenu(gui->submenu, MF_STRING, ID_SEEKF, "Seek Forwards");
+ AppendMenu(gui->submenu, MF_SEPARATOR, 0, 0);
+ AppendMenu(gui->submenu, MF_STRING | MF_POPUP, (UINT) gui->aspectmenu, "Aspect Ratio");
+ AppendMenu(gui->submenu, MF_STRING | MF_POPUP, (UINT) gui->subtitlemenu, "Subtitle Options");
+ AppendMenu(gui->submenu, MF_STRING | MF_POPUP, (UINT) gui->dvdmenu, "DVD Options");
+#ifdef USE_DVDREAD
+ AppendMenu(gui->dvdmenu, MF_STRING | MF_GRAYED, ID_CHAPTERSEL, "Select Title/Chapter...");
+#endif
+ AppendMenu(gui->subtitlemenu, MF_STRING, IDSUB_TOGGLE, "Subtitle Visibility On/Off");
+ AppendMenu(gui->subtitlemenu, MF_STRING, IDSUB_CYCLE, "Cycle Subtitle Languages");
+ AppendMenu(gui->aspectmenu, MF_STRING, ID_ASPECT1, "Set 16:9");
+ AppendMenu(gui->aspectmenu, MF_STRING, ID_ASPECT2, "Set 4:3");
+ AppendMenu(gui->aspectmenu, MF_STRING, ID_ASPECT3, "Set 2.35");
+ AppendMenu(gui->aspectmenu, MF_SEPARATOR, 0, 0);
+ AppendMenu(gui->aspectmenu, MF_STRING, ID_ASPECT4, "Original Aspect");
+ AppendMenu(gui->submenu, MF_SEPARATOR, 0, 0);
+ AppendMenu(gui->submenu, MF_STRING, IDEXIT, "&Exit");
+}
+
+static void maketransparent(HWND hwnd, COLORREF crTransparent)
+{
+ HDC mdc = GetDC(hwnd);
+ RECT rd;
+ HRGN crRgnres, crRgn, crRgnTmp;
+ int iX = 0, iY = 0, iLeftX = 0;
+ int width, height;
+ GetWindowRect(hwnd, &rd);
+ width = rd.right - rd.left;
+ height = rd.bottom - rd.top;
+
+ /* create an empty region */
+ crRgn = CreateRectRgn(0, 0, 0, 0);
+
+ /* Create a region from a bitmap with transparency colour of Purple */
+ for (iY = -1; iY < height; iY++)
+ {
+ do
+ {
+ /* skip over transparent pixels at start of lines */
+ while (iX <= width && GetPixel(mdc,iX, iY) == crTransparent) iX++;
+
+ /* remember this pixel */
+ iLeftX = iX;
+
+ /* now find first non transparent pixel */
+ while (iX <= width && GetPixel(mdc,iX, iY) != crTransparent) ++iX;
+
+ /* create a temp region on this info */
+ crRgnTmp = CreateRectRgn(iLeftX, iY, iX, iY+1);
+
+ /* combine into main region */
+ crRgnres = crRgn;
+ CombineRgn(crRgnres, crRgn, crRgnTmp, RGN_OR);
+ crRgn = crRgnres;
+
+ /* delete the temp region for next pass (otherwise you'll get an ASSERT) */
+ DeleteObject(crRgnTmp);
+ } while (iX < width);
+ iX = 0;
+ }
+ SetWindowRgn(hwnd, crRgn, TRUE);
+ DeleteObject(crRgn);
+ ReleaseDC(hwnd,mdc);
+}
+
+static int window_render(gui_t *gui, HWND hWnd, HDC hdc, window_priv_t *priv, window *desc, BITMAPINFO binfo)
+{
+ int i;
+ SetWindowLongPtr(hWnd, GWLP_USERDATA, (DWORD) gui);
+ (gui->window_priv_count)++;
+ gui->window_priv = realloc(gui->window_priv, sizeof(window_priv_t *) * gui->window_priv_count);
+ priv = gui->window_priv[gui->window_priv_count - 1] = calloc(1, sizeof(window_priv_t));
+ priv->hwnd = hWnd;
+ priv->type = desc->type;
+ priv->background = desc->base->bitmap[0];
+ memcpy(&priv->img, desc->base->bitmap[0], sizeof(image));
+ hdc = GetDC(hWnd);
+ binfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ binfo.bmiHeader.biWidth = priv->img.width;
+ binfo.bmiHeader.biHeight = -priv->img.height;
+ binfo.bmiHeader.biPlanes = 1;
+ binfo.bmiHeader.biSizeImage = priv->img.width * priv->img.height * (gui->screenbpp / 8);
+ binfo.bmiHeader.biXPelsPerMeter = 0;
+ binfo.bmiHeader.biYPelsPerMeter = 0;
+ binfo.bmiHeader.biClrUsed = 0;
+ binfo.bmiHeader.biClrImportant = 0;
+ binfo.bmiHeader.biBitCount = gui->screenbpp;
+ binfo.bmiHeader.biCompression = BI_RGB;
+ priv->bitmap = CreateDIBSection(hdc, &binfo, DIB_RGB_COLORS, (void **) &priv->img.data, NULL, 0);
+ if(!priv->bitmap)
+ {
+ mp_msg(MSGT_GPLAYER, MSGL_FATAL, "[GUI] unable to create bitmap for skinned window\n");
+ return 0;
+ }
+ memcpy(priv->img.data, desc->base->bitmap[0]->data, binfo.bmiHeader.biSizeImage);
+ ReleaseDC(hWnd,hdc);
+
+ for (i=0; i<gui->skin->widgetcount; i++)
+ if(gui->skin->widgets[i]->window == desc->type)
+ renderwidget(gui->skin, &priv->img, gui->skin->widgets[i], 1);
+
+ return 0;
+}
+
+/* creates the sub (AKA video) window,*/
+extern int create_subwindow(gui_t *gui, char *skindir)
+{
+ HINSTANCE instance = GetModuleHandle(NULL);
+ WNDCLASS wc;
+ RECT rect;
+ HWND hWnd;
+ DWORD style = 0;
+ HDC hdc = NULL;
+ BITMAPINFO binfo;
+ window_priv_t *priv = NULL;
+ window *desc = NULL;
+ int i, x = -1, y = -1;
+
+ for (i=0; i<gui->skin->windowcount; i++)
+ if(gui->skin->windows[i]->type == wiSub)
+ desc = gui->skin->windows[i];
+
+ if(!desc)
+ {
+ mp_msg(MSGT_GPLAYER, MSGL_FATAL, "[GUI] Invalid skin description\n");
+ return 1;
+ }
+
+ windowcolor = vo_colorkey;
+ colorbrush = CreateSolidBrush(windowcolor);
+ wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
+ wc.lpfnWndProc = SubProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = instance;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hIcon = gui->icon;
+ wc.hbrBackground = colorbrush;
+ wc.lpszClassName = "MPlayer Sub for Windows";
+ wc.lpszMenuName = NULL;
+ RegisterClass(&wc);
+
+ /* create the sub window menu */
+ create_submenu(gui);
+
+ rect.top = rect.left = 100;
+ rect.bottom = rect.top+desc->base->bitmap[0]->height;
+ rect.right = rect.left+desc->base->bitmap[0]->width;
+
+ /* our window aspect */
+ sub_aspect = (float)(rect.right-rect.left)/(rect.bottom-rect.top);
+
+ style = WS_OVERLAPPEDWINDOW | WS_SYSMENU | WS_MINIMIZEBOX;
+ AdjustWindowRect(&rect, style, 0);
+
+ if (gui_sub_pos_x >= 0)
+ x = gui_sub_pos_x;
+ if (gui_sub_pos_y >= 0)
+ y = gui_sub_pos_y;
+
+ /* out of bounds check */
+ if (x <= -1 || (x+(rect.right-rect.left) > GetSystemMetrics(SM_CXSCREEN)))
+ x = CW_USEDEFAULT;
+ if (y <= -1 || (y+(rect.bottom-rect.top) > GetSystemMetrics(SM_CYSCREEN)))
+ y = x;
+
+ hWnd = CreateWindowEx(0, "MPlayer Sub for Windows", "MPlayer for Windows", style,
+ x, y, rect.right-rect.left, rect.bottom-rect.top,
+ gui->subwindow, NULL, instance, NULL);
+
+ /* load all the window images */
+ window_render(gui, hWnd, hdc, priv, desc, binfo);
+
+ /* enable drag and drop support */
+ DragAcceptFiles(hWnd, TRUE);
+
+ gui->subwindow = hWnd;
+ if(sub_window)
+ WinID = gui->subwindow;
+ ShowWindow(gui->subwindow, SW_SHOW);
+ UpdateWindow(gui->subwindow);
+ return 0;
+}
+
+/* loads/updates a skin and creates windows for it */
+extern int create_window(gui_t *gui, char *skindir)
+{
+ HINSTANCE instance = GetModuleHandle(NULL);
+ WNDCLASS wc;
+ RECT rect;
+ DWORD style = 0;
+ HWND hwnd;
+ HDC hdc = NULL;
+ BITMAPINFO binfo;
+ window_priv_t *priv = NULL;
+ window *desc = NULL;
+ char dir[MAX_PATH];
+ unsigned int i;
+
+ /* destroy the current main window */
+ if(gui->skin) destroy_window(gui);
+
+ /* get screenproperties */
+ gui->screenbpp = GetDesktopBitsPerPixel();
+ gui->screenw = GetSystemMetrics(SM_CXSCREEN);
+ gui->screenh = GetSystemMetrics(SM_CYSCREEN);
+
+ /* load the new skin */
+ gui->skin = loadskin(skindir, gui->screenbpp);
+ if(!gui->skin)
+ {
+ mp_msg(MSGT_GPLAYER, MSGL_FATAL, "[GUI] fatal error during skinload\n");
+ /* Set default Skin */
+ if (skinName) free(skinName);
+ skinName = strdup("Blue");
+ /* then force write conf */
+ cfg_write();
+ return 1;
+ }
+
+ /* find the description of the mainwindow */
+ for (i=0; i<gui->skin->windowcount; i++)
+ if(gui->skin->windows[i]->type == wiMain)
+ desc = gui->skin->windows[i];
+
+ if(!desc)
+ {
+ mp_msg(MSGT_GPLAYER, MSGL_FATAL, "[GUI] Invalid skin description\n");
+ return 1;
+ }
+
+ /* load the icon from the executable */
+ GetModuleFileName(NULL, dir, MAX_PATH);
+ gui->icon = ExtractIcon(instance, dir, 0);
+ int x = -1, y = -1;
+
+ /* create the window class */
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = EventProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = instance;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hIcon = gui->icon;
+ wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
+ wc.lpszClassName = gui->classname = "MPlayer GUI for Windows";
+ wc.lpszMenuName = NULL;
+ RegisterClass(&wc);
+
+ /* create a context menu */
+ create_menu(gui);
+ /* create the systray menu */
+ create_traymenu(gui);
+
+ /* create the mainwindow */
+ /* TODO implement aligning as described in skin.html */
+ rect.top = rect.left = 100;
+ rect.bottom = rect.top+desc->base->bitmap[0]->height;
+ rect.right = rect.left+desc->base->bitmap[0]->width;
+ if(desc->decoration) style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
+ else style = WS_POPUP | WS_SYSMENU;
+
+ AdjustWindowRect(&rect, style, 0);
+
+ /* Check if out of screen */
+ if (gui_main_pos_x >= 0)
+ x = gui_main_pos_x;
+ if (gui_main_pos_y >= 0)
+ y = gui_main_pos_y;
+
+ if (x <= -1 || (x+(rect.right-rect.left) > GetSystemMetrics(SM_CXFULLSCREEN)))
+ {
+ x = (GetSystemMetrics(SM_CXSCREEN) / 2) - ((rect.right-rect.left) / 2);
+ gui_main_pos_x = x;
+ }
+ if (y <= -1 || (y+(rect.bottom-rect.top) > GetSystemMetrics(SM_CYFULLSCREEN)))
+ {
+ y = ((GetSystemMetrics(SM_CYSCREEN)-40) - (rect.bottom-rect.top));
+ gui_main_pos_y = y;
+ }
+
+ hwnd = CreateWindowEx(0, gui->classname, "MPlayer for Windows", style,
+ x, y, rect.right-rect.left, rect.bottom-rect.top,
+ gui->mainwindow, NULL, instance, NULL);
+
+ /* set the systray icon properties */
+ nid.cbSize = sizeof(NOTIFYICONDATA);
+ nid.hWnd = hwnd;
+ nid.uID = 1;
+ nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
+ nid.uCallbackMessage = WM_SYSTRAY;
+ nid.hIcon = gui->icon;
+ strcpy(nid.szTip, "MPlayer for Windows");
+
+ /* register the systray icon */
+ Shell_NotifyIcon(NIM_ADD, &nid);
+
+ /* load all the window images */
+ window_render(gui, hwnd, hdc, priv, desc, binfo);
+
+ /* enable drag and drop support */
+ DragAcceptFiles(hwnd, TRUE);
+
+ updatedisplay(gui, hwnd);
+ gui->mainwindow = hwnd;
+
+ /* display */
+ ShowWindow(gui->mainwindow, SW_SHOW);
+ UpdateWindow(gui->mainwindow);
+ maketransparent(gui->mainwindow, RGB(255, 0, 255));
+ return 0;
+}
+
+gui_t *create_gui(char *skindir, char *skinName, void (*playercontrol)(int event))
+{
+ gui_t *gui = calloc(1, sizeof(gui_t));
+
+ HWND runningmplayer = FindWindow("MPlayer GUI for Windows", "MPlayer for Windows");
+ if(runningmplayer)
+ {
+ free(gui);
+ return NULL;
+ }
+
+ gui->startplay = startplay;
+ gui->playercontrol = playercontrol;
+ gui->uninit = uninit;
+ gui->updatedisplay = updatedisplay;
+
+ /* create playlist */
+ gui->playlist = create_playlist();
+
+ if(!skinName) skinName = strdup("Blue");
+ char temp[MAX_PATH];
+ sprintf(temp, "%s\\%s", skindir, skinName);
+ if(create_window(gui, temp)) return NULL;
+ if(create_subwindow(gui, temp)) return NULL;
+ if(console) console_toggle();
+ return gui;
+}