Initial import of MPlayer SVN rev 28382 and FFmpeg SVN rev 16846.
[vaapi:athaifas-mplayer.git] / gui / win32 / interface.c
1 /*
2  * MPlayer GUI for Win32
3  * Copyright (C) 2003 Sascha Sommer <saschasommer@freenet.de>
4  * Copyright (C) 2006 Erik Augustson <erik_27can@yahoo.com>
5  * Copyright (C) 2006 Gianluigi Tiesi <sherpya@netfarm.it>
6  *
7  * This file is part of MPlayer.
8  *
9  * MPlayer is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * MPlayer is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with MPlayer; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23
24 #include <windows.h>
25 #include <get_path.h>
26 #include "gui/interface.h"
27 #include "m_option.h"
28 #include "mixer.h"
29 #include "mp_msg.h"
30 #include "help_mp.h"
31 #include "codec-cfg.h"
32 #include "stream/stream.h"
33 #include "libmpdemux/demuxer.h"
34 #include "libmpdemux/stheader.h"
35 #ifdef CONFIG_DVDREAD
36 #include "stream/stream_dvd.h"
37 #endif
38 #include "input/input.h"
39 #include "libvo/video_out.h"
40 #include "libao2/audio_out.h"
41 #include "access_mpcontext.h"
42 #include "gui.h"
43 #include "dialogs.h"
44 #ifdef CONFIG_LIBCDIO
45 #include <cdio/cdio.h>
46 #endif
47
48 extern int abs_seek_pos;
49 extern float rel_seek_secs;
50 extern int vcd_track;
51 extern af_cfg_t af_cfg;
52 int guiWinID = 0;
53
54 char *skinName = NULL;
55 char *codecname = NULL;
56 int mplGotoTheNext = 1;
57 static gui_t *mygui = NULL;
58 static int update_subwindow(void);
59 static RECT old_rect;
60 static DWORD style;
61 static HANDLE hThread;
62 static unsigned threadId;
63 const ao_functions_t *audio_out = NULL;
64 const vo_functions_t *video_out = NULL;
65 mixer_t *mixer = NULL;
66
67 /* test for playlist files, no need to specify -playlist on the commandline.
68  * add any conceivable playlist extensions here.
69  * - Erik
70  */
71 int parse_filename(char *file, play_tree_t *playtree, m_config_t *mconfig, int clear)
72 {
73     if(clear)
74         mygui->playlist->clear_playlist(mygui->playlist);
75
76     if(strstr(file, ".m3u") || strstr(file, ".pls"))
77     {
78         playtree = parse_playlist_file(file);
79         import_playtree_playlist_into_gui(playtree, mconfig);
80         return 1;
81     }
82     return 0;
83 }
84
85 /**
86  * \brief this actually creates a new list containing only one element...
87  */
88 void gaddlist( char ***list, const char *entry)
89 {
90     int i;
91
92     if (*list)
93     {
94         for (i=0; (*list)[i]; i++) free((*list)[i]);
95         free(*list);
96     }
97
98     *list = malloc(2 * sizeof(char **));
99     (*list)[0] = gstrdup(entry);
100     (*list)[1] = NULL;
101 }
102
103 char *gstrdup(const char *str)
104 {
105     if (!str) return NULL;
106     return strdup(str);
107 }
108
109 /**
110  * \brief this replaces a string starting with search by replace.
111  * If not found, replace is appended.
112  */
113 void greplace(char ***list, char *search, char *replace)
114 {
115     int i = 0;
116     int len = (search) ? strlen(search) : 0;
117
118     if (*list)
119     {
120         for (i = 0; (*list)[i]; i++)
121         {
122             if (search && (!strncmp((*list)[i], search, len)))
123             {
124                 free((*list)[i]);
125                 (*list)[i] = gstrdup(replace);
126                 return;
127             }
128         }
129     *list = realloc(*list, (i + 2) * sizeof(char *));
130     }
131     else
132         *list = malloc(2 * sizeof(char *));
133
134     (*list)[i] = gstrdup(replace);
135     (*list)[i + 1] = NULL;
136 }
137
138 /* this function gets called by the gui to update mplayer */
139 static void guiSetEvent(int event)
140 {
141     if(guiIntfStruct.mpcontext)
142         mixer = mpctx_get_mixer(guiIntfStruct.mpcontext);
143
144     switch(event)
145     {
146         case evPlay:
147         case evPlaySwitchToPause:
148         case evPauseSwitchToPlay:
149             mplPlay();
150             break;
151         case evPause:
152             mplPause();
153             break;
154 #ifdef CONFIG_DVDREAD
155         case evPlayDVD:
156         {
157             static char dvdname[MAX_PATH];
158             guiIntfStruct.DVD.current_title = dvd_title;
159             guiIntfStruct.DVD.current_chapter = dvd_chapter;
160             guiIntfStruct.DVD.current_angle = dvd_angle;
161             guiIntfStruct.DiskChanged = 1;
162
163             mplSetFileName(NULL, dvd_device, STREAMTYPE_DVD);
164             dvdname[0] = 0;
165             strcat(dvdname, "DVD Movie");
166             GetVolumeInformation(dvd_device, dvdname, MAX_PATH, NULL, NULL, NULL, NULL, 0);
167             capitalize(dvdname);
168             mp_msg(MSGT_GPLAYER, MSGL_V, "Opening DVD %s -> %s\n", dvd_device, dvdname);
169             guiGetEvent(guiSetParameters, (char *) STREAMTYPE_DVD);
170             mygui->playlist->clear_playlist(mygui->playlist);
171             mygui->playlist->add_track(mygui->playlist, filename, NULL, dvdname, 0);
172             mygui->startplay(mygui);
173             break;
174         }
175 #endif
176 #ifdef CONFIG_LIBCDIO
177         case evPlayCD:
178         {
179             int i;
180             char track[10];
181             char trackname[10];
182             CdIo_t *p_cdio = cdio_open(NULL, DRIVER_UNKNOWN);
183             track_t i_tracks;
184
185             if(p_cdio == NULL) printf("Couldn't find a driver.\n");
186             i_tracks = cdio_get_num_tracks(p_cdio);
187
188             mygui->playlist->clear_playlist(mygui->playlist);
189             for(i=0;i<i_tracks;i++)
190             {
191                 sprintf(track, "cdda://%d", i+1);
192                 sprintf(trackname, "Track %d", i+1);
193                 mygui->playlist->add_track(mygui->playlist, track, NULL, trackname, 0);
194             }
195             cdio_destroy(p_cdio);
196             mygui->startplay(mygui);
197             break;
198         }
199 #endif
200         case evFullScreen:
201             mp_input_queue_cmd(mp_input_parse_cmd("vo_fullscreen"));
202             break;
203         case evExit:
204         {
205             /* We are asking mplayer to exit, later it will ask us after uninit is made
206                this should be the only safe way to quit */
207             mygui->activewidget = NULL;
208             mp_input_queue_cmd(mp_input_parse_cmd("quit"));
209             break;
210         }
211         case evStop:
212             if(guiIntfStruct.Playing)
213                 guiGetEvent(guiCEvent, (void *) guiSetStop);
214             break;
215         case evSetMoviePosition:
216         {
217             rel_seek_secs = guiIntfStruct.Position / 100.0f;
218             abs_seek_pos = 3;
219             break;
220         }
221         case evForward10sec:
222         {
223             rel_seek_secs = 10.0f;
224             abs_seek_pos = 0;
225             break;
226         }
227         case evBackward10sec:
228         {
229             rel_seek_secs = -10.0f;
230             abs_seek_pos = 0;
231             break;
232         }
233         case evSetBalance:
234         case evSetVolume:
235         {
236             float l,r;
237
238             if (guiIntfStruct.Playing == 0)
239                 break;
240
241             if (guiIntfStruct.Balance == 50.0f)
242                 mixer_setvolume(mixer, guiIntfStruct.Volume, guiIntfStruct.Volume);
243
244             l = guiIntfStruct.Volume * ((100.0f - guiIntfStruct.Balance) / 50.0f);
245             r = guiIntfStruct.Volume * ((guiIntfStruct.Balance) / 50.0f);
246
247             if (l > guiIntfStruct.Volume) l=guiIntfStruct.Volume;
248             if (r > guiIntfStruct.Volume) r=guiIntfStruct.Volume;
249             mixer_setvolume(mixer, l, r);
250             /* Check for balance support on mixer - there is a better way ?? */
251             if (r != l)
252             {
253                 mixer_getvolume(mixer, &l, &r);
254                 if (r == l)
255                 {
256                     mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] Mixer doesn't support balanced audio\n");
257                     mixer_setvolume(mixer, guiIntfStruct.Volume, guiIntfStruct.Volume);
258                     guiIntfStruct.Balance = 50.0f;
259                 }
260             }
261             break;
262         }
263         case evMute:
264         {
265             mp_cmd_t * cmd = calloc(1, sizeof(*cmd));
266             cmd->id=MP_CMD_MUTE;
267             cmd->name=strdup("mute");
268             mp_input_queue_cmd(cmd);
269             break;
270         }
271         case evDropFile:
272         case evLoadPlay:
273         {
274             switch(guiIntfStruct.StreamType)
275             {
276 #ifdef CONFIG_DVDREAD
277                 case STREAMTYPE_DVD:
278                 {
279                     guiIntfStruct.Title = guiIntfStruct.DVD.current_title;
280                     guiIntfStruct.Chapter = guiIntfStruct.DVD.current_chapter;
281                     guiIntfStruct.Angle = guiIntfStruct.DVD.current_angle;
282                     guiIntfStruct.DiskChanged = 1;
283                     guiGetEvent(guiCEvent, (void *) guiSetPlay);
284                     break;
285                 }
286 #endif
287                 default:
288                 {
289                     guiIntfStruct.FilenameChanged = guiIntfStruct.NewPlay = 1;
290                     update_playlistwindow();
291                     mplGotoTheNext = guiIntfStruct.Playing? 0 : 1;
292                     guiGetEvent(guiCEvent, (void *) guiSetStop);
293                     guiGetEvent(guiCEvent, (void *) guiSetPlay);
294                     break;
295                }
296            }
297            break;
298         }
299         case evNext:
300             mplNext();
301             break;
302         case evPrev:
303             mplPrev();
304             break;
305     }
306 }
307
308 void mplPlay( void )
309 {
310    if((!guiIntfStruct.Filename ) || (guiIntfStruct.Filename[0] == 0))
311      return;
312
313    if(guiIntfStruct.Playing > 0)
314    {
315        mplPause();
316        return;
317    }
318    guiIntfStruct.NewPlay = 1;
319    guiGetEvent(guiCEvent, (void *) guiSetPlay);
320 }
321
322 void mplPause( void )
323 {
324    if(!guiIntfStruct.Playing) return;
325
326    if(guiIntfStruct.Playing == 1)
327    {
328        mp_cmd_t * cmd = calloc(1, sizeof(*cmd));
329        cmd->id=MP_CMD_PAUSE;
330        cmd->name=strdup("pause");
331        mp_input_queue_cmd(cmd);
332    } else guiIntfStruct.Playing = 1;
333 }
334
335 void mplNext(void)
336 {
337     if(guiIntfStruct.Playing == 2) return;
338     switch(guiIntfStruct.StreamType)
339     {
340 #ifdef CONFIG_DVDREAD
341         case STREAMTYPE_DVD:
342             if(guiIntfStruct.DVD.current_chapter == (guiIntfStruct.DVD.chapters - 1))
343                 return;
344             guiIntfStruct.DVD.current_chapter++;
345             break;
346 #endif
347         default:
348             if(mygui->playlist->current == (mygui->playlist->trackcount - 1))
349                 return;
350             mplSetFileName(NULL, mygui->playlist->tracks[(mygui->playlist->current)++]->filename,
351                            STREAMTYPE_STREAM);
352             break;
353     }
354     mygui->startplay(mygui);
355 }
356
357 void mplPrev(void)
358 {
359     if(guiIntfStruct.Playing == 2) return;
360     switch(guiIntfStruct.StreamType)
361     {
362 #ifdef CONFIG_DVDREAD
363         case STREAMTYPE_DVD:
364             if(guiIntfStruct.DVD.current_chapter == 1)
365                 return;
366             guiIntfStruct.DVD.current_chapter--;
367             break;
368 #endif
369         default:
370             if(mygui->playlist->current == 0)
371                 return;
372             mplSetFileName(NULL, mygui->playlist->tracks[(mygui->playlist->current)--]->filename,
373                            STREAMTYPE_STREAM);
374             break;
375     }
376     mygui->startplay(mygui);
377 }
378
379 void mplEnd( void )
380 {
381     if(!mplGotoTheNext && guiIntfStruct.Playing)
382     {
383         mplGotoTheNext = 1;
384         return;
385     }
386
387     if(mplGotoTheNext && guiIntfStruct.Playing &&
388       (mygui->playlist->current < (mygui->playlist->trackcount - 1)) &&
389       guiIntfStruct.StreamType != STREAMTYPE_DVD &&
390       guiIntfStruct.StreamType != STREAMTYPE_DVDNAV)
391     {
392         /* we've finished this file, reset the aspect */
393         if(movie_aspect >= 0)
394             movie_aspect = -1;
395
396         mplGotoTheNext = guiIntfStruct.FilenameChanged = guiIntfStruct.NewPlay = 1;
397         mplSetFileName(NULL, mygui->playlist->tracks[(mygui->playlist->current)++]->filename, STREAMTYPE_STREAM);
398         //sprintf(guiIntfStruct.Filename, mygui->playlist->tracks[(mygui->playlist->current)++]->filename);
399     }
400
401     if(guiIntfStruct.FilenameChanged && guiIntfStruct.NewPlay)
402         return;
403
404     guiIntfStruct.TimeSec = 0;
405     guiIntfStruct.Position = 0;
406     guiIntfStruct.AudioType = 0;
407
408 #ifdef CONFIG_DVDREAD
409     guiIntfStruct.DVD.current_title = 1;
410     guiIntfStruct.DVD.current_chapter = 1;
411     guiIntfStruct.DVD.current_angle = 1;
412 #endif
413
414     if (mygui->playlist->current == (mygui->playlist->trackcount - 1))
415         mygui->playlist->current = 0;
416
417     fullscreen = 0;
418     if(style == WS_VISIBLE | WS_POPUP)
419     {
420         style = WS_OVERLAPPEDWINDOW | WS_SIZEBOX;
421         SetWindowLong(mygui->subwindow, GWL_STYLE, style);
422     }
423     guiGetEvent(guiCEvent, (void *) guiSetStop);
424 }
425
426 void mplSetFileName(char *dir, char *name, int type)
427 {
428     if(!name) return;
429     if(!dir)
430         guiSetFilename(guiIntfStruct.Filename, name)
431     else
432         guiSetDF(guiIntfStruct.Filename, dir, name);
433
434     guiIntfStruct.StreamType = type;
435     free((void **) &guiIntfStruct.AudioFile);
436     free((void **) &guiIntfStruct.Subtitlename);
437 }
438
439 void mplFullScreen( void )
440 {
441     if(!guiIntfStruct.sh_video) return;
442
443     if(sub_window)
444     {
445         if(!fullscreen && IsWindowVisible(mygui->subwindow) && !IsIconic(mygui->subwindow))
446            GetWindowRect(mygui->subwindow, &old_rect);
447
448         if(fullscreen)
449         {
450             fullscreen = 0;
451             style = WS_OVERLAPPEDWINDOW | WS_SIZEBOX;
452         } else {
453             fullscreen = 1;
454             style = WS_VISIBLE | WS_POPUP;
455         }
456         SetWindowLong(mygui->subwindow, GWL_STYLE, style);
457         update_subwindow();
458     }
459     video_out->control(VOCTRL_FULLSCREEN, 0);
460     if(sub_window) ShowWindow(mygui->subwindow, SW_SHOW);
461 }
462
463 static unsigned __stdcall GuiThread(void* param)
464 {
465     MSG msg;
466
467     if(!skinName) skinName = strdup("Blue");
468     if(!mygui) mygui = create_gui(get_path("skins"), skinName, guiSetEvent);
469     if(!mygui) exit_player("Unable to load GUI.");
470
471     if(autosync && autosync != gtkAutoSync)
472     {
473        gtkAutoSyncOn = 1;
474        gtkAutoSync = autosync;
475     }
476
477     while(GetMessage(&msg, NULL, 0, 0))
478     {
479         TranslateMessage(&msg);
480         DispatchMessage(&msg);
481     }
482     fprintf(stderr, "[GUI] GUI thread terminated.\n");
483     fflush(stderr);
484     return 0;
485 }
486
487 void guiInit(void)
488 {
489     memset(&guiIntfStruct, 0, sizeof(guiIntfStruct));
490     /* Create The gui thread */
491     if (!mygui)
492     {
493         hThread = _beginthreadex(NULL, 0, GuiThread, NULL, 0, &threadId);
494         mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] Creating GUI Thread 0x%04x\n", threadId);
495     }
496
497     /* Wait until the gui is created */
498     while(!mygui) Sleep(100);
499     mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] GUI thread started.\n");
500 }
501
502 void guiDone(void)
503 {
504     if(mygui)
505     {
506         fprintf(stderr, "[GUI] Closed by main mplayer window\n");
507         fflush(stderr);
508         PostThreadMessage(threadId, WM_QUIT, 0, 0);
509         WaitForSingleObject(hThread, INFINITE);
510         CloseHandle(hThread);
511         mygui->uninit(mygui);
512         free(mygui);
513         mygui = NULL;
514     }
515     /* Remove tray icon */
516     Shell_NotifyIcon(NIM_DELETE, &nid);
517     cfg_write();
518 }
519
520 /* this function gets called by mplayer to update the gui */
521 int guiGetEvent(int type, char *arg)
522 {
523     stream_t *stream = (stream_t *) arg;
524 #ifdef CONFIG_DVDREAD
525     dvd_priv_t *dvdp = (dvd_priv_t *) arg;
526 #endif
527     if(!mygui || !mygui->skin) return 0;
528
529     if(guiIntfStruct.mpcontext)
530     {
531         audio_out = mpctx_get_audio_out(guiIntfStruct.mpcontext);
532         video_out = mpctx_get_video_out(guiIntfStruct.mpcontext);
533         mixer = mpctx_get_mixer(guiIntfStruct.mpcontext);
534         playtree = mpctx_get_playtree_iter(guiIntfStruct.mpcontext);
535     }
536
537     switch (type)
538     {
539         case guiSetFileFormat:
540             guiIntfStruct.FileFormat = (int) arg;
541             break;
542         case guiSetParameters:
543         {
544             guiGetEvent(guiSetDefaults, NULL);
545             guiIntfStruct.DiskChanged = 0;
546             guiIntfStruct.FilenameChanged = 0;
547             guiIntfStruct.NewPlay = 0;
548             switch(guiIntfStruct.StreamType)
549             {
550                 case STREAMTYPE_PLAYLIST:
551                     break;
552 #ifdef CONFIG_DVDREAD
553                 case STREAMTYPE_DVD:
554                 {
555                     char tmp[512];
556                     dvd_title = guiIntfStruct.DVD.current_title;
557                     dvd_chapter = guiIntfStruct.DVD.current_chapter;
558                     dvd_angle = guiIntfStruct.DVD.current_angle;
559                     sprintf(tmp,"dvd://%d", guiIntfStruct.Title);
560                     guiSetFilename(guiIntfStruct.Filename, tmp);
561                     break;
562                 }
563 #endif
564             }
565             if(guiIntfStruct.Filename)
566                 filename = strdup(guiIntfStruct.Filename);
567             else if(filename)
568                 strcpy(guiIntfStruct.Filename, filename);
569             break;
570         }
571         case guiSetAudioOnly:
572         {
573             guiIntfStruct.AudioOnly = (int) arg;
574             if(IsWindowVisible(mygui->subwindow))
575                 ShowWindow(mygui->subwindow, SW_HIDE);
576             break;
577         }
578         case guiSetContext:
579             guiIntfStruct.mpcontext = (void *) arg;
580             break;
581         case guiSetDemuxer:
582             guiIntfStruct.demuxer = (void *) arg;
583             break;
584         case guiSetValues:
585         {
586             guiIntfStruct.sh_video = arg;
587             if (arg)
588             {
589                 sh_video_t *sh = (sh_video_t *)arg;
590                 codecname = sh->codec->name;
591                 guiIntfStruct.FPS = sh->fps;
592
593                 /* we have video, show the subwindow */
594                 if(!IsWindowVisible(mygui->subwindow) || IsIconic(mygui->subwindow))
595                     ShowWindow(mygui->subwindow, SW_SHOWNORMAL);
596                 if(WinID == -1)
597                     update_subwindow();
598
599             }
600             break;
601         }
602         case guiSetShVideo:
603         {
604             guiIntfStruct.MovieWidth = vo_dwidth;
605             guiIntfStruct.MovieHeight = vo_dheight;
606
607             sub_aspect = (float)guiIntfStruct.MovieWidth/guiIntfStruct.MovieHeight;
608             if(WinID != -1)
609                update_subwindow();
610             break;
611         }
612         case guiSetStream:
613         {
614             guiIntfStruct.StreamType = stream->type;
615             switch(stream->type)
616             {
617 #ifdef CONFIG_DVDREAD
618                 case STREAMTYPE_DVD:
619                     guiGetEvent(guiSetDVD, (char *) stream->priv);
620                     break;
621 #endif
622             }
623             break;
624         }
625 #ifdef CONFIG_DVDREAD
626         case guiSetDVD:
627         {
628             guiIntfStruct.DVD.titles = dvdp->vmg_file->tt_srpt->nr_of_srpts;
629             guiIntfStruct.DVD.chapters = dvdp->vmg_file->tt_srpt->title[dvd_title].nr_of_ptts;
630             guiIntfStruct.DVD.angles = dvdp->vmg_file->tt_srpt->title[dvd_title].nr_of_angles;
631             guiIntfStruct.DVD.nr_of_audio_channels = dvdp->nr_of_channels;
632             memcpy(guiIntfStruct.DVD.audio_streams, dvdp->audio_streams, sizeof(dvdp->audio_streams));
633             guiIntfStruct.DVD.nr_of_subtitles = dvdp->nr_of_subtitles;
634             memcpy(guiIntfStruct.DVD.subtitles, dvdp->subtitles, sizeof(dvdp->subtitles));
635             guiIntfStruct.DVD.current_title = dvd_title + 1;
636             guiIntfStruct.DVD.current_chapter = dvd_chapter + 1;
637             guiIntfStruct.DVD.current_angle = dvd_angle + 1;
638             guiIntfStruct.Track = dvd_title + 1;
639             break;
640         }
641 #endif
642         case guiReDraw:
643             mygui->updatedisplay(mygui, mygui->mainwindow);
644             break;
645         case guiSetAfilter:
646             guiIntfStruct.afilter = (void *) arg;
647             break;
648         case guiCEvent:
649         {
650             guiIntfStruct.Playing = (int) arg;
651             switch (guiIntfStruct.Playing)
652             {
653                 case guiSetPlay:
654                 {
655                     guiIntfStruct.Playing = 1;
656                     break;
657                 }
658                 case guiSetStop:
659                 {
660                     guiIntfStruct.Playing = 0;
661                     if(movie_aspect >= 0)
662                         movie_aspect = -1;
663                     update_subwindow();
664                     break;
665                 }
666                 case guiSetPause:
667                     guiIntfStruct.Playing = 2;
668                     break;
669             }
670             break;
671         }
672         case guiIEvent:
673         {
674             mp_msg(MSGT_GPLAYER,MSGL_V, "cmd: %d\n", (int) arg);
675             /* MPlayer asks us to quit */
676             switch((int) arg)
677             {
678                 case MP_CMD_GUI_FULLSCREEN:
679                     mplFullScreen();
680                     break;
681                 case MP_CMD_QUIT:
682                 {
683                     mygui->uninit(mygui);
684                     free(mygui);
685                     mygui = NULL;
686                     exit_player("Done");
687                     return 0;
688                 }
689                 case MP_CMD_GUI_STOP:
690                     guiGetEvent(guiCEvent, (void *) guiSetStop);
691                     break;
692                 case MP_CMD_GUI_PLAY:
693                     guiGetEvent(guiCEvent, (void *) guiSetPlay);
694                     break;
695                 case MP_CMD_GUI_SKINBROWSER:
696                     if(fullscreen) guiSetEvent(evFullScreen);
697                     PostMessage(mygui->mainwindow, WM_COMMAND, (WPARAM) ID_SKINBROWSER, 0);
698                     break;
699                 case MP_CMD_GUI_PLAYLIST:
700                     if(fullscreen) guiSetEvent(evFullScreen);
701                     PostMessage(mygui->mainwindow, WM_COMMAND, (WPARAM) ID_PLAYLIST, 0);
702                     break;
703                 case MP_CMD_GUI_PREFERENCES:
704                     if(fullscreen) guiSetEvent(evFullScreen);
705                     PostMessage(mygui->mainwindow, WM_COMMAND, (WPARAM) ID_PREFS, 0);
706                     break;
707                 case MP_CMD_GUI_LOADFILE:
708                     if(fullscreen) guiSetEvent(evFullScreen);
709                     PostMessage(mygui->mainwindow, WM_COMMAND, (WPARAM) IDFILE_OPEN, 0);
710                     break;
711                 case MP_CMD_GUI_LOADSUBTITLE:
712                     if(fullscreen) guiSetEvent(evFullScreen);
713                     PostMessage(mygui->mainwindow, WM_COMMAND, (WPARAM) IDSUBTITLE_OPEN, 0);
714                     break;
715                 default:
716                     break;
717             }
718             break;
719         }
720         case guiSetFileName:
721             if (arg) guiIntfStruct.Filename = (char *) arg;
722             break;
723         case guiSetDefaults:
724         {
725             audio_id = -1;
726             video_id = -1;
727             dvdsub_id = -1;
728             vobsub_id = -1;
729             stream_cache_size = -1;
730             autosync = 0;
731             vcd_track = 0;
732             dvd_title = 0;
733             force_fps = 0;
734             if(!mygui->playlist->tracks) return 0;
735             filename = guiIntfStruct.Filename = mygui->playlist->tracks[mygui->playlist->current]->filename;
736             guiIntfStruct.Track = mygui->playlist->current + 1;
737             if(gtkAONorm) greplace(&af_cfg.list, "volnorm", "volnorm");
738             if(gtkAOExtraStereo)
739             {
740                 char *name = malloc(12 + 20 + 1);
741                 snprintf(name, 12 + 20, "extrastereo=%f", gtkAOExtraStereoMul);
742                 name[12 + 20] = 0;
743                 greplace(&af_cfg.list, "extrastereo", name);
744                 free(name);
745             }
746             if(gtkCacheOn) stream_cache_size = gtkCacheSize;
747             if(gtkAutoSyncOn) autosync = gtkAutoSync;
748             break;
749         }
750         case guiSetVolume:
751         {
752             if(audio_out)
753             {
754                 /* Some audio_out drivers do not support balance e.g. dsound */
755                 /* FIXME this algo is not correct */
756                 float l, r;
757                 mixer_getvolume(mixer, &l, &r);
758                 guiIntfStruct.Volume = (r > l ? r : l); /* max(r,l) */
759                 if (r != l)
760                     guiIntfStruct.Balance = ((r-l) + 100.0f) * 0.5f;
761                 else
762                     guiIntfStruct.Balance = 50.0f;
763             }
764             break;
765         }
766         default:
767             mp_msg(MSGT_GPLAYER, MSGL_ERR, "[GUI] GOT UNHANDLED EVENT %i\n", type);
768     }
769     return 0;
770 }
771
772 /* This function adds/inserts one file into the gui playlist */
773 int import_file_into_gui(char *pathname, int insert)
774 {
775     char filename[MAX_PATH];
776     char *filepart = filename;
777
778     if (strstr(pathname, "://"))
779     {
780         mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] Adding special %s\n", pathname);
781         mygui->playlist->add_track(mygui->playlist, pathname, NULL, NULL, 0);
782         return 1;
783     }
784     if (GetFullPathName(pathname, MAX_PATH, filename, &filepart))
785     {
786         if (!(GetFileAttributes(filename) & FILE_ATTRIBUTE_DIRECTORY))
787         {
788             mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] Adding filename: %s - fullpath: %s\n", filepart, filename);
789             mygui->playlist->add_track(mygui->playlist, filename, NULL, filepart, 0);
790             return 1;
791         }
792         else
793             mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] Cannot add %s\n", filename);
794     }
795
796     return 0;
797 }
798
799 /*  This function imports the initial playtree (based on cmd-line files) into the gui playlist
800     by either:
801     - overwriting gui pl (enqueue=0) */
802
803 int import_initial_playtree_into_gui(play_tree_t *my_playtree, m_config_t *config, int enqueue)
804 {
805     play_tree_iter_t *my_pt_iter = NULL;
806     int result = 0;
807
808     if(!mygui) guiInit();
809
810     if((my_pt_iter = pt_iter_create(&my_playtree, config)))
811     {
812         while ((filename = pt_iter_get_next_file(my_pt_iter)) != NULL)
813         {
814             if (parse_filename(filename, my_playtree, config, 0))
815                 result = 1;
816             else if (import_file_into_gui(filename, 0)) /* Add it to end of list */
817                 result = 1;
818         }
819     }
820     mplGotoTheNext = 1;
821
822     if (result)
823     {
824         mygui->playlist->current = 0;
825         filename = mygui->playlist->tracks[0]->filename;
826     }
827     return result;
828 }
829
830 /* This function imports and inserts an playtree, that is created "on the fly", for example by
831    parsing some MOV-Reference-File; or by loading an playlist with "File Open"
832    The file which contained the playlist is thereby replaced with it's contents. */
833
834 int import_playtree_playlist_into_gui(play_tree_t *my_playtree, m_config_t *config)
835 {
836     play_tree_iter_t *my_pt_iter = NULL;
837     int result = 0;
838
839     if((my_pt_iter = pt_iter_create(&my_playtree, config)))
840     {
841         while ((filename = pt_iter_get_next_file(my_pt_iter)) != NULL)
842             if (import_file_into_gui(filename, 1)) /* insert it into the list and set plCurrent = new item */
843                 result = 1;
844         pt_iter_destroy(&my_pt_iter);
845     }
846     filename = NULL;
847     return result;
848 }
849
850 inline void gtkMessageBox(int type, const char *str)
851 {
852     if (type & GTK_MB_FATAL)
853         MessageBox(NULL, str, "MPlayer GUI for Windows Error", MB_OK | MB_ICONERROR);
854
855     fprintf(stderr, "[GUI] MessageBox: %s\n", str);
856     fflush(stderr);
857 }
858
859 void guiMessageBox(int level, char *str)
860 {
861     switch(level)
862     {
863         case MSGL_FATAL:
864             gtkMessageBox(GTK_MB_FATAL | GTK_MB_SIMPLE, str);
865             break;
866         case MSGL_ERR:
867             gtkMessageBox(GTK_MB_ERROR | GTK_MB_SIMPLE, str);
868             break;
869     }
870 }
871
872 static int update_subwindow(void)
873 {
874     int x,y;
875     RECT rd;
876     WINDOWPOS wp;
877
878     if(!sub_window)
879     {
880         WinID = -1; // so far only directx supports WinID in windows
881
882         if(IsWindowVisible(mygui->subwindow) && guiIntfStruct.sh_video && guiIntfStruct.Playing)
883         {
884             ShowWindow(mygui->subwindow, SW_HIDE);
885             return 0;
886         }
887         else if(guiIntfStruct.AudioOnly)
888             return 0;
889         else ShowWindow(mygui->subwindow, SW_SHOW);
890     }
891
892     /* we've come out of fullscreen at the end of file */
893     if((!IsWindowVisible(mygui->subwindow) || IsIconic(mygui->subwindow)) && !guiIntfStruct.AudioOnly)
894         ShowWindow(mygui->subwindow, SW_SHOWNORMAL);
895
896     /* get our current window coordinates */
897     GetWindowRect(mygui->subwindow, &rd);
898
899     x = rd.left;
900     y = rd.top;
901
902     /* restore sub window position when coming out of fullscreen */
903     if(x <= 0) x = old_rect.left;
904     if(y <= 0) y = old_rect.top;
905
906     if(!guiIntfStruct.Playing)
907     {
908         window *desc = NULL;
909         int i;
910
911         for (i=0; i<mygui->skin->windowcount; i++)
912             if(mygui->skin->windows[i]->type == wiSub)
913                 desc = mygui->skin->windows[i];
914
915         rd.right = rd.left+desc->base->bitmap[0]->width;
916         rd.bottom = rd.top+desc->base->bitmap[0]->height;
917         sub_aspect = (float)(rd.right-rd.left)/(rd.bottom-rd.top);
918     }
919     else
920     {
921         rd.right = rd.left+guiIntfStruct.MovieWidth;
922         rd.bottom = rd.top+guiIntfStruct.MovieHeight;
923
924         if (movie_aspect > 0.0)       // forced aspect from the cmdline
925             sub_aspect = movie_aspect;
926     }
927
928
929     AdjustWindowRect(&rd, WS_OVERLAPPEDWINDOW | WS_SIZEBOX, 0);
930     SetWindowPos(mygui->subwindow, 0, x, y, rd.right-rd.left, rd.bottom-rd.top, SWP_NOOWNERZORDER);
931
932     wp.hwnd = mygui->subwindow;
933     wp.x = rd.left;
934     wp.y = rd.top;
935     wp.cx = rd.right-rd.left;
936     wp.cy = rd.bottom-rd.top;
937     wp.flags = SWP_NOOWNERZORDER | SWP_SHOWWINDOW;
938
939     /* erase the bitmap image if there's video */
940     if(guiIntfStruct.Playing != 0 && guiIntfStruct.sh_video)
941         SendMessage(mygui->subwindow, WM_ERASEBKGND, (WPARAM)GetDC(mygui->subwindow), 0);
942
943     /* reset the window aspect */
944     SendMessage(mygui->subwindow, WM_WINDOWPOSCHANGED, 0, (LPARAM)&wp);
945     return 0;
946 }
947
948 void guiEventHandling(void) {}