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