diff options
-rw-r--r-- | Gui/win32/Changelog | 317 | ||||
-rw-r--r-- | Gui/win32/README | 17 | ||||
-rw-r--r-- | Gui/win32/dialogs.c | 1142 | ||||
-rw-r--r-- | Gui/win32/dialogs.h | 129 | ||||
-rw-r--r-- | Gui/win32/gui.c | 1555 | ||||
-rw-r--r-- | Gui/win32/gui.h | 118 | ||||
-rw-r--r-- | Gui/win32/interface.c | 975 | ||||
-rw-r--r-- | Gui/win32/playlist.c | 154 | ||||
-rw-r--r-- | Gui/win32/playlist.h | 57 | ||||
-rw-r--r-- | Gui/win32/preferences.c | 714 | ||||
-rw-r--r-- | Gui/win32/skinload.c | 809 | ||||
-rw-r--r-- | Gui/win32/skinload.h | 213 | ||||
-rw-r--r-- | Gui/win32/widgetrender.c | 350 | ||||
-rw-r--r-- | Gui/win32/wincfg.c | 143 | ||||
-rw-r--r-- | Gui/win32/wincfg.h | 38 |
15 files changed, 6731 insertions, 0 deletions
diff --git a/Gui/win32/Changelog b/Gui/win32/Changelog new file mode 100644 index 0000000000..d439fa9dcd --- /dev/null +++ b/Gui/win32/Changelog @@ -0,0 +1,317 @@ +HISTORY +2006/06/30 - Erik Augustson <erik_27can@yahoo.com> +- Fixed display of wrong aspect ratios. + +2006/06/13 - Erik Augustson <erik_27can@yahoo.com> +- Minor bugfixes. +- Updated to current SVN + +2006/04/14 - Erik Augustson <erik_27can@yahoo.com> +- Fixed a crash bug. +- Fixed a major fullscreen bug (WinID wasn't getting + reset when FS switching). + +2006/04/13 - Erik Augustson <erik_27can@yahoo.com> +- More minor fixups + +2006/04/07 - Erik Augustson <erik_27can@yahoo.com> +- Minor fixups to openurl and openfile from dialogs.c + +2006/04/06 - Erik Augustson <erik_27can@yahoo.com> +- Fixed IPC and drag&drop appending files to the + playlist instead of opening them right away. +- Updated dvdnav patch. + +2006/04/03 - Erik Augustson <erik_27can@yahoo.com> +- Fixed a long pathnames issue with WM_COPYDATA. +- Fixed a minor crash happening when rendering the + codec name. +- Some code cleanup. + +2006/04/01 - Erik Augustson <erik_27can@yahoo.com> +- Added ability to enable/disable videos displaying + in the sub window in preferences. +- Small fix in update_subwindow() for coming out + of fullscreen when the sub window was minimized. + +2006/03/27 - Erik Augustson <erik_27can@yahoo.com> +- Updated to current CVS. +- Debug console now shows the extensions mplayer + was compiled with. + +2006/03/23 - Erik Augustson <erik_27can@yahoo.com> +- Fixed using -playlist and -shuffle. + +2006/03/22 - Erik Augustson <erik_27can@yahoo.com> +- Fixed a small bug with input events for dialogs. + +2006/03/16 - Erik Augustson <erik_27can@yahoo.com> +- Fixed left button mouse event in dvdnav patch. +- More aspect fixes. +- Fixed double-click in the playlist. +- Fixed some drag&drop functionality. + +2006/03/14 - Erik Augustson <erik_27can@yahoo.com> +- Simplified title/chapter selection dialog. +- Code cleanup. + +2006/03/14 - Erik Augustson <erik_27can@yahoo.com> + +- Fixed resetting aspect on file ending in mplEnd() + +2006/03/13 - Erik Augustson <erik_27can@yahoo.com> +- Fixed double click events, forgot to add CS_DBLCLKS + to sub window's window style. +- Fixed window focusing with drag&drop files. +- Re-arranged some menu items, and added support for + runtime aspect switching. This adds 3 lines to + mplayer.c but is well worth it IMO. + +2006/03/12 - Erik Augustson <erik_27can@yahoo.com> +- Fixed window positioning for both windows. +- Added more mouse button events. + +2006/03/10 - Erik Augustson <erik_27can@yahoo.com> +- Fixed mouse and sub window vanishing after coming + out of fullscreen by end of file. +- Fixed sub window popping up when switching to + fullscreen and *not* using directx. +- Added codec name to widgets to properly render + in some skins. +- Middle and scroll wheel mouse event should work + now on the sub window. +- #ifdef'd USE_DVDREAD to allow for compilation + when disabling mpdvdkit. +- Updated license information. + +2006/03/08 - Erik Augustson <erik_27can@yahoo.com> +- Removed unnecessary playerinfo struct +- Fixed movies playing at wrong aspects +- Minor bugfixes all around + +2006/03/07 - Erik Augustson <erik_27can@yahoo.com> +- Fixed some skin labels not displaying properly + +2006/03/06 - Gianluigi Tiesi <sherpya@netfarm.it> +- Temporaly fix crash if no vo_driver is specified + (interface.c:877) + +2006/02/28 - Erik Augustson <erik_27can@yahoo.com> +- Added sub window. The sub window is the WinID + (-wid) when using the directx vo. The sub window + hides when the file is audio only, and as well + when the vo is not directx, and automatically + adjusts and maintains video aspect ratios +- Minor fixups +- TODO: Get WinID working when using gl2, and add + fix for both windows if going out of bounds on + right and bottom of screen. + +2006/01/30 - Erik Augustson <erik_27can@yahoo.com> +- Fixed playing movies from network drives. + +2006/01/27 - Erik Augustson <erik_27can@yahoo.com> +- Fixed a small annoyance when playing a network file + with file associations when mplayer wasn't running, + using GetLongPathNameA() + +2006/01/15 - Erik Augustson <erik_27can@yahoo.com> +- Added some CD functionality if using libcdio. + +2005/12/02 - Erik Augustson <erik_27can@yahoo.com> +- Fix to disable gui if running in slave mode. + +2005/11/14 - Erik Augustson <erik_27can@yahoo.com> +- Implemented IPC with WM_COPYDATA to open new + files/playlists in the current running mplayer, + rather than having a new mplayer process spawn. + +2005/11/12 - Erik Augustson <erik_27can@yahoo.com> +- Modified evMute to mute/unmute +- Mute button should show as pressed when muted +- Added evDecVolume and evIncVolume + +2005/11/09 - Erik Augustson <erik_27can@yahoo.com> +- Fixed screensaver issues + +2005/11/06 - Erik Augustson <erik_27can@yahoo.com> +- Display fixes + +2005/09/18 - Erik Augustson <erik_27can@yahoo.com> +- Playlist additions +- Minor playlist bugfixes + +2005/09/16 - Gianluigi Tiesi <sherpya@netfarm.it> +- Code cleanup + +2005/09/05 - Erik Augustson <erik_27can@yahoo.com> +- Updated to apply to current CVS + +2005/07/27 - Erik Augustson <erik_27can@yahoo.com> +- Added initial evEqualizer for brightness, contrast, + hue and saturation of videos. + +2005/07/26 - Erik Augustson <erik_27can@yahoo.com> +- Fixed double click on playlist +- Added support for screenshot video filter, vf_screenshot patch + is also needed + +2005/06/19 - Gianluigi Tiesi <sherpya@netfarm.it> +- Removed -console switch, moved console stuff out of mplayer main, + console option is handled in wincfg, it's switchable at runtime + from the gui and the state is saved + +2005/06/15 - Erik Augustson <erik_27can@yahoo.com> +- Fixed bugs with DVD chapter skipping +- Title/chapter switching dialog works again :) +- Fixed a bug with url's not working after playing a DVD +- Removed fullscreen handling from mplayer.c. It's now + handled in interface.c +- Disabled loading/saving playlists, and adding files/urls + while playing a DVD + +2005/06/12 - Gianluigi Tiesi <sherpya@netfarm.it> +- Added -console cmd line option to bring up a dos console + that displays mplayer messages + +2005/06/10 - Erik Augustson <erik_27can@yahoo.com> +- Fixed a bug with the audio filters not loading +- Fixed bugs with the audio delay and stereo sliders +- Added a few safety checks + +2005/06/08 - Erik Augustson <erik_27can@yahoo.com> +- Added initial evPreferences +- Fixed a bug with the load subtitle dialog +- Some code cleanup and minor fixes here and there + +2005/06/02 - Erik Augustson <erik_27can@yahoo.com> +- Fixed a bug with pathnames in the open url dialog + +2005/05/26 - Erik Augustson <erik_27can@yahoo.com> +- Added "Add file" and "Add url" menu to the playlist +- Fixed file skipping when double-clicking playlist entries + +2005/05/19 - Erik Augustson <erik_27can@yahoo.com> +- added simple url history + +2005/05/12 - Erik Augustson <erik_27can@yahoo.com> +- added load and save playlists options +- fixed opening remote m3u and pls files in open url +- no problems so far with evprev and evnext :) + +2005/05/10 - Erik Augustson <erik_27can@yahoo.com> +- more evNext and evPrev fixes + +2005/05/06 - Erik Augustson <erik_27can@yahoo.com> +- implemented mplEnd() for proper looping fix +- fixed bugs in evNext and evPrev +- re-organized the menus + +2005/03/02 - Gianluigi Tiesi <sherpya@netfarm.it> +- adapted subtitle patch from Raul <zomps@mail.astar.ee> +- readapted endless loop fix to not touch mp_msg.c +Erik Augustson <erik_27can@yahoo.com> +- small fixes, orginal endless loop fix + +2005/02/25 - Gianluigi Tiesi <sherpya@netfarm.it> +- Fixed exit stuff (I hope ;P) +- Fixes to Erik's title/chapter selector +Erik Augustson <erik_27can@yahoo.com> +- Added additional gui events +- Added evPrev and evNext dvd chapter switching + +2005/02/23 - Erik Augustson <erik_27can@yahoo.com> +- added dvd title/chapter switching + +2005/02/20 - Gianluigi Tiesi <sherpya@netfarm.it> +- fixed dvd stop and play +Erik Augustson <erik_27can@yahoo.com> +- imported some stuff from unix gui +- fixed file play after dvd + +2005/02/18 - Erik Augustson <erik_27can@yahoo.com> +- addons for dvd playing + +2005/02/16 - Gianluigi Tiesi <sherpya@netfarm.it> +- renamed README to README.txt +- retain window position even when switching the skin +- converted all opendir calls to native win32 calls +- adding filename as title without directory for all calls +- more cleanups in skinloader/unloader +- removed a lot of warnings +- removed unused includes +Erik Augustson <erik_27can@yahoo.com> +- added online help menu + +2005/02/15 - Gianluigi Tiesi <sherpya@netfarm.it> +- Disabled access to gui when gui->mainwindow doesn't match hwnd passed to windproc +- Fixed save position for main window gui +- Cleanups in skinloader/unloader +Erik Augustson erik_27can@yahoo.com +- Added saving main window position to gui config +- Fixes on playlist for vcd + +2005/02/13 - Gianluigi Tiesi <sherpya@netfarm.it> +- Fixed multithreaded (I hope ;P) +- Skinbrowser window is closed when a skin is changed, this prevents crashes if multiple clicks +- Playlist window is updated if files are added while playlist is visible +- Removed patch on mplayer.rc, take icon using the included routine +- SkinBrowser and Playlist dialogs can be opened/closed by clicking multiple times gui buttons +- Added support for DVD, stop dvd + play is broken ;( +- ifdef-ed a lot of debug stuff +- Fixed systray icon removing +- Added Erik and me to about dialog ;) +Erik Augustson <erik_27can@yahoo.com> +- Added key handling for the gui window +- Small fixes on tray icon stuff + +2005/02/11 - Gianluigi Tiesi <sherpya@netfarm.it> +- fixed sliders, balance is not 100% working, anyway dsound output driver doesn't support balanced audio +- remade threaded +- removed demuxer/avi patches, really needed ?? +- added a fake vo_init if opengl is not enabled +Erik Augustson <erik_27can@yahoo.com> +- fixes on traymenu play +- added a base configuration reader/writer - only support for skin selection for now + +2005/02/10 - Gianluigi Tiesi <sherpya@netfarm.it> +- fixed (workarounded) the NULL filename bug +- moved add directory directly into gui.c +- it starts to be usable :) +Erik Augustson <erik_27can@yahoo.com> +- Added systray support +- Added skin browser option to menu (some skins don't show a skin browser button) + +2005/02/09 - Gianluigi Tiesi <sherpya@netfarm.it> +- Fixed window disappearing bug +- Made a patch compatible with current tree +- Fixed icons in minor dialogs +- Major cleanup and code reorganization + +2005/02/08 - Erik Augustson <erik_27can@yahoo.com> +- Removed multi-threading, mplayer now runs in a single thread +- Play directory now works as intended +- Added a Skin browser, double-click skin names to switch skins +- Still more things todo + +pre4 +- URL open +- use windows native menus +- Gui runs in a seperate thread now because some controls interupt playback :( + +pre 3 +- some of the previous features broken again +- full font loading/display support +- better integration into mplayer +- seek bar, balance, volume control work + +pre 2 +- playlist +- Drag 'N Drop support +- fixed segfault when no skinfile found + +pre 1 +- initial revision +- play/pause works +- loads "blue" skin +- still lot of things todo diff --git a/Gui/win32/README b/Gui/win32/README new file mode 100644 index 0000000000..f0a7123be7 --- /dev/null +++ b/Gui/win32/README @@ -0,0 +1,17 @@ +MPlayer Windows GUI (c) +2003 Sascha Sommer - <saschasommer@freenet.de> +2006 Erik Augustson - <erik_27can@yahoo.com> +2006 Gianluigi Tiesi - <sherpya@netfarm.it> + +This beta gui for win32 was originally written by Sascha Sommer and +has since been heavily modified by myself (Erik Augustson) and Gianluigi +Tiesi. It follows the same concept for the linux gui, and should be +able to load all(most) of the current skins available for the linux gui. + +To compile, quite simply pass --enable-gui to configure, and it is highly +recommended to also pass --enable-static="-mwindows" to link mplayer as +a windows binary. NOTE: this will also link mencoder with -mwindows +and thus link mencoder as a windows binary as well. + +Please send all bug reports/comments/requests/gripes to: +<erik_27can@yahoo.com> diff --git a/Gui/win32/dialogs.c b/Gui/win32/dialogs.c new file mode 100644 index 0000000000..815aab0cc1 --- /dev/null +++ b/Gui/win32/dialogs.c @@ -0,0 +1,1142 @@ +/* + 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 <windows.h> +#include <commctrl.h> +#include <interface.h> +#include <mp_msg.h> +#include <help_mp.h> +#include <libmpdemux/stream.h> +#include <libmpdemux/demuxer.h> +#include <libmpdemux/stheader.h> +#include "gui.h" +#include "wincfg.h" +#include "dialogs.h" + +WNDPROC OldUrlWndProc; +LRESULT CALLBACK SubUrlWndProc(HWND, UINT, WPARAM, LPARAM); +extern int vo_gamma_brightness; +extern int vo_gamma_saturation; +extern int vo_gamma_contrast; +extern int vo_gamma_hue; +extern int set_video_colors(sh_video_t *sh_video, char *item, int value); +extern int get_video_colors(sh_video_t *sh_video, char *item, int *value); + +guiInterface_t guiIntfStruct; +int addurl = 0; + +#ifdef USE_SUB +extern mp_osd_obj_t* vo_osd_list; +extern char **sub_name; + +void guiLoadSubtitle(char *name) +{ + if (!guiIntfStruct.Playing) + { + guiIntfStruct.SubtitleChanged = 1; + return; + } + if (subdata) + { + mp_msg(MSGT_GPLAYER, MSGL_INFO, MSGTR_DeletingSubtitles); + sub_free(subdata); + subdata = NULL; + vo_sub = NULL; + if (vo_osd_list) + { + int len; + mp_osd_obj_t *osd = vo_osd_list; + while (osd) + { + if (osd->type == OSDTYPE_SUBTITLE) break; + osd = osd->next; + } + if (osd && osd->flags & OSDFLAG_VISIBLE) + { + len = osd->stride * (osd->bbox.y2 - osd->bbox.y1); + memset(osd->bitmap_buffer, 0, len); + memset(osd->alpha_buffer, 0, len); + } + } + } + + if (name) + { + mp_msg(MSGT_GPLAYER, MSGL_INFO, MSGTR_LoadingSubtitles, name); + subdata = sub_read_file(strdup(name), guiIntfStruct.FPS); + if (!subdata) mp_msg(MSGT_GPLAYER, MSGL_ERR, MSGTR_CantLoadSub,name); + sub_name = (malloc(2 * sizeof(char*))); /* when mplayer will be restarted */ + sub_name[0] = strdup(name); /* sub_name[0] will be read */ + sub_name[1] = NULL; + } + update_set_of_subtitles(); +} +#endif + +int display_openfilewindow(gui_t *gui, int add) +{ + OPENFILENAME fileopen; + int result = 0; + char filelist[MAXFILE]; + char filename[MAX_PATH]; + char directory[MAX_PATH]; + char *filespec = NULL; + char *filepart = NULL; + + memset(&fileopen, 0, sizeof(OPENFILENAME)); + memset(filelist, 0, sizeof(filelist)); + + fileopen.lStructSize = sizeof(OPENFILENAME); + fileopen.hwndOwner = gui->mainwindow; + fileopen.hInstance = GetModuleHandle(NULL); + fileopen.lpstrFilter = "All Files (*.*)\0*.*\0" + "Media Files (*.avi;*.asf;*.wmv;*.mpg;*.mpeg;*.m2v;*.mov;\ + *.rmvb;*.rm;*.ogm;*.mp3;*.wav;*.wma;*.ra;*.ogg)\0\ + *.avi;*.asf;*.wmv;*.mpg;*.mpeg;*.m2v;*.mov;\ + *.rmvb;*.rm;*.ogm;*.mp3;*.wav;*.wma;*.ra;*.ogg\0" + "Video Files (*.avi;*.mpg;*.mpeg;*.mov)\0*.avi;*.mpg;*.mpeg;*.mov\0" + "Avisynth Scripts (*.avs)\0*.avs\0" + "Audio Files (*.mp3;*.wav;*.ra)\0*.mp3;*.wav;*.ra\000"; + fileopen.nFilterIndex = 0; + fileopen.lpstrTitle = "Add file(s)..."; + fileopen.Flags = OFN_ALLOWMULTISELECT | OFN_FILEMUSTEXIST| OFN_LONGNAMES | OFN_EXPLORER| OFN_READONLY | OFN_HIDEREADONLY; + fileopen.lpstrFile = filelist; + fileopen.lpstrCustomFilter = NULL; + fileopen.nMaxFile = MAXFILE; + + if(GetOpenFileName(&fileopen)) + { + /* clear playlist */ + if(!add) gui->playlist->clear_playlist(gui->playlist); + + memcpy(directory, fileopen.lpstrFile, fileopen.nFileOffset - 1); + directory[fileopen.nFileOffset - 1] = 0; + + do + { + filespec = &fileopen.lpstrFile[fileopen.nFileOffset]; + filename[0] = 0; + strcat(filename, directory); + strcat(filename, "\\"); + strcat(filename, filespec); + + if (GetFileAttributes(filename) & FILE_ATTRIBUTE_DIRECTORY) + mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] %s is a directory, skipping...\n", filename); + else + { + if (GetFullPathName(filename, MAX_PATH, filename, &filepart)) + { + if(!parse_filename(filename, playtree, mconfig, add? 0 : 1)) + gui->playlist->add_track(gui->playlist, filename, NULL, filepart, 0); + mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] Adding file: %s - path %s\n", filespec, filename); + result++; + } + } + fileopen.nFileOffset += strlen(filespec) + 1; + } while (*filespec); + } + return result; +} + +#ifdef USE_SUB +void display_opensubtitlewindow(gui_t *gui) +{ + OPENFILENAME subtitleopen; + char subtitlefile[MAX_PATH]; + + /* Safety check */ + if (guiIntfStruct.Playing == 0 || !guiIntfStruct.sh_video) return; + + memset(&subtitleopen, 0, sizeof(OPENFILENAME)); + memset(subtitlefile, 0, sizeof(subtitlefile)); + + subtitleopen.lStructSize = sizeof(OPENFILENAME); + subtitleopen.hwndOwner = gui->mainwindow; + subtitleopen.hInstance = GetModuleHandle(NULL); + subtitleopen.lpstrFilter = "All Files (*.*)\0*.*\0" + "Subtitle Files (*.srt;*.txt;*.vob)\0*.srt;*.txt;*.vob\0"; + subtitleopen.nFilterIndex = 0; + subtitleopen.lpstrTitle = "Add Subtitle..."; + subtitleopen.Flags = OFN_FILEMUSTEXIST | OFN_LONGNAMES | OFN_EXPLORER | OFN_READONLY | OFN_HIDEREADONLY; + subtitleopen.lpstrFile = subtitlefile; + subtitleopen.lpstrCustomFilter = NULL; + subtitleopen.nMaxFile = MAXFILE; + + if(GetOpenFileName(&subtitleopen)) + guiLoadSubtitle(subtitlefile); +} +#endif + +void display_loadplaylistwindow(gui_t *gui) +{ + OPENFILENAME playlistopen; + char playlistfile[MAX_PATH]; + + memset(&playlistopen, 0, sizeof(OPENFILENAME)); + memset(playlistfile, 0, sizeof(playlistfile)); + + playlistopen.lStructSize = sizeof(OPENFILENAME); + playlistopen.hwndOwner = gui->mainwindow; + playlistopen.hInstance = GetModuleHandle(NULL); + playlistopen.lpstrFilter = "All Files (*.*)\0*.*\0" + "Playlist Files (*.m3u;*.pls;*.txt)\0*.m3u;*.pls;*.txt\0"; + playlistopen.nFilterIndex = 0; + playlistopen.lpstrTitle = "Load Playlist..."; + playlistopen.Flags = OFN_FILEMUSTEXIST | OFN_LONGNAMES | OFN_EXPLORER | OFN_READONLY | OFN_HIDEREADONLY; + playlistopen.lpstrFile = playlistfile; + playlistopen.lpstrCustomFilter = NULL; + playlistopen.nMaxFile = MAXFILE; + + if(GetOpenFileName(&playlistopen)) + { + if(parse_filename(playlistfile, playtree, mconfig, 1)) + gui->startplay(gui); + } +} + +void display_saveplaylistwindow(gui_t* gui) +{ + OPENFILENAME playlistsave; + static FILE *playlist_file = NULL; + char playlistname[MAX_PATH]; + + memset(&playlistsave, 0, sizeof(OPENFILENAME)); + memset(playlistname, 0, sizeof(playlistname)); + + playlistsave.lStructSize = sizeof(OPENFILENAME); + playlistsave.hwndOwner = gui->mainwindow; + playlistsave.hInstance = GetModuleHandle(NULL); + playlistsave.lpstrFilter = "Playlist Files (*.pls)\0*.pls\0"; + playlistsave.nFilterIndex = 0; + playlistsave.lpstrTitle = "Save Playlist..."; + playlistsave.Flags = OFN_LONGNAMES | OFN_EXPLORER | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY; + playlistsave.lpstrFile = playlistname; + playlistsave.lpstrCustomFilter = NULL; + playlistsave.nMaxFile = MAXFILE; + + if(GetSaveFileName(&playlistsave)) + { + int i=0; + HANDLE my_playlist; + + if(!strstr(playlistname, ".pls")) strcat(playlistname, ".pls"); + + my_playlist = CreateFile(playlistname, + GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, + NULL); + + if(my_playlist != INVALID_HANDLE_VALUE) + { + CloseHandle(my_playlist); /* close the file first so we can write to it */ + playlist_file = fopen(playlistsave.lpstrFile, "w"); + fprintf(playlist_file, "[playlist]\n"); + fprintf(playlist_file, "numberofentries=%d\n", gui->playlist->trackcount); + + for(i=0; i<(gui->playlist->trackcount); i++) + { + fprintf(playlist_file, "File%i=%s\n", i + 1, gui->playlist->tracks[i]->filename); + fprintf(playlist_file, "Length%i=-1\n", i + 1); + } + fclose(playlist_file); + } + } +} + +static LRESULT CALLBACK OpenUrlWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + static HWND url; + HWND wdg; + FILE *f; + char *history = get_path("gui.url"); + gui_t *gui = (gui_t *) GetWindowLongPtr(hwnd, GWLP_USERDATA); + switch (iMsg) + { + case WM_CREATE: + wdg = CreateWindow("button", "Ok", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 4, 43, 80, 25, hwnd, + (HMENU) ID_OK, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(wdg, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + wdg = CreateWindow("button", "Cancel", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 90, 43, 80, 25, hwnd, + (HMENU) ID_CANCEL, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(wdg, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + url = wdg = CreateWindowEx(WS_EX_CLIENTEDGE, + "edit", NULL, + WS_CHILD | WS_VISIBLE | ES_LEFT | ES_AUTOHSCROLL, + 4, 10, 300, 25, hwnd, + (HMENU) ID_URL, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(wdg, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + SendMessage(wdg, EM_SETLIMITTEXT, MAX_PATH, 0); + + /*subclass the edit box to capture the VK_RETURN key*/ + OldUrlWndProc = (WNDPROC)SetWindowLongPtr(url, GWLP_WNDPROC, (LONG_PTR)SubUrlWndProc); + + if((f = fopen(history, "r"))) + { + char lasturl[MAX_PATH]; + fgets(lasturl, MAX_PATH, f); + SendMessage(url, WM_SETTEXT, 0, (LPARAM) lasturl); + SendMessage(url, EM_SETSEL, 0, -1); + fclose(f); + } + break; + case WM_KEYDOWN: + switch (LOWORD(wParam)) + { + case VK_RETURN: + SendMessage(hwnd, WM_COMMAND, (WPARAM) ID_OK, 0); + break; + } + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case ID_CANCEL: + DestroyWindow(hwnd); + return 0; + case ID_OK: + { + char file[MAX_PATH]; + SendMessage(url, WM_GETTEXT, MAX_PATH, (LPARAM) file); + mplSetFileName(NULL, file, STREAMTYPE_STREAM); + if((f = fopen(history, "wt+"))) + { + fprintf(f, file); + fclose(f); + } + if(!parse_filename(file, playtree, mconfig, addurl? 0 : 1)) + gui->playlist->add_track(gui->playlist, file, NULL, NULL, 0); + if(!addurl) + gui->startplay(gui); + else update_playlistwindow(); + DestroyWindow(hwnd); + } + break; + } + } + return 0; + case WM_DESTROY: + { + PostQuitMessage (0); + addurl = 0; + return 0; + } + } + return DefWindowProc(hwnd, iMsg, wParam, lParam); +} + +LRESULT CALLBACK SubUrlWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + switch(iMsg) + { + case WM_KEYDOWN: + switch (LOWORD(wParam)) + { + case VK_RETURN: + SendMessage(FindWindow(NULL, "MPlayer - Open URL..."), WM_COMMAND, (WPARAM) ID_OK, 0); + break; + } + } + return CallWindowProc(OldUrlWndProc, hwnd, iMsg, wParam, lParam); +} + +void display_openurlwindow(gui_t *gui, int add) +{ + if(add) addurl = 1; + HWND hWnd; + HINSTANCE hInstance = GetModuleHandle(NULL); + WNDCLASS wc; + int x, y; + if(FindWindow(NULL, "MPlayer - Open URL...")) return; + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = OpenUrlWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(NULL,IDC_ARROW); + wc.hIcon = gui->icon; + wc.hbrBackground = SOLID_GREY2; + wc.lpszClassName = "MPlayer - URL"; + wc.lpszMenuName = NULL; + RegisterClass(&wc); + x = (GetSystemMetrics(SM_CXSCREEN) / 2) - (320 / 2); + y = (GetSystemMetrics(SM_CYSCREEN) / 2) - (100 / 2); + hWnd = CreateWindow("MPlayer - URL", + "MPlayer - Open URL...", + WS_POPUPWINDOW | WS_CAPTION, + x, + y, + 320, + 100, + NULL, + NULL, + hInstance, + NULL); + SetWindowLongPtr(hWnd, GWLP_USERDATA, (DWORD) gui); + ShowWindow(hWnd, SW_SHOW); + UpdateWindow(hWnd); +} + +static void create_playlistmenu(gui_t *gui) +{ + gui->playlistmenu = CreatePopupMenu(); + AppendMenu(gui->playlistmenu, MF_STRING, ID_ADDFILE, "Add File..."); + AppendMenu(gui->playlistmenu, MF_STRING, ID_ADDURL, "Add Url..."); + AppendMenu(gui->playlistmenu, MF_SEPARATOR, 0, 0); + AppendMenu(gui->playlistmenu, MF_STRING, ID_REMOVE, "Remove Selected"); + AppendMenu(gui->playlistmenu, MF_STRING, ID_CLEAR, "Clear Playlist"); + AppendMenu(gui->playlistmenu, MF_SEPARATOR, 0, 0); + AppendMenu(gui->playlistmenu, MF_STRING, ID_CLOSE, "Close"); +} + +static void updatetracklist(HWND hwnd) +{ + int i=0; + gui_t *gui = (gui_t *) GetWindowLongPtr(hwnd, GWLP_USERDATA); + HWND tracklist = GetDlgItem(hwnd, ID_TRACKLIST); + /* clear listbox */ + SendMessage(tracklist, LB_RESETCONTENT, 0, 0); + for (i=0; i < gui->playlist->trackcount; i++) + if (gui->playlist->tracks[i]->title) + SendMessage(tracklist, LB_ADDSTRING, 0, (LPARAM)gui->playlist->tracks[i]->title); + else + SendMessage(tracklist, LB_ADDSTRING, 0, (LPARAM)gui->playlist->tracks[i]->filename); +} + +static LRESULT CALLBACK PlayListWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + HWND wdg; + POINT cursor; + gui_t *gui = (gui_t *) GetWindowLongPtr(hwnd, GWLP_USERDATA); + playlist_t *pl = gui ? gui->playlist : NULL; + switch (iMsg) + { + case WM_CREATE: + { + wdg = CreateWindow("button", "Play", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 4, 10, 80, 25, hwnd, + (HMENU) ID_PLAY, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(wdg, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + wdg = CreateWindow ("button", "Up", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 4, 37, 80, 25, hwnd, + (HMENU) ID_UP, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(wdg, WM_SETFONT,(WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + wdg = CreateWindow ("button", "Down", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 4, 64, 80, 25, hwnd, + (HMENU) ID_DOWN, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(wdg, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT),0); + + wdg = CreateWindow ("button", "Remove", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 4, 91, 80, 25, hwnd, + (HMENU) ID_REMOVE, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(wdg, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT),0); + + wdg = CreateWindow ("button", "Load", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 4, 118, 80, 25, hwnd, + (HMENU) ID_PLAYLISTLOAD, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(wdg, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT),0); + + wdg = CreateWindow ("button", "Save", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 4, 145, 80, 25, hwnd, + (HMENU) ID_PLAYLISTSAVE, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(wdg, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT),0); + + wdg = CreateWindow ("button", "Close", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 4, 193, 80, 25, hwnd, + (HMENU) ID_CLOSE, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(wdg, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT),0); + + wdg = CreateWindow ("listbox", "tracklist", WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL | + WS_HSCROLL | LBS_DISABLENOSCROLL, 92, 10, 300, 208, hwnd, (HMENU) ID_TRACKLIST, + ((LPCREATESTRUCT) lParam) -> hInstance, NULL); + SendMessage(wdg, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + SendMessage(wdg, LB_SETHORIZONTALEXTENT, MAX_PATH*4, 0); + break; + } + case WM_CONTEXTMENU: + { + GetCursorPos(&cursor); + SetForegroundWindow(hwnd); + TrackPopupMenu(gui->playlistmenu, 0, cursor.x, cursor.y, 0, hwnd, NULL); + break; + } + case WM_COMMAND: + { + HWND tracklist = GetDlgItem(hwnd, ID_TRACKLIST); + int selected = 0; + int i; + for (i=0; i<pl->trackcount; i++) + if(0 < SendMessage(tracklist, LB_GETSEL, i, 0)) selected = i + 1; + switch (LOWORD(wParam)) + { + case ID_CLOSE: + DestroyWindow(hwnd); + return 0; + case ID_TRACKLIST: + if(HIWORD(wParam) == LBN_DBLCLK) + { + if(selected) pl->current = selected - 1; + mplGotoTheNext = 0; + gui->startplay(gui); + } + return 0; + case ID_UP: + { + if(selected) pl->moveup_track(pl, selected); + selected--; + break; + } + case ID_DOWN: + { + if(selected) pl->movedown_track(pl, selected); + selected++; + break; + } + case ID_PLAY: + { + if(selected) pl->current = selected - 1; + mplGotoTheNext = 0; + gui->startplay(gui); + break; + } + case ID_REMOVE: + if(selected) pl->remove_track(pl, selected); + break; + case ID_ADDFILE: + { + if(guiIntfStruct.StreamType == STREAMTYPE_DVD || + guiIntfStruct.StreamType == STREAMTYPE_DVDNAV) return 0; + display_openfilewindow(gui, 1); + break; + } + case ID_ADDURL: + { + if(guiIntfStruct.StreamType == STREAMTYPE_DVD || + guiIntfStruct.StreamType == STREAMTYPE_DVDNAV) return 0; + display_openurlwindow(gui, 1); + break; + } + case ID_CLEAR: + { + if(!gui->playlist->trackcount) return 0; + gui->playlist->clear_playlist(gui->playlist); + break; + } + case ID_PLAYLISTLOAD: + { + if(guiIntfStruct.StreamType == STREAMTYPE_DVD || + guiIntfStruct.StreamType == STREAMTYPE_DVDNAV) return 0; + display_loadplaylistwindow(gui); + break; + } + case ID_PLAYLISTSAVE: + { + /* no point saving an empty playlist */ + if(!gui->playlist->trackcount || + guiIntfStruct.StreamType == STREAMTYPE_DVD || + guiIntfStruct.StreamType == STREAMTYPE_DVDNAV) + return 0; + display_saveplaylistwindow(gui); + break; + } + } + updatetracklist(hwnd); + if(selected < 1) selected = 1; + else if(selected>pl->trackcount) selected = pl->trackcount; + SendMessage(tracklist, LB_SETCURSEL, selected - 1, 0); + return 0; + } + case WM_DROPFILES: + { + 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, 0)) + pl->add_track(pl, file, NULL, NULL, 0); + } + DragFinish((HDROP) wParam); + updatetracklist(hwnd); + } + break; + case WM_DESTROY: + PostQuitMessage(0); + return 0; + } + return DefWindowProc(hwnd, iMsg, wParam, lParam); +} + +void update_playlistwindow(void) +{ + HWND hWnd = FindWindow(NULL, "MPlayer Playlist"); + if (hWnd) updatetracklist(hWnd); +} + +void display_playlistwindow(gui_t *gui) +{ + HWND hWnd = FindWindow(NULL, "MPlayer Playlist"); + if (hWnd) + { + SendMessage(hWnd, WM_CLOSE, 0, 0); + return; + } + + HINSTANCE hInstance = GetModuleHandle(NULL); + WNDCLASS wc; + int x, y; + + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = PlayListWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(NULL,IDC_ARROW); + wc.hIcon = gui->icon; + wc.hbrBackground = SOLID_GREY2; + wc.lpszClassName = "MPlayer - Playlist"; + wc.lpszMenuName = NULL; + RegisterClass(&wc); + create_playlistmenu(gui); + x = (GetSystemMetrics(SM_CXSCREEN) / 2) - (400 / 2); /* Erik: center popup window on screen */ + y = (GetSystemMetrics(SM_CYSCREEN) / 2) - (254 / 2); + hWnd = CreateWindow("MPlayer - Playlist", + "MPlayer Playlist", + WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX, + x, + y, + 400, + 254, + NULL, + NULL, + hInstance, + NULL); + SetWindowLongPtr(hWnd, GWLP_USERDATA, (DWORD)gui); + updatetracklist(hWnd); + DragAcceptFiles(hWnd,TRUE); + ShowWindow(hWnd, SW_SHOW); + UpdateWindow(hWnd); +} + +static LRESULT CALLBACK SkinBrowserWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + static HWND listbox; + static char skinspath[MAX_PATH]; + gui_t* gui = (gui_t*) GetWindowLongPtr(hwnd, GWLP_USERDATA); + switch (iMsg) + { + case WM_CREATE: + { + listbox = CreateWindow("listbox", NULL, + WS_CHILD | WS_VISIBLE | LBS_NOTIFY | LBS_NOINTEGRALHEIGHT | + LBS_DISABLENOSCROLL | WS_VSCROLL | WS_TABSTOP, + 4, 5, 166, 60, hwnd, + (HMENU) ID_DIR, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(listbox, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + /* This opens the skins directory, lists the directory names, and adds them to the listbox */ + sprintf(skinspath, "%s/*.", get_path("skins")); + + HANDLE skinHandle = INVALID_HANDLE_VALUE; + WIN32_FIND_DATA finddata; + + skinHandle = FindFirstFile(skinspath, &finddata); + if (skinHandle != INVALID_HANDLE_VALUE) + { + do + { + if (finddata.cFileName[0] == '.') continue; + /* populate the listbox */ + capitalize(finddata.cFileName); + SendDlgItemMessage(hwnd, ID_DIR, LB_ADDSTRING, 0, (LPARAM) finddata.cFileName); + } while (FindNextFile(skinHandle, &finddata)); + FindClose(skinHandle); + } + else + mp_msg(MSGT_GPLAYER, MSGL_FATAL, "Error opening %s\n", get_path("skins")); + break; + } + case WM_COMMAND: + { + if ((HWND) lParam == listbox) + { + if(HIWORD(wParam) == LBN_DBLCLK) + { + int index = SendMessage(listbox, LB_GETCURSEL, 0, 0); + int len = SendMessage(listbox, LB_GETTEXTLEN, index, 0); + if (len) + { + if (skinName) free(skinName); + skinName = (char *) malloc(len+1); + SendMessage(listbox, LB_GETTEXT, (WPARAM) index, (LPARAM) skinName); + /* fill out the full pathname to the skin */ + strcpy(skinspath, get_path("skins")); + strcat(skinspath, "\\"); + strcat(skinspath, skinName); + ShowWindow(hwnd, SW_HIDE); + Shell_NotifyIcon(NIM_DELETE, &nid); + destroy_window(gui); + create_window(gui, skinspath); + create_subwindow(gui, skinspath); + SendMessage(hwnd, WM_CLOSE, 0, 0); /* Avoid crashing when switching skin */ + } + } + } + } + return 0; + case WM_DESTROY: + PostQuitMessage(0); + return 0; + } + return DefWindowProc(hwnd, iMsg, wParam, lParam); +} + +void display_skinbrowser(gui_t* gui) +{ + HWND hWnd = FindWindow(NULL, "Skin Browser"); + if (hWnd) + { + SendMessage(hWnd, WM_CLOSE, 0, 0); + return; + } + + HINSTANCE hInstance = GetModuleHandle(NULL); + WNDCLASS wc; + int x, y; + + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = SkinBrowserWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hIcon = gui->icon; + wc.hbrBackground = SOLID_GREY2; + wc.lpszClassName = "Skin Browser"; + wc.lpszMenuName = NULL; + RegisterClass(&wc); + x = (GetSystemMetrics(SM_CXSCREEN) / 2) - (180 / 2); + y = (GetSystemMetrics(SM_CYSCREEN) / 2) - (102 / 2); + hWnd = CreateWindow("Skin Browser", + "Skin Browser", + WS_POPUPWINDOW |WS_CAPTION, + x, + y, + 180, + 102, + NULL, + NULL, + hInstance, + NULL); + SetWindowLongPtr(hWnd, GWLP_USERDATA, (DWORD) gui); + ShowWindow(hWnd, SW_SHOW); + UpdateWindow(hWnd); +} + +#ifdef USE_DVDREAD +static LRESULT CALLBACK TitleChapterWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + static HWND title; + static HWND chapter; + HWND wdg; + int i=0, j=0; + char titles[MAX_PATH] = ""; + char chapters[MAX_PATH] = ""; + switch (iMsg) + { + case WM_CREATE: + wdg = CreateWindow("button", "Ok", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 4, 43, 80, 25, hwnd, + (HMENU) ID_OK, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(wdg, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + wdg = CreateWindow("button", "Cancel", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 90, 43, 80, 25, hwnd, + (HMENU) ID_CANCEL, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(wdg, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + title = CreateWindow("combobox", NULL, + CBS_DROPDOWNLIST | CB_SHOWDROPDOWN | CBS_NOINTEGRALHEIGHT | CBS_HASSTRINGS | + WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, + 4, 10, 80, 160, hwnd, + (HMENU) ID_TITLESEL, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + + SendMessage(title, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + chapter = CreateWindow("combobox", NULL, + CBS_DROPDOWNLIST | CB_SHOWDROPDOWN | CBS_NOINTEGRALHEIGHT | CBS_HASSTRINGS | + WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, + 90, 10, 80, 160, hwnd, + (HMENU) ID_CHAPTERSEL, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(chapter, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + for (i=0; i<guiIntfStruct.DVD.titles; i++) + { + /* we have to reverse the order here because of the way CB_INSERTSTRING adds items */ + sprintf(&titles[i], "%d", guiIntfStruct.DVD.titles - i); + SendDlgItemMessage(hwnd, ID_TITLESEL, CB_INSERTSTRING, 0, (LPARAM) &titles[i]); + } + SendDlgItemMessage(hwnd, ID_TITLESEL, CB_SETCURSEL, dvd_title, 0); + + for (j=0; j<guiIntfStruct.DVD.chapters; j++) + { + sprintf(&chapters[j], "%d", guiIntfStruct.DVD.chapters - j); + SendDlgItemMessage(hwnd, ID_CHAPTERSEL, CB_INSERTSTRING, 0, (LPARAM) &chapters[j]); + } + SendDlgItemMessage(hwnd, ID_CHAPTERSEL, CB_SETCURSEL, dvd_chapter, 0); + + break; + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case ID_CANCEL: + DestroyWindow(hwnd); + return 0; + case ID_OK: + { + guiIntfStruct.DVD.current_title = SendMessage(title, CB_GETCURSEL, 0, 0) + 1; + guiIntfStruct.DVD.current_chapter = SendMessage(chapter, CB_GETCURSEL, 0, 0) + 1; + + if((guiIntfStruct.DVD.current_title != 0 || guiIntfStruct.DVD.current_chapter != 0)) + { + mplGotoTheNext = 0; + guiGetEvent(guiCEvent, (void *) guiSetStop); + guiGetEvent(guiCEvent, (void *) guiSetPlay); + DestroyWindow(hwnd); + } + } + break; + } + } + return 0; + case WM_DESTROY: + PostQuitMessage (0); + return 0; + } + return DefWindowProc(hwnd, iMsg, wParam, lParam); +} + +void display_chapterselwindow(gui_t *gui) +{ + HWND hWnd; + HINSTANCE hInstance = GetModuleHandle(NULL); + WNDCLASS wc; + int x, y; + + if (guiIntfStruct.StreamType != STREAMTYPE_DVD) return; + if (FindWindow(NULL, "Select Title/Chapter...")) return; + + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = TitleChapterWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(NULL,IDC_ARROW); + wc.hIcon = gui->icon; + wc.hbrBackground = SOLID_GREY2; + wc.lpszClassName = "Select Title/Chapter..."; + wc.lpszMenuName = NULL; + RegisterClass(&wc); + x = (GetSystemMetrics(SM_CXSCREEN) / 2) - (180 / 2); + y = (GetSystemMetrics(SM_CYSCREEN) / 2) - (100 / 2); + hWnd = CreateWindow("Select Title/Chapter...", + "Select Title/Chapter...", + WS_POPUPWINDOW | WS_CAPTION, + x, + y, + 180, + 100, + NULL, + NULL, + hInstance, + NULL); + SetWindowLongPtr(hWnd, GWLP_USERDATA, (DWORD) gui); + ShowWindow(hWnd, SW_SHOW); + UpdateWindow(hWnd); +} +#endif + +static LRESULT CALLBACK EqWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + HWND btn, label, eq0, eq1, eq2, eq3; + + switch (iMsg) + { + case WM_CREATE: + { + btn = CreateWindow("button", "Reset", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 157, 143, 80, 25, hwnd, + (HMENU) ID_DEFAULTS, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(btn, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + btn = CreateWindow("button", "Close", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 243, 143, 80, 25, hwnd, + (HMENU) ID_CLOSE, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(btn, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + label = CreateWindow("static", "Brightness", + WS_CHILD | WS_VISIBLE, + 12, 122, 70, 15, hwnd, + NULL, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(label, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + label = CreateWindow("static", "Contrast", + WS_CHILD | WS_VISIBLE, + 99, 122, 70, 15, hwnd, + NULL, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(label, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + label = CreateWindow("static", "Hue", + WS_CHILD | WS_VISIBLE, + 191, 122, 70, 15, hwnd, + NULL, + ((LPCREATESTRUCT) lParam) -> hInstance, NULL); + SendMessage(label, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + label = CreateWindow("static", "Saturation", + WS_CHILD | WS_VISIBLE, + 260, 122, 70, 15, hwnd, + NULL, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(label, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + eq0 = CreateWindow(TRACKBAR_CLASS, "brightness", + WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_DISABLED | + TBS_VERT | TBS_NOTICKS, + 30, 0, 20, 120, hwnd, + (HMENU) ID_EQ0, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendDlgItemMessage(hwnd, ID_EQ0, TBM_SETRANGE, 1, MAKELONG(0, 200)); + + eq1 = CreateWindow(TRACKBAR_CLASS, "contrast", + WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_DISABLED | + TBS_VERT | TBS_NOTICKS, + 112, 0, 20, 120, hwnd, + (HMENU) ID_EQ1, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendDlgItemMessage(hwnd, ID_EQ1, TBM_SETRANGE, 1, MAKELONG(0, 200)); + + eq2 = CreateWindow(TRACKBAR_CLASS, "hue", + WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_DISABLED | + TBS_VERT | TBS_NOTICKS, + 194, 0, 20, 120, hwnd, + (HMENU) ID_EQ2, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendDlgItemMessage(hwnd, ID_EQ2, TBM_SETRANGE, 1, MAKELONG(0, 200)); + + eq3 = CreateWindow(TRACKBAR_CLASS, "saturation", + WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_DISABLED | + TBS_VERT | TBS_NOTICKS, + 276, 0, 20, 120, hwnd, + (HMENU) ID_EQ3, + ((LPCREATESTRUCT) lParam) -> hInstance, NULL); + SendDlgItemMessage(hwnd, ID_EQ3, TBM_SETRANGE, 1, MAKELONG(0, 200)); + + if(guiIntfStruct.sh_video && guiIntfStruct.Playing) + { + EnableWindow(eq0, 1); EnableWindow(eq1, 1); EnableWindow(eq2, 1); EnableWindow(eq3, 1); + get_video_colors(guiIntfStruct.sh_video, "brightness", &vo_gamma_brightness); + get_video_colors(guiIntfStruct.sh_video, "contrast", &vo_gamma_contrast); + get_video_colors(guiIntfStruct.sh_video, "hue", &vo_gamma_hue); + get_video_colors(guiIntfStruct.sh_video, "saturation", &vo_gamma_saturation); + } + SendDlgItemMessage(hwnd, ID_EQ0, TBM_SETPOS, 1, (LPARAM)100 - vo_gamma_brightness); + SendDlgItemMessage(hwnd, ID_EQ1, TBM_SETPOS, 1, (LPARAM)100 - vo_gamma_contrast); + SendDlgItemMessage(hwnd, ID_EQ2, TBM_SETPOS, 1, (LPARAM)100 - vo_gamma_hue); + SendDlgItemMessage(hwnd, ID_EQ3, TBM_SETPOS, 1, (LPARAM)100 - vo_gamma_saturation); + break; + } + case WM_VSCROLL: + { + switch (LOWORD(wParam)) + { + case TB_THUMBTRACK: + if(guiIntfStruct.sh_video && guiIntfStruct.Playing) + { + vo_gamma_brightness = 100 - SendDlgItemMessage(hwnd, ID_EQ0, TBM_GETPOS, 0, 0); + set_video_colors(guiIntfStruct.sh_video, "brightness", vo_gamma_brightness); + + vo_gamma_contrast = 100 - SendDlgItemMessage(hwnd, ID_EQ1, TBM_GETPOS, 0, 0); + set_video_colors(guiIntfStruct.sh_video, "contrast", vo_gamma_contrast); + + vo_gamma_hue = 100 - SendDlgItemMessage(hwnd, ID_EQ2, TBM_GETPOS, 0, 0); + set_video_colors(guiIntfStruct.sh_video, "hue", vo_gamma_hue); + + vo_gamma_saturation = 100 - SendDlgItemMessage(hwnd, ID_EQ3, TBM_GETPOS, 0, 0); + set_video_colors(guiIntfStruct.sh_video, "saturation", vo_gamma_saturation); + } + else + { + EnableWindow(GetDlgItem(hwnd, ID_EQ0), 0); + EnableWindow(GetDlgItem(hwnd, ID_EQ1), 0); + EnableWindow(GetDlgItem(hwnd, ID_EQ2), 0); + EnableWindow(GetDlgItem(hwnd, ID_EQ3), 0); + } + break; + } + } + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + { + HDC hdc = (HDC)wParam; + SetBkMode(hdc, TRANSPARENT); + return (INT_PTR)SOLID_GREY2; + } + break; + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case ID_CLOSE: + DestroyWindow(hwnd); + return 0; + case ID_DEFAULTS: + if(guiIntfStruct.sh_video && guiIntfStruct.Playing) + { + vo_gamma_brightness=0; + SendDlgItemMessage(hwnd, ID_EQ0, TBM_SETPOS, 1, (LPARAM)100); + set_video_colors(guiIntfStruct.sh_video, "brightness", vo_gamma_brightness); + + vo_gamma_contrast=0; + SendDlgItemMessage(hwnd, ID_EQ1, TBM_SETPOS, 1, (LPARAM)100); + set_video_colors(guiIntfStruct.sh_video, "contrast", vo_gamma_contrast); + + vo_gamma_hue=0; + SendDlgItemMessage(hwnd, ID_EQ2, TBM_SETPOS, 1, (LPARAM)100); + set_video_colors(guiIntfStruct.sh_video, "hue", vo_gamma_hue); + + vo_gamma_saturation=0; + SendDlgItemMessage(hwnd, ID_EQ3, TBM_SETPOS, 1, (LPARAM)100); + set_video_colors(guiIntfStruct.sh_video, "saturation", vo_gamma_saturation); + } + break; + } + } + return 0; + case WM_DESTROY: + PostQuitMessage (0); + return 0; + } + return DefWindowProc(hwnd, iMsg, wParam, lParam); +} + +void display_eqwindow(gui_t *gui) +{ + if(!guiIntfStruct.sh_video) return; + + HWND hWnd; + HINSTANCE hInstance = GetModuleHandle(NULL); + WNDCLASS wc; + int x, y; + if(FindWindow(NULL, "MPlayer - Equalizer")) return; + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = EqWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(NULL,IDC_ARROW); + wc.hIcon = gui->icon; + wc.hbrBackground = SOLID_GREY2; + wc.lpszClassName = "MPlayer - Equalizer"; + wc.lpszMenuName = NULL; + RegisterClass(&wc); + x = (GetSystemMetrics(SM_CXSCREEN) / 2) - (332 / 2); + y = (GetSystemMetrics(SM_CYSCREEN) / 2) - (200 / 2); + hWnd = CreateWindow("MPlayer - Equalizer", + "MPlayer - Equalizer", + WS_POPUPWINDOW | WS_CAPTION, + x, + y, + 332, + 200, + NULL, + NULL, + hInstance, + NULL); + SetWindowLongPtr(hWnd, GWLP_USERDATA, (DWORD) gui); + ShowWindow(hWnd, SW_SHOW); + UpdateWindow(hWnd); +} diff --git a/Gui/win32/dialogs.h b/Gui/win32/dialogs.h new file mode 100644 index 0000000000..ac80f2c058 --- /dev/null +++ b/Gui/win32/dialogs.h @@ -0,0 +1,129 @@ +/* + 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 +*/ + +#ifndef _DIALOGS_H +#define _DIALOGS_H + +#define TBS_TOOLTIPS 0x0100 +#define WM_SYSTRAY (WM_USER+1) +#define UDM_SETRANGE32 (WM_USER+111) +#define UDM_GETRANGE32 (WM_USER+112) +#define UDM_SETPOS32 (WM_USER+113) +#define UDM_GETPOS32 (WM_USER+114) + +#define SOLID_GREY (HBRUSH) CreateSolidBrush(RGB(232, 232, 232)) +#define SOLID_GREY2 (HBRUSH) CreateSolidBrush(RGB(175, 175, 175)) + +#define gfree free + +#define MAXFILE 1024 + +#define COPYRIGHT " MPlayer GUI for Windows\n\n" \ + " Copyright (c) 2003 Sascha Sommer\n" \ + " Copyright (c) 2006 Erik Augustson\n" \ + " Copyright (c) 2006 Gianluigi Tiesi" + +#define ONLINE_HELP_URL "http://www.mplayerhq.hu/DOCS/HTML/en/index.html" + +#define ID_OK 12 +#define ID_APPLY 13 +#define ID_CANCEL 14 +#define ID_CLOSE 15 +#define ID_DEFAULTS 16 +#define ID_VO_DRIVER 17 +#define ID_AO_DRIVER 18 +#define ID_DOUBLE 19 +#define ID_DIRECT 20 +#define ID_FRAMEDROP 21 +#define ID_NORMALIZE 22 +#define ID_SOFTMIX 23 +#define ID_EXTRASTEREO 24 +#define ID_TRACKBAR1 25 +#define ID_TRACKBAR2 26 +#define ID_UPDOWN1 27 +#define ID_UPDOWN2 28 +#define ID_EDIT1 29 +#define ID_EDIT2 30 +#define ID_CACHE 31 +#define ID_AUTOSYNC 32 +#define ID_NONE 33 +#define ID_OSD1 34 +#define ID_OSD2 35 +#define ID_OSD3 36 +#define ID_DVDDEVICE 37 +#define ID_CDDEVICE 38 +#define ID_PRIO 39 +#define ID_URL 40 +#define ID_TITLESEL 41 +#define ID_UP 42 +#define ID_DOWN 43 +#define ID_REMOVE 44 +#define ID_ADDFILE 45 +#define ID_TRACKLIST 46 +#define ID_SUBTITLE 47 +#define ID_PLAYLISTLOAD 48 +#define ID_PLAYLISTSAVE 49 +#define ID_ADDURL 50 +#define ID_DIR 51 +#define ID_PLAY 52 +#define ID_STOP 53 +#define ID_SEEKF 54 +#define ID_SEEKB 55 +#define ID_NTRACK 56 +#define ID_PTRACK 57 +#define ID_PLAYLIST 58 +#define ID_CLEAR 59 +#define ID_SHOWHIDE 60 +#define ID_SKINBROWSER 61 +#define ID_KEYHELP 62 +#define ID_ONLINEHELP 63 +#define ID_CHAPTERSEL 64 +#define ID_PREFS 65 +#define TRAYMENU 66 +#define IDFILE_OPEN 67 +#define IDEXIT 68 +#define IDURL_OPEN 69 +#define IDDIR_OPEN 70 +#define IDFILE_NEW 71 +#define IDFILE_SAVE 72 +#define IDHELP_ABOUT 73 +#define IDSUBTITLE_OPEN 74 +#define IDPLAYDISK 75 +#define ID_CONSOLE 76 +#define ID_EQ0 77 +#define ID_EQ1 78 +#define ID_EQ2 79 +#define ID_EQ3 80 +#define IDSUB_TOGGLE 81 +#define IDSUB_CYCLE 82 +#define ID_ASPECT1 83 +#define ID_ASPECT2 84 +#define ID_ASPECT3 85 +#define ID_ASPECT4 86 +#define ID_SUBWINDOW 87 + +/* gtk emulation */ +#define GTK_MB_FATAL 0x1 +#define GTK_MB_ERROR 0x2 +#define GTK_MB_WARNING 0x4 +#define GTK_MB_SIMPLE 0x8 + +#endif 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; +} diff --git a/Gui/win32/gui.h b/Gui/win32/gui.h new file mode 100644 index 0000000000..e777c12c34 --- /dev/null +++ b/Gui/win32/gui.h @@ -0,0 +1,118 @@ +/* + 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 +*/ + +#ifndef _GUI_H +#define _GUI_H +#include <config.h> +#include <playtree.h> +#include <m_config.h> +#include "skinload.h" +#include "playlist.h" + +extern char *skinName; +extern float sub_aspect; +extern play_tree_t* playtree; +extern m_config_t* mconfig; + +extern NOTIFYICONDATA nid; + +typedef struct window_priv_t window_priv_t; +struct window_priv_t +{ + HWND hwnd; + image img; + image *background; + HBITMAP bitmap; + int type; +}; + +typedef struct gui_t gui_t; +struct gui_t +{ + /* screenproperties */ + int screenw, screenh, screenbpp; + /* window related stuff */ + char *classname; + HICON icon; + unsigned int window_priv_count; + window_priv_t **window_priv; + + HWND mainwindow; + HWND subwindow; + + /* for event handling */ + widget *activewidget; + + int mousewx, mousewy; /* mousepos inside widget */ + int mousex, mousey; + + HMENU menu; + HMENU diskmenu; + HMENU traymenu; + HMENU trayplaymenu; + HMENU trayplaybackmenu; + HMENU submenu; + HMENU subtitlemenu; + HMENU aspectmenu; + HMENU dvdmenu; + HMENU playlistmenu; + + int skinbrowserwindow; + int playlistwindow; + int aboutwindow; + + skin_t *skin; + playlist_t *playlist; + + void (*startplay)(gui_t *gui); + void (*updatedisplay)(gui_t *gui, HWND hwnd); + void (*playercontrol)(int event); /* userdefine call back function */ + void (*uninit)(gui_t *gui); +}; + +#define wsShowWindow 8 +#define wsHideWindow 16 +#define wsShowFrame 1 +#define wsMovable 2 +#define wsSizeable 4 + +extern gui_t *create_gui(char *skindir, char *skinName, void (*playercontrol)(int event)); +extern int destroy_window(gui_t *gui); +extern int create_window(gui_t *gui, char *skindir); +extern int create_subwindow(gui_t *gui, char *skindir); +extern int parse_filename(char *file, play_tree_t *playtree, m_config_t *mconfig, int clear); +extern void capitalize(char *filename); +extern int import_playtree_playlist_into_gui(play_tree_t *my_playtree, m_config_t *config); + +/* Dialogs */ +extern void display_playlistwindow(gui_t *gui); +extern void update_playlistwindow(void); +extern int display_openfilewindow(gui_t *gui, int add); +extern void display_openurlwindow(gui_t *gui, int add); +extern void display_skinbrowser(gui_t *gui); +extern void display_chapterselwindow(gui_t *gui); +extern void display_eqwindow(gui_t *gui); +extern void display_prefswindow(gui_t *gui); +#ifdef USE_SUB +extern void display_opensubtitlewindow(gui_t *gui); +#endif + +#endif diff --git a/Gui/win32/interface.c b/Gui/win32/interface.c new file mode 100644 index 0000000000..99c4453fdf --- /dev/null +++ b/Gui/win32/interface.c @@ -0,0 +1,975 @@ +/* + 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 <windows.h> +#include <interface.h> +#include <m_option.h> +#include <mixer.h> +#include <mp_msg.h> +#include <help_mp.h> +#include <codec-cfg.h> +#include <libmpdemux/stream.h> +#include <libmpdemux/demuxer.h> +#include <libmpdemux/stheader.h> +#ifdef USE_DVDREAD +#include <libmpdemux/stream_dvd.h> +#endif +#include <input/input.h> +#include <libvo/video_out.h> +#include <libao2/audio_out.h> +#include "gui.h" +#include "dialogs.h" +#include "wincfg.h" +#ifdef HAVE_LIBCDIO +#include <cdio/cdio.h> +#endif + +extern m_obj_settings_t* vo_plugin_args; +extern vo_functions_t *video_out; +extern ao_functions_t *audio_out; +extern void exit_player(char *how); +extern char *filename; +extern int abs_seek_pos; +extern float rel_seek_secs; +extern mixer_t mixer; +extern int audio_id; +extern int video_id; +extern int dvdsub_id; +extern int vobsub_id; +extern int stream_cache_size; +extern int autosync; +extern int vcd_track; +extern int dvd_title; +extern float force_fps; +extern af_cfg_t af_cfg; +int guiWinID = 0; + +char *skinName = NULL; +char *codecname = NULL; +int mplGotoTheNext = 1; +static gui_t *mygui = NULL; +static int update_subwindow(void); + +/* test for playlist files, no need to specify -playlist on the commandline. + * add any conceivable playlist extensions here. + * - Erik + */ +int parse_filename(char *file, play_tree_t *playtree, m_config_t *mconfig, int clear) +{ + if(clear) + mygui->playlist->clear_playlist(mygui->playlist); + + if(strstr(file, ".m3u") || strstr(file, ".pls")) + { + playtree = parse_playlist_file(file); + import_playtree_playlist_into_gui(playtree, mconfig); + return 1; + } + return 0; +} + +/** + * \brief this actually creates a new list containing only one element... + */ +void gaddlist( char ***list, char *entry) +{ + int i; + + if (*list) + { + for (i=0; (*list)[i]; i++) free((*list)[i]); + free(*list); + } + + *list = malloc(2 * sizeof(char **)); + (*list)[0] = gstrdup(entry); + (*list)[1] = NULL; +} + +char *gstrdup(char *str) +{ + if (!str) return NULL; + return strdup(str); +} + +/** + * \brief this replaces a string starting with search by replace. + * If not found, replace is appended. + */ +void greplace(char ***list, char *search, char *replace) +{ + int i = 0; + int len = (search) ? strlen(search) : 0; + + if (*list) + { + for (i = 0; (*list)[i]; i++) + { + if (search && (!strncmp((*list)[i], search, len))) + { + free((*list)[i]); + (*list)[i] = gstrdup(replace); + return; + } + } + *list = realloc(*list, (i + 2) * sizeof(char *)); + } + else + *list = malloc(2 * sizeof(char *)); + + (*list)[i] = gstrdup(replace); + (*list)[i + 1] = NULL; +} + +/* this function gets called by the gui to update mplayer */ +static void guiSetEvent(int event) +{ + switch(event) + { + case evPlay: + case evPlaySwitchToPause: + mplPlay(); + break; + case evPause: + mplPause(); + break; +#ifdef USE_DVDREAD + case evPlayDVD: + { + static char dvdname[MAX_PATH]; + guiIntfStruct.DVD.current_title = dvd_title; + guiIntfStruct.DVD.current_chapter = dvd_chapter; + guiIntfStruct.DVD.current_angle = dvd_angle; + guiIntfStruct.DiskChanged = 1; + + mplSetFileName(NULL, dvd_device, STREAMTYPE_DVD); + guiIntfStruct.Title = guiIntfStruct.DVD.current_title; + guiIntfStruct.Chapter = guiIntfStruct.DVD.current_chapter; + guiIntfStruct.Angle = guiIntfStruct.DVD.current_angle; + + dvdname[0] = 0; + strcat(dvdname, "DVD Movie"); + GetVolumeInformation(dvd_device, dvdname, MAX_PATH, NULL, NULL, NULL, NULL, 0); + capitalize(dvdname); + mp_msg(MSGT_GPLAYER, MSGL_V, "Opening DVD %s -> %s\n", dvd_device, dvdname); + guiGetEvent(guiSetParameters, (char *) STREAMTYPE_DVD); + mygui->playlist->clear_playlist(mygui->playlist); + mygui->playlist->add_track(mygui->playlist, filename, NULL, dvdname, 0); + mygui->startplay(mygui); + break; + } +#endif +#ifdef HAVE_LIBCDIO + case evPlayCD: + { + int i; + char track[10]; + char trackname[10]; + CdIo_t *p_cdio = cdio_open(NULL, DRIVER_UNKNOWN); + track_t i_tracks; + + if(p_cdio == NULL) printf("Couldn't find a driver.\n"); + i_tracks = cdio_get_num_tracks(p_cdio); + + mygui->playlist->clear_playlist(mygui->playlist); + for(i=0;i<i_tracks;i++) + { + sprintf(track, "cdda://%d", i+1); + sprintf(trackname, "Track %d", i+1); + mygui->playlist->add_track(mygui->playlist, track, NULL, trackname, 0); + } + cdio_destroy(p_cdio); + mygui->startplay(mygui); + break; + } +#endif + case evFullScreen: + mp_input_queue_cmd(mp_input_parse_cmd("vo_fullscreen")); + break; + case evExit: + { + /* We are asking mplayer to exit, later it will ask us after uninit is made + this should be the only safe way to quit */ + mygui->activewidget = NULL; + mp_input_queue_cmd(mp_input_parse_cmd("quit")); + break; + } + case evStop: + if(guiIntfStruct.Playing) + guiGetEvent(guiCEvent, (void *) guiSetStop); + break; + case evSetMoviePosition: + { + rel_seek_secs = guiIntfStruct.Position / 100.0f; + abs_seek_pos = 3; + break; + } + case evForward10sec: + { + rel_seek_secs = 10.0f; + abs_seek_pos = 0; + break; + } + case evBackward10sec: + { + rel_seek_secs = -10.0f; + abs_seek_pos = 0; + break; + } + case evSetBalance: + case evSetVolume: + { + float l,r; + + if (guiIntfStruct.Balance == 50.0f) + mixer_setvolume(&mixer, guiIntfStruct.Volume, guiIntfStruct.Volume); + + l = guiIntfStruct.Volume * ((100.0f - guiIntfStruct.Balance) / 50.0f); + r = guiIntfStruct.Volume * ((guiIntfStruct.Balance) / 50.0f); + + if (l > guiIntfStruct.Volume) l=guiIntfStruct.Volume; + if (r > guiIntfStruct.Volume) r=guiIntfStruct.Volume; + mixer_setvolume(&mixer, l, r); + /* Check for balance support on mixer - there is a better way ?? */ + if (r != l) + { + mixer_getvolume(&mixer, &l, &r); + if (r == l) + { + mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] Mixer doesn't support balanced audio\n"); + mixer_setvolume(&mixer, guiIntfStruct.Volume, guiIntfStruct.Volume); + guiIntfStruct.Balance = 50.0f; + } + } + break; + } + case evMute: + { + mp_cmd_t * cmd = (mp_cmd_t *)calloc(1, sizeof(*cmd)); + cmd->id=MP_CMD_MUTE; + cmd->name=strdup("mute"); + mp_input_queue_cmd(cmd); + break; + } + case evDropFile: + case evLoadPlay: + { + mplSetFileName(NULL, filename, STREAMTYPE_FILE); + guiIntfStruct.FilenameChanged = guiIntfStruct.NewPlay = 1; + update_playlistwindow(); + guiGetEvent(guiCEvent, (void *) guiSetStop); + guiGetEvent(guiCEvent, (void *) guiSetPlay); + break; + } + case evNext: + mplNext(); + break; + case evPrev: + mplPrev(); + break; + } +} + +void mplPlay( void ) +{ + if((!guiIntfStruct.Filename ) || (guiIntfStruct.Filename[0] == 0)) + return; + + if(guiIntfStruct.Playing > 0) + { + mplPause(); + return; + } + guiIntfStruct.NewPlay = 1; + guiGetEvent(guiCEvent, (void *) guiSetPlay); +} + +void mplPause( void ) +{ + if(!guiIntfStruct.Playing) return; + + if(guiIntfStruct.Playing == 1) + { + mp_cmd_t * cmd = (mp_cmd_t *)calloc(1, sizeof(*cmd)); + cmd->id=MP_CMD_PAUSE; + cmd->name=strdup("pause"); + mp_input_queue_cmd(cmd); + } else guiIntfStruct.Playing = 1; +} + +void mplNext(void) +{ + if(guiIntfStruct.Playing == 2) return; + switch(guiIntfStruct.StreamType) + { +#ifdef USE_DVDREAD + case STREAMTYPE_DVD: + if(guiIntfStruct.DVD.current_chapter == (guiIntfStruct.DVD.chapters - 1)) + return; + guiIntfStruct.DVD.current_chapter++; + break; +#endif + default: + if(mygui->playlist->current == (mygui->playlist->trackcount - 1)) + return; + mplSetFileName(NULL, mygui->playlist->tracks[(mygui->playlist->current)++]->filename, + STREAMTYPE_STREAM); + break; + } + mplGotoTheNext = 0; + mygui->startplay(mygui); +} + +void mplPrev(void) +{ + if(guiIntfStruct.Playing == 2) return; + switch(guiIntfStruct.StreamType) + { +#ifdef USE_DVDREAD + case STREAMTYPE_DVD: + if(guiIntfStruct.DVD.current_chapter == 1) + return; + guiIntfStruct.DVD.current_chapter--; + break; +#endif + default: + if(mygui->playlist->current == 0) + return; + mplSetFileName(NULL, mygui->playlist->tracks[(mygui->playlist->current)--]->filename, + STREAMTYPE_STREAM); + break; + } + mplGotoTheNext = 0; + mygui->startplay(mygui); +} + +void mplEnd( void ) +{ + if(!mplGotoTheNext && guiIntfStruct.Playing) + { + mplGotoTheNext = 1; + return; + } + + if(mplGotoTheNext && guiIntfStruct.Playing && + (mygui->playlist->current < (mygui->playlist->trackcount - 1)) && + guiIntfStruct.StreamType != STREAMTYPE_DVD && + guiIntfStruct.StreamType != STREAMTYPE_DVDNAV) + { + /* we've finished this file, reset the aspect */ + if(movie_aspect >= 0) + movie_aspect = -1; + + mplGotoTheNext = guiIntfStruct.FilenameChanged = guiIntfStruct.NewPlay = 1; + mplSetFileName(NULL, mygui->playlist->tracks[(mygui->playlist->current)++]->filename, STREAMTYPE_STREAM); + //sprintf(guiIntfStruct.Filename, mygui->playlist->tracks[(mygui->playlist->current)++]->filename); + } + + if(guiIntfStruct.FilenameChanged && guiIntfStruct.NewPlay) + return; + + guiIntfStruct.TimeSec = 0; + guiIntfStruct.Position = 0; + guiIntfStruct.AudioType = 0; + +#ifdef USE_DVDREAD + guiIntfStruct.DVD.current_title = 1; + guiIntfStruct.DVD.current_chapter = 1; + guiIntfStruct.DVD.current_angle = 1; +#endif + + if (mygui->playlist->current == (mygui->playlist->trackcount - 1)) + mygui->playlist->current = 0; + + guiGetEvent(guiCEvent, (void *) guiSetStop); +} + +void mplSetFileName(char *dir, char *name, int type) +{ + if(!name) return; + if(!dir) + guiSetFilename(guiIntfStruct.Filename, name) + else + guiSetDF(guiIntfStruct.Filename, dir, name); + + guiIntfStruct.StreamType = type; + free((void **) &guiIntfStruct.AudioFile); + free((void **) &guiIntfStruct.Subtitlename); +} + +static DWORD WINAPI GuiThread(void) +{ + MSG msg; + + if(!skinName) skinName = strdup("Blue"); + if(!mygui) mygui = create_gui(get_path("skins"), skinName, guiSetEvent); + if(!mygui) exit_player("Unable to load gui"); + + if(autosync && autosync != gtkAutoSync) + { + gtkAutoSyncOn = 1; + gtkAutoSync = autosync; + } + + while(mygui) + { + GetMessage(&msg, NULL, 0, 0); + TranslateMessage(&msg); + DispatchMessage(&msg); + } + fprintf(stderr, "[GUI] Gui Thread Terminated\n"); + fflush(stderr); + return 0; +} + +void guiInit(void) +{ + memset(&guiIntfStruct, 0, sizeof(guiIntfStruct)); + /* Create The gui thread */ + if (!mygui) + mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] Creating GUI Thread 0x%04x\n", + (int) CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) GuiThread, NULL, 0, NULL)); + + /* Wait until the gui is created */ + while(!mygui) Sleep(100); + mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] Gui Thread started\n"); +} + +void guiDone(void) +{ + if(mygui) + { + fprintf(stderr, "[GUI] Closed by main mplayer window\n"); + fflush(stderr); + mygui->uninit(mygui); + free(mygui); + TerminateThread(GuiThread, 0); + mygui = NULL; + } + /* Remove tray icon */ + Shell_NotifyIcon(NIM_DELETE, &nid); + cfg_write(); +} + +static void add_vop(char * str) +{ + mp_msg(MSGT_GPLAYER, MSGL_STATUS, MSGTR_AddingVideoFilter, str); + if (vo_plugin_args) + { + int i = 0; + while (vo_plugin_args[i].name) + if (!strcmp(vo_plugin_args[i++].name, str)) + { + i = -1; + break; + } + if (i != -1) + { + vo_plugin_args = realloc(vo_plugin_args, (i + 2) * sizeof(m_obj_settings_t)); + vo_plugin_args[i].name = strdup(str); + vo_plugin_args[i].attribs = NULL; + vo_plugin_args[i + 1].name = NULL; + } + } + else + { + vo_plugin_args = malloc(2 * sizeof(m_obj_settings_t)); + vo_plugin_args[0].name = strdup(str); + vo_plugin_args[0].attribs = NULL; + vo_plugin_args[1].name = NULL; + } +} + +static void remove_vop(char * str) +{ + int n = 0; + if (!vo_plugin_args ) return; + + mp_msg(MSGT_GPLAYER,MSGL_STATUS, MSGTR_RemovingVideoFilter, str); + + while (vo_plugin_args[n++].name); + n--; + if ( n > -1 ) + { + int i = 0, m = -1; + while (vo_plugin_args[i].name) + if (!strcmp(vo_plugin_args[i++].name, str)) + { + m = i - 1; + break; + } + i--; + if (m > -1) + { + if (n == 1) + { + free(vo_plugin_args[0].name); + free(vo_plugin_args[0].attribs); + free(vo_plugin_args); + vo_plugin_args=NULL; + } + else + { + free(vo_plugin_args[i].name); + free(vo_plugin_args[i].attribs); + memcpy(&vo_plugin_args[i], &vo_plugin_args[i + 1], (n - i) * sizeof(m_obj_settings_t)); + } + } + } +} + +/* this function gets called by mplayer to update the gui */ +int guiGetEvent(int type, char *arg) +{ + if(!mygui || !mygui->skin) return 0; + + stream_t *stream = (stream_t *) arg; +#ifdef USE_DVDREAD + dvd_priv_t *dvdp = (dvd_priv_t *) arg; +#endif + + switch (type) + { + case guiSetFileFormat: + guiIntfStruct.FileFormat = (int) arg; + break; + case guiSetParameters: + { + guiGetEvent(guiSetDefaults, NULL); + guiIntfStruct.DiskChanged = 0; + guiIntfStruct.FilenameChanged = 0; + guiIntfStruct.NewPlay = 0; + switch(guiIntfStruct.StreamType) + { + case STREAMTYPE_PLAYLIST: + break; +#ifdef USE_DVDREAD + case STREAMTYPE_DVD: + { + char tmp[512]; + dvd_title = guiIntfStruct.DVD.current_title; + dvd_chapter = guiIntfStruct.DVD.current_chapter; + dvd_angle = guiIntfStruct.DVD.current_angle; + sprintf(tmp,"dvd://%d", guiIntfStruct.Title); + guiSetFilename(guiIntfStruct.Filename, tmp); + break; + } +#endif + } + if(guiIntfStruct.Filename) + filename = strdup(guiIntfStruct.Filename); + else if(filename) + strcpy(guiIntfStruct.Filename, filename); + break; + } + case guiSetAudioOnly: + { + guiIntfStruct.AudioOnly = (int) arg; + if(IsWindowVisible(mygui->subwindow)) + ShowWindow(mygui->subwindow, SW_HIDE); + break; + } + case guiSetDemuxer: + guiIntfStruct.demuxer = (void *) arg; + break; + case guiSetValues: + { + guiIntfStruct.sh_video = arg; + if (arg) + { + sh_video_t *sh = (sh_video_t *)arg; + codecname = sh->codec->name; + guiIntfStruct.FPS = sh->fps; + + /* we have video, show the subwindow */ + if(!IsWindowVisible(mygui->subwindow) || IsIconic(mygui->subwindow)) + ShowWindow(mygui->subwindow, SW_SHOWNORMAL); + if(WinID == -1) + update_subwindow(); + + } + break; + } + case guiSetShVideo: + { + guiIntfStruct.MovieWidth = vo_dwidth; + guiIntfStruct.MovieHeight = vo_dheight; + + sub_aspect = (float)guiIntfStruct.MovieWidth/guiIntfStruct.MovieHeight; + if(WinID != -1) + update_subwindow(); + break; + } + case guiSetStream: + { + guiIntfStruct.StreamType = stream->type; + switch(stream->type) + { +#ifdef USE_DVDREAD + case STREAMTYPE_DVD: + guiGetEvent(guiSetDVD, (char *) stream->priv); + break; +#endif + } + break; + } +#ifdef USE_DVDREAD + case guiSetDVD: + { + guiIntfStruct.DVD.titles = dvdp->vmg_file->tt_srpt->nr_of_srpts; + guiIntfStruct.DVD.chapters = dvdp->vmg_file->tt_srpt->title[dvd_title].nr_of_ptts; + guiIntfStruct.DVD.angles = dvdp->vmg_file->tt_srpt->title[dvd_title].nr_of_angles; + guiIntfStruct.DVD.nr_of_audio_channels = dvdp->nr_of_channels; + memcpy(guiIntfStruct.DVD.audio_streams, dvdp->audio_streams, sizeof(dvdp->audio_streams)); + guiIntfStruct.DVD.nr_of_subtitles = dvdp->nr_of_subtitles; + memcpy(guiIntfStruct.DVD.subtitles, dvdp->subtitles, sizeof(dvdp->subtitles)); + guiIntfStruct.DVD.current_title = dvd_title + 1; + guiIntfStruct.DVD.current_chapter = dvd_chapter + 1; + guiIntfStruct.DVD.current_angle = dvd_angle + 1; + guiIntfStruct.Track = dvd_title + 1; + break; + } +#endif + case guiReDraw: + mygui->updatedisplay(mygui, mygui->mainwindow); + break; + case guiSetAfilter: + guiIntfStruct.afilter = (void *) arg; + break; + case guiCEvent: + { + guiIntfStruct.Playing = (int) arg; + switch (guiIntfStruct.Playing) + { + case guiSetPlay: + { + guiIntfStruct.Playing = 1; + break; + } + case guiSetStop: + { + guiIntfStruct.Playing = 0; + if(movie_aspect >= 0) + movie_aspect = -1; + update_subwindow(); + break; + } + case guiSetPause: + guiIntfStruct.Playing = 2; + break; + } + break; + } + case guiIEvent: + { + mp_msg(MSGT_GPLAYER,MSGL_V, "cmd: %d\n", (int) arg); + /* MPlayer asks us to quit */ + switch((int) arg) + { + case MP_CMD_GUI_FULLSCREEN: + { + if(!guiIntfStruct.sh_video) break; + video_out->control(VOCTRL_FULLSCREEN, 0); + + /* no WinID, keep the sub window hidden */ + if((video_driver_list && !strstr(video_driver_list[0], "directx")) || !sub_window) + break; + + if(vo_fs) + { + WinID = -1; + ShowWindow(mygui->subwindow, SW_HIDE); + while(ShowCursor(FALSE) >= 0){} + } else { + WinID = mygui->subwindow; + ShowWindow(mygui->subwindow, SW_SHOW); + while(ShowCursor(TRUE) <= 0){} + } + break; + } + case MP_CMD_QUIT: + { + mygui->uninit(mygui); + free(mygui); + mygui = NULL; + exit_player("Done"); + return 0; + } + case MP_CMD_GUI_STOP: + guiGetEvent(guiCEvent, (void *) guiSetStop); + break; + case MP_CMD_GUI_PLAY: + guiGetEvent(guiCEvent, (void *) guiSetPlay); + break; + case MP_CMD_GUI_SKINBROWSER: + if(vo_fs) guiSetEvent(evFullScreen); + PostMessage(mygui->mainwindow, WM_COMMAND, (WPARAM) ID_SKINBROWSER, 0); + break; + case MP_CMD_GUI_PLAYLIST: + if(vo_fs) guiSetEvent(evFullScreen); + PostMessage(mygui->mainwindow, WM_COMMAND, (WPARAM) ID_PLAYLIST, 0); + break; + case MP_CMD_GUI_PREFERENCES: + if(vo_fs) guiSetEvent(evFullScreen); + PostMessage(mygui->mainwindow, WM_COMMAND, (WPARAM) ID_PREFS, 0); + break; + case MP_CMD_GUI_LOADFILE: + if(vo_fs) guiSetEvent(evFullScreen); + PostMessage(mygui->mainwindow, WM_COMMAND, (WPARAM) IDFILE_OPEN, 0); + break; +#ifdef USE_SUB + case MP_CMD_GUI_LOADSUBTITLE: + if(vo_fs) guiSetEvent(evFullScreen); + PostMessage(mygui->mainwindow, WM_COMMAND, (WPARAM) IDSUBTITLE_OPEN, 0); + break; +#endif + default: + break; + } + break; + } + case guiSetFileName: + if (arg) guiIntfStruct.Filename = (char *) arg; + break; + case guiSetDefaults: + { + audio_id = -1; + video_id = -1; + dvdsub_id = -1; + vobsub_id = -1; + stream_cache_size = -1; + autosync = 0; + vcd_track = 0; + dvd_title = 0; + force_fps = 0; + if(!mygui->playlist->tracks) return 0; + filename = guiIntfStruct.Filename = mygui->playlist->tracks[mygui->playlist->current]->filename; + guiIntfStruct.Track = mygui->playlist->current + 1; + if(gtkAONorm) greplace(&af_cfg.list, "volnorm", "volnorm"); + if(gtkAOExtraStereo) + { + char *name = malloc(12 + 20 + 1); + snprintf(name, 12 + 20, "extrastereo=%f", gtkAOExtraStereoMul); + name[12 + 20] = 0; + greplace(&af_cfg.list, "extrastereo", name); + free(name); + } + if(gtkCacheOn) stream_cache_size = gtkCacheSize; + if(gtkAutoSyncOn) autosync = gtkAutoSync; + break; + } + case guiSetVolume: + { + if(audio_out) + { + /* Some audio_out drivers do not support balance e.g. dsound */ + /* FIXME this algo is not correct */ + float l, r; + mixer_getvolume(&mixer, &l, &r); + guiIntfStruct.Volume = (r > l ? r : l); /* max(r,l) */ + if (r != l) + guiIntfStruct.Balance = ((r-l) + 100.0f) * 0.5f; + else + guiIntfStruct.Balance = 50.0f; + } + break; + } + default: + mp_msg(MSGT_GPLAYER, MSGL_ERR, "[GUI] GOT UNHANDLED EVENT %i\n", type); + } + return 0; +} + +/* This function adds/inserts one file into the gui playlist */ +int import_file_into_gui(char *pathname, int insert) +{ + char filename[MAX_PATH]; + char *filepart = filename; + + if (strstr(pathname, "://")) + { + mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] Adding special %s\n", pathname); + mygui->playlist->add_track(mygui->playlist, pathname, NULL, NULL, 0); + return 1; + } + if (GetFullPathName(pathname, MAX_PATH, filename, &filepart)) + { + if (!(GetFileAttributes(filename) & FILE_ATTRIBUTE_DIRECTORY)) + { + mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] Adding filename: %s - fullpath: %s\n", filepart, filename); + mygui->playlist->add_track(mygui->playlist, filename, NULL, filepart, 0); + return 1; + } + else + mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] Cannot add %s\n", filename); + } + + return 0; +} + +/* This function imports the initial playtree (based on cmd-line files) into the gui playlist + by either: + - overwriting gui pl (enqueue=0) */ + +int import_initial_playtree_into_gui(play_tree_t *my_playtree, m_config_t *config, int enqueue) +{ + play_tree_iter_t *my_pt_iter = NULL; + int result = 0; + + if(!mygui) guiInit(); + + if((my_pt_iter = pt_iter_create(&my_playtree, config))) + { + while ((filename = pt_iter_get_next_file(my_pt_iter)) != NULL) + { + if (parse_filename(filename, my_playtree, config, 0)) + result = 1; + else if (import_file_into_gui(filename, 0)) /* Add it to end of list */ + result = 1; + } + } + mplGotoTheNext = 1; + + if (result) + { + mygui->playlist->current = 0; + filename = mygui->playlist->tracks[0]->filename; + } + return result; +} + +/* This function imports and inserts an playtree, that is created "on the fly", for example by + parsing some MOV-Reference-File; or by loading an playlist with "File Open" + The file which contained the playlist is thereby replaced with it's contents. */ + +int import_playtree_playlist_into_gui(play_tree_t *my_playtree, m_config_t *config) +{ + play_tree_iter_t *my_pt_iter = NULL; + int result = 0; + + if((my_pt_iter = pt_iter_create(&my_playtree, config))) + { + while ((filename = pt_iter_get_next_file(my_pt_iter)) != NULL) + if (import_file_into_gui(filename, 1)) /* insert it into the list and set plCurrent = new item */ + result = 1; + pt_iter_destroy(&my_pt_iter); + } + filename = NULL; + return result; +} + +inline void gtkMessageBox(int type, const char *str) +{ + if (type & GTK_MB_FATAL) + MessageBox(NULL, str, "MPlayer GUI for Windows Error", MB_OK | MB_ICONERROR); + + fprintf(stderr, "[GUI] MessageBox: %s\n", str); + fflush(stderr); +} + +void guiMessageBox(int level, char *str) +{ + switch(level) + { + case MSGL_FATAL: + gtkMessageBox(GTK_MB_FATAL | GTK_MB_SIMPLE, str); + break; + case MSGL_ERR: + gtkMessageBox(GTK_MB_ERROR | GTK_MB_SIMPLE, str); + break; + } +} + +static int update_subwindow(void) +{ + int x,y; + RECT rd; + WINDOWPOS wp; + + /* it's not the best way to check if selected driver is directx, + if no driver is specified video_driver_list is null. + Right now I don't have a functional way to do this + - Sherpya */ + if((video_driver_list && !strstr(video_driver_list[0], "directx")) || !sub_window) + { + WinID = -1; // so far only directx supports WinID in windows + + if(IsWindowVisible(mygui->subwindow) && guiIntfStruct.sh_video && guiIntfStruct.Playing) + { + ShowWindow(mygui->subwindow, SW_HIDE); + return 0; + } + else if(guiIntfStruct.AudioOnly) + return 0; + else ShowWindow(mygui->subwindow, SW_SHOW); + } + + /* we've come out of fullscreen at the end of file */ + if((!IsWindowVisible(mygui->subwindow) || IsIconic(mygui->subwindow)) && !guiIntfStruct.AudioOnly) + ShowWindow(mygui->subwindow, SW_SHOWNORMAL); + + /* get our current window coordinates */ + GetWindowRect(mygui->subwindow, &rd); + x = rd.left; + y = rd.top; + + if(!guiIntfStruct.Playing) + { + window *desc = NULL; + int i; + + for (i=0; i<mygui->skin->windowcount; i++) + if(mygui->skin->windows[i]->type == wiSub) + desc = mygui->skin->windows[i]; + + rd.right = rd.left+desc->base->bitmap[0]->width; + rd.bottom = rd.top+desc->base->bitmap[0]->height; + sub_aspect = (float)(rd.right-rd.left)/(rd.bottom-rd.top); + } + else + { + rd.right = rd.left+guiIntfStruct.MovieWidth; + rd.bottom = rd.top+guiIntfStruct.MovieHeight; + + if (movie_aspect > 0.0) // forced aspect from the cmdline + sub_aspect = movie_aspect; + } + + AdjustWindowRect(&rd, WS_OVERLAPPEDWINDOW | WS_SIZEBOX, 0); + SetWindowPos(mygui->subwindow, HWND_NOTOPMOST, x, y, rd.right-rd.left, rd.bottom-rd.top, SWP_NOOWNERZORDER); + + wp.hwnd = mygui->subwindow; + wp.x = rd.left; + wp.y = rd.top; + wp.cx = rd.right-rd.left; + wp.cy = rd.bottom-rd.top; + wp.flags = SWP_NOOWNERZORDER | SWP_SHOWWINDOW; + + /* erase the bitmap image if there's video */ + if(guiIntfStruct.Playing != 0 && guiIntfStruct.sh_video) + SendMessage(mygui->subwindow, WM_ERASEBKGND, (WPARAM)GetDC(mygui->subwindow), 0); + + /* reset the window aspect */ + SendMessage(mygui->subwindow, WM_WINDOWPOSCHANGED, 0, (LPARAM)&wp); + return 0; +} + +void guiEventHandling(void) {} diff --git a/Gui/win32/playlist.c b/Gui/win32/playlist.c new file mode 100644 index 0000000000..65556e9dee --- /dev/null +++ b/Gui/win32/playlist.c @@ -0,0 +1,154 @@ +/* + 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 <windows.h> +#include <mp_msg.h> +#include "playlist.h" + +/* TODO: implement sort_playlist */ + +BOOL adddirtoplaylist(playlist_t *playlist, const char *path, BOOL recursive) +{ + HANDLE findHandle = INVALID_HANDLE_VALUE; + WIN32_FIND_DATA finddata; + char findpath[MAX_PATH], filename[MAX_PATH]; + char *filepart; + + sprintf(findpath, "%s\\*.*", path); + + findHandle = FindFirstFile(findpath, &finddata); + + if (findHandle == INVALID_HANDLE_VALUE) return FALSE; + do + { + if (finddata.cFileName[0] == '.' || strstr(finddata.cFileName, "Thumbs.db")) continue; + sprintf(findpath, "%s\\%s", path, finddata.cFileName); + + if (GetFileAttributes(findpath) & FILE_ATTRIBUTE_DIRECTORY) + { + if(recursive) + adddirtoplaylist(playlist, findpath, recursive); + } + else + { + if (GetFullPathName(findpath, MAX_PATH, filename, &filepart)) + playlist->add_track(playlist, filename, NULL, filepart, 0); + } + } while (FindNextFile(findHandle, &finddata)); + FindClose(findHandle); + return TRUE; +} + +static void add_track(playlist_t *playlist, const char *filename, const char *artist, const char *title, int duration) +{ + (playlist->trackcount)++; + playlist->tracks = realloc(playlist->tracks, playlist->trackcount * sizeof(pl_track_t *)); + playlist->tracks[playlist->trackcount - 1] = calloc(1, sizeof(pl_track_t)); + if(filename) playlist->tracks[playlist->trackcount - 1]->filename = strdup(filename); + if(artist) playlist->tracks[playlist->trackcount - 1]->artist = strdup(artist); + if(title) playlist->tracks[playlist->trackcount - 1]->title = strdup(title); + if(duration) playlist->tracks[playlist->trackcount - 1]->duration = duration; +} + +static void remove_track(playlist_t *playlist, int number) +{ + pl_track_t **tmp = calloc(1, playlist->trackcount * sizeof(pl_track_t *)); + int i, p = 0; + memcpy(tmp, playlist->tracks, playlist->trackcount * sizeof(pl_track_t *)); + (playlist->trackcount)--; + playlist->tracks = realloc(playlist->tracks, playlist->trackcount * sizeof(pl_track_t *)); + for(i=0; i<playlist->trackcount + 1; i++) + { + if(i != (number - 1)) + { + playlist->tracks[p] = tmp[i]; + p++; + } + else + { + if(tmp[i]->filename) free(tmp[i]->filename); + if(tmp[i]->artist) free(tmp[i]->artist); + if(tmp[i]->title) free(tmp[i]->title); + free(tmp[i]); + } + } + free(tmp); +} + +static void moveup_track(playlist_t *playlist, int number) +{ + pl_track_t *tmp; + if(number == 1) return; /* already first */ + tmp = playlist->tracks[number - 2]; + playlist->tracks[number - 2] = playlist->tracks[number - 1]; + playlist->tracks[number - 1] = tmp; +} + +static void movedown_track(playlist_t *playlist, int number) +{ + pl_track_t *tmp; + if(number == playlist->trackcount) return; /* already latest */ + tmp = playlist->tracks[number]; + playlist->tracks[number] = playlist->tracks[number - 1]; + playlist->tracks[number - 1] = tmp; +} + +static void sort_playlist(playlist_t *playlist, int opt) {} + +static void clear_playlist(playlist_t *playlist) +{ + while(playlist->trackcount) playlist->remove_track(playlist, 1); + playlist->tracks = NULL; + playlist->current = 0; +} + +static void free_playlist(playlist_t *playlist) +{ + if(playlist->tracks) playlist->clear_playlist(playlist); + free(playlist); +} + +static void dump_playlist(playlist_t *playlist) +{ + int i; + for (i=0; i<playlist->trackcount; i++) + { + mp_msg(MSGT_GPLAYER, MSGL_V, "track %i %s ", i + 1, playlist->tracks[i]->filename); + if(playlist->tracks[i]->artist) mp_msg(MSGT_GPLAYER, MSGL_V, "%s ", playlist->tracks[i]->artist); + if(playlist->tracks[i]->title) mp_msg(MSGT_GPLAYER, MSGL_V, "- %s ", playlist->tracks[i]->title); + if(playlist->tracks[i]->duration) mp_msg(MSGT_GPLAYER, MSGL_V, "%i ", playlist->tracks[i]->duration); + mp_msg(MSGT_GPLAYER, MSGL_V, "\n"); + } +} + +playlist_t *create_playlist(void) +{ + playlist_t *playlist = calloc(1, sizeof(playlist_t)); + playlist->add_track = add_track; + playlist->remove_track = remove_track; + playlist->moveup_track = moveup_track; + playlist->movedown_track = movedown_track; + playlist->dump_playlist = dump_playlist; + playlist->sort_playlist = sort_playlist; + playlist->clear_playlist = clear_playlist; + playlist->free_playlist = free_playlist; + return playlist; +} diff --git a/Gui/win32/playlist.h b/Gui/win32/playlist.h new file mode 100644 index 0000000000..41766d169d --- /dev/null +++ b/Gui/win32/playlist.h @@ -0,0 +1,57 @@ +/* + 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 +*/ + +#ifndef _PLAYLIST_H +#define _PLAYLIST_H + +typedef struct +{ + char *filename; + char *artist; + char *title; + int duration; +} pl_track_t; + +typedef struct playlist_t playlist_t; +struct playlist_t +{ + int current; /* currently used track */ + int trackcount; /* number of tracknumber */ + pl_track_t **tracks; /* tracklist */ + void (*add_track)(playlist_t* playlist, const char *filename, const char *artist, const char *title, int duration); + void (*remove_track)(playlist_t* playlist, int number); + void (*moveup_track)(playlist_t* playlist, int number); + void (*movedown_track)(playlist_t* playlist, int number); + void (*dump_playlist)(playlist_t* playlist); + void (*sort_playlist)(playlist_t* playlist, int opt); + void (*clear_playlist)(playlist_t* playlist); + void (*free_playlist)(playlist_t* playlist); +}; + +#define SORT_BYFILENAME 1 +#define SORT_BYARTIST 2 +#define SORT_BYTITLE 3 +#define SORT_BYDURATION 4 + +extern playlist_t *create_playlist(void); +extern BOOL adddirtoplaylist(playlist_t *playlist, const char* path, BOOL recursive); + +#endif diff --git a/Gui/win32/preferences.c b/Gui/win32/preferences.c new file mode 100644 index 0000000000..c31a02aaae --- /dev/null +++ b/Gui/win32/preferences.c @@ -0,0 +1,714 @@ +/* + 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 <windows.h> +#include <commctrl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <libvo/video_out.h> +#include <libao2/audio_out.h> +#include <mixer.h> +#include "interface.h" +#include "gui.h" +#include "mp_msg.h" +#include "help_mp.h" +#include "dialogs.h" +#include "wincfg.h" + +extern int vo_doublebuffering; +extern int vo_directrendering; +extern int frame_dropping; +extern int soft_vol; +extern float audio_delay; +extern int osd_level; +extern char *dvd_device, *cdrom_device; +extern char *proc_priority; + +static void set_defaults(void); + +static LRESULT CALLBACK PrefsWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + HWND btn, label, edit1, edit2, edit3, updown1, updown2, track1, track2; + static HWND vo_driver, ao_driver, prio; + int i = 0, j = 0; + char dvddevice[MAX_PATH]; + char cdromdevice[MAX_PATH]; + char procprio[11]; + float x = 10.0, y = 100.0, stereopos, delaypos; + stereopos = gtkAOExtraStereoMul * x; + delaypos = audio_delay * y; + + switch (iMsg) + { + case WM_CREATE: + { + /* video and audio drivers */ + label = CreateWindow("static", "Video Driver:", + WS_CHILD | WS_VISIBLE, + 10, 13, 70, 15, hwnd, + NULL, ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(label, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + label = CreateWindow("static", "Audio Driver:", + WS_CHILD | WS_VISIBLE, + 190, 13, 70, 15, hwnd, + NULL, ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(label, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + label = CreateWindow("static", "Extra stereo coefficient:", + WS_CHILD | WS_VISIBLE, + 10, 126, 115, 15, hwnd, + NULL, ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(label, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + label = CreateWindow("static", "Audio delay:", + WS_CHILD | WS_VISIBLE, + 36, 165, 115, 15, hwnd, + NULL, ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(label, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + label = CreateWindow("static", "OSD level:", + WS_CHILD | WS_VISIBLE, + 10, 264, 115, 15, hwnd, + NULL, ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(label, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + label = CreateWindow("static", "DVD device:", + WS_CHILD | WS_VISIBLE, + 80, 363, 115, 15, hwnd, + NULL, ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(label, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + label = CreateWindow("static", "CD device:", + WS_CHILD | WS_VISIBLE, + 202, 363, 115, 15, hwnd, + NULL, ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(label, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + label = CreateWindow("static", "Priority:", + WS_CHILD | WS_VISIBLE, + 217, 264, 115, 15, hwnd, + NULL, ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(label, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + vo_driver = CreateWindow("combobox", NULL, + CBS_DROPDOWNLIST | CB_SHOWDROPDOWN | + CBS_NOINTEGRALHEIGHT | CBS_HASSTRINGS | + WS_CHILD | WS_VISIBLE | + WS_VSCROLL | WS_TABSTOP, + 80, 10, 100, 160, hwnd, + (HMENU) ID_VO_DRIVER, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + + ao_driver = CreateWindow("combobox", NULL, + CBS_DROPDOWNLIST | CB_SHOWDROPDOWN | + CBS_NOINTEGRALHEIGHT | CBS_HASSTRINGS | + WS_CHILD | WS_VISIBLE | + WS_VSCROLL | WS_TABSTOP, + 260, 10, 100, 160, hwnd, + (HMENU) ID_AO_DRIVER, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + + prio = CreateWindow("combobox", NULL, + CBS_DROPDOWNLIST | CB_SHOWDROPDOWN | + CBS_NOINTEGRALHEIGHT | CBS_HASSTRINGS | + WS_CHILD | WS_VISIBLE | + WS_VSCROLL | WS_TABSTOP, + 260, 260, 100, 160, hwnd, + (HMENU) ID_PRIO, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + + /* checkboxes */ + btn = CreateWindow("button", "Enable double buffering", + WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, + 25, 35, 150, 25, + hwnd, (HMENU) ID_DOUBLE, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(btn, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + btn = CreateWindow("button", "Enable direct rendering", + WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, + 25, 57, 150, 25, + hwnd, (HMENU) ID_DIRECT, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(btn, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + btn = CreateWindow("button", "Enable framedropping", + WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, + 25, 79, 150, 25, + hwnd, (HMENU) ID_FRAMEDROP, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(btn, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + btn = CreateWindow("button", "Normalize sound", + WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, + 205, 35, 150, 25, + hwnd, (HMENU) ID_NORMALIZE, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(btn, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + btn = CreateWindow("button", "Enable software mixer", + WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, + 205, 57, 150, 25, + hwnd, (HMENU) ID_SOFTMIX, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(btn, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + btn = CreateWindow("button", "Enable extra stereo", + WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, + 205, 79, 150, 25, + hwnd, (HMENU) ID_EXTRASTEREO, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(btn, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + btn = CreateWindow("button", "Enable cache", + WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, + 10, 200, 90, 25, + hwnd, (HMENU) ID_CACHE, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(btn, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + btn = CreateWindow("button", "Enable autosync", + WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, + 192, 200, 100, 25, hwnd, + (HMENU) ID_AUTOSYNC, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(btn, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + btn = CreateWindow("button", "Display videos in the sub window (directx only)", + WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, + 55, 227, 250, 25, + hwnd, (HMENU) ID_SUBWINDOW, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(btn, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + /* osd level */ + btn = CreateWindow("button", "None", + WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON, + 95, 260, 100, 25, hwnd, + (HMENU) ID_NONE, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(btn, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + btn = CreateWindow("button", "Timer and indicators", + WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON, + 95, 280, 180, 25, hwnd, + (HMENU) ID_OSD1, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(btn, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + btn = CreateWindow("button", "Progress bar only", + WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON, + 95, 300, 180, 25, hwnd, + (HMENU) ID_OSD2, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(btn, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + btn = CreateWindow("button", "Timer, percentage, and total time", + WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON, + 95, 320, 180, 25, hwnd, + (HMENU) ID_OSD3, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(btn, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + btn = CreateWindow("button", "Apply", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 199, 395, 80, 25, hwnd, + (HMENU) ID_APPLY, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(btn, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + btn = CreateWindow("button", "Cancel", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 285, 395, 80, 25, hwnd, + (HMENU) ID_CANCEL, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(btn, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + btn = CreateWindow("button", "Defaults", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 4, 395, 80, 25, hwnd, + (HMENU) ID_DEFAULTS, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(btn, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + /* extra stereo coefficient trackbar */ + track1 = CreateWindow(TRACKBAR_CLASS, "Coefficient", + WS_CHILD | WS_VISIBLE | WS_TABSTOP | + WS_DISABLED | TBS_HORZ | + TBS_BOTTOM | TBS_NOTICKS, + 120, 120, 245, 35, hwnd, + (HMENU) ID_TRACKBAR1, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendDlgItemMessage(hwnd, ID_TRACKBAR1, TBM_SETRANGE, 1, MAKELONG(-100, 100)); + + /* audio delay */ + track2 = CreateWindow(TRACKBAR_CLASS, "Audio delay", + WS_CHILD | WS_VISIBLE | WS_TABSTOP | + WS_DISABLED | TBS_HORZ | + TBS_BOTTOM | TBS_NOTICKS, + 120, 160, 245, 35, hwnd, + (HMENU) ID_TRACKBAR2, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendDlgItemMessage(hwnd, ID_TRACKBAR2, TBM_SETRANGE, 1, MAKELONG(-1000, 1000)); + + /* cache */ + edit1 = CreateWindowEx(WS_EX_CLIENTEDGE, "edit", "cache", + WS_CHILD | WS_VISIBLE | WS_DISABLED | + ES_LEFT | ES_AUTOHSCROLL, + 105, 203, 40, 20, hwnd, + (HMENU) ID_EDIT1, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(edit1, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + updown1 = CreateUpDownControl(WS_CHILD | WS_VISIBLE | + WS_DISABLED | UDS_SETBUDDYINT | + UDS_ARROWKEYS | UDS_NOTHOUSANDS, + 145, 203, 20, 20, hwnd, + ID_UPDOWN1, + ((LPCREATESTRUCT) lParam) -> hInstance, + (HWND)edit1, 0, 0, 0); + SendDlgItemMessage(hwnd, ID_UPDOWN1, UDM_SETRANGE32, (WPARAM)0, (LPARAM)65535); + + /* autosync */ + edit2 = CreateWindowEx(WS_EX_CLIENTEDGE, "edit", "autosync", + WS_CHILD | WS_VISIBLE | WS_DISABLED | + ES_LEFT | ES_AUTOHSCROLL, + 300, 203, 40, 20, hwnd, + (HMENU) ID_EDIT2, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(edit2, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + updown2 = CreateUpDownControl(WS_CHILD | WS_VISIBLE | + WS_DISABLED | UDS_SETBUDDYINT | + UDS_ARROWKEYS | UDS_NOTHOUSANDS, + 340, 203, 20, 20, hwnd, + ID_UPDOWN2, + ((LPCREATESTRUCT) lParam) -> hInstance, + (HWND)edit2, 0, 0, 0); + SendDlgItemMessage(hwnd, ID_UPDOWN2, UDM_SETRANGE32, (WPARAM)0, (LPARAM)10000); + + /* dvd and cd devices */ + edit3 = CreateWindowEx(WS_EX_CLIENTEDGE, "edit", NULL, + WS_CHILD | WS_VISIBLE | + ES_LEFT | ES_AUTOHSCROLL, + 145, 360, 20, 20, hwnd, + (HMENU) ID_DVDDEVICE, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(edit3, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + edit3 = CreateWindowEx(WS_EX_CLIENTEDGE, "edit", NULL, + WS_CHILD | WS_VISIBLE | + ES_LEFT| ES_AUTOHSCROLL, + 260, 360, 20, 20, hwnd, + (HMENU) ID_CDDEVICE, + ((LPCREATESTRUCT) lParam) -> hInstance, + NULL); + SendMessage(edit3, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + while(video_out_drivers[i]) + { + const vo_info_t *info = video_out_drivers[i++]->info; + if(!video_driver_list) gaddlist(&video_driver_list, (char *)info->short_name); + SendDlgItemMessage(hwnd, ID_VO_DRIVER, CB_ADDSTRING, 0, (LPARAM) info->short_name); + } + /* Special case for directx:noaccel */ + SendDlgItemMessage(hwnd, ID_VO_DRIVER, CB_ADDSTRING, 0, (LPARAM) "directx:noaccel"); + SendMessage(vo_driver, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + while(audio_out_drivers[j]) + { + const ao_info_t *info = audio_out_drivers[j++]->info; + if(!audio_driver_list) + { + gaddlist(&audio_driver_list, (char *)info->short_name); + audio_driver_list[0] = "win32"; + } + SendDlgItemMessage(hwnd, ID_AO_DRIVER, CB_ADDSTRING, 0, (LPARAM) info->short_name); + } + SendMessage(ao_driver, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + /* priority list, i'm leaving out realtime for safety's sake */ + SendDlgItemMessage(hwnd, ID_PRIO, CB_INSERTSTRING, 0, (LPARAM) "low"); + SendDlgItemMessage(hwnd, ID_PRIO, CB_INSERTSTRING, 0, (LPARAM) "belownormal"); + SendDlgItemMessage(hwnd, ID_PRIO, CB_INSERTSTRING, 0, (LPARAM) "normal"); + SendDlgItemMessage(hwnd, ID_PRIO, CB_INSERTSTRING, 0, (LPARAM) "abovenormal"); + SendDlgItemMessage(hwnd, ID_PRIO, CB_INSERTSTRING, 0, (LPARAM) "high"); + SendMessage(prio, WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0); + + /* set our preferences on what we already have */ + if(video_driver_list) + SendDlgItemMessage(hwnd, ID_VO_DRIVER, CB_SETCURSEL, + (WPARAM)SendMessage(vo_driver, CB_FINDSTRING, -1, + (LPARAM)video_driver_list[0]), 0); + + if(audio_driver_list) + SendDlgItemMessage(hwnd, ID_AO_DRIVER, CB_SETCURSEL, + (WPARAM)SendMessage(ao_driver, CB_FINDSTRING, -1, + (LPARAM)audio_driver_list[0]), 0); + + if(vo_doublebuffering) + SendDlgItemMessage(hwnd, ID_DOUBLE, BM_SETCHECK, 1, 0); + if(vo_directrendering) + SendDlgItemMessage(hwnd, ID_DIRECT, BM_SETCHECK, 1, 0); + if(frame_dropping) + SendDlgItemMessage(hwnd, ID_FRAMEDROP, BM_SETCHECK, 1, 0); + if(gtkAONorm) + SendDlgItemMessage(hwnd, ID_NORMALIZE, BM_SETCHECK, 1, 0); + if(soft_vol) + SendDlgItemMessage(hwnd, ID_SOFTMIX, BM_SETCHECK, 1, 0); + if(gtkAOExtraStereo) + { + SendDlgItemMessage(hwnd, ID_EXTRASTEREO, BM_SETCHECK, 1, 0); + if(!guiIntfStruct.Playing) + { + EnableWindow(track1, 1); + EnableWindow(track2, 1); + } + } + else gtkAOExtraStereoMul = 1.0; + SendDlgItemMessage(hwnd, ID_TRACKBAR1, TBM_SETPOS, 1, (LPARAM)stereopos); + + if(audio_delay) + SendDlgItemMessage(hwnd, ID_TRACKBAR2, TBM_SETPOS, 1, (LPARAM)delaypos); + + if(gtkCacheOn) { + SendDlgItemMessage(hwnd, ID_CACHE, BM_SETCHECK, 1, 0); + EnableWindow(edit1, 1); + EnableWindow(updown1, 1); + } + else gtkCacheSize = 2048; + SendDlgItemMessage(hwnd, ID_UPDOWN1, UDM_SETPOS32, 0, (LPARAM)gtkCacheSize); + + if(gtkAutoSyncOn) { + SendDlgItemMessage(hwnd, ID_AUTOSYNC, BM_SETCHECK, 1, 0); + EnableWindow(edit2, 1); + EnableWindow(updown2, 1); + } + else gtkAutoSync = 0; + SendDlgItemMessage(hwnd, ID_UPDOWN2, UDM_SETPOS32, 0, (LPARAM)gtkAutoSync); + + if(sub_window) + SendDlgItemMessage(hwnd, ID_SUBWINDOW, BM_SETCHECK, 1, 0); + + if(!osd_level) + SendDlgItemMessage(hwnd, ID_NONE, BM_SETCHECK, 1, 0); + else if(osd_level == 1) + SendDlgItemMessage(hwnd, ID_OSD1, BM_SETCHECK, 1, 0); + else if(osd_level == 2) + SendDlgItemMessage(hwnd, ID_OSD2, BM_SETCHECK, 1, 0); + else if(osd_level == 3) + SendDlgItemMessage(hwnd, ID_OSD3, BM_SETCHECK, 1, 0); + + if(dvd_device) + SendDlgItemMessage(hwnd, ID_DVDDEVICE, WM_SETTEXT, 0, (LPARAM)dvd_device); + else SendDlgItemMessage(hwnd, ID_DVDDEVICE, WM_SETTEXT, 0, (LPARAM)"D:"); + + if(cdrom_device) + SendDlgItemMessage(hwnd, ID_CDDEVICE, WM_SETTEXT, 0, (LPARAM)cdrom_device); + else SendDlgItemMessage(hwnd, ID_CDDEVICE, WM_SETTEXT, 0, (LPARAM)"D:"); + + if(proc_priority) + SendDlgItemMessage(hwnd, ID_PRIO, CB_SETCURSEL, + (WPARAM)SendMessage(prio, CB_FINDSTRING, -1, + (LPARAM)proc_priority), 0); + + else SendDlgItemMessage(hwnd, ID_PRIO, CB_SETCURSEL, 2, 0); + + break; + } + case WM_CTLCOLORDLG: + case WM_CTLCOLOREDIT: + case WM_CTLCOLORBTN: + case WM_CTLCOLORSTATIC: + { + HDC hdc = (HDC)wParam; + SetBkMode(hdc, TRANSPARENT); + return (INT_PTR)SOLID_GREY; + } + break; + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case ID_EXTRASTEREO: + { + if(SendDlgItemMessage(hwnd, ID_EXTRASTEREO, BM_GETCHECK, 0, 0) == BST_CHECKED) + { + EnableWindow(GetDlgItem(hwnd, ID_TRACKBAR1), 1); + EnableWindow(GetDlgItem(hwnd, ID_TRACKBAR2), 1); + } else { + EnableWindow(GetDlgItem(hwnd, ID_TRACKBAR1), 0); + EnableWindow(GetDlgItem(hwnd, ID_TRACKBAR2), 0); + SendDlgItemMessage(hwnd, ID_TRACKBAR1, TBM_SETPOS, 1, (LPARAM)10.0); + SendDlgItemMessage(hwnd, ID_TRACKBAR2, TBM_SETPOS, 1, (LPARAM)0); + } + break; + } + case ID_CACHE: + { + if(SendDlgItemMessage(hwnd, ID_CACHE, BM_GETCHECK, 0, 0) == BST_CHECKED) + { + EnableWindow(GetDlgItem(hwnd, ID_EDIT1), 1); + EnableWindow(GetDlgItem(hwnd, ID_UPDOWN1), 1); + } else { + EnableWindow(GetDlgItem(hwnd, ID_EDIT1), 0); + EnableWindow(GetDlgItem(hwnd, ID_UPDOWN1), 0); + SendDlgItemMessage(hwnd, ID_UPDOWN1, UDM_SETPOS32, 1, (LPARAM)2048); + } + break; + } + case ID_AUTOSYNC: + { + if(SendDlgItemMessage(hwnd, ID_AUTOSYNC, BM_GETCHECK, 0, 0) == BST_CHECKED) + { + EnableWindow(GetDlgItem(hwnd, ID_EDIT2), 1); + EnableWindow(GetDlgItem(hwnd, ID_UPDOWN2), 1); + } else { + EnableWindow(GetDlgItem(hwnd, ID_EDIT2), 0); + EnableWindow(GetDlgItem(hwnd, ID_UPDOWN2), 0); + SendDlgItemMessage(hwnd, ID_UPDOWN2, UDM_SETPOS32, 1, (LPARAM)0); + } + break; + } + case ID_DEFAULTS: + { + set_defaults(); + SendDlgItemMessage(hwnd, ID_VO_DRIVER, CB_SETCURSEL, + (WPARAM)SendMessage(vo_driver, CB_FINDSTRING, -1, (LPARAM)"directx"), 0); + + SendDlgItemMessage(hwnd, ID_AO_DRIVER, CB_SETCURSEL, + (WPARAM)SendMessage(ao_driver, CB_FINDSTRING, -1, (LPARAM)"dsound"), 0); + + SendDlgItemMessage(hwnd, ID_PRIO, CB_SETCURSEL, + (WPARAM)SendMessage(prio, CB_FINDSTRING, -1, (LPARAM)proc_priority), 0); + + SendDlgItemMessage(hwnd, ID_TRACKBAR1, TBM_SETPOS, 1, (LPARAM)10.0); + SendDlgItemMessage(hwnd, ID_TRACKBAR2, TBM_SETPOS, 1, (LPARAM)0.0); + SendDlgItemMessage(hwnd, ID_UPDOWN1, UDM_SETPOS32, 0, (LPARAM)gtkCacheSize); + SendDlgItemMessage(hwnd, ID_UPDOWN2, UDM_SETPOS32, 0, (LPARAM)gtkAutoSync); + SendDlgItemMessage(hwnd, ID_DOUBLE, BM_SETCHECK, 0, 0); + SendDlgItemMessage(hwnd, ID_DIRECT, BM_SETCHECK, 0, 0); + SendDlgItemMessage(hwnd, ID_FRAMEDROP, BM_SETCHECK, 0, 0); + SendDlgItemMessage(hwnd, ID_NORMALIZE, BM_SETCHECK, 0, 0); + SendDlgItemMessage(hwnd, ID_SOFTMIX, BM_SETCHECK, 0, 0); + SendDlgItemMessage(hwnd, ID_EXTRASTEREO, BM_SETCHECK, 0, 0); + SendDlgItemMessage(hwnd, ID_CACHE, BM_SETCHECK, 0, 0); + SendDlgItemMessage(hwnd, ID_AUTOSYNC, BM_SETCHECK, 0, 0); + SendDlgItemMessage(hwnd, ID_SUBWINDOW, BM_SETCHECK, 1, 0); + SendDlgItemMessage(hwnd, ID_NONE, BM_SETCHECK, 0, 0); + SendDlgItemMessage(hwnd, ID_OSD1, BM_SETCHECK, 1, 0); + SendDlgItemMessage(hwnd, ID_OSD2, BM_SETCHECK, 0, 0); + SendDlgItemMessage(hwnd, ID_OSD3, BM_SETCHECK, 0, 0); + SendDlgItemMessage(hwnd, ID_DVDDEVICE, WM_SETTEXT, 0, (LPARAM)"D:"); + SendDlgItemMessage(hwnd, ID_CDDEVICE, WM_SETTEXT, 0, (LPARAM)"D:"); + SendMessage(hwnd, WM_COMMAND, (WPARAM)ID_APPLY, 0); + break; + } + case ID_CANCEL: + DestroyWindow(hwnd); + return 0; + case ID_APPLY: + { + if(guiIntfStruct.Playing) guiGetEvent(guiCEvent, (void *)guiSetStop); + + /* Set the video driver */ + SendMessage(vo_driver, CB_GETLBTEXT, (WPARAM)SendMessage(vo_driver, CB_GETCURSEL, 0, 0), + (LPARAM)video_driver_list[0]); + + /* Set the audio driver */ + SendMessage(ao_driver, CB_GETLBTEXT, (WPARAM)SendMessage(ao_driver, CB_GETCURSEL, 0, 0), + (LPARAM)audio_driver_list[0]); + + /* Set the priority level */ + SendMessage(prio, CB_GETLBTEXT, (WPARAM)SendMessage(prio, CB_GETCURSEL, 0, 0), (LPARAM)procprio); + proc_priority = strdup(procprio); + + /* double buffering */ + if(SendDlgItemMessage(hwnd, ID_DOUBLE, BM_GETCHECK, 0, 0) == BST_CHECKED) + vo_doublebuffering = 1; + else vo_doublebuffering = 0; + + /* direct rendering */ + if(SendDlgItemMessage(hwnd, ID_DIRECT, BM_GETCHECK, 0, 0) == BST_CHECKED) + vo_directrendering = 1; + else vo_directrendering = 0; + + /* frame dropping */ + if(SendDlgItemMessage(hwnd, ID_FRAMEDROP, BM_GETCHECK, 0, 0) == BST_CHECKED) + frame_dropping = 1; + else frame_dropping = 0; + + /* normalize */ + if(SendDlgItemMessage(hwnd, ID_NORMALIZE, BM_GETCHECK, 0, 0) == BST_CHECKED) + gtkAONorm = 1; + else gtkAONorm = 0; + + /* software mixer */ + if(SendDlgItemMessage(hwnd, ID_SOFTMIX, BM_GETCHECK, 0, 0) == BST_CHECKED) + soft_vol = 1; + else soft_vol = 0; + + /* extra stereo */ + if(SendDlgItemMessage(hwnd, ID_EXTRASTEREO, BM_GETCHECK, 0, 0) == BST_CHECKED) + gtkAOExtraStereo = 1; + else { + gtkAOExtraStereo = 0; + gtkAOExtraStereoMul = 10.0; + } + gtkAOExtraStereoMul = SendDlgItemMessage(hwnd, ID_TRACKBAR1, TBM_GETPOS, 0, 0) / 10.0; + + /* audio delay */ + audio_delay = SendDlgItemMessage(hwnd, ID_TRACKBAR2, TBM_GETPOS, 0, 0) / 100.0; + + /* cache */ + if(SendDlgItemMessage(hwnd, ID_CACHE, BM_GETCHECK, 0, 0) == BST_CHECKED) + gtkCacheOn = 1; + else gtkCacheOn = 0; + gtkCacheSize = SendDlgItemMessage(hwnd, ID_UPDOWN1, UDM_GETPOS32, 0, 0); + + /* autosync */ + if(SendDlgItemMessage(hwnd, ID_AUTOSYNC, BM_GETCHECK, 0, 0) == BST_CHECKED) + gtkAutoSyncOn = 1; + else gtkAutoSyncOn = 0; + gtkAutoSync = SendDlgItemMessage(hwnd, ID_UPDOWN2, UDM_GETPOS32, 0, 0); + + /* sub window */ + if(SendDlgItemMessage(hwnd, ID_SUBWINDOW, BM_GETCHECK, 0, 0) == BST_CHECKED) + sub_window = 1; + else sub_window = 0; + + /* osd level */ + if(SendDlgItemMessage(hwnd, ID_NONE, BM_GETCHECK, 0, 0) == BST_CHECKED) + osd_level = 0; + else if(SendDlgItemMessage(hwnd, ID_OSD1, BM_GETCHECK, 0, 0) == BST_CHECKED) + osd_level = 1; + else if(SendDlgItemMessage(hwnd, ID_OSD2, BM_GETCHECK, 0, 0) == BST_CHECKED) + osd_level = 2; + else if(SendDlgItemMessage(hwnd, ID_OSD3, BM_GETCHECK, 0, 0) == BST_CHECKED) + osd_level = 3; + + /* dvd and cd devices */ + SendDlgItemMessage(hwnd, ID_DVDDEVICE, WM_GETTEXT, MAX_PATH, (LPARAM)dvddevice); + dvd_device = strdup(dvddevice); + SendDlgItemMessage(hwnd, ID_CDDEVICE, WM_GETTEXT, MAX_PATH, (LPARAM)cdromdevice); + cdrom_device = strdup(cdromdevice); + + MessageBox(hwnd, "You must restart MPlayer for the changes to take effect.", "MPlayer - Info:", MB_OK); + DestroyWindow(hwnd); + break; + } + } + return 0; + } + case WM_DESTROY: + PostQuitMessage (0); + return 0; + } + return DefWindowProc(hwnd, iMsg, wParam, lParam); +} + +void display_prefswindow(gui_t *gui) +{ + HWND hWnd; + HINSTANCE hInstance = GetModuleHandle(NULL); + WNDCLASS wc; + int x, y; + if(FindWindow(NULL, "MPlayer - Preferences")) return; + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = PrefsWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(NULL,IDC_ARROW); + wc.hIcon = gui->icon; + wc.hbrBackground = SOLID_GREY; + wc.lpszClassName = "MPlayer - Preferences"; + wc.lpszMenuName = NULL; + RegisterClass(&wc); + x = (GetSystemMetrics(SM_CXSCREEN) / 2) - (375 / 2); + y = (GetSystemMetrics(SM_CYSCREEN) / 2) - (452 / 2); + hWnd = CreateWindow("MPlayer - Preferences", + "MPlayer - Preferences", + WS_POPUPWINDOW | WS_CAPTION, + x, + y, + 375, + 452, + NULL, + NULL, + hInstance, + NULL); + SetWindowLongPtr(hWnd, GWLP_USERDATA, (DWORD) gui); + ShowWindow(hWnd, SW_SHOW); + UpdateWindow(hWnd); +} + +static void set_defaults(void) +{ + proc_priority = "normal"; + vo_doublebuffering = 1; + vo_directrendering = 0; + frame_dropping = 0; + soft_vol = 0; + gtkAONorm = 0; + gtkAOExtraStereo = 0; + gtkAOExtraStereoMul = 1.0; + audio_delay = 0.0; + sub_window = 1; + gtkCacheOn = 0; + gtkCacheSize = 2048; + gtkAutoSyncOn = 0; + gtkAutoSync = 0; +} diff --git a/Gui/win32/skinload.c b/Gui/win32/skinload.c new file mode 100644 index 0000000000..9c56e93348 --- /dev/null +++ b/Gui/win32/skinload.c @@ -0,0 +1,809 @@ +/* + 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 <stdlib.h> +#include <inttypes.h> +#include <windows.h> +#include <png.h> + +#include <mp_msg.h> +#include <cpudetect.h> +#include <libswscale/rgb2rgb.h> +#include <libswscale/swscale.h> + +#include "gui.h" + +#define MAX_LINESIZE 256 + +typedef struct +{ + int msg; + char *name; +} evName; + +static const evName evNames[] = +{ + { evNone, "evNone" }, + { evPlay, "evPlay" }, + { evDropFile, "evDropFile" }, + { evStop, "evStop" }, + { evPause, "evPause" }, + { evPrev, "evPrev" }, + { evNext, "evNext" }, + { evLoad, "evLoad" }, + { evEqualizer, "evEqualizer" }, + { evEqualizer, "evEqualeaser" }, + { evPlayList, "evPlaylist" }, + { evExit, "evExit" }, + { evIconify, "evIconify" }, + { evIncBalance, "evIncBalance" }, + { evDecBalance, "evDecBalance" }, + { evFullScreen, "evFullScreen" }, + { evFName, "evFName" }, + { evMovieTime, "evMovieTime" }, + { evAbout, "evAbout" }, + { evLoadPlay, "evLoadPlay" }, + { evPreferences, "evPreferences" }, + { evSkinBrowser, "evSkinBrowser" }, + { evBackward10sec, "evBackward10sec" }, + { evForward10sec, "evForward10sec" }, + { evBackward1min, "evBackward1min" }, + { evForward1min, "evForward1min" }, + { evBackward10min, "evBackward10min" }, + { evForward10min, "evForward10min" }, + { evIncVolume, "evIncVolume" }, + { evDecVolume, "evDecVolume" }, + { evMute, "evMute" }, + { evIncAudioBufDelay, "evIncAudioBufDelay" }, + { evDecAudioBufDelay, "evDecAudioBufDelay" }, + { evPlaySwitchToPause, "evPlaySwitchToPause" }, + { evPauseSwitchToPlay, "evPauseSwitchToPlay" }, + { evNormalSize, "evNormalSize" }, + { evDoubleSize, "evDoubleSize" }, + { evSetMoviePosition, "evSetMoviePosition" }, + { evSetVolume, "evSetVolume" }, + { evSetBalance, "evSetBalance" }, + { evHelp, "evHelp" }, + { evLoadSubtitle, "evLoadSubtitle" }, + { evPlayDVD, "evPlayDVD" }, + { evPlayVCD, "evPlayVCD" }, + { evSetURL, "evSetURL" }, + { evLoadAudioFile, "evLoadAudioFile" }, + { evDropSubtitle, "evDropSubtitle" }, + { evSetAspect, "evSetAspect" } +}; + +static const int evBoxs = sizeof(evNames) / sizeof(evName); + +static char *geteventname(int event) +{ + int i; + for(i=0; i<evBoxs; i++) + if(evNames[i].msg == event) + return evNames[i].name; + return NULL; +} + +static inline int get_sws_cpuflags(void) +{ + return (gCpuCaps.hasMMX ? SWS_CPU_CAPS_MMX : 0) | + (gCpuCaps.hasMMX2 ? SWS_CPU_CAPS_MMX2 : 0) | + (gCpuCaps.has3DNow ? SWS_CPU_CAPS_3DNOW : 0); +} + +/* reads a complete image as is into image buffer */ +static image *pngRead(skin_t *skin, unsigned char *fname) +{ + unsigned char header[8]; + png_structp png; + png_infop info; + png_infop endinfo; + png_bytep *row_p; + int color, h; + png_uint_32 i; + int BPP; + char *img; + unsigned int imgsize; + image *bf; + char *filename; + FILE *fp; + + if(!stricmp(fname, "NULL")) return 0; + + /* find filename in order file file.png */ + if(!(fp = fopen(fname, "rb"))) + { + filename = calloc(1, strlen(skin->skindir) + strlen(fname) + 6); + sprintf(filename, "%s\\%s.png", skin->skindir, fname); + if(!(fp = fopen(filename, "rb"))) + { + mp_msg(MSGT_GPLAYER, MSGL_ERR, "[png] cannot find image %s\n", filename); + free(filename); + return 0; + } + free(filename); + } + + for (i=0; i < skin->imagecount; i++) + if(!strcmp(fname, skin->images[i]->name)) + { +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[png] skinfile %s already exists\n", fname); +#endif + return skin->images[i]; + } + (skin->imagecount)++; + skin->images = realloc(skin->images, sizeof(image *) * skin->imagecount); + bf = skin->images[(skin->imagecount) - 1] = calloc(1, sizeof(image)); + bf->name = strdup(fname); + fread(header,1,8,fp); + if (!png_check_sig(header, 8)) return 0; + png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + info = png_create_info_struct(png); + endinfo = png_create_info_struct(png); + + png_init_io(png, fp); + png_set_sig_bytes(png, 8); + png_read_info(png, info); + png_get_IHDR(png, info, (png_uint_32*) &bf->width, (png_uint_32*) &bf->height, &BPP, &color, NULL, NULL, NULL); + + if(color & PNG_COLOR_MASK_ALPHA) + { + if(color & PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY_ALPHA ) BPP *= 2; + else BPP *= 4; + } + else + { + if(color & PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY ) BPP *= 1; + else BPP *= 3; + } + row_p = (png_bytep *) malloc (sizeof(png_bytep) * bf->height); + img = (png_bytep) calloc(png_get_rowbytes(png, info), bf->height); + for (h=0; h < bf->height; h++) + row_p[h] = &img[png_get_rowbytes(png, info) * h]; + png_read_image(png, row_p); + free(row_p); + + png_read_end(png, endinfo); + png_destroy_read_struct(&png, &info, &endinfo); + fclose(fp); + imgsize=bf->width * bf->height * (BPP / 8); + +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[png] loaded image %s\n", fname); + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[png] size: %dx%d bits: %d\n", bf->width, bf->height, BPP); + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[png] imagesize: %u\n", imgsize); +#endif + + bf->size = bf->width * bf->height * skin->desktopbpp / 8; + bf->data = malloc(bf->size); + if(skin->desktopbpp == 16 && BPP == 24) rgb24tobgr15(img, bf->data, imgsize); + else if(skin->desktopbpp == 16 && BPP == 32) rgb32tobgr15(img, bf->data, imgsize); + else if(skin->desktopbpp == 24 && BPP == 24) rgb24tobgr24(img, bf->data, imgsize); + else if(skin->desktopbpp == 24 && BPP == 32) rgb32tobgr24(img, bf->data, imgsize); + else if(skin->desktopbpp == 32 && BPP == 24) rgb24tobgr32(img, bf->data, imgsize); + else if(skin->desktopbpp == 32 && BPP == 32) rgb32tobgr32(img, bf->data, imgsize); + free(img); + return bf; +} + +/* frees all skin images */ +static void freeimages(skin_t *skin) +{ + unsigned int i; + for (i=0; i<skin->imagecount; i++) + { + if(skin->images && skin->images[i]) + { + if(skin->images[i]->data) free(skin->images[i]->data); + if(skin->images[i]->name) free(skin->images[i]->name); + free(skin->images[i]); + } + } + free(skin->images); +} + +#ifdef DEBUG +void dumpwidgets(skin_t *skin) +{ + unsigned int i; + for (i=0; i<skin->widgetcount; i++) + mp_msg(MSGT_GPLAYER, MSGL_V, "widget %p id %i\n", skin->widgets[i], skin->widgets[i]->id); +} +#endif + +static int counttonextchar(const char *s1, char c) +{ + unsigned int i; + for (i=0; i<strlen(s1); i++) + if(s1[i] == c) return i; + return 0; +} + +static char *findnextstring(char *temp, const char *desc, int *base) +{ + int len = counttonextchar(*base + desc, ','); + memset(temp, 0, strlen(desc) + 1); + if(!len) len = strlen(desc); + memcpy(temp, *base + desc, len); + *base += (len+1); + return temp; +} + +static void freeskin(skin_t *skin) +{ + unsigned int i; + if(skin->skindir) + { + free(skin->skindir); + skin->skindir = NULL; + } + + for (i=1; i<=skin->lastusedid; i++) + skin->removewidget(skin, i); + + if(skin->widgets) + { + free(skin->widgets); + skin->widgets = NULL; + } + + freeimages(skin); + for(i=0; i<skin->windowcount; i++) + { + if(skin->windows[i]->name) + { + free(skin->windows[i]->name); + skin->windows[i]->name = NULL; + } + free(skin->windows[i]); + } + + free(skin->windows); + skin->windows = NULL; + + for (i=0; i<skin->fontcount; i++) + { + unsigned int x; + if(skin->fonts[i]->name) + { + free(skin->fonts[i]->name); + skin->fonts[i]->name = NULL; + } + + if(skin->fonts[i]->id) + { + free(skin->fonts[i]->id); + skin->fonts[i]->id = NULL; + } + + for (x=0; x<skin->fonts[i]->charcount; x++) + { + free(skin->fonts[i]->chars[x]); + skin->fonts[i]->chars[x] = NULL; + } + + if(skin->fonts[i]->chars) + { + free(skin->fonts[i]->chars); + skin->fonts[i]->chars = NULL; + } + + free(skin->fonts[i]); + skin->fonts[i] = NULL; + } + free(skin->fonts); + skin->fonts = NULL; +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN FREE] skin freed\n"); +#endif + free(skin); + skin = NULL; +} + +static void removewidget(skin_t *skin, int id) +{ + unsigned int i; + unsigned int pos=0; + widget **temp = calloc(skin->widgetcount - 1, sizeof(widget *)); + + for (i=0; i<skin->widgetcount; i++) + { + if(skin->widgets[i]->id == id) + { + if(skin->widgets[i]->label) + free(skin->widgets[i]->label); + free(skin->widgets[i]); + skin->widgets[i] = NULL; + } + else + { + temp[pos] = skin->widgets[i]; + pos++; + } + } + if (pos != i) + { + (skin->widgetcount)--; + free(skin->widgets); + skin->widgets = temp; +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "removed widget %i\n", id); +#endif + return; + } + free(temp); + mp_msg(MSGT_GPLAYER, MSGL_ERR, "widget %i not found\n", id); +} + +static void addwidget(skin_t *skin, window *win, const char *desc) +{ + widget *mywidget; + char *temp = calloc(1, strlen(desc) + 1); + (skin->widgetcount)++; + (skin->lastusedid)++; + skin->widgets = realloc(skin->widgets, sizeof(widget *) * skin->widgetcount); + mywidget = skin->widgets[(skin->widgetcount) - 1] = calloc(1, sizeof(widget)); + mywidget->id = skin->lastusedid; + mywidget->window = win->type; + /* parse and fill widget specific info */ + if(!strncmp(desc, "base", 4)) + { + int base = counttonextchar(desc, '=') + 1; + mywidget->type = tyBase; + mywidget->bitmap[0] = pngRead(skin, findnextstring(temp, desc, &base)); + mywidget->wx = mywidget->x = atoi(findnextstring(temp, desc, &base)); + mywidget->wy = mywidget->y = atoi(findnextstring(temp, desc, &base)); + mywidget->wwidth = mywidget->width = atoi(findnextstring(temp, desc, &base)); + mywidget->wheight = mywidget->height = atoi(findnextstring(temp, desc, &base)); + win->base = mywidget; +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [ITEM] [BASE] %s %i %i %i %i\n", + (mywidget->bitmap[0]) ? mywidget->bitmap[0]->name : NULL, + mywidget->x, mywidget->y, mywidget->width, mywidget->height); +#endif + } + else if(!strncmp(desc, "button", 6)) + { + int base = counttonextchar(desc, '=') + 1; + int i; + mywidget->type = tyButton; + mywidget->bitmap[0] = pngRead(skin, findnextstring(temp, desc, &base)); + mywidget->wx = mywidget->x = atoi(findnextstring(temp, desc, &base)); + mywidget->wy = mywidget->y = atoi(findnextstring(temp, desc, &base)); + mywidget->wwidth = mywidget->width = atoi(findnextstring(temp, desc, &base)); + mywidget->wheight = mywidget->height = atoi(findnextstring(temp, desc, &base)); + findnextstring(temp, desc, &base); + + /* Assign corresponding event to the widget */ + mywidget->msg = evNone; + for (i=0; i<evBoxs; i++) + { + if(!strcmp(temp, evNames[i].name)) + { + mywidget->msg = evNames[i].msg; + break; + } + } + +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [ITEM] [BUTTON] %s %i %i %i %i msg %i\n", + (mywidget->bitmap[0]) ? mywidget->bitmap[0]->name : NULL, + mywidget->x, mywidget->y, mywidget->width, mywidget->height, mywidget->msg); +#endif + } + else if(!strncmp(desc, "hpotmeter", 9) || !strncmp(desc, "vpotmeter", 9)) + { + int base = counttonextchar(desc, '=') + 1; + int i; + /* hpotmeter = button, bwidth, bheight, phases, numphases, default, X, Y, width, height, message */ + if(!strncmp(desc, "hpotmeter", 9)) mywidget->type = tyHpotmeter; + else mywidget->type = tyVpotmeter; + mywidget->bitmap[0] = pngRead(skin, findnextstring(temp, desc, &base)); + mywidget->width = atoi(findnextstring(temp, desc, &base)); + mywidget->height = atoi(findnextstring(temp, desc, &base)); + mywidget->bitmap[1] = pngRead(skin, findnextstring(temp, desc, &base)); + mywidget->phases = atoi(findnextstring(temp, desc, &base)); + mywidget->value = atof(findnextstring(temp, desc, &base)); + mywidget->x = mywidget->wx = atoi(findnextstring(temp, desc, &base)); + mywidget->y = mywidget->wy = atoi(findnextstring(temp, desc, &base)); + mywidget->wwidth = atoi(findnextstring(temp, desc, &base)); + mywidget->wheight = atoi(findnextstring(temp, desc, &base)); + findnextstring(temp, desc, &base); + mywidget->msg = evNone; + for (i=0; i<evBoxs; i++) + { + if(!strcmp(temp, evNames[i].name)) + { + mywidget->msg = evNames[i].msg; + break; + } + } +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [ITEM] %s %s %i %i %s %i %f %i %i %i %i msg %i\n", + (mywidget->type == tyHpotmeter) ? "[HPOTMETER]" : "[VPOTMETER]", + (mywidget->bitmap[0]) ? mywidget->bitmap[0]->name : NULL, + mywidget->width, mywidget->height, + (mywidget->bitmap[1]) ? mywidget->bitmap[1]->name : NULL, + mywidget->phases, mywidget->value, + mywidget->wx, mywidget->wy, mywidget->wwidth, mywidget->wwidth, + mywidget->msg); +#endif + } + else if(!strncmp(desc, "potmeter", 8)) + { + int base = counttonextchar(desc, '=') + 1; + int i; + /* potmeter = phases, numphases, default, X, Y, width, height, message */ + mywidget->type = tyPotmeter; + mywidget->bitmap[0] = pngRead(skin, findnextstring(temp, desc, &base)); + mywidget->phases = atoi(findnextstring(temp, desc, &base)); + mywidget->value = atof(findnextstring(temp, desc, &base)); + mywidget->wx = mywidget->x = atoi(findnextstring(temp, desc, &base)); + mywidget->wy = mywidget->y = atoi(findnextstring(temp, desc, &base)); + mywidget->wwidth = mywidget->width = atoi(findnextstring(temp, desc, &base)); + mywidget->wheight = mywidget->height = atoi(findnextstring(temp, desc, &base)); + findnextstring(temp, desc, &base); + mywidget->msg = evNone; + for (i=0; i<evBoxs; i++) + { + if(!strcmp(temp, evNames[i].name)) + { + mywidget->msg=evNames[i].msg; + break; + } + } +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [ITEM] [POTMETER] %s %i %i %i %f %i %i msg %i\n", + (mywidget->bitmap[0]) ? mywidget->bitmap[0]->name : NULL, + mywidget->width, mywidget->height, + mywidget->phases, mywidget->value, + mywidget->x, mywidget->y, + mywidget->msg); +#endif + } + else if(!strncmp(desc, "menu", 4)) + { + int base = counttonextchar(desc, '=') + 1; + int i; + mywidget->type = tyMenu; + mywidget->wx=atoi(findnextstring(temp, desc, &base)); + mywidget->x=0; + mywidget->wy=mywidget->y=atoi(findnextstring(temp, desc, &base)); + mywidget->wwidth=mywidget->width=atoi(findnextstring(temp, desc, &base)); + mywidget->wheight=mywidget->height=atoi(findnextstring(temp, desc, &base)); + findnextstring(temp, desc, &base); + mywidget->msg = evNone; + for (i=0; i<evBoxs; i++) + { + if(!strcmp(temp, evNames[i].name)) + { + mywidget->msg = evNames[i].msg; + break; + } + } +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [ITEM] [MENU] %i %i %i %i msg %i\n", + mywidget->x, mywidget->y, mywidget->width, mywidget->height, mywidget->msg); +#endif + } + else if(!strncmp(desc, "selected", 8)) + { + win->base->bitmap[1] = pngRead(skin, (char *) desc + 9); +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [ITEM] [BASE] added image %s\n", win->base->bitmap[1]->name); +#endif + } + else if(!strncmp(desc, "slabel",6)) + { + int base = counttonextchar(desc, '=') + 1; + unsigned int i; + mywidget->type = tySlabel; + mywidget->wx = mywidget->x = atoi(findnextstring(temp, desc, &base)); + mywidget->wy = mywidget->y = atoi(findnextstring(temp, desc, &base)); + findnextstring(temp, desc, &base); + mywidget->font = NULL; + for (i=0; i<skin->fontcount; i++) + { + if(!strcmp(temp, skin->fonts[i]->name)) + { + mywidget->font = skin->fonts[i]; + break; + } + } + mywidget->label = strdup(findnextstring(temp, desc, &base)); +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [ITEM] [SLABEL] %i %i %s %s\n", + mywidget->x, mywidget->y, mywidget->font->name, mywidget->label); +#endif + } + else if(!strncmp(desc, "dlabel", 6)) + { + int base = counttonextchar(desc, '=') + 1; + unsigned int i; + mywidget->type = tyDlabel; + mywidget->wx = mywidget->x = atoi(findnextstring(temp, desc, &base)); + mywidget->wy = mywidget->y = atoi(findnextstring(temp, desc, &base)); + mywidget->length = atoi(findnextstring(temp, desc, &base)); + mywidget->align = atoi(findnextstring(temp, desc, &base)); + findnextstring(temp, desc, &base); + mywidget->font = NULL; + for (i=0; i<skin->fontcount; i++) + { + if(!strcmp(temp, skin->fonts[i]->name)) + { + mywidget->font=skin->fonts[i]; + break; + } + } + mywidget->label=strdup(findnextstring(temp, desc, &base)); +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [ITEM] [DLABEL] %i %i %i %i %s \"%s\"\n", + mywidget->x, mywidget->y, mywidget->length, mywidget->align, mywidget->font->name, mywidget->label); +#endif + } + free(temp); +} + +static void loadfonts(skin_t* skin) +{ + unsigned int x; + for (x=0; x<skin->fontcount; x++) + { + FILE *fp; + int linenumber=0; + char *filename; + char *tmp = calloc(1, MAX_LINESIZE); + char *desc = calloc(1, MAX_LINESIZE); + filename = calloc(1, strlen(skin->skindir) + strlen(skin->fonts[x]->name) + 6); + sprintf(filename, "%s\\%s.fnt", skin->skindir, skin->fonts[x]->name); + if(!(fp = fopen(filename,"rb"))) + { + mp_msg(MSGT_GPLAYER, MSGL_ERR, "[FONT LOAD] Font not found \"%s\"\n", skin->fonts[x]->name); + return; + } + while(!feof(fp)) + { + int pos = 0; + unsigned int i; + fgets(tmp, MAX_LINESIZE, fp); + linenumber++; + memset(desc, 0, MAX_LINESIZE); + for (i=0; i<strlen(tmp); i++) + { + /* remove spaces and linebreaks */ + if((tmp[i] == ' ') || (tmp[i] == '\n') || (tmp[i] == '\r')) continue; + /* remove comments */ + if((tmp[i] == ';') && ((i < 1) || (tmp[i-1] != '\"'))) + { +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[FONT LOAD] Comment: %s", tmp + i + 1); +#endif + break; + } + desc[pos] = tmp[i]; + pos++; + } + if(!strlen(desc)) continue; + /* now we have "readable" output -> parse it */ + if(!strncmp(desc, "image", 5)) + { + skin->fonts[x]->image = pngRead(skin, desc + 6); +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[FONT] [IMAGE] \"%s\"\n", desc + 6); +#endif + } + else + { + int base = 4; + if(*desc != '"') break; + if(*(desc + 1) == 0) break; + (skin->fonts[x]->charcount)++; + skin->fonts[x]->chars = realloc(skin->fonts[x]->chars, sizeof(char_t *) *skin->fonts[x]->charcount); + skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]=calloc(1, sizeof(char_t)); + skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]->c = ((*(desc + 1) == '"') && (*(desc + 2) != '"')) ? ' ': *(desc + 1); + if((*(desc + 1) == '"') && (*(desc + 2) != '"')) base = 3; + skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]->x = atoi(findnextstring(tmp, desc, &base)); + skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]->y = atoi(findnextstring(tmp, desc, &base)); + skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]->width = atoi(findnextstring(tmp, desc, &base)); + skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]->height = atoi(findnextstring(tmp, desc, &base)); +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[FONT] [CHAR] %c %i %i %i %i\n", + skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]->c, + skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]->x, + skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]->y, + skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]->width, + skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]->height); +#endif + } + } + free(desc); + free(filename); + free(tmp); + fclose(fp); + } +} + +skin_t* loadskin(char* skindir, int desktopbpp) +{ + FILE *fp; + int reachedendofwindow = 0; + int linenumber = 0; + skin_t *skin = calloc(1, sizeof(skin_t)); + char *filename; + char *tmp = calloc(1, MAX_LINESIZE); + char *desc = calloc(1, MAX_LINESIZE); + window* mywindow = NULL; + + /* init swscaler */ + sws_rgb2rgb_init(get_sws_cpuflags()); + /* setup funcs */ + skin->freeskin = freeskin; + skin->pngRead = pngRead; + skin->addwidget = addwidget; + skin->removewidget = removewidget; + skin->geteventname = geteventname; + skin->desktopbpp = desktopbpp; + skin->skindir = strdup(skindir); + + filename = calloc(1, strlen(skin->skindir) + strlen("skin") + 2); + sprintf(filename, "%s\\skin", skin->skindir); + if(!(fp = fopen(filename, "rb"))) + { + mp_msg(MSGT_GPLAYER, MSGL_FATAL, "[SKIN LOAD] Skin \"%s\" not found\n", skindir); + skin->freeskin(skin); + return NULL; + } + + while(!feof(fp)) + { + int pos = 0; + unsigned int i; + int insidequote = 0; + fgets(tmp, MAX_LINESIZE, fp); + linenumber++; + memset(desc, 0, MAX_LINESIZE); + for (i=0; i<strlen(tmp); i++) + { + if((tmp[i] == '"') && !insidequote) { insidequote=1; continue; } + else if((tmp[i] == '"') && insidequote) { insidequote=0 ; continue; } + /* remove spaces and linebreaks */ + if((!insidequote && (tmp[i] == ' ')) || (tmp[i] == '\n') || (tmp[i] == '\r')) continue; + /* remove comments */ + else if(tmp[i] == ';') + { +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN LOAD] Comment: %s", tmp + i + 1); +#endif + break; + } + desc[pos] = tmp[i]; + pos++; + } + + if(!strlen(desc)) continue; + /* now we have "readable" output -> parse it */ + /* parse window specific info */ + if(!strncmp(desc, "section", 7)) + { +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [SECTION] \"%s\"\n", desc + 8); +#endif + } + else if(!strncmp(desc, "window", 6)) + { +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [WINDOW] \"%s\"\n", desc + 7); +#endif + reachedendofwindow = 0; + (skin->windowcount)++; + skin->windows = realloc(skin->windows, sizeof(window *) * skin->windowcount); + mywindow = skin->windows[(skin->windowcount) - 1] = calloc(1, sizeof(window)); + mywindow->name = strdup(desc + 7); + if(!strncmp(desc + 7, "main", 4)) mywindow->type = wiMain; + else if(!strncmp(desc+7, "sub", 3)) + { + mywindow->type = wiSub; + mywindow->decoration = 1; + } + else if(!strncmp(desc + 7, "menu", 4)) mywindow->type = wiMenu; + else if(!strncmp(desc + 7, "playbar", 7)) mywindow->type = wiPlaybar; + else mp_msg(MSGT_GPLAYER, MSGL_V, "[SKIN] warning found unknown windowtype"); + } + else if(!strncmp(desc, "decoration", 10) && !strncmp(desc + 11, "enable", 6)) + { + mywindow->decoration = 1; +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [DECORATION] enabled decoration for window \"%s\"\n", mywindow->name); +#endif + } + else if(!strncmp(desc, "background", 10)) + { + int base = counttonextchar(desc, '=') + 1; + char temp[MAX_LINESIZE]; + mywindow->backgroundcolor[0] = atoi(findnextstring(temp, desc, &base)); + mywindow->backgroundcolor[1] = atoi(findnextstring(temp, desc, &base)); + mywindow->backgroundcolor[2] = atoi(findnextstring(temp, desc, &base)); +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [BACKGROUND] window \"%s\" has backgroundcolor (%i,%i,%i)\n", mywindow->name, + mywindow->backgroundcolor[0], + mywindow->backgroundcolor[1], + mywindow->backgroundcolor[2]); +#endif + } + else if(!strncmp(desc, "end", 3)) + { + if(reachedendofwindow) + { +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [END] of section\n"); +#endif + } + else + { + reachedendofwindow = 1; +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [END] of window \"%s\"\n", mywindow->name); +#endif + } + } + else if(!strncmp(desc, "font", 4)) + { + unsigned int i; + int id = 0; + char temp[MAX_LINESIZE]; + int base = counttonextchar(desc, '=')+1; + findnextstring(temp, desc, &base); + findnextstring(temp, desc, &base); + for (i=0; i<skin->fontcount; i++) + if(!strcmp(skin->fonts[i]->id, temp)) + { + id = i; + break; + } + if(!id) + { + int base = counttonextchar(desc, '=') + 1; + findnextstring(temp, desc, &base); + id = skin->fontcount; + (skin->fontcount)++; + skin->fonts = realloc(skin->fonts, sizeof(font_t *) * skin->fontcount); + skin->fonts[id]=calloc(1, sizeof(font_t)); + skin->fonts[id]->name = strdup(temp); + skin->fonts[id]->id = strdup(findnextstring(temp, desc, &base)); + } +#ifdef DEBUG + mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [FONT] id \"%s\" name \"%s\"\n", skin->fonts[id]->name, skin->fonts[id]->id); +#endif + } + else + skin->addwidget(skin, mywindow, desc); + } + + free(desc); + free(filename); + free(tmp); + fclose(fp); + loadfonts(skin); + mp_msg(MSGT_GPLAYER, MSGL_V, "[SKIN LOAD] loaded skin \"%s\"\n", skin->skindir); + /* dumpwidgets(skin); */ + return skin; +} diff --git a/Gui/win32/skinload.h b/Gui/win32/skinload.h new file mode 100644 index 0000000000..3103539dc3 --- /dev/null +++ b/Gui/win32/skinload.h @@ -0,0 +1,213 @@ +/* + 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 +*/ + +#ifndef _SKINLOAD_H +#define _SKINLOAD_H + +typedef struct +{ + char *name; /* image name */ + int size; /* image data size in bytes */ + int width; /* image width */ + int height; /* image height */ + char *data; /* pointer to image data */ +} image; + +typedef struct +{ + char c; + int x; + int y; + int width; + int height; +} char_t; + +typedef struct +{ + char *name; + char *id; + image *image; + unsigned int charcount; + char_t **chars; +} font_t; + +typedef struct +{ + int id; /* widget id */ + int type; /* widget type */ + int window; /* the window it belongs to */ + // --- + int x, y; /* x and y position the button */ + int wx, wy; /* x and y postion of the widget */ + int width, height; /* width and height of the button */ + int wwidth, wheight; /* width and height of the widget */ + // --- + // --- + int msg, msg2; + int pressed, tmp; + int key, key2; + int phases; + float value; + image *bitmap[2]; /* Associated image(s) in imagepool */ + // --- + font_t *font; + int length; + int align; + char *label; + // --- + int event; +} widget; + +typedef struct +{ + char *name; + int decoration; + int type; + widget *base; + int backgroundcolor[3]; + void *priv; +} window; + +typedef struct skin_t skin_t; +struct skin_t +{ + char *skindir; + unsigned int widgetcount; /* number of widgets */ + unsigned int lastusedid; /* which widget id was used last */ + widget **widgets; /* widget handle */ + unsigned int imagecount; /* number of images */ + image **images; /* image handle */ + int desktopbpp; /* image format of those images */ + unsigned int fontcount; + font_t **fonts; + + unsigned int windowcount; /* number of windows */ + window **windows; + void (*freeskin)(skin_t* skin); + void (*addwidget)(skin_t *skin, window *win, const char *desc); + void (*removewidget)(skin_t *skin, int id); + char *(*geteventname)(int event); + image *(*pngRead)(skin_t *skin, unsigned char *fname); +}; + +extern skin_t *loadskin(char *skindir, int desktopbpp); + +// --- Widget types --- + +#define tyBase 1 +#define tyButton 2 +#define tyHpotmeter 3 +#define tyVpotmeter 4 +#define tyPotmeter 5 +#define tyMenu 6 +#define tySlabel 7 +#define tyDlabel 8 + +// --- Window types --- + +#define wiMain 1 +#define wiSub 2 +#define wiMenu 3 +#define wiPlaybar 4 + +// --- User events ------ + +#define evNone 0 +#define evPlay 1 +#define evStop 2 +#define evPause 3 +#define evPrev 6 +#define evNext 7 +#define evLoad 8 +#define evEqualizer 9 +#define evPlayList 10 +#define evIconify 11 +#define evAbout 12 +#define evLoadPlay 13 +#define evPreferences 14 +#define evSkinBrowser 15 +#define evPlaySwitchToPause 16 +#define evPauseSwitchToPlay 17 + +#define evBackward10sec 18 +#define evForward10sec 19 +#define evBackward1min 20 +#define evForward1min 21 +#define evBackward10min 22 +#define evForward10min 23 + +#define evNormalSize 24 +#define evDoubleSize 25 +#define evFullScreen 26 + +#define evSetMoviePosition 27 +#define evSetVolume 28 +#define evSetBalance 29 +#define evMute 30 + +#define evIncVolume 31 +#define evDecVolume 32 +#define evIncAudioBufDelay 33 +#define evDecAudioBufDelay 34 +#define evIncBalance 35 +#define evDecBalance 36 + +#define evHelp 37 + +#define evLoadSubtitle 38 +#define evDropSubtitle 43 +#define evPlayDVD 39 +#define evPlayVCD 40 +#define evPlayNetwork 41 +#define evLoadAudioFile 42 +#define evSetAspect 44 +#define evSetAudio 45 +#define evSetVideo 46 +#define evDropFile 47 +#define evPlayCD 48 + +#define evExit 1000 + +// --- General events --- + +#define evFileLoaded 5000 +#define evHideMouseCursor 5001 +#define evMessageBox 5002 +#define evGeneralTimer 5003 +#define evGtkIsOk 5004 +#define evShowPopUpMenu 5005 +#define evHidePopUpMenu 5006 +#define evSetDVDAudio 5007 +#define evSetDVDSubtitle 5008 +#define evSetDVDTitle 5009 +#define evSetDVDChapter 5010 +#define evSubtitleLoaded 5011 +#define evSetVCDTrack 5012 +#define evSetURL 5013 + +#define evFName 7000 +#define evMovieTime 7001 +#define evRedraw 7002 +#define evHideWindow 7003 +#define evShowWindow 7004 +#define evFirstLoad 7005 + +#endif diff --git a/Gui/win32/widgetrender.c b/Gui/win32/widgetrender.c new file mode 100644 index 0000000000..e93dc5ce26 --- /dev/null +++ b/Gui/win32/widgetrender.c @@ -0,0 +1,350 @@ +/* + 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 <ctype.h> +#include <windows.h> +#include <interface.h> +#include "gui.h" + +extern char *codecname; +#define MAX_LABELSIZE 250 + +static void render(int bitsperpixel, image *dst, image *src, int x, int y, int sx, int sy, int sw, int sh, int transparent) +{ + int i; + int bpp = bitsperpixel / 8; + int offset = (dst->width * bpp * y) + (x * bpp); + int soffset = (src->width * bpp * sy) + (sx * bpp); + + for(i=0; i<sh; i++) + { + int c; + for(c=0; c < (sw * bpp); c += bpp) + { + if(bpp == 2) + { + if(!transparent || (((src->data + soffset + (i * src->width * bpp) + c)[0] != 0x1f) + && ((src->data + soffset + (i * src->width * bpp) + c)[1] != 0x7c))) + memcpy(dst->data + offset + c, src->data + soffset + (i * src->width * bpp) + c, bpp); + } + else if(bpp > 2) + { + if(!transparent || *((unsigned int *) (src->data + soffset + (i * src->width * bpp) + c)) != 0x00ff00ff) + memcpy(dst->data + offset + c, src->data + soffset + (i * src->width * bpp) + c, bpp); + } + } + offset += (dst->width * bpp); + } +} + +static image *find_background(skin_t *skin, widget *item) +{ + unsigned int i; + for (i=0; i < skin->windowcount; i++) + if(skin->windows[i]->type == item->window) + return skin->windows[i]->base->bitmap[0]; + return NULL; +} + +/******************************************************************/ +/* FONT related functions */ +/******************************************************************/ + +/* returns the pos of s2 inside s1 or -1 if s1 doesn't contain s2 */ +static int strpos(char *s1, const char* s2) +{ + unsigned int i, x; + for (i=0; i < strlen(s1); i++) + { + if(s1[i] == s2[0]) + { + if(strlen(s1 + i) >= strlen(s2)) + { + for (x=0; x <strlen(s2); x++) + if(s1[i + x] != s2[x]) break; + if(x == strlen(s2)) return i; + } + } + } + return -1; +} + +/* replaces all occurences of what in dest with format */ +static void stringreplace(char *dest, const char *what, const char *format, ... ) +{ + char tmp[MAX_LABELSIZE]; + int offset=0; + va_list va; + va_start(va, format); + vsnprintf(tmp, MAX_LABELSIZE, format, va); + va_end(va); + /* no search string == replace the entire string */ + if(!what) + { + memcpy(dest, tmp, strlen(tmp)); + dest[strlen(tmp)] = 0; + return; + } + while((offset = strpos(dest, what)) != -1) + { + memmove(dest + offset + strlen(tmp), dest + offset + strlen(what), strlen(dest + offset + strlen(what)) + 1); + memcpy(dest + offset, tmp, strlen(tmp)); + } +} + +/* replaces the chars with special meaning with the associated data from the player info struct */ +static char *generatetextfromlabel(widget *item) +{ + char *text = malloc(MAX_LABELSIZE); + char tmp[MAX_LABELSIZE]; + unsigned int i; + if(!item) + { + free(text); + return NULL; + } + strcpy(text, item->label); + if(item->type == tySlabel) return text; + stringreplace(text, "$1", "%.2i:%.2i:%.2i", guiIntfStruct.TimeSec / 3600, + (guiIntfStruct.TimeSec / 60) % 60, guiIntfStruct.TimeSec % 60); + stringreplace(text, "$2", "%.4i:%.2i", guiIntfStruct.TimeSec / 60, guiIntfStruct.TimeSec % 60); + stringreplace(text, "$3", "%.2i", guiIntfStruct.TimeSec / 3600); + stringreplace(text, "$4", "%.2i", (guiIntfStruct.TimeSec / 60) % 60); + stringreplace(text, "$5", "%.2i", guiIntfStruct.TimeSec % 60); + stringreplace(text, "$6", "%.2i:%.2i:%.2i", guiIntfStruct.LengthInSec / 3600, + (guiIntfStruct.LengthInSec / 60) % 60, guiIntfStruct.LengthInSec % 60); + stringreplace(text, "$7", "%.4i:%.2i", guiIntfStruct.LengthInSec / 60, guiIntfStruct.LengthInSec % 60); + stringreplace(text, "$8", "%i:%.2i:%.2i", guiIntfStruct.TimeSec / 3600, + (guiIntfStruct.TimeSec / 60) % 60, guiIntfStruct.TimeSec % 60); + stringreplace(text, "$v", "%3.2f", guiIntfStruct.Volume); + stringreplace(text, "$V", "%3.1f", guiIntfStruct.Volume); + stringreplace(text, "$b", "%3.2f", guiIntfStruct.Balance); + stringreplace(text, "$B", "%3.1f", guiIntfStruct.Balance); + stringreplace(text, "$t", "%.2i", guiIntfStruct.Track); + stringreplace(text, "$o", "%s", guiIntfStruct.Filename); + stringreplace(text, "$x", "%i", guiIntfStruct.MovieWidth); + stringreplace(text, "$y", "%i", guiIntfStruct.MovieHeight); + stringreplace(text, "$C", "%s", guiIntfStruct.sh_video ? codecname : ""); + stringreplace(text, "$$", "$"); + + if(!strcmp(text, "$p") || !strcmp(text, "$s") || !strcmp(text, "$e")) + { + if(guiIntfStruct.Playing == 0) stringreplace(text, NULL, "s"); + else if(guiIntfStruct.Playing == 1) stringreplace(text, NULL, "p"); + else if(guiIntfStruct.Playing == 2) stringreplace(text, NULL, "e"); + } + + if(guiIntfStruct.AudioType == 0) stringreplace(text, "$a", "n"); + else if(guiIntfStruct.AudioType == 1) stringreplace(text, "$a", "m"); + else stringreplace(text, "$a", "t"); + + if(guiIntfStruct.StreamType == 0) + stringreplace(text, "$T", "f"); +#ifdef USE_DVDREAD + else if(guiIntfStruct.StreamType == STREAMTYPE_DVD || guiIntfStruct.StreamType == STREAMTYPE_DVDNAV) + stringreplace(text, "$T", "d"); +#endif + else stringreplace(text, "$T", "u"); + + if(guiIntfStruct.Filename) + { + for (i=0; i<strlen(guiIntfStruct.Filename); i++) + tmp[i] = tolower(guiIntfStruct.Filename[i]); + stringreplace(text, "$f", tmp); + + for (i=0; i<strlen(guiIntfStruct.Filename); i++) + tmp[i] = toupper(guiIntfStruct.Filename[i]); + stringreplace(text, "$F", tmp); + } + + return text; +} + +/* cuts text to buflen scrolling from right to left */ +static void scrolltext(char *text, unsigned int buflen, float *value) +{ + char *buffer = (char *) malloc(buflen + 1); + unsigned int x,i; + if(*value < buflen) x = 0; + else x = *value - buflen; + memset(buffer, ' ', buflen); + for (i = (*value>=buflen) ? 0 : buflen - *value; i<buflen; i++) + { + if(x < strlen(text)) + buffer[i] = text[x]; + x++; + } + buffer[buflen] = 0; + *value += 1.0f; + if(*value >= strlen(text) + buflen) *value = 0.0f; + strcpy(text, buffer); + free(buffer); +} + +/* updates all dlabels and slabels */ +void renderinfobox(skin_t *skin, window_priv_t *priv) +{ + unsigned int i; + if (!priv) return; + + /* repaint the area behind the text*/ + /* we have to do this for all labels here, because they may overlap in buggy skins ;( */ + + for (i=0; i<skin->widgetcount; i++) + if((skin->widgets[i]->type == tyDlabel) || (skin->widgets[i]->type == tySlabel)) + { + if(skin->widgets[i]->window == priv->type) + render(skin->desktopbpp, + &priv->img, + find_background(skin, skin->widgets[i]), + skin->widgets[i]->x, + skin->widgets[i]->y, + skin->widgets[i]->x, + skin->widgets[i]->y, + skin->widgets[i]->length, + skin->widgets[i]->font->chars[0]->height, + 1); + } + + /* load all slabels and dlabels */ + for (i=0; i<skin->widgetcount; i++) + { + widget *item = skin->widgets[i]; + if(item->window != priv->type) continue; + if((i == skin->widgetcount) || (item->type == tyDlabel) || (item->type == tySlabel)) + { + char *text = generatetextfromlabel(item); + unsigned int current, c; + int offset = 0; + unsigned int textlen; + if(!text) continue; + textlen = strlen(text); + + /* render(win, win->background, gui->skin->widgets[i]->x, gui->skin->widgets[i]->y, + gui->skin->widgets[i]->x, gui->skin->widgets[i]->y, + gui->skin->widgets[i]->length, gui->skin->widgets[i]->font->chars[0]->height,1); */ + + /* calculate text size */ + for (current=0; current<textlen; current++) + { + for (c=0; c<item->font->charcount; c++) + if(item->font->chars[c]->c == text[current]) + { + offset += item->font->chars[c]->width; + break; + } + } + + /* labels can be scrolled if they are to big */ + if((item->type == tyDlabel) && (item->length < offset)) + { + int tomuch = (offset - item->length) / (offset /textlen); + scrolltext(text, textlen - tomuch - 1, &skin->widgets[i]->value); + textlen = strlen(text); + } + + /* align the text */ + if(item->align == 1) + offset = (item->length-offset) / 2; + else if(item->align == 2) + offset = item->length-offset; + else + offset = 0; + + if(offset < 0) offset = 0; + + /* render the text */ + for (current=0; current<textlen; current++) + { + for (c=0; c<item->font->charcount; c++) + { + char_t *cchar = item->font->chars[c]; + if(cchar->c == *(text + current)) + { + render(skin->desktopbpp, + &priv->img, + item->font->image, + item->x + offset, + item->y, + cchar->x, + cchar->y, + (cchar->width + offset > item->length) ? item->length - offset : cchar->width, + cchar->height, + 1); + offset += cchar->width; + break; + } + } + } + free(text); + } + } +} + +/******************************************************************/ +/* WIDGET related functions */ +/******************************************************************/ + +void renderwidget(skin_t *skin, image *dest, widget *item, int state) +{ + if(!dest) return; + image *img = NULL; + int height; + int y; + if((item->type == tyButton) || (item->type == tyHpotmeter) || (item->type == tyPotmeter)) + img = item->bitmap[0]; + + if(!img) return; + + y = item->y; + if(item->type == tyPotmeter) + { + height = img->height / item->phases; + y = height * (int)(item->value * item->phases / 100); + if(y > img->height-height) + y = img->height - height; + } + else + { + height = img->height / 3; + y = state * height; + } + + /* redraw background */ + if(item->type == tyButton) + render(skin->desktopbpp, dest, find_background(skin,item), item->x, item->y, item->x, item->y, img->width, height, 1); + + if((item->type == tyHpotmeter) || (item->type == tyPotmeter)) + { + /* repaint the area behind the slider */ + render(skin->desktopbpp, dest, find_background(skin, item), item->wx, item->wy, item->wx, item->wy, item->wwidth, item->height, 1); + item->x = item->value * (item->wwidth-item->width) / 100 + item->wx; + if((item->x + item->width) > (item->wx + item->wwidth)) + item->x = item->wx + item->wwidth - item->width; + if(item->x < item->wx) + item->x = item->wx; + /* workaround for blue */ + if(item->type == tyHpotmeter) + height = (item->height < img->height / 3) ? item->height : img->height / 3; + } + render(skin->desktopbpp, dest, img, item->x, item->y, 0, y, img->width, height, 1); +} diff --git a/Gui/win32/wincfg.c b/Gui/win32/wincfg.c new file mode 100644 index 0000000000..605867900c --- /dev/null +++ b/Gui/win32/wincfg.c @@ -0,0 +1,143 @@ +/* + 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 <stdlib.h> +#include <string.h> + +#include <mp_msg.h> +#include <help_mp.h> + +#include <m_config.h> +#include <m_option.h> +#include <libvo/video_out.h> +#include <mixer.h> +#include "wincfg.h" +#include "interface.h" + +/* params */ +int gtkAONorm = 0; +int gtkAOExtraStereo = 0; +float gtkAOExtraStereoMul = 1.0; +int gtkCacheOn = 0; +int gtkCacheSize = 2048; +int gtkAutoSyncOn = 0; +int gtkAutoSync = 0; + +int sub_window = 0; +int console = 0; + +int gui_save_pos = 1; +int gui_main_pos_x = -2; +int gui_main_pos_y = -2; +int gui_sub_pos_x = -1; +int gui_sub_pos_y = -1; + +/* External functions */ +extern int frame_dropping; +extern char *proc_priority; +extern int m_config_parse_config_file(m_config_t *config, char *conffile); + +static m_config_t *gui_conf; +static m_option_t gui_opts[] = +{ + { "priority", &proc_priority, CONF_TYPE_STRING, 0, 0, 0, NULL}, + { "vo_driver", &video_driver_list, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL }, + { "v_framedrop", &frame_dropping, CONF_TYPE_INT, CONF_RANGE, 0, 2, NULL }, + { "vo_doublebuffering", &vo_doublebuffering, CONF_TYPE_FLAG, 0, 0, 1, NULL }, + { "vo_direct_render", &vo_directrendering, CONF_TYPE_FLAG, 0, 0, 1, NULL }, + { "ao_driver", &audio_driver_list, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL }, + { "ao_volnorm", >kAONorm, CONF_TYPE_FLAG, 0, 0, 1, NULL }, + { "softvol", &soft_vol, CONF_TYPE_FLAG, 0, 0, 1, NULL }, + { "ao_extra_stereo", >kAOExtraStereo, CONF_TYPE_FLAG, 0, 0, 1, NULL }, + { "ao_extra_stereo_coefficient", >kAOExtraStereoMul, CONF_TYPE_FLOAT, CONF_RANGE, -10, 10, NULL }, + { "delay", &audio_delay, CONF_TYPE_FLOAT, CONF_RANGE, -100.0, 100.0, NULL}, + { "dvd_device", &dvd_device, CONF_TYPE_STRING, 0, 0, 0, NULL }, + { "cdrom_device", &cdrom_device, CONF_TYPE_STRING, 0, 0, 0, NULL }, + { "osd_level", &osd_level, CONF_TYPE_INT, CONF_RANGE, 0, 3, NULL }, + { "cache", >kCacheOn, CONF_TYPE_FLAG, 0, 0, 1, NULL }, + { "cache_size", >kCacheSize, CONF_TYPE_INT, CONF_RANGE, -1, 65535, NULL }, + { "autosync", >kAutoSyncOn, CONF_TYPE_FLAG, 0, 0, 1, NULL }, + { "autosync_size", >kAutoSync, CONF_TYPE_INT, CONF_RANGE, 0, 10000, NULL }, + { "gui_skin", &skinName, CONF_TYPE_STRING, 0, 0, 0, NULL }, + { "gui_main_pos_x", &gui_main_pos_x, CONF_TYPE_INT, 0, 0, 0, NULL }, + { "gui_main_pos_y", &gui_main_pos_y, CONF_TYPE_INT, 0, 0, 0, NULL }, + { "gui_sub_pos_x", &gui_sub_pos_x, CONF_TYPE_INT, 0, 0, 0, NULL }, + { "gui_sub_pos_y", &gui_sub_pos_y, CONF_TYPE_INT, 0, 0, 0, NULL }, + { "sub_window", &sub_window, CONF_TYPE_FLAG, 0, 0, 1, NULL}, + { "console", &console, CONF_TYPE_FLAG, 0, 0, 1, NULL}, + { NULL, NULL, 0, 0, 0, 0, NULL } +}; + +char *gfgets(char *str, int size, FILE *f) +{ + char *s = fgets(str, size, f); + char c; + if(s) + { + c = s[strlen(s) - 1]; + if ((c == '\n') || (c == '\r')) + s[strlen(s) - 1]=0; + c = s[strlen(s) - 1]; + if ((c == '\n') || (c == '\r')) + s[strlen(s) - 1]=0; + } + return s; +} + +int cfg_read(void) +{ + char *cfg = get_path("gui.conf"); + + /* read configuration */ + mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] [cfg] reading config file: %s\n", cfg); + gui_conf = m_config_new(); + m_config_register_options(gui_conf, gui_opts); + if (m_config_parse_config_file(gui_conf, cfg) < 0) + mp_msg(MSGT_GPLAYER, MSGL_FATAL, MSGTR_ConfigFileError); + free(cfg); + return 0; +} + +int cfg_write(void) +{ + char *cfg = get_path("gui.conf"); + FILE *f; + int i; + + /* save configuration */ + if ((f = fopen(cfg, "wt+"))) + { + for (i=0; gui_opts[i].name; i++) + { + char *v = m_option_print(&gui_opts[i], gui_opts[i].p); + if(v) + { + fprintf(f, "%s = \"%s\"\n", gui_opts[i].name, v); + free(v); + } + else if((int) v == -1) + mp_msg(MSGT_GPLAYER, MSGL_WARN, MSGTR_UnableToSaveOption, gui_opts[i].name); + } + fclose(f); + } + free(cfg); + return 0; +} diff --git a/Gui/win32/wincfg.h b/Gui/win32/wincfg.h new file mode 100644 index 0000000000..9a5543c3a9 --- /dev/null +++ b/Gui/win32/wincfg.h @@ -0,0 +1,38 @@ +/* + 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 +*/ + +#ifndef _WINCFG_H +#define _WINCFG_H + +extern char *skinName; +extern int sub_window; +extern int console; + +extern int gui_save_pos; +extern int gui_main_pos_x; +extern int gui_main_pos_y; +extern int gui_sub_pos_x; +extern int gui_sub_pos_y; + +extern int cfg_read(void); +extern int cfg_write(void); + +#endif |