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