* modules/gui/wince: added dialogs provider + another massive cleanup + updates.
[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 <windowsx.h>
37 #include <commctrl.h>
38 #include <commdlg.h>
39
40 #define NUMIMAGES     9   // Number of buttons in the toolbar           
41 #define IMAGEWIDTH    17   // Width of the buttons in the toolbar  
42 #define IMAGEHEIGHT   16   // Height of the buttons in the toolbar  
43 #define BUTTONWIDTH   0    // Width of the button images in the toolbar
44 #define BUTTONHEIGHT  0    // Height of the button images in the toolbar
45 #define ID_TOOLBAR    2000 // Identifier of the main tool bar
46
47 // Help strings
48 #define HELP_SIMPLE _T("Quick file open")
49 #define HELP_ADV    _T("Advanced open")
50 #define HELP_FILE   _T("Open a file")
51 #define HELP_DISC   _T("Open Disc Media")
52 #define HELP_NET    _T("Open a network stream")
53 #define HELP_SAT    _T("Open a satellite stream")
54 #define HELP_EJECT  _T("Eject the DVD/CD")
55 #define HELP_EXIT   _T("Exit this program")
56
57 #define HELP_OTHER _T("Open other types of inputs")
58
59 #define HELP_PLAYLIST   _T("Open the playlist")
60 #define HELP_LOGS       _T("Show the program logs")
61 #define HELP_FILEINFO   _T("Show information about the file being played")
62
63 #define HELP_PREFS _T("Go to the preferences menu")
64
65 #define HELP_ABOUT _T("About this program")
66
67 #define HELP_STOP _T("Stop")
68
69 #define HELP_PLAY _T("Play")
70 #define HELP_PAUSE _T("Pause")
71 #define HELP_PLO _T("Playlist")
72 #define HELP_PLP _T("Previous playlist item")
73 #define HELP_PLN _T("Next playlist item")
74 #define HELP_SLOW _T("Play slower")
75 #define HELP_FAST _T("Play faster")
76
77 // The TBBUTTON structure contains information the toolbar buttons.
78 static TBBUTTON tbButton[] =      
79 {
80   {0, ID_FILE_QUICKOPEN,        TBSTATE_ENABLED, TBSTYLE_BUTTON},
81   {1, ID_FILE_OPENNET,       TBSTATE_ENABLED, TBSTYLE_BUTTON},
82   {0, 0,              TBSTATE_ENABLED, TBSTYLE_SEP},
83   {2, StopStream_Event,       TBSTATE_ENABLED, TBSTYLE_BUTTON},
84   {3, PlayStream_Event,        TBSTATE_ENABLED, TBSTYLE_BUTTON},
85   {0, 0,              TBSTATE_ENABLED, TBSTYLE_SEP},
86   {4, ID_VIEW_PLAYLIST,       TBSTATE_ENABLED, TBSTYLE_BUTTON},
87   {0, 0,              TBSTATE_ENABLED, TBSTYLE_SEP},
88   {5, PrevStream_Event,      TBSTATE_ENABLED, TBSTYLE_BUTTON},
89   {6, NextStream_Event,      TBSTATE_ENABLED, TBSTYLE_BUTTON},
90   {0, 0,              TBSTATE_ENABLED, TBSTYLE_SEP},
91   {7, SlowStream_Event,      TBSTATE_ENABLED, TBSTYLE_BUTTON},
92   {8, FastStream_Event,       TBSTATE_ENABLED, TBSTYLE_BUTTON},
93 };
94
95 // Toolbar ToolTips
96 TCHAR * szToolTips[] = 
97 {
98     HELP_SIMPLE, HELP_NET, HELP_STOP, HELP_PLAY, HELP_PLO, HELP_PLP,
99     HELP_PLN, HELP_SLOW, HELP_FAST
100 };
101
102 /*****************************************************************************
103  * Constructor.
104  *****************************************************************************/
105 Interface::Interface()
106   : hwndMain(0), hwndCB(0), hwndTB(0), hwndSlider(0), hwndLabel(0),
107     hwndVol(0), hwndSB(0), timer(0), video(0), b_volume_hold(0)
108 {
109 }
110
111 Interface::~Interface()
112 {
113     if( timer ) delete timer;
114     if( video ) delete video;
115 }
116
117 BOOL Interface::InitInstance( HINSTANCE hInstance, intf_thread_t *_p_intf )
118 {
119     /* Initializations */
120     p_intf = _p_intf;
121     i_old_playing_status = PAUSE_S;
122
123     hInst = hInstance; // Store instance handle in our global variable
124
125     int i_style = WS_VISIBLE;
126
127 #ifndef UNDER_CE
128     i_style |= WS_OVERLAPPEDWINDOW | WS_SIZEBOX;
129 #endif
130
131     // Create main window
132     hwndMain =
133         CreateWindow( _T("VLC WinCE"), _T("VLC media player"), i_style,
134                       0, MENU_HEIGHT, CW_USEDEFAULT, CW_USEDEFAULT,
135                       NULL, NULL, hInstance, (void *)this );
136
137     if( !hwndMain ) return FALSE;
138
139     ShowWindow( hwndMain, TRUE );
140     UpdateWindow( hwndMain );
141
142     return TRUE;
143 }
144
145 /***********************************************************************
146 FUNCTION: 
147   CreateMenuBar
148
149 PURPOSE: 
150   Creates a menu bar.
151 ***********************************************************************/
152 HWND Interface::CreateMenuBar( HWND hwnd, HINSTANCE hInst )
153 {
154     HMENU menu_file, menu_view;
155
156 #ifdef UNDER_CE
157     SHMENUBARINFO mbi;
158     memset( &mbi, 0, sizeof(SHMENUBARINFO) );
159     mbi.cbSize     = sizeof(SHMENUBARINFO);
160     mbi.hwndParent = hwnd;
161     mbi.hInstRes   = hInst;
162     mbi.nToolBarId = IDR_MENUBAR;
163
164     if( !SHCreateMenuBar( &mbi ) )
165     {
166         MessageBox(hwnd, _T("SHCreateMenuBar Failed"), _T("Error"), MB_OK);
167         return 0;
168     }
169
170     TBBUTTONINFO tbbi;
171     tbbi.cbSize = sizeof(tbbi);
172     tbbi.dwMask = TBIF_LPARAM;
173
174     SendMessage( mbi.hwndMB, TB_GETBUTTONINFO, IDM_FILE, (LPARAM)&tbbi );
175     menu_file = (HMENU)tbbi.lParam;
176     RemoveMenu( menu_file, 0, MF_BYPOSITION );
177     SendMessage( mbi.hwndMB, TB_GETBUTTONINFO, IDM_VIEW, (LPARAM)&tbbi );
178     menu_view = (HMENU)tbbi.lParam;
179     RemoveMenu( menu_view, 0, MF_BYPOSITION );
180     SendMessage( mbi.hwndMB, TB_GETBUTTONINFO, IDM_SETTINGS, (LPARAM)&tbbi );
181     menu_settings = (HMENU)tbbi.lParam;
182     SendMessage( mbi.hwndMB, TB_GETBUTTONINFO, IDM_VIDEO, (LPARAM)&tbbi );
183     menu_video = (HMENU)tbbi.lParam;
184     SendMessage( mbi.hwndMB, TB_GETBUTTONINFO, IDM_AUDIO, (LPARAM)&tbbi );
185     menu_audio = (HMENU)tbbi.lParam;
186     SendMessage( mbi.hwndMB, TB_GETBUTTONINFO, IDM_NAVIGATION, (LPARAM)&tbbi );
187     menu_navigation = (HMENU)tbbi.lParam;
188
189 #else
190     menu_file = CreatePopupMenu();
191     menu_view = CreatePopupMenu();
192     menu_settings = CreatePopupMenu();
193     menu_audio = CreatePopupMenu();
194     menu_video = CreatePopupMenu();
195     menu_navigation = CreatePopupMenu();
196 #endif
197
198     AppendMenu( menu_file, MF_STRING, ID_FILE_QUICKOPEN,
199                 _T("Quick &Open File...") );
200     AppendMenu( menu_file, MF_SEPARATOR, 0, 0 );
201     AppendMenu( menu_file, MF_STRING, ID_FILE_OPENFILE,
202                 _T("Open &File...") );
203     AppendMenu( menu_file, MF_STRING, ID_FILE_OPENDIR,
204                 _T("Open &Directory...") );
205     AppendMenu( menu_file, MF_STRING, ID_FILE_OPENNET,
206                 _T("Open &Network Stream...") );
207     AppendMenu( menu_file, MF_SEPARATOR, 0, 0 );
208     AppendMenu( menu_file, MF_STRING, ID_FILE_ABOUT,
209                 _T("About VLC") );
210     AppendMenu( menu_file, MF_STRING, ID_FILE_EXIT,
211                 _T("E&xit") );
212
213     AppendMenu( menu_view, MF_STRING, ID_VIEW_PLAYLIST,
214                 _T("&Playlist...") );
215     AppendMenu( menu_view, MF_STRING, ID_VIEW_MESSAGES,
216                 _T("&Messages...") );
217     AppendMenu( menu_view, MF_STRING, ID_VIEW_STREAMINFO,
218                 _T("Stream and Media &info...") );
219
220     AppendMenu( menu_settings, MF_STRING, ID_PREFERENCES,
221                 _T("&Preferences...") );
222
223
224 #ifdef UNDER_CE
225     return mbi.hwndMB;
226
227 #else
228     HMENU hmenu = CreateMenu();
229
230     AppendMenu( hmenu, MF_POPUP|MF_STRING, (UINT)menu_file, _T("File") );
231     AppendMenu( hmenu, MF_POPUP|MF_STRING, (UINT)menu_view, _T("View") );
232     AppendMenu( hmenu, MF_POPUP|MF_STRING, (UINT)menu_settings,
233                 _T("Settings") );
234     AppendMenu( hmenu, MF_POPUP|MF_STRING, (UINT)menu_audio, _T("Audio") );
235     AppendMenu( hmenu, MF_POPUP|MF_STRING, (UINT)menu_video, _T("Video") );
236     AppendMenu( hmenu, MF_POPUP|MF_STRING, (UINT)menu_navigation, _T("Nav") );
237
238     SetMenu( hwnd, hmenu );
239     return 0;
240
241 #endif
242 }
243
244 /***********************************************************************
245 FUNCTION: 
246   CreateToolBar
247
248 PURPOSE: 
249   Registers the TOOLBAR control class and creates a toolbar.
250 ***********************************************************************/
251 HWND CreateToolBar( HWND hwnd, HINSTANCE hInst )
252 {
253     DWORD dwStyle;
254     HWND hwndTB;
255     RECT rect, rectTB;
256
257     INITCOMMONCONTROLSEX iccex;
258     iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
259     iccex.dwICC = ICC_BAR_CLASSES;
260
261     // Registers TOOLBAR control classes from the common control dll
262     InitCommonControlsEx (&iccex);
263
264     //  Create the toolbar control
265     dwStyle = WS_VISIBLE | WS_CHILD | TBSTYLE_TOOLTIPS |
266         WS_EX_OVERLAPPEDWINDOW | CCS_NOPARENTALIGN;
267
268     hwndTB = CreateToolbarEx( hwnd, dwStyle, 0, NUMIMAGES,
269         hInst, IDB_BITMAP1, tbButton, sizeof(tbButton) / sizeof(TBBUTTON),
270         BUTTONWIDTH, BUTTONHEIGHT, IMAGEWIDTH, IMAGEHEIGHT, sizeof(TBBUTTON) );
271
272     if( !hwndTB ) return NULL;
273   
274     // Add ToolTips to the toolbar.
275     SendMessage( hwndTB, TB_SETTOOLTIPS, (WPARAM)NUMIMAGES, 
276                  (LPARAM)szToolTips );
277
278     // Reposition the toolbar.
279     GetClientRect( hwnd, &rect );
280     GetWindowRect( hwndTB, &rectTB );
281     MoveWindow( hwndTB, rect.left, rect.bottom - rect.top - 2*MENU_HEIGHT, 
282                 rect.right - rect.left, MENU_HEIGHT, TRUE );
283
284     return hwndTB;
285 }
286
287 /***********************************************************************
288
289 FUNCTION: 
290   CreateSliderBar
291
292 PURPOSE: 
293   Registers the TRACKBAR_CLASS control class and creates a trackbar.
294
295 ***********************************************************************/
296 HWND CreateSliderBar( HWND hwnd, HINSTANCE hInst )
297 {
298     HWND hwndSlider;
299     RECT rect;
300
301     INITCOMMONCONTROLSEX iccex;
302     iccex.dwSize = sizeof( INITCOMMONCONTROLSEX );
303     iccex.dwICC = ICC_BAR_CLASSES;
304
305     // Registers TRACKBAR_CLASS control classes from the common control dll
306     InitCommonControlsEx( &iccex );
307
308     hwndSlider = CreateWindowEx( 0, TRACKBAR_CLASS, NULL,
309                 WS_CHILD | WS_VISIBLE | TBS_HORZ | WS_EX_OVERLAPPEDWINDOW |
310                 TBS_BOTTOM,  //|WS_CLIPSIBLINGS,
311                 0, 0, 0, 0, hwnd, NULL, hInst, NULL );
312
313     if( !hwndSlider ) return NULL;
314
315     SendMessage( hwndSlider, TBM_SETRANGEMIN, 1, 0 );
316     SendMessage( hwndSlider, TBM_SETRANGEMAX, 1, SLIDER_MAX_POS );
317     SendMessage( hwndSlider, TBM_SETPOS, 1, 0 );
318
319     // Reposition the trackbar
320     GetClientRect( hwnd, &rect );
321     MoveWindow( hwndSlider, rect.left, 
322                 rect.bottom - rect.top - 2*(MENU_HEIGHT-1) - SLIDER_HEIGHT, 
323                 rect.right - rect.left - 40, 30, TRUE );
324
325     ShowWindow( hwndSlider, SW_HIDE );
326
327     return hwndSlider;
328 }
329
330 HWND CreateStaticText( HWND hwnd, HINSTANCE hInst )
331 {
332     HWND hwndLabel;
333     RECT rect;
334
335     hwndLabel = CreateWindowEx( 0, _T("STATIC"), _T("label"),
336                                 WS_CHILD | WS_VISIBLE | SS_CENTER ,
337                                 0, 0, 0, 0, hwnd, (HMENU)1980, hInst, NULL );
338
339     // Reposition the trackbar
340     GetClientRect( hwnd, &rect );
341
342     MoveWindow( hwndLabel, rect.left,
343                 rect.bottom - rect.top - 2*(MENU_HEIGHT-1) - SLIDER_HEIGHT +30,
344                 rect.right - rect.left - 40,
345                 SLIDER_HEIGHT - 30, TRUE );
346
347     ShowWindow( hwndLabel, SW_HIDE );
348
349     return hwndLabel;
350 }
351
352 /***********************************************************************
353
354 FUNCTION: 
355   CreateVolTrackBar
356
357 PURPOSE: 
358   Registers the TRACKBAR_CLASS control class and creates a trackbar.
359
360 ***********************************************************************/
361 HWND CreateVolTrackBar( HWND hwnd, HINSTANCE hInst )
362 {
363     HWND hwndVol;
364     RECT rect;
365
366     INITCOMMONCONTROLSEX iccex;
367     iccex.dwSize = sizeof( INITCOMMONCONTROLSEX );
368     iccex.dwICC = ICC_BAR_CLASSES;
369
370     // Registers TRACKBAR_CLASS control classes from the common control dll
371     InitCommonControlsEx( &iccex );
372
373     hwndVol = CreateWindowEx( 0, TRACKBAR_CLASS, NULL,
374                 WS_CHILD | WS_VISIBLE | TBS_VERT | TBS_RIGHT | TBS_AUTOTICKS |
375                 WS_EX_OVERLAPPEDWINDOW, //|WS_CLIPSIBLINGS,
376                 0, 0, 0, 0, hwnd, NULL, hInst, NULL );
377
378     if( !hwndVol ) return NULL;
379
380     SendMessage( hwndVol, TBM_SETRANGEMIN, 1, 0 );
381     SendMessage( hwndVol, TBM_SETRANGEMAX, 1, 200 );
382     SendMessage( hwndVol, TBM_SETPOS, 1, 100 );
383     SendMessage( hwndVol, TBM_SETTICFREQ, 50, 0 );  
384
385     // Reposition the trackbar
386     GetClientRect( hwnd, &rect );
387     MoveWindow( hwndVol, rect.right - rect.left - 40, 
388                 rect.bottom - rect.top - 2*(MENU_HEIGHT-1) - SLIDER_HEIGHT, 
389                 40, SLIDER_HEIGHT, TRUE );
390
391     ShowWindow( hwndVol, SW_HIDE );
392
393     return hwndVol;
394 }
395
396 /***********************************************************************
397
398 FUNCTION: 
399   CreateStatusBar
400
401 PURPOSE: 
402   Registers the StatusBar control class and creates a Statusbar.
403
404 ***********************************************************************/
405 HWND CreateStatusBar( HWND hwnd, HINSTANCE hInst )
406 {
407     DWORD dwStyle;
408     HWND hwndSB;
409     RECT rect;
410
411     INITCOMMONCONTROLSEX iccex;
412     iccex.dwSize = sizeof (INITCOMMONCONTROLSEX);
413     iccex.dwICC = ICC_BAR_CLASSES;
414
415     // Registers Statusbar control classes from the common control dll
416     InitCommonControlsEx( &iccex );
417
418     // Create the statusbar control
419     dwStyle = WS_VISIBLE | WS_CHILD | TBSTYLE_TOOLTIPS | CCS_NOPARENTALIGN;
420
421     hwndSB = CreateWindowEx( 0, STATUSCLASSNAME, NULL,
422                              WS_CHILD | WS_VISIBLE | TBS_VERT | TBS_BOTTOM |
423                              TBS_RIGHT  |WS_CLIPSIBLINGS,
424                              0, 0, CW_USEDEFAULT, 50, hwnd, NULL, hInst, 0 );
425
426     if (!hwndSB ) return NULL;
427
428     // Get the coordinates of the parent window's client area. 
429     GetClientRect( hwnd, &rect );
430
431     // allocate memory for the panes of status bar
432     int nopanes = 2;
433     int *indicators = new int[nopanes];
434
435     // set width for the panes
436     indicators[0] = 3 * ( rect.right - rect.left ) / 4;
437     indicators[1] = rect.right - rect.left;
438
439     // call functions to set style
440     SendMessage( hwndSB, SB_SETPARTS, (WPARAM)nopanes, (LPARAM)indicators );
441
442     return hwndSB;
443 }
444
445 /***********************************************************************
446 FUNCTION: 
447   WndProc
448
449 PURPOSE: 
450   Processes messages sent to the main window.
451 ***********************************************************************/
452 LRESULT Interface::WndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
453 {
454     switch( msg )
455     {
456     case WM_CREATE:
457         hwndCB = CreateMenuBar( hwnd, hInst );
458         hwndTB = CreateToolBar( hwnd, hInst );
459         hwndSlider = CreateSliderBar( hwnd, hInst );
460         hwndLabel = CreateStaticText( hwnd, hInst );
461         hwndVol = CreateVolTrackBar( hwnd, hInst );
462 #ifdef UNDER_CE
463         hwndSB = CreateStatusBar( hwnd, hInst );
464 #endif
465
466         /* Video window */
467         if( config_GetInt( p_intf, "wince-embed" ) )
468             video = CreateVideoWindow( p_intf, hwnd );
469
470         timer = new Timer( p_intf, hwnd, this );
471         break;
472
473     case WM_COMMAND:
474         switch( GET_WM_COMMAND_ID(wp,lp) )
475         {
476         case ID_FILE_QUICKOPEN: 
477         case ID_FILE_OPENFILE: 
478         case ID_FILE_OPENDIR:
479         case ID_FILE_OPENNET:
480         case ID_VIEW_STREAMINFO:
481         case ID_VIEW_MESSAGES:
482         case ID_VIEW_PLAYLIST:
483         case ID_PREFERENCES:
484             OnShowDialog( GET_WM_COMMAND_ID(wp,lp) );
485             break;
486
487         case PlayStream_Event: OnPlayStream(); break;
488         case StopStream_Event: OnStopStream(); break;
489         case PrevStream_Event: OnPrevStream(); break;
490         case NextStream_Event: OnNextStream(); break;
491         case SlowStream_Event: OnSlowStream(); break;
492         case FastStream_Event: OnFastStream(); break;
493
494         case ID_FILE_ABOUT: 
495         {
496             string about = (string)"VLC media player " PACKAGE_VERSION +
497                 _("\n(WinCE interface)\n\n") +
498                 _("(c) 1996-2005 - the VideoLAN Team\n\n") +
499                 _("The VideoLAN team <videolan@videolan.org>\n"
500                   "http://www.videolan.org/\n\n");
501
502             MessageBox( hwnd, _FROMMB(about.c_str()),
503                         _T("About VLC media player"), MB_OK );
504             break;
505         }
506
507         case ID_FILE_EXIT:
508             SendMessage( hwnd, WM_CLOSE, 0, 0 );
509             break;
510
511         default:
512             OnMenuEvent( p_intf, GET_WM_COMMAND_ID(wp,lp) );
513             // we should test if it is a menu command
514         }
515         break;
516   
517     case WM_TIMER:
518         timer->Notify();
519         break;
520
521     case WM_CTLCOLORSTATIC: 
522         if( ( (HWND)lp == hwndSlider ) || ( (HWND)lp == hwndVol ) )
523         { 
524             return( (LRESULT)::GetSysColorBrush(COLOR_3DFACE) ); 
525         }
526         if( (HWND)lp == hwndLabel )
527         {
528             SetBkColor( (HDC)wp, RGB (192, 192, 192) ); 
529             return( (LRESULT)::GetSysColorBrush(COLOR_3DFACE) ); 
530         }
531         break;
532
533     case WM_HSCROLL:
534         if( (HWND)lp == hwndSlider ) OnSliderUpdate( wp );
535         break;
536
537     case WM_VSCROLL:
538         if( (HWND)lp == hwndVol ) OnChange( wp );
539         break;
540
541     case WM_INITMENUPOPUP:
542         if( (HMENU)wp == menu_settings )
543             RefreshSettingsMenu( p_intf, menu_settings );
544         if( (HMENU)wp == menu_audio )
545             RefreshAudioMenu( p_intf, menu_audio );
546         if( (HMENU)wp == menu_video )
547             RefreshVideoMenu( p_intf, menu_video );
548         if( (HMENU)wp == menu_navigation )
549             RefreshNavigMenu( p_intf, menu_navigation );
550         /* Fall through */
551
552     case WM_KILLFOCUS:
553         SHFullScreen( hwnd, SHFS_SHOWSIPBUTTON );
554     case WM_ENTERMENULOOP:
555         if( video && video->hWnd )
556             SendMessage( video->hWnd, WM_KILLFOCUS, 0, 0 );
557         break;
558
559     case WM_SETFOCUS:
560         SHSipPreference( hwnd, SIP_DOWN ); 
561         SHFullScreen( GetForegroundWindow(), SHFS_HIDESIPBUTTON );
562     case WM_EXITMENULOOP:
563         if( video && video->hWnd )
564             SendMessage( video->hWnd, WM_SETFOCUS, 0, 0 );
565         break;
566
567     case WM_LBUTTONDOWN:
568         {
569             SHRGINFO shrg;
570             shrg.cbSize = sizeof( shrg );
571             shrg.hwndClient = hwnd;
572             shrg.ptDown.x = LOWORD(lp);
573             shrg.ptDown.y = HIWORD(lp);
574             shrg.dwFlags = SHRG_RETURNCMD ;
575
576             if( SHRecognizeGesture( &shrg ) == GN_CONTEXTMENU )
577                 PopupMenu( p_intf, hwnd, shrg.ptDown );
578         }
579         break;
580
581    case WM_RBUTTONUP:
582         {
583             POINT point;
584             point.x = LOWORD(lp);
585             point.y = HIWORD(lp);
586             PopupMenu( p_intf, hwnd, point );
587         }
588         break;
589
590     case WM_HELP:
591         MessageBox (hwnd, _T("Help"), _T("Help"), MB_OK);
592         break;
593
594     case WM_CLOSE:
595         if( hwndCB ) DestroyWindow( hwndCB );
596         DestroyWindow( hwnd );
597         break;
598
599     case WM_DESTROY:
600         PostQuitMessage( 0 );
601         break;
602     }
603
604     return DefWindowProc( hwnd, msg, wp, lp );
605 }
606
607 void Interface::OnShowDialog( int i_dialog_event )
608 {
609     int i_id;
610
611     switch( i_dialog_event )
612     {
613     case ID_FILE_QUICKOPEN: i_id = INTF_DIALOG_FILE_SIMPLE; break;
614     case ID_FILE_OPENFILE: i_id = INTF_DIALOG_FILE; break;
615     case ID_FILE_OPENDIR: i_id = INTF_DIALOG_DIRECTORY; break;
616     case ID_FILE_OPENNET: i_id = INTF_DIALOG_NET; break;
617     case ID_VIEW_PLAYLIST: i_id = INTF_DIALOG_PLAYLIST; break;
618     case ID_VIEW_MESSAGES: i_id = INTF_DIALOG_MESSAGES; break;
619     case ID_VIEW_STREAMINFO: i_id = INTF_DIALOG_FILEINFO; break;
620     case ID_PREFERENCES: i_id = INTF_DIALOG_PREFS; break;
621     default: i_id = INTF_DIALOG_FILE; break;
622     }
623
624     if( p_intf->p_sys->pf_show_dialog )
625         p_intf->p_sys->pf_show_dialog( p_intf, i_id, 1, 0 );
626 }
627
628 void Interface::OnPlayStream( void )
629 {
630     playlist_t *p_playlist = (playlist_t *)
631         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
632     if( p_playlist == NULL ) return;
633
634     if( p_playlist->i_size && p_playlist->i_enabled )
635     {
636         vlc_value_t state;
637
638         input_thread_t *p_input = (input_thread_t *)
639             vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );
640
641         if( p_input == NULL )
642         {
643             /* No stream was playing, start one */
644             playlist_Play( p_playlist );
645             TogglePlayButton( PLAYING_S );
646             vlc_object_release( p_playlist );
647             return;
648         }
649
650         var_Get( p_input, "state", &state );
651
652         if( state.i_int != PAUSE_S )
653         {
654             /* A stream is being played, pause it */
655             state.i_int = PAUSE_S;
656         }
657         else
658         {
659             /* Stream is paused, resume it */
660             state.i_int = PLAYING_S;
661         }
662         var_Set( p_input, "state", state );
663
664         TogglePlayButton( state.i_int );
665         vlc_object_release( p_input );
666         vlc_object_release( p_playlist );
667     }
668     else
669     {
670         /* If the playlist is empty, open a file requester instead */
671         vlc_object_release( p_playlist );
672         OnShowDialog( ID_FILE_QUICKOPEN );
673     }
674 }
675
676 void Interface::TogglePlayButton( int i_playing_status )
677 {
678     TBREPLACEBITMAP tbrb;
679     tbrb.hInstOld = tbrb.hInstNew = (HINSTANCE) hInst;
680     tbrb.nButtons = NUMIMAGES;
681
682     if( i_playing_status == i_old_playing_status ) return;
683
684     if( i_playing_status == PLAYING_S )
685     {
686         tbrb.nIDOld = IDB_BITMAP2;
687         tbrb.nIDNew = IDB_BITMAP1;
688
689         SendMessage( hwndTB, TB_REPLACEBITMAP, (WPARAM)0,
690                      (LPARAM)(LPTBREPLACEBITMAP)&tbrb );
691     }
692     else
693     {
694         tbrb.nIDOld = IDB_BITMAP1;
695         tbrb.nIDNew = IDB_BITMAP2;
696
697         SendMessage( hwndTB, TB_REPLACEBITMAP, (WPARAM)0,
698                      (LPARAM)(LPTBREPLACEBITMAP)&tbrb );
699     }
700
701     UpdateWindow( hwndTB );
702
703     i_old_playing_status = i_playing_status;
704 }
705
706 void Interface::OnVideoOnTop( void )
707 {
708     vlc_value_t val;
709
710     vout_thread_t *p_vout = (vout_thread_t *)
711         vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
712
713     if( p_vout == NULL ) return;
714
715     if( var_Get( (vlc_object_t *)p_vout, "video-on-top", &val ) < 0 )
716         return;
717
718     val.b_bool = !val.b_bool;
719     var_Set( (vlc_object_t *)p_vout, "video-on-top", val );
720
721     vlc_object_release( (vlc_object_t *)p_vout );
722 }
723
724 void Interface::OnSliderUpdate( int wp )
725 {
726     vlc_mutex_lock( &p_intf->change_lock );
727     input_thread_t *p_input = p_intf->p_sys->p_input;
728
729     int dwPos = SendMessage( hwndSlider, TBM_GETPOS, 0, 0 ); 
730
731     if( (int)LOWORD(wp) == SB_THUMBPOSITION ||
732         (int)LOWORD(wp) == SB_ENDSCROLL )
733     {
734         if( p_intf->p_sys->i_slider_pos != dwPos && p_input )
735         {
736             vlc_value_t pos;
737             pos.f_float = (float)dwPos / (float)SLIDER_MAX_POS;
738             var_Set( p_input, "position", pos );
739         }
740
741         p_intf->p_sys->b_slider_free = VLC_TRUE;
742     }
743     else
744     {
745         p_intf->p_sys->b_slider_free = VLC_FALSE;
746
747         if( p_input )
748         {
749             /* Update stream date */
750             char psz_time[ MSTRTIME_MAX_SIZE ], psz_total[ MSTRTIME_MAX_SIZE ];
751             mtime_t i_seconds;
752
753             i_seconds = var_GetTime( p_input, "length" ) / I64C(1000000 );
754             secstotimestr( psz_total, i_seconds );
755
756             i_seconds = var_GetTime( p_input, "time" ) / I64C(1000000 );
757             secstotimestr( psz_time, i_seconds );
758
759             SendMessage( hwndLabel, WM_SETTEXT, (WPARAM)1,
760                          (LPARAM)_FROMMB(psz_time) );
761         }
762     }
763
764     vlc_mutex_unlock( &p_intf->change_lock );
765 }
766
767 void Interface::OnChange( int wp )
768 {
769     DWORD dwPos = SendMessage( hwndVol, TBM_GETPOS, 0, 0 );
770
771     if( LOWORD(wp) == SB_THUMBPOSITION || LOWORD(wp) == SB_ENDSCROLL )
772     {
773         VolumeChange( 200 - (int)dwPos );
774         b_volume_hold = VLC_FALSE;
775     }
776     else
777     {
778         b_volume_hold = VLC_TRUE;
779     }
780 }
781
782 void Interface::VolumeChange( int i_volume )
783 {
784     aout_VolumeSet( p_intf, i_volume * AOUT_VOLUME_MAX / 200 / 2 );
785 }
786
787 void Interface::VolumeUpdate()
788 {
789     audio_volume_t i_volume;
790
791     if( b_volume_hold ) return;
792
793     aout_VolumeGet( p_intf, &i_volume );
794
795     int i_volume_ctrl = 200 - i_volume * 200 * 2 / AOUT_VOLUME_MAX;
796
797     DWORD dwPos = SendMessage( hwndVol, TBM_GETPOS, 0, 0 );
798     if( i_volume_ctrl == (int)dwPos ) return;
799
800     SendMessage( hwndVol, TBM_SETPOS, 1, i_volume_ctrl );
801 }
802
803 void Interface::OnStopStream( void )
804 {
805     playlist_t * p_playlist = (playlist_t *)
806         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
807     if( p_playlist == NULL ) return;
808
809     playlist_Stop( p_playlist );
810     TogglePlayButton( PAUSE_S );
811     vlc_object_release( p_playlist );
812 }
813
814 void Interface::OnPrevStream( void )
815 {
816     playlist_t * p_playlist = (playlist_t *)
817         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
818     if( p_playlist == NULL ) return;
819
820     playlist_Prev( p_playlist );
821     vlc_object_release( p_playlist );
822 }
823
824 void Interface::OnNextStream( void )
825 {
826     playlist_t * p_playlist = (playlist_t *)
827         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
828     if( p_playlist == NULL ) return;
829
830     playlist_Next( p_playlist );
831     vlc_object_release( p_playlist );
832 }
833
834 void Interface::OnSlowStream( void )
835 {
836     input_thread_t *p_input = (input_thread_t *)
837         vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );
838
839     if( p_input == NULL ) return;
840
841     vlc_value_t val; val.b_bool = VLC_TRUE;
842     var_Set( p_input, "rate-slower", val );
843     vlc_object_release( p_input );
844 }
845
846 void Interface::OnFastStream( void )
847 {
848     input_thread_t *p_input = (input_thread_t *)
849         vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );
850
851     if( p_input == NULL ) return;
852
853     vlc_value_t val; val.b_bool = VLC_TRUE;
854     var_Set( p_input, "rate-faster", val );
855     vlc_object_release( p_input );
856 }
857
858 void Interface::Update()
859 {
860     /* Misc updates */
861     VolumeUpdate();
862 }