/* * MPlayer GUI for Win32 * Copyright (C) 2003 Sascha Sommer * Copyright (C) 2006 Erik Augustson * Copyright (C) 2006 Gianluigi Tiesi * * This file is part of MPlayer. * * MPlayer 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. * * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include "version.h" #include "mplayer.h" #include "mp_fifo.h" #include "mp_msg.h" #include "help_mp.h" #include "input/input.h" #include "input/mouse.h" #include "osdep/keycodes.h" #include "stream/stream.h" #include "libvo/video_out.h" #include "gui/interface.h" #include "gui.h" #include "dialogs.h" // HACK around bug in old mingw #undef INVALID_FILE_ATTRIBUTES #define INVALID_FILE_ATTRIBUTES ((DWORD)-1) #ifndef WM_XBUTTONDOWN # define WM_XBUTTONDOWN 0x020B # define WM_XBUTTONUP 0x020C # define WM_XBUTTONDBLCLK 0x020D #endif /* 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 print_version(void); float sub_aspect; DWORD oldtime; NOTIFYICONDATA nid; int console_state = 0; play_tree_t *playtree = NULL; static HBRUSH colorbrush = NULL; //Handle to colorkey brush static COLORREF windowcolor = RGB(255,0,255); //Windowcolor == colorkey 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); print_version(); 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; iwindow_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; iwindow_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; iwindow_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; case evLoadSubtitle: display_opensubtitlewindow(gui); break; 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; iskin->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) { unsigned int i; window_priv_t *priv = NULL; DWORD time = timeGetTime(); if(!hwnd) return; /* load all potmeters hpotmeters */ for(i=0; iskin->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 */ if((time - oldtime) < 100) return; oldtime=time; /* suppress directx's fullscreen window when using the sub window */ if(sub_window && &video_driver_list[0] && strstr("directx", video_driver_list[0])) { HWND hWndFS = NULL; //handle to directx's fullscreen window if(hWndFS == NULL) { hWndFS = FindWindow(NULL, "MPlayer Fullscreen"); if(hWndFS != NULL) DestroyWindow(hWndFS); //sub window handles fullscreen } } for (i=0; iwindow_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; LPITEMIDLIST pidl; memset(&bi, 0, sizeof(BROWSEINFO)); bi.lpszTitle = "Choose a Directory..."; 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_FULLSCREEN: mp_input_queue_cmd(mp_input_parse_cmd("vo_fullscreen")); break; case ID_MUTE: mp_input_queue_cmd(mp_input_parse_cmd("mute")); break; 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; iplaylist->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: { int x = GET_WHEEL_DELTA_WPARAM(wParam); if(vo_nomouse_input) break; 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_TIMER: { if(fullscreen) while(ShowCursor(FALSE) >= 0){} KillTimer(hWnd, ID_TIMER); return 0; } case WM_MOUSEMOVE: { ShowCursor(TRUE); SetTimer(hWnd, ID_TIMER, 3000, (TIMERPROC) NULL); break; } case WM_WINDOWPOSCHANGED: { int tmpheight=0; static uint32_t rect_width; static uint32_t rect_height; RECT rd; POINT pt; 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, 0, fullscreen?0:pt.x+rd.left, fullscreen?0:pt.y+rd.top, fullscreen?vo_screenwidth:rd.right-rd.left, fullscreen?vo_screenheight:rd.bottom-rd.top, SWP_NOOWNERZORDER); SetForegroundWindow(hWnd); return 0; } case WM_SYSCOMMAND: { switch(wParam) { case SC_SCREENSAVE: case SC_MONITORPOWER: mp_msg(MSGT_VO, MSGL_V ,"killing screensaver\n" ); return 0; } break; } case WM_PAINT: { PAINTSTRUCT ps; RECT rect; HDC hdc = BeginPaint(hWnd, &ps); HDC hMemDC = CreateCompatibleDC(hdc); HBRUSH blackbrush = (HBRUSH)GetStockObject(BLACK_BRUSH); 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; iskin->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); } else { FillRect(GetDC(hWnd), &rect, fullscreen?blackbrush:colorbrush); } 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_COPYDATA: { if(lParam) { PCOPYDATASTRUCT cdData; cdData = (PCOPYDATASTRUCT) lParam; mplSetFileName(NULL, cdData->lpData, STREAMTYPE_FILE); 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; iplaylist->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; UINT errmode; point.x = GET_X_LPARAM(lParam); point.y = GET_Y_LPARAM(lParam); ClientToScreen(hWnd, &point); errmode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); while (GetMenuItemCount(gui->diskmenu) > 0) DeleteMenu(gui->diskmenu, 0, MF_BYPOSITION); len = GetLogicalDriveStrings(MAX_PATH, device); while(pos < len) { if(GetDriveType(device + pos) == DRIVE_CDROM) { char volname[MAX_PATH]; char menuitem[MAX_PATH]; int flags = MF_STRING; 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) flags |= MF_ENABLED; else if(GetFileAttributes(searchpath2) != INVALID_FILE_ATTRIBUTES) flags |= MF_ENABLED; #ifdef HAVE_LIBCDIO else if(GetFileAttributes(searchpath3) != INVALID_FILE_ATTRIBUTES) flags |= MF_ENABLED; #endif else flags |= MF_GRAYED; volname[0] = 0; strcpy(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, flags, IDPLAYDISK + cdromdrive, menuitem); cdromdrive++; } pos += strlen(device + pos) + 1; } SetErrorMode(errmode); 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; LPITEMIDLIST pidl; memset(&bi, 0, sizeof(BROWSEINFO)); bi.lpszTitle = "Choose a Directory..."; 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; case ID_MUTE: mp_input_queue_cmd(mp_input_parse_cmd("mute")); break; case IDSUBTITLE_OPEN: display_opensubtitlewindow(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; 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) { sprintf(searchpath, "%sVIDEO_TS", device + pos); if(GetFileAttributes(searchpath) != INVALID_FILE_ATTRIBUTES) { #ifdef USE_DVDREAD if (dvd_device) free(dvd_device); dvd_device = strdup(device + pos); dvd_title = dvd_chapter = dvd_angle = 1; handlemsg(hWnd, evPlayDVD); #endif } sprintf(searchpath, "%sTrack01.cda", device + pos); if(GetFileAttributes(searchpath) != INVALID_FILE_ATTRIBUTES) { #ifdef HAVE_LIBCDIO 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; iwindow_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) { gui->diskmenu = CreatePopupMenu(); 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); AppendMenu(gui->menu, MF_STRING, IDSUBTITLE_OPEN, "Open Subtitle"); 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); AppendMenu(gui->traymenu, MF_STRING, ID_MUTE, "Toggle Mute"); AppendMenu(gui->traymenu, MF_SEPARATOR, 0, 0); AppendMenu(gui->traymenu, MF_STRING, IDSUBTITLE_OPEN, "Open Subtitle"); 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, ID_FULLSCREEN, "Toggle Fullscreen"); AppendMenu(gui->submenu, MF_STRING, ID_MUTE, "Toggle Mute"); 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; iskin->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; vo_colorkey = 0xff00ff; for (i=0; iskin->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 = NULL; //WM_PAINT will handle background color switching; 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 = fullscreen?WS_VISIBLE | WS_POPUP: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; int x = -1, y = -1; /* 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; iskin->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); /* 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)); char temp[MAX_PATH]; 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"); 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; }