6c7c49d3f17e462ab801fa61873a463ee2735ffd
[vlc.git] / modules / gui / wince / interface.cpp
1 /*****************************************************************************
2  * interface.cpp: WinCE gui plugin for VLC
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id$
6  *
7  * Authors: Marodon Cedric <cedric_marodon@yahoo.fr>
8  *          Gildas Bazin <gbazin@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111,
23  * USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include <vlc/vlc.h>
30 #include <vlc/aout.h>
31 #include <vlc/vout.h>
32 #include <vlc/intf.h>
33
34 #include "wince.h"
35
36 #include <winuser.h>
37 #include <windows.h>
38 #include <windowsx.h>
39 #include <commctrl.h>
40 #include <commdlg.h>
41 #include <shlobj.h>
42
43 #define NUMIMAGES     9   // Number of buttons in the toolbar           
44 #define IMAGEWIDTH    17   // Width of the buttons in the toolbar  
45 #define IMAGEHEIGHT   16   // Height of the buttons in the toolbar  
46 #define BUTTONWIDTH   0    // Width of the button images in the toolbar
47 #define BUTTONHEIGHT  0    // Height of the button images in the toolbar
48 #define ID_TOOLBAR    2000 // Identifier of the main tool bar
49
50 // Help strings
51 #define HELP_SIMPLE _T("Quick file open")
52 #define HELP_ADV    _T("Advanced open")
53 #define HELP_FILE   _T("Open a file")
54 #define HELP_DISC   _T("Open Disc Media")
55 #define HELP_NET    _T("Open a network stream")
56 #define HELP_SAT    _T("Open a satellite stream")
57 #define HELP_EJECT  _T("Eject the DVD/CD")
58 #define HELP_EXIT   _T("Exit this program")
59
60 #define HELP_OTHER _T("Open other types of inputs")
61
62 #define HELP_PLAYLIST   _T("Open the playlist")
63 #define HELP_LOGS       _T("Show the program logs")
64 #define HELP_FILEINFO   _T("Show information about the file being played")
65
66 #define HELP_PREFS _T("Go to the preferences menu")
67
68 #define HELP_ABOUT _T("About this program")
69
70 #define HELP_STOP _T("Stop")
71
72 #define HELP_PLAY _T("Play")
73 #define HELP_PAUSE _T("Pause")
74 #define HELP_PLO _T("Playlist")
75 #define HELP_PLP _T("Previous playlist item")
76 #define HELP_PLN _T("Next playlist item")
77 #define HELP_SLOW _T("Play slower")
78 #define HELP_FAST _T("Play faster")
79
80 // The TBBUTTON structure contains information the toolbar buttons.
81 static TBBUTTON tbButton[] =      
82 {
83   {0, ID_FILE_QUICKOPEN,        TBSTATE_ENABLED, TBSTYLE_BUTTON},
84   {1, ID_FILE_OPENNET,       TBSTATE_ENABLED, TBSTYLE_BUTTON},
85   {0, 0,              TBSTATE_ENABLED, TBSTYLE_SEP},
86   {2, StopStream_Event,       TBSTATE_ENABLED, TBSTYLE_BUTTON},
87   {3, PlayStream_Event,        TBSTATE_ENABLED, TBSTYLE_BUTTON},
88   {0, 0,              TBSTATE_ENABLED, TBSTYLE_SEP},
89   {4, ID_VIEW_PLAYLIST,       TBSTATE_ENABLED, TBSTYLE_BUTTON},
90   {0, 0,              TBSTATE_ENABLED, TBSTYLE_SEP},
91   {5, PrevStream_Event,      TBSTATE_ENABLED, TBSTYLE_BUTTON},
92   {6, NextStream_Event,      TBSTATE_ENABLED, TBSTYLE_BUTTON},
93   {0, 0,              TBSTATE_ENABLED, TBSTYLE_SEP},
94   {7, SlowStream_Event,      TBSTATE_ENABLED, TBSTYLE_BUTTON},
95   {8, FastStream_Event,       TBSTATE_ENABLED, TBSTYLE_BUTTON},
96 };
97
98 // Toolbar ToolTips
99 TCHAR * szToolTips[] = 
100 {
101     HELP_SIMPLE, HELP_NET, HELP_STOP, HELP_PLAY, HELP_PLO, HELP_PLP,
102     HELP_PLN, HELP_SLOW, HELP_FAST
103 };
104
105 /*****************************************************************************
106  * Constructor.
107  *****************************************************************************/
108 Interface::Interface()
109   : hwndMain(0), hwndCB(0), hwndTB(0), hwndSlider(0), hwndLabel(0),
110     hwndVol(0), hwndSB(0),
111     fileinfo(0), messages(0), preferences(0), playlist(0),
112     timer(0), open(0), video(0), b_volume_hold(0)
113 {
114 }
115
116 Interface::~Interface()
117 {
118     if( timer ) delete timer;
119     if( video ) delete video;
120 }
121
122 BOOL Interface::InitInstance( HINSTANCE hInstance, intf_thread_t *_p_intf )
123 {
124     /* Initializations */
125     p_intf = _p_intf;
126     i_old_playing_status = PAUSE_S;
127
128     hInst = hInstance; // Store instance handle in our global variable
129
130     // Register window class
131     WNDCLASS wc;
132     wc.style = CS_HREDRAW | CS_VREDRAW ;
133     wc.lpfnWndProc = (WNDPROC)BaseWndProc;
134     wc.cbClsExtra = 0;
135     wc.cbWndExtra = 0;
136     wc.hIcon = NULL;
137     wc.hInstance = hInstance;
138     wc.hCursor = NULL;
139     wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
140     wc.lpszMenuName = NULL;
141     wc.lpszClassName = _T("VLC WinCE");
142     if( !RegisterClass( &wc ) ) return FALSE;
143
144     int i_style = WS_VISIBLE;
145
146 #ifndef UNDER_CE
147     i_style |= WS_OVERLAPPEDWINDOW | WS_SIZEBOX;
148 #endif
149
150     // Create main window
151     hwndMain =
152         CreateWindow( _T("VLC WinCE"), _T("VLC media player"), i_style,
153                       0, MENU_HEIGHT, CW_USEDEFAULT, CW_USEDEFAULT,
154                       NULL, NULL, hInstance, (void *)this );
155
156     if( !hwndMain ) return FALSE;
157
158     ShowWindow( hwndMain, TRUE );
159     UpdateWindow( hwndMain );
160
161     return TRUE;
162 }
163
164 /***********************************************************************
165 FUNCTION: 
166   CreateMenuBar
167
168 PURPOSE: 
169   Creates a menu bar.
170 ***********************************************************************/
171 HWND Interface::CreateMenuBar( HWND hwnd, HINSTANCE hInst )
172 {
173     HMENU menu_file, menu_view;
174
175 #ifdef UNDER_CE
176     SHMENUBARINFO mbi;
177     memset( &mbi, 0, sizeof(SHMENUBARINFO) );
178     mbi.cbSize     = sizeof(SHMENUBARINFO);
179     mbi.hwndParent = hwnd;
180     mbi.hInstRes   = hInst;
181     mbi.nToolBarId = IDR_MENUBAR;
182
183     if( !SHCreateMenuBar( &mbi ) )
184     {
185         MessageBox(hwnd, _T("SHCreateMenuBar Failed"), _T("Error"), MB_OK);
186         return 0;
187     }
188
189     TBBUTTONINFO tbbi;
190     tbbi.cbSize = sizeof(tbbi);
191     tbbi.dwMask = TBIF_LPARAM;
192
193     SendMessage( mbi.hwndMB, TB_GETBUTTONINFO, IDM_FILE, (LPARAM)&tbbi );
194     menu_file = (HMENU)tbbi.lParam;
195     RemoveMenu( menu_file, 0, MF_BYPOSITION );
196     SendMessage( mbi.hwndMB, TB_GETBUTTONINFO, IDM_VIEW, (LPARAM)&tbbi );
197     menu_view = (HMENU)tbbi.lParam;
198     RemoveMenu( menu_view, 0, MF_BYPOSITION );
199     SendMessage( mbi.hwndMB, TB_GETBUTTONINFO, IDM_SETTINGS, (LPARAM)&tbbi );
200     menu_settings = (HMENU)tbbi.lParam;
201     SendMessage( mbi.hwndMB, TB_GETBUTTONINFO, IDM_VIDEO, (LPARAM)&tbbi );
202     menu_video = (HMENU)tbbi.lParam;
203     SendMessage( mbi.hwndMB, TB_GETBUTTONINFO, IDM_AUDIO, (LPARAM)&tbbi );
204     menu_audio = (HMENU)tbbi.lParam;
205     SendMessage( mbi.hwndMB, TB_GETBUTTONINFO, IDM_NAVIGATION, (LPARAM)&tbbi );
206     menu_navigation = (HMENU)tbbi.lParam;
207
208 #else
209     menu_file = CreatePopupMenu();
210     menu_view = CreatePopupMenu();
211     menu_settings = CreatePopupMenu();
212     menu_audio = CreatePopupMenu();
213     menu_video = CreatePopupMenu();
214     menu_navigation = CreatePopupMenu();
215 #endif
216
217     AppendMenu( menu_file, MF_STRING, ID_FILE_QUICKOPEN,
218                 _T("Quick &Open File...") );
219     AppendMenu( menu_file, MF_SEPARATOR, 0, 0 );
220     AppendMenu( menu_file, MF_STRING, ID_FILE_OPENFILE,
221                 _T("Open &File...") );
222     AppendMenu( menu_file, MF_STRING, ID_FILE_OPENDIR,
223                 _T("Open &Directory...") );
224     AppendMenu( menu_file, MF_STRING, ID_FILE_OPENNET,
225                 _T("Open &Network Stream...") );
226     AppendMenu( menu_file, MF_SEPARATOR, 0, 0 );
227     AppendMenu( menu_file, MF_STRING, ID_FILE_ABOUT,
228                 _T("About VLC") );
229     AppendMenu( menu_file, MF_STRING, ID_FILE_EXIT,
230                 _T("E&xit") );
231
232     AppendMenu( menu_view, MF_STRING, ID_VIEW_PLAYLIST,
233                 _T("&Playlist...") );
234     AppendMenu( menu_view, MF_STRING, ID_VIEW_MESSAGES,
235                 _T("&Messages...") );
236     AppendMenu( menu_view, MF_STRING, ID_VIEW_STREAMINFO,
237                 _T("Stream and Media &info...") );
238
239     AppendMenu( menu_settings, MF_STRING, ID_PREFERENCES,
240                 _T("&Preferences...") );
241
242
243 #ifdef UNDER_CE
244     return mbi.hwndMB;
245
246 #else
247     HMENU hmenu = CreateMenu();
248
249     AppendMenu( hmenu, MF_POPUP|MF_STRING, (UINT)menu_file, _T("File") );
250     AppendMenu( hmenu, MF_POPUP|MF_STRING, (UINT)menu_view, _T("View") );
251     AppendMenu( hmenu, MF_POPUP|MF_STRING, (UINT)menu_settings,
252                 _T("Settings") );
253     AppendMenu( hmenu, MF_POPUP|MF_STRING, (UINT)menu_audio, _T("Audio") );
254     AppendMenu( hmenu, MF_POPUP|MF_STRING, (UINT)menu_video, _T("Video") );
255     AppendMenu( hmenu, MF_POPUP|MF_STRING, (UINT)menu_navigation, _T("Nav") );
256
257     SetMenu( hwnd, hmenu );
258     return 0;
259
260 #endif
261 }
262
263 /***********************************************************************
264 FUNCTION: 
265   CreateToolBar
266
267 PURPOSE: 
268   Registers the TOOLBAR control class and creates a toolbar.
269 ***********************************************************************/
270 HWND CreateToolBar( HWND hwnd, HINSTANCE hInst )
271 {
272     DWORD dwStyle;
273     HWND hwndTB;
274     RECT rect, rectTB;
275
276     INITCOMMONCONTROLSEX iccex;
277     iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
278     iccex.dwICC = ICC_BAR_CLASSES;
279
280     // Registers TOOLBAR control classes from the common control dll
281     InitCommonControlsEx (&iccex);
282
283     //  Create the toolbar control
284     dwStyle = WS_VISIBLE | WS_CHILD | TBSTYLE_TOOLTIPS |
285         WS_EX_OVERLAPPEDWINDOW | CCS_NOPARENTALIGN;
286
287     hwndTB = CreateToolbarEx( hwnd, dwStyle, 0, NUMIMAGES,
288         hInst, IDB_BITMAP1, tbButton, sizeof(tbButton) / sizeof(TBBUTTON),
289         BUTTONWIDTH, BUTTONHEIGHT, IMAGEWIDTH, IMAGEHEIGHT, sizeof(TBBUTTON) );
290
291     if( !hwndTB ) return NULL;
292   
293     // Add ToolTips to the toolbar.
294     SendMessage( hwndTB, TB_SETTOOLTIPS, (WPARAM)NUMIMAGES, 
295                  (LPARAM)szToolTips );
296
297     // Reposition the toolbar.
298     GetClientRect( hwnd, &rect );
299     GetWindowRect( hwndTB, &rectTB );
300     MoveWindow( hwndTB, rect.left, rect.bottom - rect.top - 2*MENU_HEIGHT, 
301                 rect.right - rect.left, MENU_HEIGHT, TRUE );
302
303     return hwndTB;
304 }
305
306 /***********************************************************************
307
308 FUNCTION: 
309   CreateSliderBar
310
311 PURPOSE: 
312   Registers the TRACKBAR_CLASS control class and creates a trackbar.
313
314 ***********************************************************************/
315 HWND CreateSliderBar( HWND hwnd, HINSTANCE hInst )
316 {
317     HWND hwndSlider;
318     RECT rect;
319
320     INITCOMMONCONTROLSEX iccex;
321     iccex.dwSize = sizeof( INITCOMMONCONTROLSEX );
322     iccex.dwICC = ICC_BAR_CLASSES;
323
324     // Registers TRACKBAR_CLASS control classes from the common control dll
325     InitCommonControlsEx( &iccex );
326
327     hwndSlider = CreateWindowEx( 0, TRACKBAR_CLASS, NULL,
328                 WS_CHILD | WS_VISIBLE | TBS_HORZ | WS_EX_OVERLAPPEDWINDOW |
329                 TBS_BOTTOM,  //|WS_CLIPSIBLINGS,
330                 0, 0, 0, 0, hwnd, NULL, hInst, NULL );
331
332     if( !hwndSlider ) return NULL;
333
334     SendMessage( hwndSlider, TBM_SETRANGEMIN, 1, 0 );
335     SendMessage( hwndSlider, TBM_SETRANGEMAX, 1, SLIDER_MAX_POS );
336     SendMessage( hwndSlider, TBM_SETPOS, 1, 0 );
337
338     // Reposition the trackbar
339     GetClientRect( hwnd, &rect );
340     MoveWindow( hwndSlider, rect.left, 
341                 rect.bottom - rect.top - 2*(MENU_HEIGHT-1) - SLIDER_HEIGHT, 
342                 rect.right - rect.left - 40, 30, TRUE );
343
344     ShowWindow( hwndSlider, SW_HIDE );
345
346     return hwndSlider;
347 }
348
349 HWND CreateStaticText( HWND hwnd, HINSTANCE hInst )
350 {
351     HWND hwndLabel;
352     RECT rect;
353
354     hwndLabel = CreateWindowEx( 0, _T("STATIC"), _T("label"),
355                                 WS_CHILD | WS_VISIBLE | SS_CENTER ,
356                                 0, 0, 0, 0, hwnd, (HMENU)1980, hInst, NULL );
357
358     // Reposition the trackbar
359     GetClientRect( hwnd, &rect );
360
361     MoveWindow( hwndLabel, rect.left,
362                 rect.bottom - rect.top - 2*(MENU_HEIGHT-1) - SLIDER_HEIGHT +30,
363                 rect.right - rect.left - 40,
364                 SLIDER_HEIGHT - 30, TRUE );
365
366     ShowWindow( hwndLabel, SW_HIDE );
367
368     return hwndLabel;
369 }
370
371 /***********************************************************************
372
373 FUNCTION: 
374   CreateVolTrackBar
375
376 PURPOSE: 
377   Registers the TRACKBAR_CLASS control class and creates a trackbar.
378
379 ***********************************************************************/
380 HWND CreateVolTrackBar( HWND hwnd, HINSTANCE hInst )
381 {
382     HWND hwndVol;
383     RECT rect;
384
385     INITCOMMONCONTROLSEX iccex;
386     iccex.dwSize = sizeof( INITCOMMONCONTROLSEX );
387     iccex.dwICC = ICC_BAR_CLASSES;
388
389     // Registers TRACKBAR_CLASS control classes from the common control dll
390     InitCommonControlsEx( &iccex );
391
392     hwndVol = CreateWindowEx( 0, TRACKBAR_CLASS, NULL,
393                 WS_CHILD | WS_VISIBLE | TBS_VERT | TBS_RIGHT | TBS_AUTOTICKS |
394                 WS_EX_OVERLAPPEDWINDOW, //|WS_CLIPSIBLINGS,
395                 0, 0, 0, 0, hwnd, NULL, hInst, NULL );
396
397     if( !hwndVol ) return NULL;
398
399     SendMessage( hwndVol, TBM_SETRANGEMIN, 1, 0 );
400     SendMessage( hwndVol, TBM_SETRANGEMAX, 1, 200 );
401     SendMessage( hwndVol, TBM_SETPOS, 1, 100 );
402     SendMessage( hwndVol, TBM_SETTICFREQ, 50, 0 );  
403
404     // Reposition the trackbar
405     GetClientRect( hwnd, &rect );
406     MoveWindow( hwndVol, rect.right - rect.left - 40, 
407                 rect.bottom - rect.top - 2*(MENU_HEIGHT-1) - SLIDER_HEIGHT, 
408                 40, SLIDER_HEIGHT, TRUE );
409
410     ShowWindow( hwndVol, SW_HIDE );
411
412     return hwndVol;
413 }
414
415 /***********************************************************************
416
417 FUNCTION: 
418   CreateStatusBar
419
420 PURPOSE: 
421   Registers the StatusBar control class and creates a Statusbar.
422
423 ***********************************************************************/
424 HWND CreateStatusBar( HWND hwnd, HINSTANCE hInst )
425 {
426     DWORD dwStyle;
427     HWND hwndSB;
428     RECT rect;
429
430     INITCOMMONCONTROLSEX iccex;
431     iccex.dwSize = sizeof (INITCOMMONCONTROLSEX);
432     iccex.dwICC = ICC_BAR_CLASSES;
433
434     // Registers Statusbar control classes from the common control dll
435     InitCommonControlsEx( &iccex );
436
437     // Create the statusbar control
438     dwStyle = WS_VISIBLE | WS_CHILD | TBSTYLE_TOOLTIPS | CCS_NOPARENTALIGN;
439
440     hwndSB = CreateWindowEx( 0, STATUSCLASSNAME, NULL,
441                              WS_CHILD | WS_VISIBLE | TBS_VERT | TBS_BOTTOM |
442                              TBS_RIGHT  |WS_CLIPSIBLINGS,
443                              0, 0, CW_USEDEFAULT, 50, hwnd, NULL, hInst, 0 );
444
445     if (!hwndSB ) return NULL;
446
447     // Get the coordinates of the parent window's client area. 
448     GetClientRect( hwnd, &rect );
449
450     // allocate memory for the panes of status bar
451     int nopanes = 2;
452     int *indicators = new int[nopanes];
453
454     // set width for the panes
455     indicators[0] = 3 * ( rect.right - rect.left ) / 4;
456     indicators[1] = rect.right - rect.left;
457
458     // call functions to set style
459     SendMessage( hwndSB, SB_SETPARTS, (WPARAM)nopanes, (LPARAM)indicators );
460
461     return hwndSB;
462 }
463
464 /***********************************************************************
465 FUNCTION:
466   CreateDialogBox
467
468 PURPOSE:
469   Creates a Dialog Box.
470 ***********************************************************************/
471 int CBaseWindow::CreateDialogBox( HWND hwnd, CBaseWindow *p_obj )
472 {
473     uint8_t p_buffer[sizeof(DLGTEMPLATE) + sizeof(WORD) * 4];
474     DLGTEMPLATE *p_dlg_template = (DLGTEMPLATE *)p_buffer;
475     memset( p_dlg_template, 0, sizeof(DLGTEMPLATE) + sizeof(WORD) * 4 );
476
477     // these values are arbitrary, they won't be used normally anyhow
478     p_dlg_template->x  = 0; p_dlg_template->y  = 0;
479     p_dlg_template->cx = 300; p_dlg_template->cy = 300;
480     p_dlg_template->style =
481         DS_MODALFRAME|WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_SIZEBOX;
482
483     return DialogBoxIndirectParam( GetModuleHandle(0), p_dlg_template, hwnd,
484                                    (DLGPROC)p_obj->BaseWndProc, (LPARAM)p_obj );
485 }
486
487 /***********************************************************************
488 FUNCTION: 
489   BaseWndProc
490
491 PURPOSE: 
492   Processes messages sent to the main window.
493 ***********************************************************************/
494 LRESULT CALLBACK CBaseWindow::BaseWndProc( HWND hwnd, UINT msg, WPARAM wParam,
495                                            LPARAM lParam )
496 {
497     CBaseWindow *p_obj;
498
499     // check to see if a copy of the 'this' pointer needs to be saved
500     if( msg == WM_CREATE )
501     {
502         p_obj = (CBaseWindow *)(((LPCREATESTRUCT)lParam)->lpCreateParams);
503         SetWindowLong( hwnd, GWL_USERDATA,
504                        (LONG)((LPCREATESTRUCT)lParam)->lpCreateParams );
505
506         p_obj->hWnd = hwnd;
507     }
508
509     if( msg == WM_INITDIALOG )
510     {
511         p_obj = (CBaseWindow *)lParam;
512         SetWindowLong( hwnd, GWL_USERDATA, lParam );
513         p_obj->hWnd = hwnd;
514     }
515
516     // Retrieve the pointer
517     p_obj = (CBaseWindow *)GetWindowLong( hwnd, GWL_USERDATA );
518
519     if( !p_obj ) return DefWindowProc( hwnd, msg, wParam, lParam );
520
521     // Filter message through child classes
522     return p_obj->WndProc( hwnd, msg, wParam, lParam );
523 }
524
525 /***********************************************************************
526 FUNCTION: 
527   WndProc
528
529 PURPOSE: 
530   Processes messages sent to the main window.
531 ***********************************************************************/
532 LRESULT Interface::WndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
533 {
534     switch( msg )
535     {
536     case WM_CREATE:
537         hwndCB = CreateMenuBar( hwnd, hInst );
538         hwndTB = CreateToolBar( hwnd, hInst );
539         hwndSlider = CreateSliderBar( hwnd, hInst );
540         hwndLabel = CreateStaticText( hwnd, hInst );
541         hwndVol = CreateVolTrackBar( hwnd, hInst );
542 #ifdef UNDER_CE
543         hwndSB = CreateStatusBar( hwnd, hInst );
544 #endif
545
546         /* Video window */
547         if( config_GetInt( p_intf, "wince-embed" ) )
548             video = CreateVideoWindow( p_intf, hwnd );
549
550         timer = new Timer( p_intf, hwnd, this );
551
552         // Hide the SIP button (WINCE only)
553         SetForegroundWindow( hwnd );
554         SHFullScreen( GetForegroundWindow(), SHFS_HIDESIPBUTTON );
555         break;
556
557     case WM_COMMAND:
558         switch( GET_WM_COMMAND_ID(wp,lp) )
559         {
560         case ID_FILE_QUICKOPEN: 
561             OnOpenFileSimple();
562             break;
563
564         case ID_FILE_OPENFILE: 
565             open = new OpenDialog( p_intf, hInst, FILE_ACCESS,
566                                    ID_FILE_OPENFILE, OPEN_NORMAL );
567             CreateDialogBox( hwnd, open );
568             delete open;
569             break;
570
571         case ID_FILE_OPENDIR:
572             OnOpenDirectory();
573             break;
574
575         case ID_FILE_OPENNET:
576             open = new OpenDialog( p_intf, hInst, NET_ACCESS, ID_FILE_OPENNET,
577                                    OPEN_NORMAL );
578             CreateDialogBox( hwnd, open );
579             delete open;
580             break;
581
582         case PlayStream_Event: 
583             OnPlayStream();
584             break;
585
586         case StopStream_Event: 
587             OnStopStream();
588             break;
589
590         case PrevStream_Event: 
591             OnPrevStream();
592             break;
593
594         case NextStream_Event: 
595             OnNextStream();
596             break;
597
598         case SlowStream_Event: 
599             OnSlowStream();
600             break;
601
602         case FastStream_Event: 
603             OnFastStream();
604             break;
605
606         case ID_FILE_ABOUT: 
607         {
608             string about = (string)"VLC media player " PACKAGE_VERSION +
609                 _("\n(WinCE interface)\n\n") +
610                 _("(c) 1996-2005 - the VideoLAN Team\n\n") +
611                 _("The VideoLAN team <videolan@videolan.org>\n"
612                   "http://www.videolan.org/\n\n");
613
614             MessageBox( hwnd, _FROMMB(about.c_str()),
615                         _T("About VLC media player"), MB_OK );
616             break;
617         }
618
619         case ID_FILE_EXIT:
620             SendMessage( hwnd, WM_CLOSE, 0, 0 );
621             break;
622
623         case ID_VIEW_STREAMINFO:
624             fileinfo = new FileInfo( p_intf, hInst );
625             CreateDialogBox( hwnd, fileinfo );
626             delete fileinfo;
627             break;
628
629         case ID_VIEW_MESSAGES:
630             messages = new Messages( p_intf, hInst );
631             CreateDialogBox( hwnd, messages );
632             delete messages;
633             break;
634
635         case ID_VIEW_PLAYLIST:
636             playlist = new Playlist( p_intf, hInst );
637             CreateDialogBox( hwnd, playlist );
638             delete playlist;
639             break;
640
641         case ID_PREFERENCES:
642             preferences = new PrefsDialog( p_intf, hInst );
643             CreateDialogBox( hwnd, preferences );
644             delete preferences;
645             break;
646                   
647         default:
648             OnMenuEvent( p_intf, GET_WM_COMMAND_ID(wp,lp) );
649             // we should test if it is a menu command
650         }
651         break;
652   
653     case WM_TIMER:
654         timer->Notify();
655         break;
656
657     case WM_CTLCOLORSTATIC: 
658         if( ( (HWND)lp == hwndSlider ) || ( (HWND)lp == hwndVol ) )
659         { 
660             return( (LRESULT)::GetSysColorBrush(COLOR_3DFACE) ); 
661         }
662         if( (HWND)lp == hwndLabel )
663         {
664             SetBkColor( (HDC)wp, RGB (192, 192, 192) ); 
665             return( (LRESULT)::GetSysColorBrush(COLOR_3DFACE) ); 
666         }
667         break;
668
669     case WM_HSCROLL:
670         if( (HWND)lp == hwndSlider ) OnSliderUpdate( wp );
671         break;
672
673     case WM_VSCROLL:
674         if( (HWND)lp == hwndVol ) OnChange( wp );
675         break;
676
677     case WM_INITMENUPOPUP:
678         if( (HMENU)wp == menu_settings )
679             RefreshSettingsMenu( p_intf, menu_settings );
680         if( (HMENU)wp == menu_audio )
681             RefreshAudioMenu( p_intf, menu_audio );
682         if( (HMENU)wp == menu_video )
683             RefreshVideoMenu( p_intf, menu_video );
684         if( (HMENU)wp == menu_navigation )
685             RefreshNavigMenu( p_intf, menu_navigation );
686         /* Fall through */
687
688     case WM_ENTERMENULOOP:
689     case WM_KILLFOCUS:
690         if( video && video->hWnd )
691             SendMessage( video->hWnd, WM_KILLFOCUS, 0, 0 );
692         break;
693
694     case WM_EXITMENULOOP:
695     case WM_SETFOCUS:
696         if( video && video->hWnd )
697             SendMessage( video->hWnd, WM_SETFOCUS, 0, 0 );
698         break;
699
700     case WM_LBUTTONDOWN:
701         {
702             SHRGINFO shrg;
703             shrg.cbSize = sizeof( shrg );
704             shrg.hwndClient = hwnd;
705             shrg.ptDown.x = LOWORD(lp);
706             shrg.ptDown.y = HIWORD(lp);
707             shrg.dwFlags = SHRG_RETURNCMD ;
708
709             if( SHRecognizeGesture( &shrg ) == GN_CONTEXTMENU )
710                 PopupMenu( p_intf, hwnd, shrg.ptDown );
711         }
712         break;
713
714    case WM_RBUTTONUP:
715         {
716             POINT point;
717             point.x = LOWORD(lp);
718             point.y = HIWORD(lp);
719             PopupMenu( p_intf, hwnd, point );
720         }
721         break;
722
723     case WM_HELP:
724         MessageBox (hwnd, _T("Help"), _T("Help"), MB_OK);
725         break;
726
727     case WM_CLOSE:
728         if( hwndCB ) DestroyWindow( hwndCB );
729         DestroyWindow( hwnd );
730         break;
731
732     case WM_DESTROY:
733         PostQuitMessage( 0 );
734         break;
735     }
736
737     return DefWindowProc( hwnd, msg, wp, lp );
738 }
739
740 void Interface::OnOpenFileSimple( void )
741 {
742     OPENFILENAME ofn;
743     TCHAR DateiName[80+1] = _T("\0");
744     static TCHAR szFilter[] = _T("All (*.*)\0*.*\0");
745
746     playlist_t *p_playlist = (playlist_t *)
747         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
748     if( p_playlist == NULL ) return;
749
750     memset( &ofn, 0, sizeof(OPENFILENAME) );
751     ofn.lStructSize = sizeof(OPENFILENAME);
752     ofn.hwndOwner = hwndMain;
753     ofn.hInstance = hInst;
754     ofn.lpstrFilter = szFilter;
755     ofn.lpstrCustomFilter = NULL;
756     ofn.nMaxCustFilter = 0;
757     ofn.nFilterIndex = 1;     
758     ofn.lpstrFile = (LPTSTR)DateiName; 
759     ofn.nMaxFile = 80;
760     ofn.lpstrFileTitle = NULL; 
761     ofn.nMaxFileTitle = 40;
762     ofn.lpstrInitialDir = NULL;
763     ofn.lpstrTitle = _T("Quick Open File");
764     ofn.Flags = 0; 
765     ofn.nFileOffset = 0;
766     ofn.nFileExtension = 0;
767     ofn.lpstrDefExt = NULL;
768     ofn.lCustData = 0L;
769     ofn.lpfnHook = NULL;
770     ofn.lpTemplateName = NULL;
771
772     SHFullScreen( GetForegroundWindow(), SHFS_HIDESIPBUTTON );
773
774     if( GetOpenFile( &ofn ) )
775     {
776         char *psz_filename = _TOMB(ofn.lpstrFile);
777         playlist_Add( p_playlist, psz_filename, psz_filename,
778                       PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
779     }
780
781     vlc_object_release( p_playlist );
782 }
783
784 void Interface::OnOpenDirectory( void )
785 {
786     TCHAR psz_result[MAX_PATH];
787     LPMALLOC p_malloc = 0;
788     LPITEMIDLIST pidl;
789     BROWSEINFO bi;
790     playlist_t *p_playlist = 0;
791
792 #ifdef UNDER_CE
793 #   define SHGetMalloc MySHGetMalloc
794 #   define SHBrowseForFolder MySHBrowseForFolder
795 #   define SHGetPathFromIDList MySHGetPathFromIDList
796
797     HMODULE ceshell_dll = LoadLibrary( _T("ceshell") );
798     if( !ceshell_dll ) return;
799
800     HRESULT WINAPI (*SHGetMalloc)(LPMALLOC *) =
801         (HRESULT WINAPI (*)(LPMALLOC *))
802         GetProcAddress( ceshell_dll, _T("SHGetMalloc") );
803     LPITEMIDLIST WINAPI (*SHBrowseForFolder)(LPBROWSEINFO) =
804         (LPITEMIDLIST WINAPI (*)(LPBROWSEINFO))
805         GetProcAddress( ceshell_dll, _T("SHBrowseForFolder") );
806     BOOL WINAPI (*SHGetPathFromIDList)(LPCITEMIDLIST, LPTSTR) =
807         (BOOL WINAPI (*)(LPCITEMIDLIST, LPTSTR))
808         GetProcAddress( ceshell_dll, _T("SHGetPathFromIDList") );
809
810     if( !SHGetMalloc || !SHBrowseForFolder || !SHGetPathFromIDList )
811     {
812         msg_Err( p_intf, "couldn't load SHBrowseForFolder API" );
813         FreeLibrary( ceshell_dll );
814         return;
815     }
816 #endif
817
818     if( !SUCCEEDED( SHGetMalloc(&p_malloc) ) ) goto error;
819
820     p_playlist = (playlist_t *)
821         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
822     if( !p_playlist ) goto error;
823
824     memset( &bi, 0, sizeof(BROWSEINFO) );
825     bi.hwndOwner = hwndMain;
826     bi.pszDisplayName = psz_result;
827     bi.ulFlags = BIF_EDITBOX;
828 #ifndef UNDER_CE
829     bi.ulFlags |= BIF_USENEWUI;
830 #endif
831
832     if( (pidl = SHBrowseForFolder( &bi ) ) )
833     {
834         if( SHGetPathFromIDList( pidl, psz_result ) )
835         {
836             char *psz_filename = _TOMB(psz_result);
837             playlist_Add( p_playlist, psz_filename, psz_filename,
838                           PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
839         }
840         p_malloc->Free( pidl );
841     }
842
843  error:
844
845     if( p_malloc) p_malloc->Release();
846     if( p_playlist ) vlc_object_release( p_playlist );
847
848 #ifdef UNDER_CE
849     FreeLibrary( ceshell_dll );
850 #endif
851 }
852
853 void Interface::OnPlayStream( void )
854 {
855     playlist_t *p_playlist = (playlist_t *)
856         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
857     if( p_playlist == NULL ) return;
858
859     if( p_playlist->i_size && p_playlist->i_enabled )
860     {
861         vlc_value_t state;
862
863         input_thread_t *p_input = (input_thread_t *)
864             vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );
865
866         if( p_input == NULL )
867         {
868             /* No stream was playing, start one */
869             playlist_Play( p_playlist );
870             TogglePlayButton( PLAYING_S );
871             vlc_object_release( p_playlist );
872             return;
873         }
874
875         var_Get( p_input, "state", &state );
876
877         if( state.i_int != PAUSE_S )
878         {
879             /* A stream is being played, pause it */
880             state.i_int = PAUSE_S;
881         }
882         else
883         {
884             /* Stream is paused, resume it */
885             state.i_int = PLAYING_S;
886         }
887         var_Set( p_input, "state", state );
888
889         TogglePlayButton( state.i_int );
890         vlc_object_release( p_input );
891         vlc_object_release( p_playlist );
892     }
893     else
894     {
895         /* If the playlist is empty, open a file requester instead */
896         vlc_object_release( p_playlist );
897         OnOpenFileSimple();
898     }
899 }
900
901 void Interface::TogglePlayButton( int i_playing_status )
902 {
903     TBREPLACEBITMAP tbrb;
904     tbrb.hInstOld = tbrb.hInstNew = (HINSTANCE) hInst;
905     tbrb.nButtons = NUMIMAGES;
906
907     if( i_playing_status == i_old_playing_status ) return;
908
909     if( i_playing_status == PLAYING_S )
910     {
911         tbrb.nIDOld = IDB_BITMAP2;
912         tbrb.nIDNew = IDB_BITMAP1;
913
914         SendMessage( hwndTB, TB_REPLACEBITMAP, (WPARAM)0,
915                      (LPARAM)(LPTBREPLACEBITMAP)&tbrb );
916     }
917     else
918     {
919         tbrb.nIDOld = IDB_BITMAP1;
920         tbrb.nIDNew = IDB_BITMAP2;
921
922         SendMessage( hwndTB, TB_REPLACEBITMAP, (WPARAM)0,
923                      (LPARAM)(LPTBREPLACEBITMAP)&tbrb );
924     }
925
926     UpdateWindow( hwndTB );
927
928     i_old_playing_status = i_playing_status;
929 }
930
931 void Interface::OnVideoOnTop( void )
932 {
933     vlc_value_t val;
934
935     vout_thread_t *p_vout = (vout_thread_t *)
936         vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
937
938     if( p_vout == NULL ) return;
939
940     if( var_Get( (vlc_object_t *)p_vout, "video-on-top", &val ) < 0 )
941         return;
942
943     val.b_bool = !val.b_bool;
944     var_Set( (vlc_object_t *)p_vout, "video-on-top", val );
945
946     vlc_object_release( (vlc_object_t *)p_vout );
947 }
948
949 void Interface::OnSliderUpdate( int wp )
950 {
951     vlc_mutex_lock( &p_intf->change_lock );
952     input_thread_t *p_input = p_intf->p_sys->p_input;
953
954     int dwPos = SendMessage( hwndSlider, TBM_GETPOS, 0, 0 ); 
955
956     if( (int)LOWORD(wp) == SB_THUMBPOSITION ||
957         (int)LOWORD(wp) == SB_ENDSCROLL )
958     {
959         if( p_intf->p_sys->i_slider_pos != dwPos && p_input )
960         {
961             vlc_value_t pos;
962             pos.f_float = (float)dwPos / (float)SLIDER_MAX_POS;
963             var_Set( p_input, "position", pos );
964         }
965
966         p_intf->p_sys->b_slider_free = VLC_TRUE;
967     }
968     else
969     {
970         p_intf->p_sys->b_slider_free = VLC_FALSE;
971
972         if( p_input )
973         {
974             /* Update stream date */
975             char psz_time[ MSTRTIME_MAX_SIZE ], psz_total[ MSTRTIME_MAX_SIZE ];
976             mtime_t i_seconds;
977
978             i_seconds = var_GetTime( p_input, "length" ) / I64C(1000000 );
979             secstotimestr( psz_total, i_seconds );
980
981             i_seconds = var_GetTime( p_input, "time" ) / I64C(1000000 );
982             secstotimestr( psz_time, i_seconds );
983
984             SendMessage( hwndLabel, WM_SETTEXT, (WPARAM)1,
985                          (LPARAM)_FROMMB(psz_time) );
986         }
987     }
988
989     vlc_mutex_unlock( &p_intf->change_lock );
990 }
991
992 void Interface::OnChange( int wp )
993 {
994     DWORD dwPos = SendMessage( hwndVol, TBM_GETPOS, 0, 0 );
995
996     if( LOWORD(wp) == SB_THUMBPOSITION || LOWORD(wp) == SB_ENDSCROLL )
997     {
998         VolumeChange( 200 - (int)dwPos );
999         b_volume_hold = VLC_FALSE;
1000     }
1001     else
1002     {
1003         b_volume_hold = VLC_TRUE;
1004     }
1005 }
1006
1007 void Interface::VolumeChange( int i_volume )
1008 {
1009     aout_VolumeSet( p_intf, i_volume * AOUT_VOLUME_MAX / 200 / 2 );
1010 }
1011
1012 void Interface::VolumeUpdate()
1013 {
1014     audio_volume_t i_volume;
1015
1016     if( b_volume_hold ) return;
1017
1018     aout_VolumeGet( p_intf, &i_volume );
1019
1020     int i_volume_ctrl = 200 - i_volume * 200 * 2 / AOUT_VOLUME_MAX;
1021
1022     DWORD dwPos = SendMessage( hwndVol, TBM_GETPOS, 0, 0 );
1023     if( i_volume_ctrl == (int)dwPos ) return;
1024
1025     SendMessage( hwndVol, TBM_SETPOS, 1, i_volume_ctrl );
1026 }
1027
1028 void Interface::OnStopStream( void )
1029 {
1030     playlist_t * p_playlist = (playlist_t *)
1031         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
1032     if( p_playlist == NULL ) return;
1033
1034     playlist_Stop( p_playlist );
1035     TogglePlayButton( PAUSE_S );
1036     vlc_object_release( p_playlist );
1037 }
1038
1039 void Interface::OnPrevStream( void )
1040 {
1041     playlist_t * p_playlist = (playlist_t *)
1042         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
1043     if( p_playlist == NULL ) return;
1044
1045     playlist_Prev( p_playlist );
1046     vlc_object_release( p_playlist );
1047 }
1048
1049 void Interface::OnNextStream( void )
1050 {
1051     playlist_t * p_playlist = (playlist_t *)
1052         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
1053     if( p_playlist == NULL ) return;
1054
1055     playlist_Next( p_playlist );
1056     vlc_object_release( p_playlist );
1057 }
1058
1059 void Interface::OnSlowStream( void )
1060 {
1061     input_thread_t *p_input = (input_thread_t *)
1062         vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );
1063
1064     if( p_input == NULL ) return;
1065
1066     vlc_value_t val; val.b_bool = VLC_TRUE;
1067     var_Set( p_input, "rate-slower", val );
1068     vlc_object_release( p_input );
1069 }
1070
1071 void Interface::OnFastStream( void )
1072 {
1073     input_thread_t *p_input = (input_thread_t *)
1074         vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );
1075
1076     if( p_input == NULL ) return;
1077
1078     vlc_value_t val; val.b_bool = VLC_TRUE;
1079     var_Set( p_input, "rate-faster", val );
1080     vlc_object_release( p_input );
1081 }
1082
1083 void Interface::Update()
1084 {
1085     /* Misc updates */
1086     VolumeUpdate();
1087 }