]> git.sesse.net Git - vlc/blob - modules/gui/wxwidgets/interface.cpp
* modules/gui/wxwidgets: fixed build when wxWidgets isn't compiled with unicode support.
[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     /* Set minimum window size to prevent user from glitching it */
335     s = GetSize();
336     if( config_GetInt( p_intf, "wx-embed" ) )
337     {
338         wxSize  s2;
339         s2 = video_window->GetSize();
340         s.SetHeight( s.GetHeight() - s2.GetHeight() );
341     }
342     SetMinSize( s );
343
344     /* Show extended GUI if requested */
345     if( ( b_extra = config_GetInt( p_intf, "wx-extended" ) ) )
346         frame_sizer->Show( extra_frame );
347 }
348
349 Interface::~Interface()
350 {
351     WindowSettings *ws = p_intf->p_sys->p_window_settings;
352
353     if( !IsIconized() )
354     {
355         ws->SetSettings( WindowSettings::ID_MAIN, true,
356                          GetPosition(), GetSize() );
357     }
358
359         PopEventHandler(true);
360
361     if( video_window ) delete video_window;
362
363 #ifdef wxHAS_TASK_BAR_ICON
364     if( p_systray ) delete p_systray;
365 #endif
366
367     if( p_intf->p_sys->p_wxwindow ) delete p_intf->p_sys->p_wxwindow;
368
369     /* Clean up */
370     delete timer;
371 }
372
373 void Interface::Init()
374 {
375     /* Misc init */
376     SetupHotkeys();
377 }
378
379 void Interface::Update()
380 {
381     /* Misc updates */
382     ((VLCVolCtrl *)volctrl)->UpdateVolume();
383 }
384
385 void Interface::OnControlEvent( wxCommandEvent& event )
386 {
387     switch( event.GetId() )
388     {
389     case 0:
390         {
391           if( p_intf->p_sys->b_video_autosize )
392           {
393         frame_sizer->Layout();
394         frame_sizer->Fit(this);
395           }
396         }
397         break;
398
399     case 1:
400         long i_style = GetWindowStyle();
401         if( event.GetInt() ) i_style |= wxSTAY_ON_TOP;
402         else i_style &= ~wxSTAY_ON_TOP;
403         SetWindowStyle( i_style );
404         break;
405     }
406 }
407
408 /*****************************************************************************
409  * Private methods.
410  *****************************************************************************/
411 void Interface::CreateOurMenuBar()
412 {
413     int minimal = config_GetInt( p_intf, "wx-minimal" );
414
415     /* Create the "File" menu */
416     wxMenu *file_menu = new wxMenu;
417
418     if (!minimal)
419     {
420     file_menu->Append( OpenFileSimple_Event,
421                        wxU(_("Quick &Open File...\tCtrl-O")) );
422
423     file_menu->AppendSeparator();
424     file_menu->Append( OpenFile_Event, wxU(_("Open &File...\tCtrl-F")) );
425     file_menu->Append( OpenDir_Event, wxU(_("Open Dir&ectory...\tCtrl-E")) );
426     file_menu->Append( OpenDisc_Event, wxU(_("Open &Disc...\tCtrl-D")) );
427     file_menu->Append( OpenNet_Event,
428                        wxU(_("Open &Network Stream...\tCtrl-N")) );
429     file_menu->Append( OpenCapture_Event,
430                        wxU(_("Open C&apture Device...\tCtrl-A")) );
431
432     file_menu->AppendSeparator();
433     file_menu->Append( Wizard_Event, wxU(_("&Wizard...\tCtrl-W")) );
434     file_menu->AppendSeparator();
435     }
436     file_menu->Append( Exit_Event, wxU(_("E&xit\tCtrl-X")) );
437
438     /* Create the "View" menu */
439     wxMenu *view_menu = new wxMenu;
440     if (!minimal)
441     {
442     view_menu->Append( Playlist_Event, wxU(_("&Playlist...\tCtrl-P")) );
443     }
444     view_menu->Append( Logs_Event, wxU(_("&Messages...\tCtrl-M")) );
445     view_menu->Append( FileInfo_Event,
446                        wxU(_("Stream and Media &info...\tCtrl-I")) );
447
448     /* Create the "Auto-generated" menus */
449     p_settings_menu = SettingsMenu( p_intf, this );
450     p_audio_menu = AudioMenu( p_intf, this );
451     p_video_menu = VideoMenu( p_intf, this );
452     p_navig_menu = NavigMenu( p_intf, this );
453
454     /* Create the "Help" menu */
455     wxMenu *help_menu = new wxMenu;
456     help_menu->Append( About_Event, wxU(_("About VLC media player")) );
457     help_menu->AppendSeparator();
458     help_menu->Append( UpdateVLC_Event, wxU(_("Check for updates ...")) );
459
460     /* Append the freshly created menus to the menu bar... */
461     wxMenuBar *menubar = new wxMenuBar();
462     menubar->Append( file_menu, wxU(_("&File")) );
463     menubar->Append( view_menu, wxU(_("&View")) );
464     menubar->Append( p_settings_menu, wxU(_("&Settings")) );
465     menubar->Append( p_audio_menu, wxU(_("&Audio")) );
466     menubar->Append( p_video_menu, wxU(_("&Video")) );
467     menubar->Append( p_navig_menu, wxU(_("&Navigation")) );
468     menubar->Append( help_menu, wxU(_("&Help")) );
469
470     /* Attach the menu bar to the frame */
471     SetMenuBar( menubar );
472
473     /* Find out size of menu bar */
474     int i_size = 0;
475     for( unsigned int i = 0; i < menubar->GetMenuCount(); i++ )
476     {
477         int i_width, i_height;
478         menubar->GetTextExtent( menubar->GetLabelTop(i), &i_width, &i_height );
479         i_size += i_width +
480 #if defined(__WXGTK__)
481             22 /* approximate margin */;
482 #else
483 #if (wxMAJOR_VERSION <= 2) && (wxMINOR_VERSION <= 5) && (wxRELEASE_NUMBER < 3)
484             4 /* approximate margin */;
485 #else
486             18 /* approximate margin */;
487 #endif
488 #endif
489     }
490
491 /* Patch by zcot for menu wrapping */
492 #if defined(WIN32)
493     /* Find out size of msw menu bar */
494     i_size = 0;
495     SIZE sizing;
496     HDC hdc = GetDC( NULL );
497     for( unsigned int i = 0; i < menubar->GetMenuCount(); i++ )
498     {
499         //                [ MENU BUTTON WIDTH CALCULATION ]
500         // [ SM_CXDLGFRAME + pixels + textextent + pixels + SM_CXDLGFRAME ]
501         GetTextExtentPoint32( hdc, menubar->GetLabelTop(i).c_str(),
502                                 menubar->GetLabelTop(i).Length(), &sizing );
503         // + text size..
504         i_size += sizing.cx;
505         // +1 more pixel on each size
506         i_size += 2;
507         // width of 2 DLGFRAME
508         i_size += GetSystemMetrics( SM_CXDLGFRAME ) * 2;
509     }
510     ReleaseDC( NULL, hdc );
511     // Width of 2 edges of app window
512     i_size += GetSystemMetrics( SM_CXSIZEFRAME ) * 2;
513     // + 2 more pixels on each side..
514     i_size += 4;
515 #endif
516 /* End patch by zcot */
517
518     frame_sizer->SetMinSize( i_size, -1 );
519
520     /* Intercept all menu events in our custom event handler */
521     PushEventHandler( new MenuEvtHandler( p_intf, this ) );
522
523 #if wxUSE_DRAG_AND_DROP
524     /* Associate drop targets with the menubar */
525     menubar->SetDropTarget( new DragAndDrop( p_intf ) );
526 #endif
527 }
528
529 void Interface::CreateOurToolBar()
530 {
531 #define HELP_OPEN N_("Open")
532 #define HELP_STOP N_("Stop")
533 #define HELP_PLAY N_("Play")
534 #define HELP_PAUSE N_("Pause")
535 #define HELP_PLO N_("Playlist")
536 #define HELP_PLP N_("Previous playlist item")
537 #define HELP_PLN N_("Next playlist item")
538 #define HELP_SLOW N_("Play slower")
539 #define HELP_FAST N_("Play faster")
540
541     int minimal = config_GetInt( p_intf, "wx-minimal" );
542
543     wxLogNull LogDummy; /* Hack to suppress annoying log message on the win32
544                          * version because we don't include wx.rc */
545
546     wxToolBar *toolbar =
547         CreateToolBar( wxTB_HORIZONTAL | wxTB_FLAT );
548
549     toolbar->SetToolBitmapSize( wxSize(TOOLBAR_BMP_WIDTH,TOOLBAR_BMP_HEIGHT) );
550
551     if (!minimal)
552     {
553     toolbar->AddTool( OpenFile_Event, wxT(""),
554                       wxBitmap( eject_xpm ), wxU(_(HELP_OPEN)) );
555     toolbar->AddSeparator();
556     }
557
558     wxToolBarToolBase *p_tool = toolbar->AddTool( PlayStream_Event, wxT(""),
559                       wxBitmap( play_xpm ), wxU(_(HELP_PLAY)), wxITEM_CHECK );
560     p_tool->SetClientData( p_tool );
561
562     if (!minimal)
563     {
564     toolbar->AddTool( StopStream_Event, wxT(""), wxBitmap( stop_xpm ),
565                       wxU(_(HELP_STOP)) );
566     toolbar->AddSeparator();
567
568     toolbar->AddTool( PrevStream_Event, wxT(""),
569                       wxBitmap( prev_xpm ), wxU(_(HELP_PLP)) );
570     toolbar->AddTool( SlowStream_Event, wxT(""),
571                       wxBitmap( slow_xpm ), wxU(_(HELP_SLOW)) );
572     toolbar->AddTool( FastStream_Event, wxT(""),
573                       wxBitmap( fast_xpm ), wxU(_(HELP_FAST)) );
574     toolbar->AddTool( NextStream_Event, wxT(""), wxBitmap( next_xpm ),
575                       wxU(_(HELP_PLN)) );
576     toolbar->AddSeparator();
577     toolbar->AddTool( Playlist_Event, wxT(""), wxBitmap( playlist_xpm ),
578                       wxU(_(HELP_PLO)) );
579     }
580
581 #if !( (wxMAJOR_VERSION <= 2) && (wxMINOR_VERSION <= 6) && (wxRELEASE_NUMBER < 2) )
582     wxControl *p_dummy_ctrl =
583         new wxControl( toolbar, -1, wxDefaultPosition,
584                        wxSize(35, 16 ), wxBORDER_NONE );
585
586     toolbar->AddControl( p_dummy_ctrl );
587 #endif
588
589     volctrl = new VLCVolCtrl( p_intf, toolbar );
590     toolbar->AddControl( volctrl );
591
592     toolbar->Realize();
593
594 #if wxUSE_DRAG_AND_DROP
595     /* Associate drop targets with the toolbar */
596     toolbar->SetDropTarget( new DragAndDrop( p_intf ) );
597 #endif
598 }
599
600 void Interface::CreateOurSlider()
601 {
602     /* Create a new frame and sizer containing the slider */
603     slider_frame = new wxPanel( this, -1, wxDefaultPosition, wxDefaultSize );
604     slider_frame->SetAutoLayout( TRUE );
605     slider_sizer = new wxBoxSizer( wxHORIZONTAL );
606     //slider_sizer->SetMinSize( -1, 50 );
607
608     /* Create slider */
609     slider = new wxSlider( slider_frame, SliderScroll_Event, 0, 0,
610                            SLIDER_MAX_POS, wxDefaultPosition, wxDefaultSize );
611
612     /* Add Disc Buttons */
613     disc_frame = new wxPanel( slider_frame, -1, wxDefaultPosition,
614                               wxDefaultSize );
615     disc_frame->SetAutoLayout( TRUE );
616     disc_sizer = new wxBoxSizer( wxHORIZONTAL );
617
618     disc_menu_button = new wxBitmapButton( disc_frame, DiscMenu_Event,
619                                            wxBitmap( playlist_xpm ) );
620     disc_prev_button = new wxBitmapButton( disc_frame, DiscPrev_Event,
621                                            wxBitmap( prev_xpm ) );
622     disc_next_button = new wxBitmapButton( disc_frame, DiscNext_Event,
623                                            wxBitmap( next_xpm ) );
624
625     disc_sizer->Add( disc_menu_button, 1, wxEXPAND | wxLEFT | wxRIGHT, 1 );
626     disc_sizer->Add( disc_prev_button, 1, wxEXPAND | wxLEFT | wxRIGHT, 1 );
627     disc_sizer->Add( disc_next_button, 1, wxEXPAND | wxLEFT | wxRIGHT, 1 );
628
629     disc_frame->SetSizer( disc_sizer );
630     disc_sizer->Layout();
631
632     /* Add everything to the frame */
633     slider_sizer->Add( slider, 1, wxEXPAND | wxALL, 5 );
634     slider_sizer->Add( disc_frame, 0, wxALL, 2 );
635     slider_frame->SetSizer( slider_sizer );
636
637     disc_frame->Hide();
638     slider_sizer->Hide( disc_frame );
639
640     slider_sizer->Layout();
641     slider_sizer->Fit( slider_frame );
642
643     /* Hide the slider by default */
644     slider_frame->Hide();
645 }
646
647 static int ConvertHotkeyModifiers( int i_hotkey )
648 {
649     int i_accel_flags = 0;
650     if( i_hotkey & KEY_MODIFIER_ALT ) i_accel_flags |= wxACCEL_ALT;
651     if( i_hotkey & KEY_MODIFIER_CTRL ) i_accel_flags |= wxACCEL_CTRL;
652     if( i_hotkey & KEY_MODIFIER_SHIFT ) i_accel_flags |= wxACCEL_SHIFT;
653     if( !i_accel_flags ) i_accel_flags = wxACCEL_NORMAL;
654     return i_accel_flags;
655 }
656
657 static int ConvertHotkey( int i_hotkey )
658 {
659     int i_key = i_hotkey & ~KEY_MODIFIER;
660     if( i_key & KEY_ASCII ) return i_key & KEY_ASCII;
661     else if( i_key & KEY_SPECIAL )
662     {
663         switch ( i_key )
664         {
665         case KEY_LEFT: return WXK_LEFT;
666         case KEY_RIGHT: return WXK_RIGHT;
667         case KEY_UP: return WXK_UP;
668         case KEY_DOWN: return WXK_DOWN;
669         case KEY_SPACE: return WXK_SPACE;
670         case KEY_ENTER: return WXK_RETURN;
671         case KEY_F1: return WXK_F1;
672         case KEY_F2: return WXK_F2;
673         case KEY_F3: return WXK_F3;
674         case KEY_F4: return WXK_F4;
675         case KEY_F5: return WXK_F5;
676         case KEY_F6: return WXK_F6;
677         case KEY_F7: return WXK_F7;
678         case KEY_F8: return WXK_F8;
679         case KEY_F9: return WXK_F9;
680         case KEY_F10: return WXK_F10;
681         case KEY_F11: return WXK_F11;
682         case KEY_F12: return WXK_F12;
683         case KEY_HOME: return WXK_HOME;
684         case KEY_END: return WXK_END;
685         case KEY_INSERT: return WXK_INSERT;
686         case KEY_DELETE: return WXK_DELETE;
687         case KEY_MENU: return WXK_MENU;
688         case KEY_ESC: return WXK_ESCAPE;
689         case KEY_PAGEUP: return WXK_PRIOR;
690         case KEY_PAGEDOWN: return WXK_NEXT;
691         case KEY_TAB: return WXK_TAB;
692         case KEY_BACKSPACE: return WXK_BACK;
693         }
694     }
695     return WXK_F24;
696 }
697
698 void Interface::SetupHotkeys()
699 {
700     struct vlc_t::hotkey *p_hotkeys = p_intf->p_vlc->p_hotkeys;
701     int i_hotkeys;
702
703     /* Count number of hoteys */
704     for( i_hotkeys = 0; p_hotkeys[i_hotkeys].psz_action != NULL; i_hotkeys++ );
705
706     p_intf->p_sys->i_first_hotkey_event = wxID_HIGHEST + 7000;
707     p_intf->p_sys->i_hotkeys = i_hotkeys;
708
709     wxAcceleratorEntry *p_entries = new wxAcceleratorEntry[i_hotkeys];
710
711     /* Setup the hotkeys as accelerators */
712     for( int i = 0; i < i_hotkeys; i++ )
713     {
714         int i_mod = ConvertHotkeyModifiers( p_hotkeys[i].i_key );
715         int i_key = ConvertHotkey( p_hotkeys[i].i_key );
716
717 #ifdef WIN32
718         if( !(p_hotkeys[i].i_key & KEY_SPECIAL) && i_mod )
719             i_key = toupper(i_key);
720 #endif
721
722         p_entries[i].Set( i_mod, i_key,
723                           p_intf->p_sys->i_first_hotkey_event + i );
724     }
725
726     wxAcceleratorTable accel( i_hotkeys, p_entries );
727
728     if( !accel.Ok() )
729     {
730         msg_Err( p_intf, "invalid accelerator table" );
731     }
732     else
733     {
734         SetAcceleratorTable( accel );
735     }
736
737     delete [] p_entries;
738 }
739
740 void Interface::HideSlider( bool layout )
741 {
742     ShowSlider( false, layout );
743 }
744
745 void Interface::ShowSlider( bool show, bool layout )
746 {
747     if( show )
748     {
749         //prevent the hide timers from hiding it now
750         m_slider_timer.Stop();
751         m_controls_timer.Stop();
752
753         //prevent continuous layout
754         if( slider_frame->IsShown() ) return;
755     }
756     else
757     {
758         //prevent continuous layout
759         if( !slider_frame->IsShown() ) return;
760     }
761
762     if( layout && p_intf->p_sys->b_video_autosize )
763         UpdateVideoWindow( p_intf, video_window );
764
765     slider_frame->Show( show );
766     frame_sizer->Show( slider_frame, show );
767
768     if( layout )
769     {
770         frame_sizer->Layout();
771         if( p_intf->p_sys->b_video_autosize ) frame_sizer->Fit( this );
772     }
773 }
774
775 void Interface::HideDiscFrame( bool layout )
776 {
777     ShowDiscFrame( false, layout );
778 }
779
780 void Interface::ShowDiscFrame( bool show, bool layout )
781 {
782     if( show )
783     {
784         //prevent the hide timer from hiding it now
785         m_controls_timer.Stop();
786
787         //prevent continuous layout
788         if( disc_frame->IsShown() ) return;
789     }
790     else
791     {
792         //prevent continuous layout
793         if( !disc_frame->IsShown() ) return;
794     }
795
796     if( layout && p_intf->p_sys->b_video_autosize )
797         UpdateVideoWindow( p_intf, video_window );
798
799     disc_frame->Show( show );
800     slider_sizer->Show( disc_frame, show );
801
802     if( layout )
803     {
804         slider_sizer->Layout();
805         if( p_intf->p_sys->b_video_autosize )
806             slider_sizer->Fit( slider_frame );
807     }
808 }
809
810 /*****************************************************************************
811  * Event Handlers.
812  *****************************************************************************/
813 void Interface::OnControlsTimer( wxTimerEvent& WXUNUSED(event) )
814 {
815     if( p_intf->p_sys->b_video_autosize )
816         UpdateVideoWindow( p_intf, video_window );
817
818     /* Hide slider and Disc Buttons */
819     //postpone layout, we'll do it ourselves
820     HideDiscFrame( false );
821     HideSlider( false );
822
823     slider_sizer->Layout();
824     if( p_intf->p_sys->b_video_autosize )
825     {
826         slider_sizer->Fit( slider_frame );
827         frame_sizer->Fit( this );
828     }
829 }
830
831 void Interface::OnSliderTimer( wxTimerEvent& WXUNUSED(event) )
832 {
833     HideSlider();
834 }
835
836 void Interface::OnMenuOpen( wxMenuEvent& event )
837 {
838 #if defined( __WXMSW__ )
839 #   define GetEventObject GetMenu
840 #endif
841
842     if( event.GetEventObject() == p_settings_menu )
843     {
844         p_settings_menu = SettingsMenu( p_intf, this, p_settings_menu );
845
846         /* Add static items */
847         p_settings_menu->AppendCheckItem( Extended_Event,
848             wxU(_("Extended &GUI\tCtrl-G") ) );
849         if( b_extra ) p_settings_menu->Check( Extended_Event, TRUE );
850 #if 0
851         p_settings_menu->AppendCheckItem( Undock_Event,
852             wxU(_("&Undock Ext. GUI") ) );
853         if( b_undock ) p_settings_menu->Check( Undock_Event, TRUE );
854 #endif
855         p_settings_menu->Append( Bookmarks_Event,
856                                  wxU(_("&Bookmarks...\tCtrl-B") ) );
857         p_settings_menu->Append( Prefs_Event,
858                                  wxU(_("Preference&s...\tCtrl-S")) );
859     }
860
861     else if( event.GetEventObject() == p_audio_menu )
862     {
863         p_audio_menu = AudioMenu( p_intf, this, p_audio_menu );
864     }
865
866     else if( event.GetEventObject() == p_video_menu )
867     {
868         p_video_menu = VideoMenu( p_intf, this, p_video_menu );
869     }
870
871     else if( event.GetEventObject() == p_navig_menu )
872     {
873         p_navig_menu = NavigMenu( p_intf, this, p_navig_menu );
874     }
875
876 #if defined( __WXMSW__ )
877 #   undef GetEventObject
878 #endif
879 }
880
881 #if defined( __WXMSW__ ) || defined( __WXMAC__ )
882 void Interface::OnContextMenu2(wxContextMenuEvent& event)
883 {
884     /* Only show the context menu for the main interface */
885     if( GetId() != event.GetId() )
886     {
887         event.Skip();
888         return;
889     }
890
891     if( p_intf->p_sys->pf_show_dialog )
892         p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU, 1, 0 );
893 }
894 #endif
895 void Interface::OnContextMenu(wxMouseEvent& event)
896 {
897     if( p_intf->p_sys->pf_show_dialog )
898         p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU, 1, 0 );
899 }
900
901 void Interface::OnExit( wxCommandEvent& WXUNUSED(event) )
902 {
903     /* TRUE is to force the frame to close. */
904     Close(TRUE);
905 }
906
907 void Interface::OnAbout( wxCommandEvent& WXUNUSED(event) )
908 {
909     wxString msg;
910     msg.Printf( wxString(wxT("VLC media player " PACKAGE_VERSION)) +
911         wxU(_(" (wxWidgets interface)\n\n")) +
912         wxU(_("(c) 1996-2005 - the VideoLAN Team\n\n")) +
913        wxU(_("Compiled by "))+ wxU(VLC_CompileBy())+ wxU("@") +
914        wxU(VLC_CompileHost())+ wxT(".")+ wxU(VLC_CompileDomain())+ wxT(".\n") +
915        wxU(_("Compiler: "))+ wxU(VLC_Compiler())+wxT( ".\n") +
916        wxU(_("Based on SVN revision: "))+wxU(VLC_Changeset())+wxT(".\n\n") +
917 #ifdef __WXMSW__
918         wxU( vlc_wraptext(INTF_ABOUT_MSG,WRAPCOUNT,VLC_TRUE) ) + wxT("\n\n") +
919 #else
920         wxU( INTF_ABOUT_MSG ) + wxT("\n\n") +
921 #endif
922         wxU(_("The VideoLAN team <videolan@videolan.org>\n"
923               "http://www.videolan.org/\n\n")) );
924
925     wxMessageBox( msg, wxString::Format(wxU(_("About %s")),
926                   wxT("VLC media player")), wxOK | wxICON_INFORMATION, this );
927 }
928
929 void Interface::OnShowDialog( wxCommandEvent& event )
930 {
931     if( p_intf->p_sys->pf_show_dialog )
932     {
933         int i_id;
934
935         switch( event.GetId() )
936         {
937         case OpenFileSimple_Event:
938             i_id = INTF_DIALOG_FILE_SIMPLE;
939             break;
940         case OpenAdv_Event:
941             i_id = INTF_DIALOG_FILE;
942         case OpenFile_Event:
943             i_id = INTF_DIALOG_FILE;
944             break;
945         case OpenDir_Event:
946             i_id = INTF_DIALOG_DIRECTORY;
947             break;
948         case OpenDisc_Event:
949             i_id = INTF_DIALOG_DISC;
950             break;
951         case OpenNet_Event:
952             i_id = INTF_DIALOG_NET;
953             break;
954         case OpenCapture_Event:
955             i_id = INTF_DIALOG_CAPTURE;
956             break;
957         case OpenSat_Event:
958             i_id = INTF_DIALOG_SAT;
959             break;
960         case Playlist_Event:
961             i_id = INTF_DIALOG_PLAYLIST;
962             break;
963         case Logs_Event:
964             i_id = INTF_DIALOG_MESSAGES;
965             break;
966         case FileInfo_Event:
967             i_id = INTF_DIALOG_FILEINFO;
968             break;
969         case Prefs_Event:
970             i_id = INTF_DIALOG_PREFS;
971             break;
972         case Wizard_Event:
973             i_id = INTF_DIALOG_WIZARD;
974             break;
975         case Bookmarks_Event:
976             i_id = INTF_DIALOG_BOOKMARKS;
977             break;
978         case UpdateVLC_Event:
979             i_id = INTF_DIALOG_UPDATEVLC;
980             break;
981         default:
982             i_id = INTF_DIALOG_FILE;
983             break;
984         }
985
986         p_intf->p_sys->pf_show_dialog( p_intf, i_id, 1, 0 );
987     }
988 }
989
990 void Interface::OnExtended(wxCommandEvent& event)
991 {
992     b_extra = (b_extra == VLC_TRUE ? VLC_FALSE : VLC_TRUE );
993
994     if( b_extra == VLC_FALSE )
995     {
996         extra_frame->Hide();
997         frame_sizer->Hide( extra_frame );
998     }
999     else
1000     {
1001         extra_frame->Show();
1002         frame_sizer->Show( extra_frame );
1003     }
1004     frame_sizer->Layout();
1005     frame_sizer->Fit(this);
1006 }
1007
1008 #if 0
1009         if( b_undock == VLC_TRUE )
1010         {
1011                 fprintf(stderr,"Deleting window\n");
1012             if( extra_window )
1013             {
1014                 delete extra_window;
1015                 extra_window = NULL;
1016             }
1017         }
1018         else
1019         {
1020             extra_frame->Hide();
1021             frame_sizer->Hide( extra_frame );
1022             frame_sizer->Layout();
1023             frame_sizer->Fit(this);
1024         }
1025     }
1026     else
1027     {
1028         if( b_undock == VLC_TRUE )
1029         {
1030                 fprintf(stderr,"Creating window\n");
1031             extra_frame->Hide();
1032             frame_sizer->Hide( extra_frame );
1033 #if (wxCHECK_VERSION(2,5,0))
1034             frame_sizer->Detach( extra_frame );
1035 #else
1036             frame_sizer->Remove( extra_frame );
1037 #endif
1038             frame_sizer->Layout();
1039             frame_sizer->Fit(this);
1040             extra_window = new ExtraWindow( p_intf, this, extra_frame );
1041         }
1042         else
1043         {
1044                 fprintf(stderr,"Deleting window\n");
1045             if( extra_window )
1046             {
1047                 delete extra_window;
1048             }
1049             extra_frame->Show();
1050             frame_sizer->Show( extra_frame );
1051             frame_sizer->Layout();
1052             frame_sizer->Fit(this);
1053         }
1054     }
1055 }
1056
1057 void Interface::OnUndock(wxCommandEvent& event)
1058 {
1059     b_undock = (b_undock == VLC_TRUE ? VLC_FALSE : VLC_TRUE );
1060
1061     if( b_extra == VLC_TRUE )
1062     {
1063         if( b_undock == VLC_FALSE )
1064         {
1065                 fprintf(stderr,"Deleting window\n");
1066             if( extra_window )
1067             {
1068                 delete extra_window;
1069                 extra_window = NULL;
1070             }
1071             extra_frame->Show();
1072             frame_sizer->Show( extra_frame );
1073             frame_sizer->Layout();
1074             frame_sizer->Fit(this);
1075         }
1076         else
1077         {
1078                 fprintf(stderr,"Creating window\n");
1079             extra_frame->Hide();
1080             frame_sizer->Hide( extra_frame );
1081 #if (wxCHECK_VERSION(2,5,0))
1082             frame_sizer->Detach( extra_frame );
1083 #else
1084             frame_sizer->Remove( extra_frame );
1085 #endif
1086             frame_sizer->Layout();
1087             frame_sizer->Fit(this);
1088             extra_window = new ExtraWindow( p_intf, this, extra_frame );
1089         }
1090     }
1091 }
1092 #endif
1093
1094
1095 void Interface::OnPlayStream( wxCommandEvent& WXUNUSED(event) )
1096 {
1097     PlayStream();
1098 }
1099
1100 void Interface::PlayStream()
1101 {
1102     wxCommandEvent dummy;
1103     playlist_t *p_playlist =
1104         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
1105                                        FIND_ANYWHERE );
1106     if( p_playlist == NULL ) return;
1107
1108     if( p_playlist->i_size && p_playlist->i_enabled )
1109     {
1110         vlc_value_t state;
1111
1112         input_thread_t *p_input = (input_thread_t *)vlc_object_find( p_intf,
1113                                                        VLC_OBJECT_INPUT,
1114                                                        FIND_ANYWHERE );
1115         if( p_input == NULL )
1116         {
1117             /* No stream was playing, start one */
1118             playlist_Play( p_playlist );
1119             TogglePlayButton( PLAYING_S );
1120             vlc_object_release( p_playlist );
1121             return;
1122         }
1123
1124         var_Get( p_input, "state", &state );
1125
1126         if( state.i_int != PAUSE_S )
1127         {
1128             /* A stream is being played, pause it */
1129             state.i_int = PAUSE_S;
1130         }
1131         else
1132         {
1133             /* Stream is paused, resume it */
1134             state.i_int = PLAYING_S;
1135         }
1136         var_Set( p_input, "state", state );
1137
1138         TogglePlayButton( state.i_int );
1139         vlc_object_release( p_input );
1140         vlc_object_release( p_playlist );
1141     }
1142     else
1143     {
1144         /* If the playlist is empty, open a file requester instead */
1145         vlc_object_release( p_playlist );
1146         OnShowDialog( dummy );
1147     }
1148 }
1149
1150 void Interface::OnStopStream( wxCommandEvent& WXUNUSED(event) )
1151 {
1152     StopStream();
1153 }
1154 void Interface::StopStream()
1155 {
1156     playlist_t * p_playlist =
1157         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
1158                                        FIND_ANYWHERE );
1159     if( p_playlist == NULL )
1160     {
1161         return;
1162     }
1163
1164     playlist_Stop( p_playlist );
1165     TogglePlayButton( PAUSE_S );
1166     vlc_object_release( p_playlist );
1167 }
1168
1169 void Interface::OnSliderUpdate( wxScrollEvent& event )
1170 {
1171     vlc_mutex_lock( &p_intf->change_lock );
1172
1173 #ifdef WIN32
1174     if( event.GetEventType() == wxEVT_SCROLL_THUMBRELEASE
1175         || event.GetEventType() == wxEVT_SCROLL_ENDSCROLL )
1176     {
1177 #endif
1178         if( p_intf->p_sys->i_slider_pos != event.GetPosition()
1179             && p_intf->p_sys->p_input )
1180         {
1181             vlc_value_t pos;
1182             pos.f_float = (float)event.GetPosition() / (float)SLIDER_MAX_POS;
1183
1184             var_Set( p_intf->p_sys->p_input, "position", pos );
1185         }
1186
1187 #ifdef WIN32
1188         p_intf->p_sys->b_slider_free = VLC_TRUE;
1189     }
1190     else
1191     {
1192         p_intf->p_sys->b_slider_free = VLC_FALSE;
1193
1194         if( p_intf->p_sys->p_input )
1195         {
1196             /* Update stream date */
1197             char psz_time[ MSTRTIME_MAX_SIZE ], psz_total[ MSTRTIME_MAX_SIZE ];
1198             mtime_t i_seconds;
1199
1200             i_seconds = var_GetTime( p_intf->p_sys->p_input, "length" ) /
1201                         I64C(1000000 );
1202             secstotimestr( psz_total, i_seconds );
1203
1204             i_seconds = var_GetTime( p_intf->p_sys->p_input, "time" ) /
1205                         I64C(1000000 );
1206             secstotimestr( psz_time, i_seconds );
1207
1208             statusbar->SetStatusText( wxU(psz_time) + wxString(wxT(" / ") ) +
1209                                       wxU(psz_total), 0 );
1210         }
1211     }
1212 #endif
1213
1214 #undef WIN32
1215     vlc_mutex_unlock( &p_intf->change_lock );
1216 }
1217
1218 void Interface::OnPrevStream( wxCommandEvent& WXUNUSED(event) )
1219 {
1220     PrevStream();
1221 }
1222
1223 void Interface::PrevStream()
1224 {
1225     playlist_t * p_playlist =
1226         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
1227                                        FIND_ANYWHERE );
1228     if( p_playlist == NULL )
1229     {
1230         return;
1231     }
1232
1233     /* FIXME --fenrir */
1234 #if 0
1235     if( p_playlist->p_input != NULL )
1236     {
1237         vlc_mutex_lock( &p_playlist->p_input->stream.stream_lock );
1238         if( p_playlist->p_input->stream.p_selected_area->i_id > 1 )
1239         {
1240             vlc_value_t val; val.b_bool = VLC_TRUE;
1241             vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
1242             var_Set( p_playlist->p_input, "prev-title", val );
1243         } else
1244             vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
1245     }
1246     vlc_mutex_unlock( &p_playlist->object_lock );
1247 #endif
1248
1249     playlist_Prev( p_playlist );
1250     vlc_object_release( p_playlist );
1251 }
1252
1253 void Interface::OnNextStream( wxCommandEvent& WXUNUSED(event) )
1254 {
1255     NextStream();
1256 }
1257
1258 void Interface::NextStream()
1259 {
1260     playlist_t * p_playlist =
1261         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
1262                                        FIND_ANYWHERE );
1263     if( p_playlist == NULL )
1264     {
1265         return;
1266     }
1267
1268     /* FIXME --fenrir */
1269 #if 0
1270     var_Change( p_input, "title", VLC_VAR_CHOICESCOUNT, &val, NULL );
1271     vlc_mutex_lock( &p_playlist->object_lock );
1272     if( p_playlist->p_input != NULL )
1273     {
1274         vlc_mutex_lock( &p_playlist->p_input->stream.stream_lock );
1275         if( p_playlist->p_input->stream.i_area_nb > 1 &&
1276             p_playlist->p_input->stream.p_selected_area->i_id <
1277               p_playlist->p_input->stream.i_area_nb - 1 )
1278         {
1279             vlc_value_t val; val.b_bool = VLC_TRUE;
1280             vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
1281             var_Set( p_playlist->p_input, "next-title", val );
1282         } else
1283             vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
1284     }
1285     vlc_mutex_unlock( &p_playlist->object_lock );
1286 #endif
1287     playlist_Next( p_playlist );
1288     vlc_object_release( p_playlist );
1289 }
1290
1291 void Interface::OnSlowStream( wxCommandEvent& WXUNUSED(event) )
1292 {
1293     input_thread_t *p_input =
1294         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
1295                                            FIND_ANYWHERE );
1296     if( p_input )
1297     {
1298         vlc_value_t val; val.b_bool = VLC_TRUE;
1299
1300         var_Set( p_input, "rate-slower", val );
1301         vlc_object_release( p_input );
1302     }
1303 }
1304
1305 void Interface::OnFastStream( wxCommandEvent& WXUNUSED(event) )
1306 {
1307     input_thread_t *p_input =
1308         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
1309                                            FIND_ANYWHERE );
1310     if( p_input )
1311     {
1312         vlc_value_t val; val.b_bool = VLC_TRUE;
1313
1314         var_Set( p_input, "rate-faster", val );
1315         vlc_object_release( p_input );
1316     }
1317 }
1318
1319 void Interface::TogglePlayButton( int i_playing_status )
1320 {
1321     if( i_playing_status == i_old_playing_status )
1322         return;
1323
1324     wxToolBarToolBase *p_tool = (wxToolBarToolBase *)
1325         GetToolBar()->GetToolClientData( PlayStream_Event );
1326     if( !p_tool ) return;
1327
1328     if( i_playing_status == PLAYING_S )
1329     {
1330         p_tool->SetNormalBitmap( wxBitmap( pause_xpm ) );
1331         p_tool->SetLabel( wxU(_("Pause")) );
1332         p_tool->SetShortHelp( wxU(_(HELP_PAUSE)) );
1333     }
1334     else
1335     {
1336         p_tool->SetNormalBitmap( wxBitmap( play_xpm ) );
1337         p_tool->SetLabel( wxU(_("Play")) );
1338         p_tool->SetShortHelp( wxU(_(HELP_PLAY)) );
1339     }
1340
1341     GetToolBar()->Realize();
1342     GetToolBar()->ToggleTool( PlayStream_Event, true );
1343     GetToolBar()->ToggleTool( PlayStream_Event, false );
1344
1345     i_old_playing_status = i_playing_status;
1346 }
1347
1348 void Interface::OnDiscMenu( wxCommandEvent& WXUNUSED(event) )
1349 {
1350     input_thread_t *p_input =
1351         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
1352                                            FIND_ANYWHERE );
1353     if( p_input )
1354     {
1355         vlc_value_t val; val.i_int = 2;
1356
1357         var_Set( p_input, "title  0", val);
1358         vlc_object_release( p_input );
1359     }
1360 }
1361
1362 void Interface::OnDiscPrev( wxCommandEvent& WXUNUSED(event) )
1363 {
1364     input_thread_t *p_input =
1365         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
1366                                            FIND_ANYWHERE );
1367     if( p_input )
1368     {
1369         int i_type = var_Type( p_input, "prev-chapter" );
1370         vlc_value_t val; val.b_bool = VLC_TRUE;
1371
1372         var_Set( p_input, ( i_type & VLC_VAR_TYPE ) != 0 ?
1373                  "prev-chapter" : "prev-title", val );
1374
1375         vlc_object_release( p_input );
1376     }
1377 }
1378
1379 void Interface::OnDiscNext( wxCommandEvent& WXUNUSED(event) )
1380 {
1381     input_thread_t *p_input =
1382         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
1383                                            FIND_ANYWHERE );
1384     if( p_input )
1385     {
1386         int i_type = var_Type( p_input, "next-chapter" );
1387         vlc_value_t val; val.b_bool = VLC_TRUE;
1388
1389         var_Set( p_input, ( i_type & VLC_VAR_TYPE ) != 0 ?
1390                  "next-chapter" : "next-title", val );
1391
1392         vlc_object_release( p_input );
1393     }
1394 }
1395
1396 #if wxUSE_DRAG_AND_DROP
1397 /*****************************************************************************
1398  * Definition of DragAndDrop class.
1399  *****************************************************************************/
1400 DragAndDrop::DragAndDrop( intf_thread_t *_p_intf, vlc_bool_t _b_enqueue )
1401 {
1402     p_intf = _p_intf;
1403     b_enqueue = _b_enqueue;
1404 }
1405
1406 bool DragAndDrop::OnDropFiles( wxCoord, wxCoord,
1407                                const wxArrayString& filenames )
1408 {
1409     /* Add dropped files to the playlist */
1410
1411     playlist_t *p_playlist =
1412         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
1413                                        FIND_ANYWHERE );
1414     if( p_playlist == NULL )
1415     {
1416         return FALSE;
1417     }
1418
1419     for( size_t i = 0; i < filenames.GetCount(); i++ )
1420     {
1421         char *psz_utf8 = wxFromLocale( filenames[i] );
1422         playlist_Add( p_playlist, psz_utf8, psz_utf8,
1423                       PLAYLIST_APPEND | ((i | b_enqueue) ? 0 : PLAYLIST_GO),
1424                       PLAYLIST_END );
1425         wxLocaleFree( psz_utf8 );
1426     }
1427
1428     vlc_object_release( p_playlist );
1429
1430     return TRUE;
1431 }
1432 #endif
1433
1434 /*****************************************************************************
1435  * Definition of VolCtrl class.
1436  *****************************************************************************/
1437 class wxVolCtrl: public wxGauge
1438 {
1439 public:
1440     /* Constructor */
1441     wxVolCtrl( intf_thread_t *_p_intf, wxWindow* parent, wxWindowID id,
1442                wxPoint = wxDefaultPosition, wxSize = wxSize( 20, -1 ) );
1443     virtual ~wxVolCtrl() {};
1444
1445     void UpdateVolume();
1446     int GetVolume();
1447
1448     void OnChange( wxMouseEvent& event );
1449
1450 private:
1451     intf_thread_t *p_intf;
1452
1453     DECLARE_EVENT_TABLE();
1454 };
1455
1456 BEGIN_EVENT_TABLE(wxVolCtrl, wxWindow)
1457     /* Mouse events */
1458     EVT_LEFT_DOWN(wxVolCtrl::OnChange)
1459     EVT_MOTION(wxVolCtrl::OnChange)
1460 END_EVENT_TABLE()
1461
1462 wxVolCtrl::wxVolCtrl( intf_thread_t *_p_intf, wxWindow* parent, wxWindowID id,
1463                       wxPoint point, wxSize size )
1464   : wxGauge( parent, id, 200, point, size, wxGA_HORIZONTAL | wxGA_SMOOTH )
1465 {
1466     p_intf = _p_intf;
1467     UpdateVolume();
1468 }
1469
1470 void wxVolCtrl::OnChange( wxMouseEvent& event )
1471 {
1472     if( !event.LeftDown() && !event.LeftIsDown() ) return;
1473
1474     int i_volume = event.GetX() * 200 / GetClientSize().GetWidth();
1475     aout_VolumeSet( p_intf, i_volume * AOUT_VOLUME_MAX / 200 / 2 );
1476     UpdateVolume();
1477 }
1478
1479 void wxVolCtrl::UpdateVolume()
1480 {
1481     audio_volume_t i_volume;
1482     aout_VolumeGet( p_intf, &i_volume );
1483
1484     int i_gauge_volume = i_volume * 200 * 2 / AOUT_VOLUME_MAX;
1485     if( i_gauge_volume == GetValue() ) return;
1486
1487     SetValue( i_gauge_volume );
1488     SetToolTip( wxString::Format((wxString)wxU(_("Volume")) + wxT(" %d"),
1489                 i_gauge_volume / 2 ) );
1490 }
1491
1492 #if defined(__WXGTK__)
1493 #define VLCVOL_HEIGHT p_parent->GetSize().GetHeight()
1494 #else
1495 #define VLCVOL_HEIGHT TOOLBAR_BMP_HEIGHT
1496 #endif
1497 VLCVolCtrl::VLCVolCtrl( intf_thread_t *_p_intf, wxWindow *p_parent )
1498   :wxControl( p_parent, -1, wxDefaultPosition, wxSize(64, VLCVOL_HEIGHT ),
1499               wxBORDER_NONE ),
1500    i_y_offset((VLCVOL_HEIGHT - TOOLBAR_BMP_HEIGHT) / 2),
1501    b_mute(0), p_intf(_p_intf)
1502 {
1503     gauge = new wxVolCtrl( p_intf, this, -1, wxPoint( 18, i_y_offset ),
1504                            wxSize( 44, TOOLBAR_BMP_HEIGHT ) );
1505 }
1506
1507 void VLCVolCtrl::OnPaint( wxPaintEvent &evt )
1508 {
1509     wxPaintDC dc( this );
1510     wxBitmap mPlayBitmap( b_mute ? speaker_mute_xpm : speaker_xpm );
1511     dc.DrawBitmap( mPlayBitmap, 0, i_y_offset, TRUE );
1512 }
1513
1514 void VLCVolCtrl::OnChange( wxMouseEvent& event )
1515 {
1516     if( event.GetX() < TOOLBAR_BMP_WIDTH )
1517     {
1518         int i_volume;
1519         aout_VolumeMute( p_intf, (audio_volume_t *)&i_volume );
1520
1521         b_mute = !b_mute;
1522         Refresh();
1523     }
1524 }
1525
1526 void VLCVolCtrl::UpdateVolume()
1527 {
1528     gauge->UpdateVolume();
1529
1530     int i_volume = gauge->GetValue();
1531     if( !!i_volume == !b_mute ) return;
1532     b_mute = !b_mute;
1533     Refresh();
1534 }
1535
1536 /*****************************************************************************
1537  * Systray class.
1538  *****************************************************************************/
1539
1540 #ifdef wxHAS_TASK_BAR_ICON
1541
1542 BEGIN_EVENT_TABLE(Systray, wxTaskBarIcon)
1543     /* Mouse events */
1544 #ifdef WIN32
1545     EVT_TASKBAR_LEFT_DCLICK(Systray::OnLeftClick)
1546 #else
1547     EVT_TASKBAR_LEFT_DOWN(Systray::OnLeftClick)
1548 #endif
1549     /* Menu events */
1550     EVT_MENU(Iconize_Event, Systray::OnMenuIconize)
1551     EVT_MENU(Exit_Event, Systray::OnExit)
1552     EVT_MENU(PlayStream_Event, Systray::OnPlayStream)
1553     EVT_MENU(NextStream_Event, Systray::OnNextStream)
1554     EVT_MENU(PrevStream_Event, Systray::OnPrevStream)
1555     EVT_MENU(StopStream_Event, Systray::OnStopStream)
1556 END_EVENT_TABLE()
1557
1558 Systray::Systray( Interface *_p_main_interface, intf_thread_t *_p_intf )
1559 {
1560     p_main_interface = _p_main_interface;
1561     p_intf = _p_intf;
1562 }
1563
1564 /* Event handlers */
1565 void Systray::OnMenuIconize( wxCommandEvent& event )
1566 {
1567     p_main_interface->Show( ! p_main_interface->IsShown() );
1568     if ( p_main_interface->IsShown() ) p_main_interface->Raise();
1569 }
1570
1571 void Systray::OnLeftClick( wxTaskBarIconEvent& event )
1572 {
1573     wxCommandEvent cevent;
1574     OnMenuIconize(cevent);
1575 }
1576
1577 void Systray::OnExit( wxCommandEvent& event )
1578 {
1579     p_main_interface->Close(TRUE);
1580 }
1581
1582 void Systray::OnPrevStream( wxCommandEvent& event )
1583 {
1584     p_main_interface->PrevStream();
1585 }
1586
1587 void Systray::OnNextStream( wxCommandEvent& event )
1588 {
1589     p_main_interface->NextStream();
1590 }
1591
1592 void Systray::OnPlayStream( wxCommandEvent& event )
1593 {
1594     p_main_interface->PlayStream();
1595 }
1596
1597 void Systray::OnStopStream( wxCommandEvent& event )
1598 {
1599     p_main_interface->StopStream();
1600 }
1601
1602 /* Systray popup menu */
1603 wxMenu* Systray::CreatePopupMenu()
1604 {
1605     int minimal = config_GetInt( p_intf, "wx-minimal" );
1606
1607     wxMenu* systray_menu = new wxMenu;
1608     systray_menu->Append( Exit_Event, wxU(_("Quit VLC")) );
1609     systray_menu->AppendSeparator();
1610     systray_menu->Append( PlayStream_Event, wxU(_("Play/Pause")) );
1611
1612     if (!minimal)
1613     {
1614     systray_menu->Append( PrevStream_Event, wxU(_("Previous")) );
1615     systray_menu->Append( NextStream_Event, wxU(_("Next")) );
1616     systray_menu->Append( StopStream_Event, wxU(_("Stop")) );
1617     }
1618     systray_menu->AppendSeparator();
1619     systray_menu->Append( Iconize_Event, wxU(_("Show/Hide interface")) );
1620     return systray_menu;
1621 }
1622
1623 void Systray::UpdateTooltip( const wxChar* tooltip )
1624 {
1625     SetIcon( wxIcon( vlc16x16_xpm ), tooltip );
1626 }
1627 #endif