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 "config.h"
25
26 #if defined(CONFIG_LIBCDIO)
27 #if HAVE_CDIO_PARANOIA_H
28 #include <cdio/cdda.h>
29 #elif HAVE_CDIO_PARANOIA_PARANOIA_H
30 #include <cdio/paranoia/cdda.h>
31 #endif
32 #elif defined(CONFIG_CDDA)
33 #include <cdda_interface.h>
34 #endif
35
36 #include <windows.h>
37 #include <stdint.h>
38
39 #if defined(__CYGWIN__) || defined(__WINE__)
40 #define _beginthreadex CreateThread
41 #ifdef __WINE__
42 #include <winioctl.h>
43 #define WINE_MOUNTMGR_EXTENSIONS
44 #include <ddk/mountmgr.h>
45 #endif
46 #else
47 #include <process.h>
48 #endif
49
50 #include "path.h"
51 #include "gui/interface.h"
52 #include "m_option.h"
53 #include "mixer.h"
54 #include "mp_msg.h"
55 #include "help_mp.h"
56 #include "codec-cfg.h"
57 #include "stream/stream.h"
58 #include "libmpdemux/demuxer.h"
59 #include "libmpdemux/stheader.h"
60 #ifdef CONFIG_DVDREAD
61 #include "stream/stream_dvd.h"
62 #endif
63 #include "input/input.h"
64 #include "libvo/video_out.h"
65 #include "libao2/audio_out.h"
66 #include "access_mpcontext.h"
67 #include "libmpcodecs/ad.h"
68 #include "libmpcodecs/vd.h"
69 #include "libmpcodecs/dec_audio.h"
70 #include "gui/ui/actions.h"
71 #include "gui/ui/ui.h"
72 #include "gui/util/mem.h"
73 #include "gui/util/list.h"
74 #include "gui/util/string.h"
75 #include "mp_core.h"
76 #include "mpcommon.h"
77 #include "gui.h"
78 #include "dialogs.h"
79
80 #define SAME_STREAMTYPE (STREAMTYPE_DUMMY - 1)
81
82 int guiWinID = 0;
83
84 char *skinName = NULL;
85 const char *codecname = NULL;
86 static gui_t *mygui = NULL;
87 static int update_videowindow(void);
88 static RECT old_rect;
89 static DWORD style;
90 static HANDLE hThread;
91 static unsigned threadId;
92 const ao_functions_t *audio_out = NULL;
93 const vo_functions_t *video_out = NULL;
94 mixer_t *mixer = NULL;
95
96 #ifdef __WINE__
97 /**
98 * @brief Convert a Windows style path to a file name into an Unix style one.
99 *
100 * @param filename file path string to be converted
101 *
102 * @return converted file path string
103 */
unix_name(const char * win_filename)104 char *unix_name (const char *win_filename)
105 {
106 static char *unix_filename;
107 LPSTR (*CDECL wine_get_unix_file_name_ptr)(LPCWSTR);
108 int wchar_conv;
109
110 setdup(&unix_filename, win_filename);
111
112 if (*win_filename && (win_filename[1] == ':'))
113 {
114 wine_get_unix_file_name_ptr = (void *) GetProcAddress(GetModuleHandleA("KERNEL32"), "wine_get_unix_file_name");
115 wchar_conv = MultiByteToWideChar(CP_UNIXCP, 0, win_filename, -1, NULL, 0);
116
117 if (wine_get_unix_file_name_ptr && wchar_conv)
118 {
119 WCHAR *ntpath;
120 char *unix_name;
121
122 ntpath = HeapAlloc(GetProcessHeap(), 0, sizeof(*ntpath) * (wchar_conv + 1));
123 MultiByteToWideChar(CP_UNIXCP, 0, win_filename, -1, ntpath, wchar_conv);
124 unix_name = wine_get_unix_file_name_ptr(ntpath);
125 setdup(&unix_filename, unix_name);
126 HeapFree(GetProcessHeap(), 0, unix_name);
127 HeapFree(GetProcessHeap(), 0, ntpath);
128 }
129 }
130
131 return unix_filename;
132 }
133
134 #if defined(CONFIG_CDDA) || defined(CONFIG_DVDREAD)
135 /**
136 * @brief Convert a Windows style device name into an Unix style one.
137 *
138 * @param device device name to be converted
139 *
140 * @return converted device name
141 */
unix_device(char * device)142 static char *unix_device (char *device)
143 {
144 static char *unix_devname;
145 HANDLE mgr;
146 DWORD size = 1024;
147
148 mgr = CreateFileW(MOUNTMGR_DOS_DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
149
150 if (mgr != INVALID_HANDLE_VALUE)
151 {
152 struct mountmgr_unix_drive input;
153 struct mountmgr_unix_drive *data;
154
155 data = HeapAlloc(GetProcessHeap(), 0, size);
156
157 if (data)
158 {
159 memset(&input, 0, sizeof(input));
160 input.letter = *device;
161
162 if (DeviceIoControl(mgr, IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE, &input, sizeof(input), data, size, NULL, NULL))
163 {
164 if (data->device_offset)
165 {
166 setdup(&unix_devname, (char *) data + data->device_offset);
167 device = unix_devname;
168 }
169 }
170
171 HeapFree(GetProcessHeap(), 0, data);
172 }
173
174 CloseHandle(mgr);
175 }
176
177 return device;
178 }
179 #endif
180 #endif
181
182 /* test for playlist files, no need to specify -playlist on the commandline.
183 * add any conceivable playlist extensions here.
184 * - Erik
185 */
parse_filename(char * file,play_tree_t * playtree,m_config_t * mconfig,int clear)186 int parse_filename(char *file, play_tree_t *playtree, m_config_t *mconfig, int clear)
187 {
188 if(clear)
189 mygui->playlist->clear_playlist(mygui->playlist);
190
191 if(strstr(file, ".m3u") || strstr(file, ".m4u") || strstr(file, ".mxu") || strstr(file, ".pls"))
192 {
193 playtree = parse_playlist_file(file);
194 guiPlaylist(GUI_PLAYLIST_ADD, playtree, mconfig, 0);
195 return 1;
196 }
197 return 0;
198 }
199
200 /* this function gets called by the gui to update mplayer */
guiSetEvent(int event)201 static void guiSetEvent(int event)
202 {
203 if(guiInfo.mpcontext)
204 mixer = mpctx_get_mixer(guiInfo.mpcontext);
205
206 switch(event)
207 {
208 case evPlay:
209 case evPlaySwitchToPause:
210 case evPauseSwitchToPlay:
211 uiPlay();
212 break;
213 case evPause:
214 uiPause();
215 break;
216 #ifdef CONFIG_DVDREAD
217 case evPlayDVD:
218 {
219 static char dvdname[MAX_PATH];
220 guiInfo.Track = 1;
221 guiInfo.Chapter = 1;
222 guiInfo.Angle = 1;
223 guiInfo.MediumChanged = GUI_MEDIUM_SAME;
224
225 #ifdef __WINE__
226 // dvd_device is in the Windows style (D:\), which needs to be
227 // converted for MPlayer, so that it will find the device in the
228 // Linux filesystem.
229 dvd_device = unix_device(dvd_device);
230 #endif
231 uiSetFile(NULL, dvd_device, STREAMTYPE_DVD);
232 dvdname[0] = 0;
233 strcat(dvdname, "DVD Movie");
234 GetVolumeInformation(dvd_device, dvdname, MAX_PATH, NULL, NULL, NULL, NULL, 0);
235 capitalize(dvdname);
236 mp_msg(MSGT_GPLAYER, MSGL_V, "Opening DVD %s -> %s\n", dvd_device, dvdname);
237 mygui->playlist->clear_playlist(mygui->playlist);
238 mygui->playlist->add_track(mygui->playlist, filename, NULL, dvdname, 0);
239 uiPlay();
240 break;
241 }
242 #endif
243 #ifdef CONFIG_CDDA
244 case evPlayCD:
245 {
246 int i;
247 char track[10];
248 char trackname[10];
249 #ifdef CONFIG_LIBCDIO
250 cdrom_drive_t *cd;
251 #else
252 cdrom_drive *cd;
253 #endif
254 int i_tracks;
255
256 #ifdef __WINE__
257 // cdrom_device is in the Windows style (D:\), which needs to be
258 // converted for MPlayer, so that it will find the device in the
259 // Linux filesystem.
260 cdrom_device = unix_device(cdrom_device);
261 #endif
262 cd = cdda_identify(cdrom_device, 0, NULL);
263 if (cd)
264 {
265 if (cdda_open(cd) != 0)
266 {
267 cdda_close(cd);
268 cd = NULL;
269 }
270 }
271 if(!cd)
272 {
273 printf("Couldn't find a driver.\n");
274 break;
275 }
276 i_tracks = cdda_tracks(cd);
277
278 mygui->playlist->clear_playlist(mygui->playlist);
279 for(i=0;i<i_tracks;i++)
280 {
281 sprintf(track, "cdda://%d", i+1);
282 sprintf(trackname, "Track %d", i+1);
283 mygui->playlist->add_track(mygui->playlist, track, NULL, trackname, 0);
284 }
285 cdda_close(cd);
286 mygui->startplay(mygui);
287 break;
288 }
289 #endif
290 case evFullScreen:
291 mp_input_queue_cmd(mp_input_parse_cmd("vo_fullscreen"));
292 break;
293 case evExit:
294 {
295 /* We are asking mplayer to exit, later it will ask us after uninit is made
296 this should be the only safe way to quit */
297 mygui->activewidget = NULL;
298 mp_input_queue_cmd(mp_input_parse_cmd("quit"));
299 break;
300 }
301 case evStop:
302 if(guiInfo.Playing)
303 gui(GUI_SET_STATE, (void *) GUI_STOP);
304 break;
305 case evSetMoviePosition:
306 {
307 rel_seek_secs = guiInfo.Position / 100.0;
308 abs_seek_pos = SEEK_ABSOLUTE | SEEK_FACTOR;
309 break;
310 }
311 case evForward10sec:
312 {
313 rel_seek_secs = 10.0f;
314 abs_seek_pos = 0;
315 break;
316 }
317 case evBackward10sec:
318 {
319 rel_seek_secs = -10.0f;
320 abs_seek_pos = 0;
321 break;
322 }
323 case evSetBalance:
324 case evSetVolume:
325 {
326 float l,r;
327
328 if (guiInfo.Playing == GUI_STOP)
329 break;
330
331 l = guiInfo.Volume * (100.0 - guiInfo.Balance) / 50.0;
332 r = guiInfo.Volume * guiInfo.Balance / 50.0;
333
334 if (l > guiInfo.Volume) l=guiInfo.Volume;
335 if (r > guiInfo.Volume) r=guiInfo.Volume;
336 mixer_setvolume(mixer, l, r);
337 /* Check for balance support on mixer - there is a better way ?? */
338 if (r != l)
339 {
340 mixer_getvolume(mixer, &l, &r);
341 if (r == l)
342 {
343 mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] Mixer doesn't support unbalanced audio\n");
344 mixer_setvolume(mixer, guiInfo.Volume, guiInfo.Volume);
345 guiInfo.Balance = 50.0f;
346 }
347 }
348 break;
349 }
350 case evMute:
351 {
352 mp_cmd_t * cmd = calloc(1, sizeof(*cmd));
353 cmd->id=MP_CMD_MUTE;
354 ARRAY_STRCPY(cmd->name, "mute");
355 mp_input_queue_cmd(cmd);
356 break;
357 }
358 case evLoadPlay:
359 {
360 switch(guiInfo.StreamType)
361 {
362 case STREAMTYPE_DVD:
363 {
364 guiInfo.MediumChanged = GUI_MEDIUM_SAME;
365 gui(GUI_SET_STATE, (void *) GUI_PLAY);
366 break;
367 }
368 default:
369 {
370 guiInfo.MediumChanged = GUI_MEDIUM_NEW;
371 update_playlistwindow();
372 guiInfo.PlaylistNext = guiInfo.Playing? 0 : 1;
373 gui(GUI_SET_STATE, (void *) GUI_STOP);
374 gui(GUI_SET_STATE, (void *) GUI_PLAY);
375 break;
376 }
377 }
378 break;
379 }
380 case evNext:
381 uiNext();
382 break;
383 case evPrev:
384 uiPrev();
385 break;
386 }
387 }
388
uiPlay(void)389 void uiPlay( void )
390 {
391 if((!guiInfo.Filename ) || (guiInfo.Filename[0] == 0))
392 return;
393
394 if(guiInfo.Playing > GUI_STOP)
395 {
396 uiPause();
397 return;
398 }
399 guiInfo.MediumChanged = GUI_MEDIUM_NEW;
400 gui(GUI_SET_STATE, (void *) GUI_PLAY);
401 }
402
uiPause(void)403 void uiPause( void )
404 {
405 if(!guiInfo.Playing) return;
406
407 if(guiInfo.Playing == GUI_PLAY)
408 {
409 mp_cmd_t * cmd = calloc(1, sizeof(*cmd));
410 cmd->id=MP_CMD_PAUSE;
411 ARRAY_STRCPY(cmd->name, "pause");
412 mp_input_queue_cmd(cmd);
413 } else guiInfo.Playing = GUI_PLAY;
414 }
415
uiNext(void)416 void uiNext(void)
417 {
418 if(guiInfo.Playing == GUI_PAUSE) return;
419 switch(guiInfo.StreamType)
420 {
421 case STREAMTYPE_DVD:
422 if(guiInfo.Chapter == (guiInfo.Chapters - 1))
423 return;
424 guiInfo.Chapter++;
425 break;
426 default:
427 if(mygui->playlist->current == (mygui->playlist->trackcount - 1))
428 return;
429 uiSetFile(NULL, mygui->playlist->tracks[(mygui->playlist->current)++]->filename,
430 STREAMTYPE_FILE);
431 break;
432 }
433 mygui->startplay(mygui);
434 }
435
uiPrev(void)436 void uiPrev(void)
437 {
438 if(guiInfo.Playing == GUI_PAUSE) return;
439 switch(guiInfo.StreamType)
440 {
441 case STREAMTYPE_DVD:
442 if(guiInfo.Chapter == 1)
443 return;
444 guiInfo.Chapter--;
445 break;
446 default:
447 if(mygui->playlist->current == 0)
448 return;
449 uiSetFile(NULL, mygui->playlist->tracks[(mygui->playlist->current)--]->filename,
450 STREAMTYPE_FILE);
451 break;
452 }
453 mygui->startplay(mygui);
454 }
455
uiSetFile(const char * dir,const char * name,int type)456 void uiSetFile(const char *dir, const char *name, int type)
457 {
458 if(!name) return;
459 if(!dir)
460 setdup(&guiInfo.Filename, name);
461 else
462 setddup(&guiInfo.Filename, dir, name);
463
464 filename = guiInfo.Filename;
465 #ifdef __WINE__
466 // When the GUI receives the files to be played in guiPlaylist(),
467 // it calls import_file_into_gui() where the call of
468 // Wine's GetFullPathName() converts each file name into the Windows style
469 // (C:\path\to\file), which needs to be reconverted for MPlayer, so that
470 // it will find the filename in the Linux filesystem.
471 filename = unix_name(filename);
472 #endif
473
474 if (type != SAME_STREAMTYPE)
475 guiInfo.StreamType = type;
476
477 nfree(guiInfo.AudioFilename);
478 nfree(guiInfo.SubtitleFilename);
479 }
480
uiFullScreen(void)481 void uiFullScreen( void )
482 {
483 if(!guiInfo.sh_video) return;
484
485 if(video_window)
486 {
487 if(!fullscreen && IsWindowVisible(mygui->videowindow) && !IsIconic(mygui->videowindow))
488 GetWindowRect(mygui->videowindow, &old_rect);
489
490 if(fullscreen)
491 {
492 fullscreen = FALSE;
493 style = WS_OVERLAPPEDWINDOW | WS_SIZEBOX;
494 } else {
495 fullscreen = TRUE;
496 style = WS_VISIBLE | WS_POPUP;
497 }
498 SetWindowLong(mygui->videowindow, GWL_STYLE, style);
499 update_videowindow();
500 }
501 video_out->control(VOCTRL_FULLSCREEN, 0);
502 if(video_window) ShowWindow(mygui->videowindow, SW_SHOW);
503 }
504
GuiThread(void * param)505 static unsigned __stdcall GuiThread(void* param)
506 {
507 MSG msg;
508
509 (void) param;
510
511 if(!skinName) skinName = strdup("Blue");
512 if(!mygui) mygui = create_gui(get_path("skins"), guiSetEvent);
513 if(!mygui) exit_player(EXIT_ERROR);
514
515 if(autosync && autosync != gtkAutoSync)
516 {
517 gtkAutoSyncOn = TRUE;
518 gtkAutoSync = autosync;
519 }
520
521 while(GetMessage(&msg, NULL, 0, 0))
522 {
523 TranslateMessage(&msg);
524 DispatchMessage(&msg);
525 }
526 fprintf(stderr, "[GUI] GUI thread terminated.\n");
527 fflush(stderr);
528 return 0;
529 }
530
guiInit(void)531 void guiInit(void)
532 {
533 memset(&guiInfo, 0, sizeof(guiInfo));
534 /* Create The gui thread */
535 if (!mygui)
536 {
537 hThread = _beginthreadex(NULL, 0, GuiThread, NULL, 0, &threadId);
538 mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] Creating GUI Thread 0x%04x\n", threadId);
539 }
540
541 /* Wait until the gui is created */
542 while(!mygui) Sleep(100);
543 mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] GUI thread started.\n");
544
545 guiInfo.Volume = mygui->default_volume;
546 guiInfo.Balance = mygui->default_balance;
547 }
548
guiDone(void)549 void guiDone(void)
550 {
551 if(mygui)
552 {
553 fprintf(stderr, "[GUI] Closed by main mplayer window\n");
554 fflush(stderr);
555 PostThreadMessage(threadId, WM_QUIT, 0, 0);
556 WaitForSingleObject(hThread, INFINITE);
557 CloseHandle(hThread);
558 mygui->uninit(mygui);
559 nfree(mygui);
560 }
561 /* Remove tray icon */
562 Shell_NotifyIcon(NIM_DELETE, &nid);
563 cfg_write();
564 }
565
566 /* this function gets called by mplayer to update the gui */
gui(int what,void * data)567 int gui(int what, void *data)
568 {
569 int idata = (intptr_t) data;
570 stream_t *stream;
571 sh_audio_t *sh_audio;
572 #ifdef CONFIG_DVDREAD
573 dvd_priv_t *dvdp;
574 #endif
575 if(!mygui || !mygui->skin) return FALSE;
576
577 if(guiInfo.mpcontext)
578 {
579 audio_out = mpctx_get_audio_out(guiInfo.mpcontext);
580 video_out = mpctx_get_video_out(guiInfo.mpcontext);
581 mixer = mpctx_get_mixer(guiInfo.mpcontext);
582 playtree = mpctx_get_playtree_iter(guiInfo.mpcontext);
583 }
584
585 switch (what)
586 {
587 case GUI_PREPARE:
588 {
589 audio_id = -1;
590 video_id = -1;
591 dvdsub_id = -1;
592 vobsub_id = -1;
593 stream_cache_size = -1;
594 autosync = 0;
595 force_fps = 0;
596 if(!mygui->playlist->tracks) return FALSE;
597 switch(guiInfo.StreamType)
598 {
599 case STREAMTYPE_FILE:
600 case STREAMTYPE_STREAM:
601 uiSetFile(NULL, mygui->playlist->tracks[mygui->playlist->current]->filename, SAME_STREAMTYPE);
602 guiInfo.Track = mygui->playlist->current + 1;
603 break;
604 case STREAMTYPE_DVD:
605 {
606 char tmp[512];
607 #ifdef CONFIG_DVDREAD
608 dvd_chapter = guiInfo.Chapter;
609 dvd_angle = guiInfo.Angle;
610 #endif
611 sprintf(tmp,"dvd://%d", guiInfo.Track);
612 uiSetFile(NULL, tmp, SAME_STREAMTYPE);
613 break;
614 }
615 }
616 guiInfo.VideoWindow = TRUE;
617 if(gtkAONorm) listRepl(&af_cfg.list, "volnorm", "volnorm");
618 if(gtkAOExtraStereo)
619 {
620 char *name = malloc(12 + 20 + 1);
621 snprintf(name, 12 + 20, "extrastereo=%f", gtkAOExtraStereoMul);
622 name[12 + 20] = 0;
623 listRepl(&af_cfg.list, "extrastereo", name);
624 free(name);
625 }
626 if(gtkCacheOn) stream_cache_size = gtkCacheSize;
627 if(gtkAutoSyncOn) autosync = gtkAutoSync;
628 guiInfo.MediumChanged = 0;
629 break;
630 }
631 case GUI_SET_AUDIO:
632 {
633 sh_audio = data;
634 if (sh_audio)
635 {
636 guiInfo.AudioChannels = sh_audio->channels;
637 guiInfo.AudioPassthrough = (gstrcmp(sh_audio->ad_driver->info->short_name, "hwac3") == 0);
638
639 if (!guiInfo.sh_video) guiInfo.VideoWindow = FALSE;
640 }
641 else
642 {
643 guiInfo.AudioChannels = 0;
644 guiInfo.AudioPassthrough = FALSE;
645 }
646 if (guiInfo.Volume >= 0.0f) /* otherwise skin demands usage of current volume */
647 {
648 guiSetEvent(evSetVolume);
649 guiSetEvent(evSetBalance);
650 }
651 if(IsWindowVisible(mygui->videowindow) && !guiInfo.VideoWindow)
652 ShowWindow(mygui->videowindow, SW_HIDE);
653 break;
654 }
655 case GUI_SET_CONTEXT:
656 guiInfo.mpcontext = data;
657 break;
658 case GUI_SET_VIDEO:
659 {
660 guiInfo.sh_video = data;
661 if (guiInfo.sh_video)
662 {
663 codecname = codec_idx2str(guiInfo.sh_video->codec->name_idx);
664
665 /* we have video, show the video window */
666 if(!IsWindowVisible(mygui->videowindow) || IsIconic(mygui->videowindow))
667 ShowWindow(mygui->videowindow, SW_SHOWNORMAL);
668 if(WinID == -1)
669 update_videowindow();
670
671 }
672 break;
673 }
674 case GUI_SETUP_VIDEO_WINDOW:
675 {
676 guiInfo.VideoWidth = vo_dwidth;
677 guiInfo.VideoHeight = vo_dheight;
678
679 video_aspect = (float)guiInfo.VideoWidth/guiInfo.VideoHeight;
680 if(WinID != -1)
681 update_videowindow();
682 break;
683 }
684 case GUI_SET_STREAM:
685 {
686 stream = data;
687 guiInfo.StreamType = stream->type;
688 switch(guiInfo.StreamType)
689 {
690 case STREAMTYPE_DVD:
691 guiInfo.Tracks = 0;
692 stream_control(stream, STREAM_CTRL_GET_NUM_TITLES, &guiInfo.Tracks);
693 guiInfo.Chapters = 0;
694 stream_control(stream, STREAM_CTRL_GET_NUM_CHAPTERS, &guiInfo.Chapters);
695 guiInfo.Angles = 0;
696 stream_control(stream, STREAM_CTRL_GET_NUM_ANGLES, &guiInfo.Angles);
697 if (stream_control(stream, STREAM_CTRL_GET_CURRENT_TITLE, &guiInfo.Track) == STREAM_OK)
698 guiInfo.Track++;
699 // guiInfo.Chapter will be set by mplayer
700 guiInfo.Angle = 1;
701 stream_control(stream, STREAM_CTRL_GET_ANGLE, &guiInfo.Angle);
702 #ifdef CONFIG_DVDREAD
703 dvdp = stream->priv;
704 guiInfo.AudioStreams = dvdp->nr_of_channels;
705 memcpy(guiInfo.AudioStream, dvdp->audio_streams, sizeof(dvdp->audio_streams));
706 guiInfo.Subtitles = dvdp->nr_of_subtitles;
707 memcpy(guiInfo.Subtitle, dvdp->subtitles, sizeof(dvdp->subtitles));
708 #endif
709 break;
710 }
711 break;
712 }
713 case GUI_REDRAW:
714 mygui->updatedisplay(mygui, mygui->mainwindow);
715 break;
716 case GUI_SET_STATE:
717 {
718 guiInfo.Playing = idata;
719 switch (guiInfo.Playing)
720 {
721 case GUI_PLAY:
722 {
723 guiInfo.Playing = GUI_PLAY;
724 break;
725 }
726 case GUI_STOP:
727 {
728 guiInfo.Playing = GUI_STOP;
729 if(movie_aspect >= 0)
730 movie_aspect = -1;
731 update_videowindow();
732 break;
733 }
734 case GUI_PAUSE:
735 guiInfo.Playing = GUI_PAUSE;
736 break;
737 }
738 break;
739 }
740 case GUI_RUN_COMMAND:
741 {
742 mp_msg(MSGT_GPLAYER,MSGL_V, "cmd: %d\n", idata);
743 /* MPlayer asks us to quit */
744 switch(idata)
745 {
746 case MP_CMD_VO_FULLSCREEN:
747 uiFullScreen();
748 break;
749 case MP_CMD_QUIT:
750 {
751 mygui->uninit(mygui);
752 nfree(mygui);
753 exit_player(EXIT_QUIT);
754 return TRUE;
755 }
756 case MP_CMD_PLAY_TREE_STEP:
757 guiSetEvent(evNext);
758 break;
759 case -MP_CMD_PLAY_TREE_STEP:
760 guiSetEvent(evPrev);
761 break;
762 case MP_CMD_STOP:
763 guiSetEvent(evStop);
764 break;
765 default:
766 break;
767 }
768 break;
769 }
770 case GUI_RUN_MESSAGE:
771 break;
772 case GUI_SET_VOLUME_BALANCE:
773 {
774 if(audio_out)
775 {
776 /* Some audio_out drivers do not support balance e.g. dsound */
777 /* FIXME this algo is not correct */
778 float l, r;
779 mixer_getvolume(mixer, &l, &r);
780 guiInfo.Volume = (r > l ? r : l); /* max(r,l) */
781 if (r != l)
782 guiInfo.Balance = ((r-l) + 100.0) * 0.5;
783 else
784 guiInfo.Balance = 50.0f;
785 }
786 break;
787 }
788 case GUI_END_PLAY:
789 {
790 guiInfo.sh_video = NULL;
791
792 if(!guiInfo.PlaylistNext && guiInfo.Playing)
793 {
794 guiInfo.PlaylistNext = TRUE;
795 break;
796 }
797
798 if(guiInfo.PlaylistNext && guiInfo.Playing &&
799 (mygui->playlist->current < (mygui->playlist->trackcount - 1)) &&
800 guiInfo.StreamType != STREAMTYPE_DVD &&
801 guiInfo.StreamType != STREAMTYPE_DVDNAV)
802 {
803 /* we've finished this file, reset the aspect */
804 if(movie_aspect >= 0)
805 movie_aspect = -1;
806
807 guiInfo.PlaylistNext = TRUE;
808 guiInfo.MediumChanged = GUI_MEDIUM_NEW;
809 uiSetFile(NULL, mygui->playlist->tracks[(mygui->playlist->current)++]->filename, STREAMTYPE_FILE);
810 //sprintf(guiInfo.Filename, mygui->playlist->tracks[(mygui->playlist->current)++]->filename);
811 }
812
813 if(guiInfo.MediumChanged == GUI_MEDIUM_NEW)
814 break;
815
816 guiInfo.ElapsedTime = 0;
817 guiInfo.Position = 0;
818 guiInfo.AudioChannels = 0;
819 guiInfo.AudioPassthrough = FALSE;
820
821 guiInfo.Track = 1;
822 guiInfo.Chapter = 1;
823 guiInfo.Angle = 1;
824
825 if (mygui->playlist->current == (mygui->playlist->trackcount - 1))
826 mygui->playlist->current = 0;
827
828 fullscreen = FALSE;
829 if(style == (WS_VISIBLE | WS_POPUP))
830 {
831 style = WS_OVERLAPPEDWINDOW | WS_SIZEBOX;
832 SetWindowLong(mygui->videowindow, GWL_STYLE, style);
833 }
834 gui(GUI_SET_STATE, (void *) GUI_STOP);
835 break;
836 }
837 #ifdef __WINE__
838 // it's possible to have an X11 video output driver (sending events)
839 case GUI_HANDLE_X_EVENT:
840 {
841 break;
842 }
843 #endif
844 default:
845 mp_msg(MSGT_GPLAYER, MSGL_ERR, "[GUI] GOT UNHANDLED EVENT %i\n", what);
846 }
847 return TRUE;
848 }
849
850 /* This function adds/inserts one file into the gui playlist */
import_file_into_gui(char * pathname,int insert)851 static int import_file_into_gui(char *pathname, int insert)
852 {
853 char file[MAX_PATH];
854 char *filepart = file;
855
856 (void) insert; // NOTE TO MYSELF: this isn't yet implemented
857
858 if (strstr(pathname, "://"))
859 {
860 mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] Adding special %s\n", pathname);
861 mygui->playlist->add_track(mygui->playlist, pathname, NULL, NULL, 0);
862 return 1;
863 }
864 if (GetFullPathName(pathname, MAX_PATH, file, &filepart))
865 {
866 if (!(GetFileAttributes(file) & FILE_ATTRIBUTE_DIRECTORY))
867 {
868 mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] Adding filename: %s - fullpath: %s\n", filepart, file);
869 mygui->playlist->add_track(mygui->playlist, file, NULL, filepart, 0);
870 return 1;
871 }
872 else
873 mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] Cannot add %s\n", file);
874 }
875
876 return 0;
877 }
878
guiPlaylist(int what,play_tree_t * playtree,m_config_t * config,int enqueue)879 int guiPlaylist (int what, play_tree_t *playtree, m_config_t *config, int enqueue)
880 {
881 play_tree_iter_t *pt_iter = NULL;
882 char *file;
883 int added = FALSE;
884
885 switch (what)
886 {
887 /* This function imports the initial playtree (based on cmd-line files) into the gui playlist
888 by either:
889 - overwriting gui pl (enqueue=0) */
890 case GUI_PLAYLIST_INIT:
891
892 if(!mygui) guiInit();
893
894 if((pt_iter = pt_iter_create(&playtree, config)))
895 {
896 while ((file = pt_iter_get_next_file(pt_iter)) != NULL)
897 {
898 if (parse_filename(file, playtree, config, 0))
899 added = TRUE;
900 else if (import_file_into_gui(file, 0)) /* Add it to end of list */
901 added = TRUE;
902 }
903 }
904 guiInfo.PlaylistNext = TRUE;
905
906 if (added)
907 {
908 mygui->playlist->current = 0;
909 uiSetFile(NULL, mygui->playlist->tracks[0]->filename, STREAMTYPE_FILE);
910 }
911
912 if (enqueue) filename = NULL;
913
914 break;
915
916 /* This function imports and inserts an playtree, that is created "on the fly", for example by
917 parsing some MOV-Reference-File; or by loading an playlist with "File Open"
918 The file which contained the playlist is thereby replaced with it's contents. */
919 case GUI_PLAYLIST_ADD:
920
921 if((pt_iter = pt_iter_create(&playtree, config)))
922 {
923 while ((file = pt_iter_get_next_file(pt_iter)) != NULL)
924 if (import_file_into_gui(file, 1)) /* insert it into the list and set plCurrent = new item */
925 added = TRUE;
926 pt_iter_destroy(&pt_iter);
927 }
928
929 break;
930 }
931
932 return added;
933 }
934
update_videowindow(void)935 static int update_videowindow(void)
936 {
937 int x,y;
938 RECT rd;
939 WINDOWPOS wp;
940
941 if(!video_window)
942 {
943 WinID = -1;
944
945 if(IsWindowVisible(mygui->videowindow) && guiInfo.sh_video && guiInfo.Playing)
946 {
947 ShowWindow(mygui->videowindow, SW_HIDE);
948 return 0;
949 }
950 else if(!guiInfo.VideoWindow)
951 return 0;
952 else ShowWindow(mygui->videowindow, SW_SHOW);
953 }
954
955 /* we've come out of fullscreen at the end of file */
956 if((!IsWindowVisible(mygui->videowindow) || IsIconic(mygui->videowindow)) && guiInfo.VideoWindow)
957 ShowWindow(mygui->videowindow, SW_SHOWNORMAL);
958
959 /* get our current window coordinates */
960 GetWindowRect(mygui->videowindow, &rd);
961
962 x = rd.left;
963 y = rd.top;
964
965 /* restore video window position when coming out of fullscreen */
966 if(x <= 0) x = old_rect.left;
967 if(y <= 0) y = old_rect.top;
968
969 if(!guiInfo.Playing)
970 {
971 window *desc = NULL;
972 unsigned int i;
973
974 for (i=0; i<mygui->skin->windowcount; i++)
975 if(mygui->skin->windows[i]->type == wVideo)
976 desc = mygui->skin->windows[i];
977
978 rd.right = rd.left+desc->base->bitmap[0]->width;
979 rd.bottom = rd.top+desc->base->bitmap[0]->height;
980 video_aspect = (float)(rd.right-rd.left)/(rd.bottom-rd.top);
981 }
982 else
983 {
984 rd.right = rd.left+guiInfo.VideoWidth;
985 rd.bottom = rd.top+guiInfo.VideoHeight;
986
987 if (movie_aspect > 0.0f) // forced aspect from the cmdline
988 video_aspect = movie_aspect;
989 }
990
991
992 AdjustWindowRect(&rd, WS_OVERLAPPEDWINDOW | WS_SIZEBOX, 0);
993 SetWindowPos(mygui->videowindow, 0, x, y, rd.right-rd.left, rd.bottom-rd.top, SWP_NOOWNERZORDER);
994
995 wp.hwnd = mygui->videowindow;
996 wp.x = rd.left;
997 wp.y = rd.top;
998 wp.cx = rd.right-rd.left;
999 wp.cy = rd.bottom-rd.top;
1000 wp.flags = SWP_NOOWNERZORDER | SWP_SHOWWINDOW;
1001
1002 /* erase the bitmap image if there's video */
1003 if(guiInfo.Playing != GUI_STOP && guiInfo.sh_video)
1004 SendMessage(mygui->videowindow, WM_ERASEBKGND, (WPARAM)GetDC(mygui->videowindow), 0);
1005
1006 /* reset the window aspect */
1007 SendMessage(mygui->videowindow, WM_WINDOWPOSCHANGED, 0, (LPARAM)&wp);
1008 return 0;
1009 }
1010