diff Gui/win32/gui.c @ 18914:d450ec82ae57

Initial win32 gui release.
author vayne
date Thu, 06 Jul 2006 02:07:03 +0000
parents
children d7ab6268e3ea
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Gui/win32/gui.c	Thu Jul 06 02:07:03 2006 +0000
@@ -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;
+}