diff options
Diffstat (limited to 'Gui/win32/gui.c')
-rw-r--r-- | Gui/win32/gui.c | 1555 |
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; +} |