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