aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Gui/win32/Changelog317
-rw-r--r--Gui/win32/README17
-rw-r--r--Gui/win32/dialogs.c1142
-rw-r--r--Gui/win32/dialogs.h129
-rw-r--r--Gui/win32/gui.c1555
-rw-r--r--Gui/win32/gui.h118
-rw-r--r--Gui/win32/interface.c975
-rw-r--r--Gui/win32/playlist.c154
-rw-r--r--Gui/win32/playlist.h57
-rw-r--r--Gui/win32/preferences.c714
-rw-r--r--Gui/win32/skinload.c809
-rw-r--r--Gui/win32/skinload.h213
-rw-r--r--Gui/win32/widgetrender.c350
-rw-r--r--Gui/win32/wincfg.c143
-rw-r--r--Gui/win32/wincfg.h38
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", &gtkAONorm, CONF_TYPE_FLAG, 0, 0, 1, NULL },
+ { "softvol", &soft_vol, CONF_TYPE_FLAG, 0, 0, 1, NULL },
+ { "ao_extra_stereo", &gtkAOExtraStereo, CONF_TYPE_FLAG, 0, 0, 1, NULL },
+ { "ao_extra_stereo_coefficient", &gtkAOExtraStereoMul, 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", &gtkCacheOn, CONF_TYPE_FLAG, 0, 0, 1, NULL },
+ { "cache_size", &gtkCacheSize, CONF_TYPE_INT, CONF_RANGE, -1, 65535, NULL },
+ { "autosync", &gtkAutoSyncOn, CONF_TYPE_FLAG, 0, 0, 1, NULL },
+ { "autosync_size", &gtkAutoSync, 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