]> git.sesse.net Git - vlc/blob - modules/gui/wxwidgets/interface.cpp
#include "charset.h"
[vlc] / modules / gui / wxwidgets / interface.cpp
1 /*****************************************************************************
2  * interface.cpp : wxWidgets plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2005 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <vlc/vlc.h>
28 #include <vlc/aout.h>
29 #include <vlc/vout.h>
30 #include <vlc/input.h>
31 #include <vlc/intf.h>
32 #include "charset.h"
33
34 #include "wxwidgets.h"
35
36 /* include the toolbar graphics */
37 #include "bitmaps/play.xpm"
38 #include "bitmaps/pause.xpm"
39 #include "bitmaps/stop.xpm"
40 #include "bitmaps/prev.xpm"
41 #include "bitmaps/next.xpm"
42 #include "bitmaps/eject.xpm"
43 #include "bitmaps/slow.xpm"
44 #include "bitmaps/fast.xpm"
45 #include "bitmaps/playlist.xpm"
46 #include "bitmaps/speaker.xpm"
47 #include "bitmaps/speaker_mute.xpm"
48
49 #define TOOLBAR_BMP_WIDTH 16
50 #define TOOLBAR_BMP_HEIGHT 16
51
52 /* include the icon graphic */
53 #include "../../../share/vlc32x32.xpm"
54 /* include a small icon graphic for the systray icon */
55 #ifdef wxHAS_TASK_BAR_ICON
56 #include "../../../share/vlc16x16.xpm"
57 #endif
58
59 /*****************************************************************************
60  * Local class declarations.
61  *****************************************************************************/
62 class wxMenuExt: public wxMenu
63 {
64 public:
65     /* Constructor */
66     wxMenuExt( wxMenu* parentMenu, int id, const wxString& text,
67                    const wxString& helpString, wxItemKind kind,
68                    char *_psz_var, int _i_object_id, vlc_value_t _val,
69                    int _i_val_type );
70
71     virtual ~wxMenuExt() {};
72
73     char *psz_var;
74     int  i_val_type;
75     int  i_object_id;
76     vlc_value_t val;
77
78 private:
79
80 };
81
82 class wxVolCtrl;
83 class VLCVolCtrl : public wxControl
84 {
85 public:
86     VLCVolCtrl( intf_thread_t *p_intf, wxWindow *p_parent );
87     virtual ~VLCVolCtrl() {};
88
89     virtual void OnPaint( wxPaintEvent &event );
90     void OnChange( wxMouseEvent& event );
91     void UpdateVolume();
92
93   private:
94     DECLARE_EVENT_TABLE()
95
96     wxVolCtrl *gauge;
97     int i_y_offset;
98     vlc_bool_t b_mute;
99     intf_thread_t *p_intf;
100 };
101
102 BEGIN_EVENT_TABLE(VLCVolCtrl, wxControl)
103    EVT_PAINT(VLCVolCtrl::OnPaint)
104
105     /* Mouse events */
106     EVT_LEFT_UP(VLCVolCtrl::OnChange)
107 END_EVENT_TABLE()
108
109 /*****************************************************************************
110  * Event Table.
111  *****************************************************************************/
112
113 DEFINE_LOCAL_EVENT_TYPE( wxEVT_INTF );
114
115 /* IDs for the controls and the menu commands */
116 enum
117 {
118     /* menu items */
119     MenuDummy_Event = wxID_HIGHEST + 1000,
120     Exit_Event = wxID_HIGHEST,
121     OpenFileSimple_Event,
122     OpenAdv_Event,
123     OpenFile_Event,
124     OpenDir_Event,
125     OpenDisc_Event,
126     OpenNet_Event,
127     OpenCapture_Event,
128     OpenSat_Event,
129     OpenOther_Event,
130     EjectDisc_Event,
131
132     Wizard_Event,
133
134     Playlist_Event,
135     Logs_Event,
136     FileInfo_Event,
137
138     Prefs_Event,
139     Extended_Event,
140 //    Undock_Event,
141     Bookmarks_Event,
142     Skins_Event,
143
144     SliderScroll_Event,
145     StopStream_Event,
146     PlayStream_Event,
147     PrevStream_Event,
148     NextStream_Event,
149     SlowStream_Event,
150     FastStream_Event,
151
152     DiscMenu_Event,
153     DiscPrev_Event,
154     DiscNext_Event,
155
156     /* it is important for the id corresponding to the "About" command to have
157      * this standard value as otherwise it won't be handled properly under Mac
158      * (where it is special and put into the "Apple" menu) */
159     About_Event = wxID_ABOUT,
160     UpdateVLC_Event,
161
162     Iconize_Event
163 };
164
165 BEGIN_EVENT_TABLE(Interface, wxFrame)
166     /* Menu events */
167     EVT_MENU(Exit_Event, Interface::OnExit)
168     EVT_MENU(About_Event, Interface::OnAbout)
169     EVT_MENU(UpdateVLC_Event, Interface::OnShowDialog)
170
171     EVT_MENU(Playlist_Event, Interface::OnShowDialog)
172     EVT_MENU(Logs_Event, Interface::OnShowDialog)
173     EVT_MENU(FileInfo_Event, Interface::OnShowDialog)
174     EVT_MENU(Prefs_Event, Interface::OnShowDialog)
175
176     EVT_MENU_OPEN(Interface::OnMenuOpen)
177
178     EVT_MENU( Extended_Event, Interface::OnExtended )
179 //    EVT_MENU( Undock_Event, Interface::OnUndock )
180
181     EVT_MENU( Bookmarks_Event, Interface::OnShowDialog)
182
183 #if defined( __WXMSW__ ) || defined( __WXMAC__ )
184     EVT_CONTEXT_MENU(Interface::OnContextMenu2)
185 #endif
186     EVT_RIGHT_UP(Interface::OnContextMenu)
187
188     /* Toolbar events */
189     EVT_MENU(OpenFileSimple_Event, Interface::OnShowDialog)
190     EVT_MENU(OpenAdv_Event, Interface::OnShowDialog)
191     EVT_MENU(OpenFile_Event, Interface::OnShowDialog)
192     EVT_MENU(OpenDir_Event, Interface::OnShowDialog)
193     EVT_MENU(OpenDisc_Event, Interface::OnShowDialog)
194     EVT_MENU(OpenNet_Event, Interface::OnShowDialog)
195     EVT_MENU(OpenCapture_Event, Interface::OnShowDialog)
196     EVT_MENU(OpenSat_Event, Interface::OnShowDialog)
197     EVT_MENU(Wizard_Event, Interface::OnShowDialog)
198     EVT_MENU(StopStream_Event, Interface::OnStopStream)
199     EVT_MENU(PlayStream_Event, Interface::OnPlayStream)
200     EVT_MENU(PrevStream_Event, Interface::OnPrevStream)
201     EVT_MENU(NextStream_Event, Interface::OnNextStream)
202     EVT_MENU(SlowStream_Event, Interface::OnSlowStream)
203     EVT_MENU(FastStream_Event, Interface::OnFastStream)
204
205     /* Disc Buttons events */
206     EVT_BUTTON(DiscMenu_Event, Interface::OnDiscMenu)
207     EVT_BUTTON(DiscPrev_Event, Interface::OnDiscPrev)
208     EVT_BUTTON(DiscNext_Event, Interface::OnDiscNext)
209
210     /* Slider events */
211     EVT_COMMAND_SCROLL(SliderScroll_Event, Interface::OnSliderUpdate)
212
213     /* Custom events */
214     EVT_COMMAND(0, wxEVT_INTF, Interface::OnControlEvent)
215     EVT_COMMAND(1, wxEVT_INTF, Interface::OnControlEvent)
216
217     EVT_TIMER(ID_CONTROLS_TIMER, Interface::OnControlsTimer)
218     EVT_TIMER(ID_SLIDER_TIMER, Interface::OnSliderTimer)
219 END_EVENT_TABLE()
220
221 /*****************************************************************************
222  * Constructor.
223  *****************************************************************************/
224 Interface::Interface( intf_thread_t *_p_intf, long style ):
225     wxFrame( NULL, -1, wxT("VLC media player"),
226              wxDefaultPosition, wxSize(700,100), style )
227 {
228     /* Initializations */
229     p_intf = _p_intf;
230     i_old_playing_status = PAUSE_S;
231     b_extra = VLC_FALSE;
232 //    b_undock = VLC_FALSE;
233
234
235     extra_window = NULL;
236
237     /* Give our interface a nice little icon */
238     SetIcon( wxIcon( vlc_xpm ) );
239
240     /* Create a sizer for the main frame */
241     frame_sizer = new wxBoxSizer( wxVERTICAL );
242     SetSizer( frame_sizer );
243
244     /* Create a dummy widget that can get the keyboard focus */
245     wxWindow *p_dummy = new wxWindow( this, 0, wxDefaultPosition,
246                                       wxSize(0,0) );
247 #if defined(__WXGTK20__) && wxCHECK_VERSION(2,5,6)
248     /* As ugly as your butt! Please remove when wxWidgets 2.6 fixed their
249      * Accelerators bug. */
250     p_dummy->m_imData = 0;
251     m_imData = 0;
252 #endif
253     p_dummy->SetFocus();
254     frame_sizer->Add( p_dummy, 0, 0 );
255
256 #ifdef wxHAS_TASK_BAR_ICON
257     /* Systray integration */
258     p_systray = NULL;
259     if ( config_GetInt( p_intf, "wx-systray" ) )
260     {
261         p_systray = new Systray(this, p_intf);
262         p_systray->SetIcon( wxIcon( vlc16x16_xpm ), wxT("VLC media player") );
263         if ( (! p_systray->IsOk()) || (! p_systray->IsIconInstalled()) )
264         {
265             msg_Warn(p_intf, "Cannot set systray icon, weird things may happen");
266         }
267     }
268 #endif
269
270     /* Creation of the menu bar */
271     CreateOurMenuBar();
272
273     /* Creation of the tool bar */
274     CreateOurToolBar();
275
276     /* Create the extra panel */
277     extra_frame = new ExtraPanel( p_intf, this );
278     frame_sizer->Add( extra_frame, 0, wxEXPAND , 0 );
279     frame_sizer->Hide( extra_frame );
280
281     /* Creation of the status bar
282      * Helptext for menu items and toolbar tools will automatically get
283      * displayed here. */
284     int i_status_width[3] = {-6, -2, -9};
285     statusbar = CreateStatusBar( 3 );                            /* 2 fields */
286     statusbar->SetStatusWidths( 3, i_status_width );
287     statusbar->SetStatusText( wxString::Format(wxT("x%.2f"), 1.0), 1 );
288
289     /* Video window */
290     video_window = 0;
291     if( config_GetInt( p_intf, "wx-embed" ) )
292     {
293         video_window = CreateVideoWindow( p_intf, this );
294         frame_sizer->Add( p_intf->p_sys->p_video_sizer, 1, wxEXPAND, 0 );
295     }
296
297     /* Creation of the slider sub-window */
298     CreateOurSlider();
299     frame_sizer->Add( slider_frame, 0, wxEXPAND , 0 );
300     frame_sizer->Hide( slider_frame );
301
302     /* Make sure we've got the right background colour */
303     SetBackgroundColour( slider_frame->GetBackgroundColour() );
304
305     /* Layout everything */
306     frame_sizer->Layout();
307     frame_sizer->Fit(this);
308
309 #if wxUSE_DRAG_AND_DROP
310     /* Associate drop targets with the main interface */
311     SetDropTarget( new DragAndDrop( p_intf ) );
312 #endif
313
314     SetupHotkeys();
315
316     m_controls_timer.SetOwner(this, ID_CONTROLS_TIMER);
317     m_slider_timer.SetOwner(this, ID_SLIDER_TIMER);
318
319     /* Start timer */
320     timer = new Timer( p_intf, this );
321
322     /* */
323     WindowSettings *ws = p_intf->p_sys->p_window_settings;
324     wxPoint p;
325     wxSize  s;
326     bool    b_shown;
327
328     ws->SetScreen( wxSystemSettings::GetMetric( wxSYS_SCREEN_X ),
329                    wxSystemSettings::GetMetric( wxSYS_SCREEN_Y ) );
330
331     if( ws->GetSettings( WindowSettings::ID_MAIN, b_shown, p, s ) )
332         Move( p );
333 }
334
335 Interface::~Interface()
336 {
337     WindowSettings *ws = p_intf->p_sys->p_window_settings;
338
339     if( !IsIconized() )
340     {
341         ws->SetSettings( WindowSettings::ID_MAIN, true,
342                          GetPosition(), GetSize() );
343     }
344
345         PopEventHandler(true);
346
347     if( video_window ) delete video_window;
348
349 #ifdef wxHAS_TASK_BAR_ICON
350     if( p_systray ) delete p_systray;
351 #endif
352
353     if( p_intf->p_sys->p_wxwindow ) delete p_intf->p_sys->p_wxwindow;
354
355     /* Clean up */
356     delete timer;
357 }
358
359 void Interface::Init()
360 {
361     /* Misc init */
362     SetupHotkeys();
363 }
364
365 void Interface::Update()
366 {
367     /* Misc updates */
368     ((VLCVolCtrl *)volctrl)->UpdateVolume();
369 }
370
371 void Interface::OnControlEvent( wxCommandEvent& event )
372 {
373     switch( event.GetId() )
374     {
375     case 0:
376         {
377           if( p_intf->p_sys->b_video_autosize )
378           {
379         frame_sizer->Layout();
380         frame_sizer->Fit(this);
381           }
382         }
383         break;
384
385     case 1:
386         long i_style = GetWindowStyle();
387         if( event.GetInt() ) i_style |= wxSTAY_ON_TOP;
388         else i_style &= ~wxSTAY_ON_TOP;
389         SetWindowStyle( i_style );
390         break;
391     }
392 }
393
394 /*****************************************************************************
395  * Private methods.
396  *****************************************************************************/
397 void Interface::CreateOurMenuBar()
398 {
399     int minimal = config_GetInt( p_intf, "wx-minimal" );
400
401     /* Create the "File" menu */
402     wxMenu *file_menu = new wxMenu;
403
404     if (!minimal)
405     {
406     file_menu->Append( OpenFileSimple_Event,
407                        wxU(_("Quick &Open File...\tCtrl-O")) );
408
409     file_menu->AppendSeparator();
410     file_menu->Append( OpenFile_Event, wxU(_("Open &File...\tCtrl-F")) );
411     file_menu->Append( OpenDir_Event, wxU(_("Open Dir&ectory...\tCtrl-E")) );
412     file_menu->Append( OpenDisc_Event, wxU(_("Open &Disc...\tCtrl-D")) );
413     file_menu->Append( OpenNet_Event,
414                        wxU(_("Open &Network Stream...\tCtrl-N")) );
415     file_menu->Append( OpenCapture_Event,
416                        wxU(_("Open C&apture Device...\tCtrl-A")) );
417
418     file_menu->AppendSeparator();
419     file_menu->Append( Wizard_Event, wxU(_("&Wizard...\tCtrl-W")) );
420     file_menu->AppendSeparator();
421     }
422     file_menu->Append( Exit_Event, wxU(_("E&xit\tCtrl-X")) );
423
424     /* Create the "View" menu */
425     wxMenu *view_menu = new wxMenu;
426     if (!minimal)
427     {
428     view_menu->Append( Playlist_Event, wxU(_("&Playlist...\tCtrl-P")) );
429     }
430     view_menu->Append( Logs_Event, wxU(_("&Messages...\tCtrl-M")) );
431     view_menu->Append( FileInfo_Event,
432                        wxU(_("Stream and Media &info...\tCtrl-I")) );
433
434     /* Create the "Auto-generated" menus */
435     p_settings_menu = SettingsMenu( p_intf, this );
436     p_audio_menu = AudioMenu( p_intf, this );
437     p_video_menu = VideoMenu( p_intf, this );
438     p_navig_menu = NavigMenu( p_intf, this );
439
440     /* Create the "Help" menu */
441     wxMenu *help_menu = new wxMenu;
442     help_menu->Append( About_Event, wxU(_("About VLC media player")) );
443     help_menu->AppendSeparator();
444     help_menu->Append( UpdateVLC_Event, wxU(_("Check for updates ...")) );
445
446     /* Append the freshly created menus to the menu bar... */
447     wxMenuBar *menubar = new wxMenuBar();
448     menubar->Append( file_menu, wxU(_("&File")) );
449     menubar->Append( view_menu, wxU(_("&View")) );
450     menubar->Append( p_settings_menu, wxU(_("&Settings")) );
451     menubar->Append( p_audio_menu, wxU(_("&Audio")) );
452     menubar->Append( p_video_menu, wxU(_("&Video")) );
453     menubar->Append( p_navig_menu, wxU(_("&Navigation")) );
454     menubar->Append( help_menu, wxU(_("&Help")) );
455
456     /* Attach the menu bar to the frame */
457     SetMenuBar( menubar );
458
459     /* Find out size of menu bar */
460     int i_size = 0;
461     for( unsigned int i = 0; i < menubar->GetMenuCount(); i++ )
462     {
463         int i_width, i_height;
464         menubar->GetTextExtent( menubar->GetLabelTop(i), &i_width, &i_height );
465         i_size += i_width +
466 #if defined(__WXGTK__)
467             22 /* approximate margin */;
468 #else
469 #if (wxMAJOR_VERSION <= 2) && (wxMINOR_VERSION <= 5) && (wxRELEASE_NUMBER < 3)
470             4 /* approximate margin */;
471 #else
472             18 /* approximate margin */;
473 #endif
474 #endif
475     }
476     frame_sizer->SetMinSize( i_size, -1 );
477
478     /* Intercept all menu events in our custom event handler */
479     PushEventHandler( new MenuEvtHandler( p_intf, this ) );
480
481 #if wxUSE_DRAG_AND_DROP
482     /* Associate drop targets with the menubar */
483     menubar->SetDropTarget( new DragAndDrop( p_intf ) );
484 #endif
485 }
486
487 void Interface::CreateOurToolBar()
488 {
489 #define HELP_OPEN N_("Open")
490 #define HELP_STOP N_("Stop")
491 #define HELP_PLAY N_("Play")
492 #define HELP_PAUSE N_("Pause")
493 #define HELP_PLO N_("Playlist")
494 #define HELP_PLP N_("Previous playlist item")
495 #define HELP_PLN N_("Next playlist item")
496 #define HELP_SLOW N_("Play slower")
497 #define HELP_FAST N_("Play faster")
498
499     int minimal = config_GetInt( p_intf, "wx-minimal" );
500
501     wxLogNull LogDummy; /* Hack to suppress annoying log message on the win32
502                          * version because we don't include wx.rc */
503
504     wxToolBar *toolbar =
505         CreateToolBar( wxTB_HORIZONTAL | wxTB_FLAT );
506
507     toolbar->SetToolBitmapSize( wxSize(TOOLBAR_BMP_WIDTH,TOOLBAR_BMP_HEIGHT) );
508
509     if (!minimal)
510     {
511     toolbar->AddTool( OpenFile_Event, wxT(""),
512                       wxBitmap( eject_xpm ), wxU(_(HELP_OPEN)) );
513     toolbar->AddSeparator();
514     }
515
516     wxToolBarToolBase *p_tool = toolbar->AddTool( PlayStream_Event, wxT(""),
517                       wxBitmap( play_xpm ), wxU(_(HELP_PLAY)), wxITEM_CHECK );
518     p_tool->SetClientData( p_tool );
519
520     if (!minimal)
521     {
522     toolbar->AddTool( StopStream_Event, wxT(""), wxBitmap( stop_xpm ),
523                       wxU(_(HELP_STOP)) );
524     toolbar->AddSeparator();
525
526     toolbar->AddTool( PrevStream_Event, wxT(""),
527                       wxBitmap( prev_xpm ), wxU(_(HELP_PLP)) );
528     toolbar->AddTool( SlowStream_Event, wxT(""),
529                       wxBitmap( slow_xpm ), wxU(_(HELP_SLOW)) );
530     toolbar->AddTool( FastStream_Event, wxT(""),
531                       wxBitmap( fast_xpm ), wxU(_(HELP_FAST)) );
532     toolbar->AddTool( NextStream_Event, wxT(""), wxBitmap( next_xpm ),
533                       wxU(_(HELP_PLN)) );
534     toolbar->AddSeparator();
535     toolbar->AddTool( Playlist_Event, wxT(""), wxBitmap( playlist_xpm ),
536                       wxU(_(HELP_PLO)) );
537     }
538
539     wxControl *p_dummy_ctrl =
540         new wxControl( toolbar, -1, wxDefaultPosition,
541                        wxSize(35, 16 ), wxBORDER_NONE );
542
543     toolbar->AddControl( p_dummy_ctrl );
544
545     volctrl = new VLCVolCtrl( p_intf, toolbar );
546     toolbar->AddControl( volctrl );
547
548     toolbar->Realize();
549
550 #if wxUSE_DRAG_AND_DROP
551     /* Associate drop targets with the toolbar */
552     toolbar->SetDropTarget( new DragAndDrop( p_intf ) );
553 #endif
554 }
555
556 void Interface::CreateOurSlider()
557 {
558     /* Create a new frame and sizer containing the slider */
559     slider_frame = new wxPanel( this, -1, wxDefaultPosition, wxDefaultSize );
560     slider_frame->SetAutoLayout( TRUE );
561     slider_sizer = new wxBoxSizer( wxHORIZONTAL );
562     //slider_sizer->SetMinSize( -1, 50 );
563
564     /* Create slider */
565     slider = new wxSlider( slider_frame, SliderScroll_Event, 0, 0,
566                            SLIDER_MAX_POS, wxDefaultPosition, wxDefaultSize );
567
568     /* Add Disc Buttons */
569     disc_frame = new wxPanel( slider_frame, -1, wxDefaultPosition,
570                               wxDefaultSize );
571     disc_frame->SetAutoLayout( TRUE );
572     disc_sizer = new wxBoxSizer( wxHORIZONTAL );
573
574     disc_menu_button = new wxBitmapButton( disc_frame, DiscMenu_Event,
575                                            wxBitmap( playlist_xpm ) );
576     disc_prev_button = new wxBitmapButton( disc_frame, DiscPrev_Event,
577                                            wxBitmap( prev_xpm ) );
578     disc_next_button = new wxBitmapButton( disc_frame, DiscNext_Event,
579                                            wxBitmap( next_xpm ) );
580
581     disc_sizer->Add( disc_menu_button, 1, wxEXPAND | wxLEFT | wxRIGHT, 1 );
582     disc_sizer->Add( disc_prev_button, 1, wxEXPAND | wxLEFT | wxRIGHT, 1 );
583     disc_sizer->Add( disc_next_button, 1, wxEXPAND | wxLEFT | wxRIGHT, 1 );
584
585     disc_frame->SetSizer( disc_sizer );
586     disc_sizer->Layout();
587
588     /* Add everything to the frame */
589     slider_sizer->Add( slider, 1, wxEXPAND | wxALL, 5 );
590     slider_sizer->Add( disc_frame, 0, wxALL, 2 );
591     slider_frame->SetSizer( slider_sizer );
592
593     disc_frame->Hide();
594     slider_sizer->Hide( disc_frame );
595
596     slider_sizer->Layout();
597     slider_sizer->Fit( slider_frame );
598
599     /* Hide the slider by default */
600     slider_frame->Hide();
601 }
602
603 static int ConvertHotkeyModifiers( int i_hotkey )
604 {
605     int i_accel_flags = 0;
606     if( i_hotkey & KEY_MODIFIER_ALT ) i_accel_flags |= wxACCEL_ALT;
607     if( i_hotkey & KEY_MODIFIER_CTRL ) i_accel_flags |= wxACCEL_CTRL;
608     if( i_hotkey & KEY_MODIFIER_SHIFT ) i_accel_flags |= wxACCEL_SHIFT;
609     if( !i_accel_flags ) i_accel_flags = wxACCEL_NORMAL;
610     return i_accel_flags;
611 }
612
613 static int ConvertHotkey( int i_hotkey )
614 {
615     int i_key = i_hotkey & ~KEY_MODIFIER;
616     if( i_key & KEY_ASCII ) return i_key & KEY_ASCII;
617     else if( i_key & KEY_SPECIAL )
618     {
619         switch ( i_key )
620         {
621         case KEY_LEFT: return WXK_LEFT;
622         case KEY_RIGHT: return WXK_RIGHT;
623         case KEY_UP: return WXK_UP;
624         case KEY_DOWN: return WXK_DOWN;
625         case KEY_SPACE: return WXK_SPACE;
626         case KEY_ENTER: return WXK_RETURN;
627         case KEY_F1: return WXK_F1;
628         case KEY_F2: return WXK_F2;
629         case KEY_F3: return WXK_F3;
630         case KEY_F4: return WXK_F4;
631         case KEY_F5: return WXK_F5;
632         case KEY_F6: return WXK_F6;
633         case KEY_F7: return WXK_F7;
634         case KEY_F8: return WXK_F8;
635         case KEY_F9: return WXK_F9;
636         case KEY_F10: return WXK_F10;
637         case KEY_F11: return WXK_F11;
638         case KEY_F12: return WXK_F12;
639         case KEY_HOME: return WXK_HOME;
640         case KEY_END: return WXK_END;
641         case KEY_INSERT: return WXK_INSERT;
642         case KEY_DELETE: return WXK_DELETE;
643         case KEY_MENU: return WXK_MENU;
644         case KEY_ESC: return WXK_ESCAPE;
645         case KEY_PAGEUP: return WXK_PRIOR;
646         case KEY_PAGEDOWN: return WXK_NEXT;
647         case KEY_TAB: return WXK_TAB;
648         case KEY_BACKSPACE: return WXK_BACK;
649         }
650     }
651     return WXK_F24;
652 }
653
654 void Interface::SetupHotkeys()
655 {
656     struct vlc_t::hotkey *p_hotkeys = p_intf->p_vlc->p_hotkeys;
657     int i_hotkeys;
658
659     /* Count number of hoteys */
660     for( i_hotkeys = 0; p_hotkeys[i_hotkeys].psz_action != NULL; i_hotkeys++ );
661
662     p_intf->p_sys->i_first_hotkey_event = wxID_HIGHEST + 7000;
663     p_intf->p_sys->i_hotkeys = i_hotkeys;
664
665     wxAcceleratorEntry *p_entries = new wxAcceleratorEntry[i_hotkeys];
666
667     /* Setup the hotkeys as accelerators */
668     for( int i = 0; i < i_hotkeys; i++ )
669     {
670         int i_mod = ConvertHotkeyModifiers( p_hotkeys[i].i_key );
671         int i_key = ConvertHotkey( p_hotkeys[i].i_key );
672
673 #ifdef WIN32
674         if( !(p_hotkeys[i].i_key & KEY_SPECIAL) && i_mod )
675             i_key = toupper(i_key);
676 #endif
677
678         p_entries[i].Set( i_mod, i_key,
679                           p_intf->p_sys->i_first_hotkey_event + i );
680     }
681
682     wxAcceleratorTable accel( i_hotkeys, p_entries );
683
684     if( !accel.Ok() )
685     {
686         msg_Err( p_intf, "invalid accelerator table" );
687     }
688     else
689     {
690         SetAcceleratorTable( accel );
691     }
692
693     delete [] p_entries;
694 }
695
696 void Interface::HideSlider( bool layout )
697 {
698     ShowSlider( false, layout );
699 }
700
701 void Interface::ShowSlider( bool show, bool layout )
702 {
703     if( show )
704     {
705         //prevent the hide timers from hiding it now
706         m_slider_timer.Stop();
707         m_controls_timer.Stop();
708
709         //prevent continuous layout
710         if( slider_frame->IsShown() ) return;
711     }
712     else
713     {
714         //prevent continuous layout
715         if( !slider_frame->IsShown() ) return;
716     }
717
718     if( layout && p_intf->p_sys->b_video_autosize )
719         UpdateVideoWindow( p_intf, video_window );
720
721     slider_frame->Show( show );
722     frame_sizer->Show( slider_frame, show );
723
724     if( layout )
725     {
726         frame_sizer->Layout();
727         if( p_intf->p_sys->b_video_autosize ) frame_sizer->Fit( this );
728     }
729 }
730
731 void Interface::HideDiscFrame( bool layout )
732 {
733     ShowDiscFrame( false, layout );
734 }
735
736 void Interface::ShowDiscFrame( bool show, bool layout )
737 {
738     if( show )
739     {
740         //prevent the hide timer from hiding it now
741         m_controls_timer.Stop();
742
743         //prevent continuous layout
744         if( disc_frame->IsShown() ) return;
745     }
746     else
747     {
748         //prevent continuous layout
749         if( !disc_frame->IsShown() ) return;
750     }
751
752     if( layout && p_intf->p_sys->b_video_autosize )
753         UpdateVideoWindow( p_intf, video_window );
754
755     disc_frame->Show( show );
756     slider_sizer->Show( disc_frame, show );
757
758     if( layout )
759     {
760         slider_sizer->Layout();
761         if( p_intf->p_sys->b_video_autosize )
762             slider_sizer->Fit( slider_frame );
763     }
764 }
765
766 /*****************************************************************************
767  * Event Handlers.
768  *****************************************************************************/
769 void Interface::OnControlsTimer( wxTimerEvent& WXUNUSED(event) )
770 {
771     if( p_intf->p_sys->b_video_autosize )
772         UpdateVideoWindow( p_intf, video_window );
773
774     /* Hide slider and Disc Buttons */
775     //postpone layout, we'll do it ourselves
776     HideDiscFrame( false );
777     HideSlider( false );
778
779     slider_sizer->Layout();
780     if( p_intf->p_sys->b_video_autosize )
781     {
782         slider_sizer->Fit( slider_frame );
783         frame_sizer->Fit( this );
784     }
785 }
786
787 void Interface::OnSliderTimer( wxTimerEvent& WXUNUSED(event) )
788 {
789     HideSlider();
790 }
791
792 void Interface::OnMenuOpen( wxMenuEvent& event )
793 {
794 #if defined( __WXMSW__ )
795 #   define GetEventObject GetMenu
796 #endif
797
798     if( event.GetEventObject() == p_settings_menu )
799     {
800         p_settings_menu = SettingsMenu( p_intf, this, p_settings_menu );
801
802         /* Add static items */
803         p_settings_menu->AppendCheckItem( Extended_Event,
804             wxU(_("Extended &GUI\tCtrl-G") ) );
805         if( b_extra ) p_settings_menu->Check( Extended_Event, TRUE );
806 #if 0
807         p_settings_menu->AppendCheckItem( Undock_Event,
808             wxU(_("&Undock Ext. GUI") ) );
809         if( b_undock ) p_settings_menu->Check( Undock_Event, TRUE );
810 #endif
811         p_settings_menu->Append( Bookmarks_Event,
812                                  wxU(_("&Bookmarks...\tCtrl-B") ) );
813         p_settings_menu->Append( Prefs_Event,
814                                  wxU(_("Preference&s...\tCtrl-S")) );
815     }
816
817     else if( event.GetEventObject() == p_audio_menu )
818     {
819         p_audio_menu = AudioMenu( p_intf, this, p_audio_menu );
820     }
821
822     else if( event.GetEventObject() == p_video_menu )
823     {
824         p_video_menu = VideoMenu( p_intf, this, p_video_menu );
825     }
826
827     else if( event.GetEventObject() == p_navig_menu )
828     {
829         p_navig_menu = NavigMenu( p_intf, this, p_navig_menu );
830     }
831
832 #if defined( __WXMSW__ )
833 #   undef GetEventObject
834 #endif
835 }
836
837 #if defined( __WXMSW__ ) || defined( __WXMAC__ )
838 void Interface::OnContextMenu2(wxContextMenuEvent& event)
839 {
840     /* Only show the context menu for the main interface */
841     if( GetId() != event.GetId() )
842     {
843         event.Skip();
844         return;
845     }
846
847     if( p_intf->p_sys->pf_show_dialog )
848         p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU, 1, 0 );
849 }
850 #endif
851 void Interface::OnContextMenu(wxMouseEvent& event)
852 {
853     if( p_intf->p_sys->pf_show_dialog )
854         p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU, 1, 0 );
855 }
856
857 void Interface::OnExit( wxCommandEvent& WXUNUSED(event) )
858 {
859     /* TRUE is to force the frame to close. */
860     Close(TRUE);
861 }
862
863 void Interface::OnAbout( wxCommandEvent& WXUNUSED(event) )
864 {
865     wxString msg;
866     msg.Printf( wxString(wxT("VLC media player " PACKAGE_VERSION)) +
867         wxU(_(" (wxWidgets interface)\n\n")) +
868         wxU(_("(c) 1996-2005 - the VideoLAN Team\n\n")) +
869        wxU(_("Compiled by "))+ wxU(VLC_CompileBy())+ wxU("@") +
870        wxU(VLC_CompileHost())+ wxT(".")+ wxU(VLC_CompileDomain())+ wxT(".\n") +
871        wxU(_("Compiler: "))+ wxU(VLC_Compiler())+wxT( ".\n") +
872        wxU(_("Based on SVN revision: "))+wxU(VLC_Changeset())+wxT(".\n\n") +
873 #ifdef __WXMSW__
874         wxU( vlc_wraptext(INTF_ABOUT_MSG,WRAPCOUNT,VLC_TRUE) ) + wxT("\n\n") +
875 #else
876         wxU( INTF_ABOUT_MSG ) + wxT("\n\n") +
877 #endif
878         wxU(_("The VideoLAN team <videolan@videolan.org>\n"
879               "http://www.videolan.org/\n\n")) );
880
881     wxMessageBox( msg, wxString::Format(wxU(_("About %s")),
882                   wxT("VLC media player")), wxOK | wxICON_INFORMATION, this );
883 }
884
885 void Interface::OnShowDialog( wxCommandEvent& event )
886 {
887     if( p_intf->p_sys->pf_show_dialog )
888     {
889         int i_id;
890
891         switch( event.GetId() )
892         {
893         case OpenFileSimple_Event:
894             i_id = INTF_DIALOG_FILE_SIMPLE;
895             break;
896         case OpenAdv_Event:
897             i_id = INTF_DIALOG_FILE;
898         case OpenFile_Event:
899             i_id = INTF_DIALOG_FILE;
900             break;
901         case OpenDir_Event:
902             i_id = INTF_DIALOG_DIRECTORY;
903             break;
904         case OpenDisc_Event:
905             i_id = INTF_DIALOG_DISC;
906             break;
907         case OpenNet_Event:
908             i_id = INTF_DIALOG_NET;
909             break;
910         case OpenCapture_Event:
911             i_id = INTF_DIALOG_CAPTURE;
912             break;
913         case OpenSat_Event:
914             i_id = INTF_DIALOG_SAT;
915             break;
916         case Playlist_Event:
917             i_id = INTF_DIALOG_PLAYLIST;
918             break;
919         case Logs_Event:
920             i_id = INTF_DIALOG_MESSAGES;
921             break;
922         case FileInfo_Event:
923             i_id = INTF_DIALOG_FILEINFO;
924             break;
925         case Prefs_Event:
926             i_id = INTF_DIALOG_PREFS;
927             break;
928         case Wizard_Event:
929             i_id = INTF_DIALOG_WIZARD;
930             break;
931         case Bookmarks_Event:
932             i_id = INTF_DIALOG_BOOKMARKS;
933             break;
934         case UpdateVLC_Event:
935             i_id = INTF_DIALOG_UPDATEVLC;
936             break;
937         default:
938             i_id = INTF_DIALOG_FILE;
939             break;
940         }
941
942         p_intf->p_sys->pf_show_dialog( p_intf, i_id, 1, 0 );
943     }
944 }
945
946 void Interface::OnExtended(wxCommandEvent& event)
947 {
948     b_extra = (b_extra == VLC_TRUE ? VLC_FALSE : VLC_TRUE );
949
950     if( b_extra == VLC_FALSE )
951     {
952         extra_frame->Hide();
953         frame_sizer->Hide( extra_frame );
954     }
955     else
956     {
957         extra_frame->Show();
958         frame_sizer->Show( extra_frame );
959     }
960     frame_sizer->Layout();
961     frame_sizer->Fit(this);
962 }
963
964 #if 0
965         if( b_undock == VLC_TRUE )
966         {
967                 fprintf(stderr,"Deleting window\n");
968             if( extra_window )
969             {
970                 delete extra_window;
971                 extra_window = NULL;
972             }
973         }
974         else
975         {
976             extra_frame->Hide();
977             frame_sizer->Hide( extra_frame );
978             frame_sizer->Layout();
979             frame_sizer->Fit(this);
980         }
981     }
982     else
983     {
984         if( b_undock == VLC_TRUE )
985         {
986                 fprintf(stderr,"Creating window\n");
987             extra_frame->Hide();
988             frame_sizer->Hide( extra_frame );
989 #if (wxCHECK_VERSION(2,5,0))
990             frame_sizer->Detach( extra_frame );
991 #else
992             frame_sizer->Remove( extra_frame );
993 #endif
994             frame_sizer->Layout();
995             frame_sizer->Fit(this);
996             extra_window = new ExtraWindow( p_intf, this, extra_frame );
997         }
998         else
999         {
1000                 fprintf(stderr,"Deleting window\n");
1001             if( extra_window )
1002             {
1003                 delete extra_window;
1004             }
1005             extra_frame->Show();
1006             frame_sizer->Show( extra_frame );
1007             frame_sizer->Layout();
1008             frame_sizer->Fit(this);
1009         }
1010     }
1011 }
1012
1013 void Interface::OnUndock(wxCommandEvent& event)
1014 {
1015     b_undock = (b_undock == VLC_TRUE ? VLC_FALSE : VLC_TRUE );
1016
1017     if( b_extra == VLC_TRUE )
1018     {
1019         if( b_undock == VLC_FALSE )
1020         {
1021                 fprintf(stderr,"Deleting window\n");
1022             if( extra_window )
1023             {
1024                 delete extra_window;
1025                 extra_window = NULL;
1026             }
1027             extra_frame->Show();
1028             frame_sizer->Show( extra_frame );
1029             frame_sizer->Layout();
1030             frame_sizer->Fit(this);
1031         }
1032         else
1033         {
1034                 fprintf(stderr,"Creating window\n");
1035             extra_frame->Hide();
1036             frame_sizer->Hide( extra_frame );
1037 #if (wxCHECK_VERSION(2,5,0))
1038             frame_sizer->Detach( extra_frame );
1039 #else
1040             frame_sizer->Remove( extra_frame );
1041 #endif
1042             frame_sizer->Layout();
1043             frame_sizer->Fit(this);
1044             extra_window = new ExtraWindow( p_intf, this, extra_frame );
1045         }
1046     }
1047 }
1048 #endif
1049
1050
1051 void Interface::OnPlayStream( wxCommandEvent& WXUNUSED(event) )
1052 {
1053     PlayStream();
1054 }
1055
1056 void Interface::PlayStream()
1057 {
1058     wxCommandEvent dummy;
1059     playlist_t *p_playlist =
1060         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
1061                                        FIND_ANYWHERE );
1062     if( p_playlist == NULL ) return;
1063
1064     if( p_playlist->i_size && p_playlist->i_enabled )
1065     {
1066         vlc_value_t state;
1067
1068         input_thread_t *p_input = (input_thread_t *)vlc_object_find( p_intf,
1069                                                        VLC_OBJECT_INPUT,
1070                                                        FIND_ANYWHERE );
1071         if( p_input == NULL )
1072         {
1073             /* No stream was playing, start one */
1074             playlist_Play( p_playlist );
1075             TogglePlayButton( PLAYING_S );
1076             vlc_object_release( p_playlist );
1077             return;
1078         }
1079
1080         var_Get( p_input, "state", &state );
1081
1082         if( state.i_int != PAUSE_S )
1083         {
1084             /* A stream is being played, pause it */
1085             state.i_int = PAUSE_S;
1086         }
1087         else
1088         {
1089             /* Stream is paused, resume it */
1090             state.i_int = PLAYING_S;
1091         }
1092         var_Set( p_input, "state", state );
1093
1094         TogglePlayButton( state.i_int );
1095         vlc_object_release( p_input );
1096         vlc_object_release( p_playlist );
1097     }
1098     else
1099     {
1100         /* If the playlist is empty, open a file requester instead */
1101         vlc_object_release( p_playlist );
1102         OnShowDialog( dummy );
1103     }
1104 }
1105
1106 void Interface::OnStopStream( wxCommandEvent& WXUNUSED(event) )
1107 {
1108     StopStream();
1109 }
1110 void Interface::StopStream()
1111 {
1112     playlist_t * p_playlist =
1113         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
1114                                        FIND_ANYWHERE );
1115     if( p_playlist == NULL )
1116     {
1117         return;
1118     }
1119
1120     playlist_Stop( p_playlist );
1121     TogglePlayButton( PAUSE_S );
1122     vlc_object_release( p_playlist );
1123 }
1124
1125 void Interface::OnSliderUpdate( wxScrollEvent& event )
1126 {
1127     vlc_mutex_lock( &p_intf->change_lock );
1128
1129 #ifdef WIN32
1130     if( event.GetEventType() == wxEVT_SCROLL_THUMBRELEASE
1131         || event.GetEventType() == wxEVT_SCROLL_ENDSCROLL )
1132     {
1133 #endif
1134         if( p_intf->p_sys->i_slider_pos != event.GetPosition()
1135             && p_intf->p_sys->p_input )
1136         {
1137             vlc_value_t pos;
1138             pos.f_float = (float)event.GetPosition() / (float)SLIDER_MAX_POS;
1139
1140             var_Set( p_intf->p_sys->p_input, "position", pos );
1141         }
1142
1143 #ifdef WIN32
1144         p_intf->p_sys->b_slider_free = VLC_TRUE;
1145     }
1146     else
1147     {
1148         p_intf->p_sys->b_slider_free = VLC_FALSE;
1149
1150         if( p_intf->p_sys->p_input )
1151         {
1152             /* Update stream date */
1153             char psz_time[ MSTRTIME_MAX_SIZE ], psz_total[ MSTRTIME_MAX_SIZE ];
1154             mtime_t i_seconds;
1155
1156             i_seconds = var_GetTime( p_intf->p_sys->p_input, "length" ) /
1157                         I64C(1000000 );
1158             secstotimestr( psz_total, i_seconds );
1159
1160             i_seconds = var_GetTime( p_intf->p_sys->p_input, "time" ) /
1161                         I64C(1000000 );
1162             secstotimestr( psz_time, i_seconds );
1163
1164             statusbar->SetStatusText( wxU(psz_time) + wxString(wxT(" / ") ) +
1165                                       wxU(psz_total), 0 );
1166         }
1167     }
1168 #endif
1169
1170 #undef WIN32
1171     vlc_mutex_unlock( &p_intf->change_lock );
1172 }
1173
1174 void Interface::OnPrevStream( wxCommandEvent& WXUNUSED(event) )
1175 {
1176     PrevStream();
1177 }
1178
1179 void Interface::PrevStream()
1180 {
1181     playlist_t * p_playlist =
1182         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
1183                                        FIND_ANYWHERE );
1184     if( p_playlist == NULL )
1185     {
1186         return;
1187     }
1188
1189     /* FIXME --fenrir */
1190 #if 0
1191     if( p_playlist->p_input != NULL )
1192     {
1193         vlc_mutex_lock( &p_playlist->p_input->stream.stream_lock );
1194         if( p_playlist->p_input->stream.p_selected_area->i_id > 1 )
1195         {
1196             vlc_value_t val; val.b_bool = VLC_TRUE;
1197             vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
1198             var_Set( p_playlist->p_input, "prev-title", val );
1199         } else
1200             vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
1201     }
1202     vlc_mutex_unlock( &p_playlist->object_lock );
1203 #endif
1204
1205     playlist_Prev( p_playlist );
1206     vlc_object_release( p_playlist );
1207 }
1208
1209 void Interface::OnNextStream( wxCommandEvent& WXUNUSED(event) )
1210 {
1211     NextStream();
1212 }
1213
1214 void Interface::NextStream()
1215 {
1216     playlist_t * p_playlist =
1217         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
1218                                        FIND_ANYWHERE );
1219     if( p_playlist == NULL )
1220     {
1221         return;
1222     }
1223
1224     /* FIXME --fenrir */
1225 #if 0
1226     var_Change( p_input, "title", VLC_VAR_CHOICESCOUNT, &val, NULL );
1227     vlc_mutex_lock( &p_playlist->object_lock );
1228     if( p_playlist->p_input != NULL )
1229     {
1230         vlc_mutex_lock( &p_playlist->p_input->stream.stream_lock );
1231         if( p_playlist->p_input->stream.i_area_nb > 1 &&
1232             p_playlist->p_input->stream.p_selected_area->i_id <
1233               p_playlist->p_input->stream.i_area_nb - 1 )
1234         {
1235             vlc_value_t val; val.b_bool = VLC_TRUE;
1236             vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
1237             var_Set( p_playlist->p_input, "next-title", val );
1238         } else
1239             vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
1240     }
1241     vlc_mutex_unlock( &p_playlist->object_lock );
1242 #endif
1243     playlist_Next( p_playlist );
1244     vlc_object_release( p_playlist );
1245 }
1246
1247 void Interface::OnSlowStream( wxCommandEvent& WXUNUSED(event) )
1248 {
1249     input_thread_t *p_input =
1250         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
1251                                            FIND_ANYWHERE );
1252     if( p_input )
1253     {
1254         vlc_value_t val; val.b_bool = VLC_TRUE;
1255
1256         var_Set( p_input, "rate-slower", val );
1257         vlc_object_release( p_input );
1258     }
1259 }
1260
1261 void Interface::OnFastStream( wxCommandEvent& WXUNUSED(event) )
1262 {
1263     input_thread_t *p_input =
1264         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
1265                                            FIND_ANYWHERE );
1266     if( p_input )
1267     {
1268         vlc_value_t val; val.b_bool = VLC_TRUE;
1269
1270         var_Set( p_input, "rate-faster", val );
1271         vlc_object_release( p_input );
1272     }
1273 }
1274
1275 void Interface::TogglePlayButton( int i_playing_status )
1276 {
1277     if( i_playing_status == i_old_playing_status )
1278         return;
1279
1280     wxToolBarToolBase *p_tool = (wxToolBarToolBase *)
1281         GetToolBar()->GetToolClientData( PlayStream_Event );
1282     if( !p_tool ) return;
1283
1284     if( i_playing_status == PLAYING_S )
1285     {
1286         p_tool->SetNormalBitmap( wxBitmap( pause_xpm ) );
1287         p_tool->SetLabel( wxU(_("Pause")) );
1288         p_tool->SetShortHelp( wxU(_(HELP_PAUSE)) );
1289     }
1290     else
1291     {
1292         p_tool->SetNormalBitmap( wxBitmap( play_xpm ) );
1293         p_tool->SetLabel( wxU(_("Play")) );
1294         p_tool->SetShortHelp( wxU(_(HELP_PLAY)) );
1295     }
1296
1297     GetToolBar()->Realize();
1298     GetToolBar()->ToggleTool( PlayStream_Event, true );
1299     GetToolBar()->ToggleTool( PlayStream_Event, false );
1300
1301     i_old_playing_status = i_playing_status;
1302 }
1303
1304 void Interface::OnDiscMenu( wxCommandEvent& WXUNUSED(event) )
1305 {
1306     input_thread_t *p_input =
1307         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
1308                                            FIND_ANYWHERE );
1309     if( p_input )
1310     {
1311         vlc_value_t val; val.i_int = 2;
1312
1313         var_Set( p_input, "title  0", val);
1314         vlc_object_release( p_input );
1315     }
1316 }
1317
1318 void Interface::OnDiscPrev( wxCommandEvent& WXUNUSED(event) )
1319 {
1320     input_thread_t *p_input =
1321         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
1322                                            FIND_ANYWHERE );
1323     if( p_input )
1324     {
1325         int i_type = var_Type( p_input, "prev-chapter" );
1326         vlc_value_t val; val.b_bool = VLC_TRUE;
1327
1328         var_Set( p_input, ( i_type & VLC_VAR_TYPE ) != 0 ?
1329                  "prev-chapter" : "prev-title", val );
1330
1331         vlc_object_release( p_input );
1332     }
1333 }
1334
1335 void Interface::OnDiscNext( wxCommandEvent& WXUNUSED(event) )
1336 {
1337     input_thread_t *p_input =
1338         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
1339                                            FIND_ANYWHERE );
1340     if( p_input )
1341     {
1342         int i_type = var_Type( p_input, "next-chapter" );
1343         vlc_value_t val; val.b_bool = VLC_TRUE;
1344
1345         var_Set( p_input, ( i_type & VLC_VAR_TYPE ) != 0 ?
1346                  "next-chapter" : "next-title", val );
1347
1348         vlc_object_release( p_input );
1349     }
1350 }
1351
1352 #if wxUSE_DRAG_AND_DROP
1353 /*****************************************************************************
1354  * Definition of DragAndDrop class.
1355  *****************************************************************************/
1356 DragAndDrop::DragAndDrop( intf_thread_t *_p_intf, vlc_bool_t _b_enqueue )
1357 {
1358     p_intf = _p_intf;
1359     b_enqueue = _b_enqueue;
1360 }
1361
1362 bool DragAndDrop::OnDropFiles( wxCoord, wxCoord,
1363                                const wxArrayString& filenames )
1364 {
1365     /* Add dropped files to the playlist */
1366
1367     playlist_t *p_playlist =
1368         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
1369                                        FIND_ANYWHERE );
1370     if( p_playlist == NULL )
1371     {
1372         return FALSE;
1373     }
1374
1375     for( size_t i = 0; i < filenames.GetCount(); i++ )
1376     {
1377         char *psz_utf8 = FromUTF32( filenames[i].wc_str() );
1378         playlist_Add( p_playlist, psz_utf8, psz_utf8,
1379                       PLAYLIST_APPEND | ((i | b_enqueue) ? 0 : PLAYLIST_GO),
1380                       PLAYLIST_END );
1381         free( psz_utf8 );
1382     }
1383
1384     vlc_object_release( p_playlist );
1385
1386     return TRUE;
1387 }
1388 #endif
1389
1390 /*****************************************************************************
1391  * Definition of VolCtrl class.
1392  *****************************************************************************/
1393 class wxVolCtrl: public wxGauge
1394 {
1395 public:
1396     /* Constructor */
1397     wxVolCtrl( intf_thread_t *_p_intf, wxWindow* parent, wxWindowID id,
1398                wxPoint = wxDefaultPosition, wxSize = wxSize( 20, -1 ) );
1399     virtual ~wxVolCtrl() {};
1400
1401     void UpdateVolume();
1402     int GetVolume();
1403
1404     void OnChange( wxMouseEvent& event );
1405
1406 private:
1407     intf_thread_t *p_intf;
1408
1409     DECLARE_EVENT_TABLE();
1410 };
1411
1412 BEGIN_EVENT_TABLE(wxVolCtrl, wxWindow)
1413     /* Mouse events */
1414     EVT_LEFT_DOWN(wxVolCtrl::OnChange)
1415     EVT_MOTION(wxVolCtrl::OnChange)
1416 END_EVENT_TABLE()
1417
1418 wxVolCtrl::wxVolCtrl( intf_thread_t *_p_intf, wxWindow* parent, wxWindowID id,
1419                       wxPoint point, wxSize size )
1420   : wxGauge( parent, id, 200, point, size, wxGA_HORIZONTAL | wxGA_SMOOTH )
1421 {
1422     p_intf = _p_intf;
1423     UpdateVolume();
1424 }
1425
1426 void wxVolCtrl::OnChange( wxMouseEvent& event )
1427 {
1428     if( !event.LeftDown() && !event.LeftIsDown() ) return;
1429
1430     int i_volume = event.GetX() * 200 / GetClientSize().GetWidth();
1431     aout_VolumeSet( p_intf, i_volume * AOUT_VOLUME_MAX / 200 / 2 );
1432     UpdateVolume();
1433 }
1434
1435 void wxVolCtrl::UpdateVolume()
1436 {
1437     audio_volume_t i_volume;
1438     aout_VolumeGet( p_intf, &i_volume );
1439
1440     int i_gauge_volume = i_volume * 200 * 2 / AOUT_VOLUME_MAX;
1441     if( i_gauge_volume == GetValue() ) return;
1442
1443     SetValue( i_gauge_volume );
1444     SetToolTip( wxString::Format((wxString)wxU(_("Volume")) + wxT(" %d"),
1445                 i_gauge_volume / 2 ) );
1446 }
1447
1448 #if defined(__WXGTK__)
1449 #define VLCVOL_HEIGHT p_parent->GetSize().GetHeight()
1450 #else
1451 #define VLCVOL_HEIGHT TOOLBAR_BMP_HEIGHT
1452 #endif
1453 VLCVolCtrl::VLCVolCtrl( intf_thread_t *_p_intf, wxWindow *p_parent )
1454   :wxControl( p_parent, -1, wxDefaultPosition, wxSize(64, VLCVOL_HEIGHT ),
1455               wxBORDER_NONE ),
1456    i_y_offset((VLCVOL_HEIGHT - TOOLBAR_BMP_HEIGHT) / 2),
1457    b_mute(0), p_intf(_p_intf)
1458 {
1459     gauge = new wxVolCtrl( p_intf, this, -1, wxPoint( 18, i_y_offset ),
1460                            wxSize( 44, TOOLBAR_BMP_HEIGHT ) );
1461 }
1462
1463 void VLCVolCtrl::OnPaint( wxPaintEvent &evt )
1464 {
1465     wxPaintDC dc( this );
1466     wxBitmap mPlayBitmap( b_mute ? speaker_mute_xpm : speaker_xpm );
1467     dc.DrawBitmap( mPlayBitmap, 0, i_y_offset, TRUE );
1468 }
1469
1470 void VLCVolCtrl::OnChange( wxMouseEvent& event )
1471 {
1472     if( event.GetX() < TOOLBAR_BMP_WIDTH )
1473     {
1474         int i_volume;
1475         aout_VolumeMute( p_intf, (audio_volume_t *)&i_volume );
1476
1477         b_mute = !b_mute;
1478         Refresh();
1479     }
1480 }
1481
1482 void VLCVolCtrl::UpdateVolume()
1483 {
1484     gauge->UpdateVolume();
1485
1486     int i_volume = gauge->GetValue();
1487     if( !!i_volume == !b_mute ) return;
1488     b_mute = !b_mute;
1489     Refresh();
1490 }
1491
1492 /*****************************************************************************
1493  * Systray class.
1494  *****************************************************************************/
1495
1496 #ifdef wxHAS_TASK_BAR_ICON
1497
1498 BEGIN_EVENT_TABLE(Systray, wxTaskBarIcon)
1499     /* Mouse events */
1500 #ifdef WIN32
1501     EVT_TASKBAR_LEFT_DCLICK(Systray::OnLeftClick)
1502 #else
1503     EVT_TASKBAR_LEFT_DOWN(Systray::OnLeftClick)
1504 #endif
1505     /* Menu events */
1506     EVT_MENU(Iconize_Event, Systray::OnMenuIconize)
1507     EVT_MENU(Exit_Event, Systray::OnExit)
1508     EVT_MENU(PlayStream_Event, Systray::OnPlayStream)
1509     EVT_MENU(NextStream_Event, Systray::OnNextStream)
1510     EVT_MENU(PrevStream_Event, Systray::OnPrevStream)
1511     EVT_MENU(StopStream_Event, Systray::OnStopStream)
1512 END_EVENT_TABLE()
1513
1514 Systray::Systray( Interface *_p_main_interface, intf_thread_t *_p_intf )
1515 {
1516     p_main_interface = _p_main_interface;
1517     p_intf = _p_intf;
1518 }
1519
1520 /* Event handlers */
1521 void Systray::OnMenuIconize( wxCommandEvent& event )
1522 {
1523     p_main_interface->Show( ! p_main_interface->IsShown() );
1524     if ( p_main_interface->IsShown() ) p_main_interface->Raise();
1525 }
1526
1527 void Systray::OnLeftClick( wxTaskBarIconEvent& event )
1528 {
1529     wxCommandEvent cevent;
1530     OnMenuIconize(cevent);
1531 }
1532
1533 void Systray::OnExit( wxCommandEvent& event )
1534 {
1535     p_main_interface->Close(TRUE);
1536 }
1537
1538 void Systray::OnPrevStream( wxCommandEvent& event )
1539 {
1540     p_main_interface->PrevStream();
1541 }
1542
1543 void Systray::OnNextStream( wxCommandEvent& event )
1544 {
1545     p_main_interface->NextStream();
1546 }
1547
1548 void Systray::OnPlayStream( wxCommandEvent& event )
1549 {
1550     p_main_interface->PlayStream();
1551 }
1552
1553 void Systray::OnStopStream( wxCommandEvent& event )
1554 {
1555     p_main_interface->StopStream();
1556 }
1557
1558 /* Systray popup menu */
1559 wxMenu* Systray::CreatePopupMenu()
1560 {
1561     int minimal = config_GetInt( p_intf, "wx-minimal" );
1562
1563     wxMenu* systray_menu = new wxMenu;
1564     systray_menu->Append( Exit_Event, wxU(_("Quit VLC")) );
1565     systray_menu->AppendSeparator();
1566     systray_menu->Append( PlayStream_Event, wxU(_("Play/Pause")) );
1567
1568     if (!minimal)
1569     {
1570     systray_menu->Append( PrevStream_Event, wxU(_("Previous")) );
1571     systray_menu->Append( NextStream_Event, wxU(_("Next")) );
1572     systray_menu->Append( StopStream_Event, wxU(_("Stop")) );
1573     }
1574     systray_menu->AppendSeparator();
1575     systray_menu->Append( Iconize_Event, wxU(_("Show/Hide interface")) );
1576     return systray_menu;
1577 }
1578
1579 void Systray::UpdateTooltip( const wxChar* tooltip )
1580 {
1581     SetIcon( wxIcon( vlc16x16_xpm ), tooltip );
1582 }
1583 #endif