]> git.sesse.net Git - vlc/blob - modules/gui/wxwindows/interface.cpp
7f1963c29ef407f452575ba11dd284ba2b0bec49
[vlc] / modules / gui / wxwindows / interface.cpp
1 /*****************************************************************************
2  * interface.cpp : wxWindows plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2004, 2003 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/intf.h>
31
32 #include "wxwindows.h"
33
34 /* include the toolbar graphics */
35 #include "bitmaps/play.xpm"
36 #include "bitmaps/pause.xpm"
37 #include "bitmaps/stop.xpm"
38 #include "bitmaps/prev.xpm"
39 #include "bitmaps/next.xpm"
40 #include "bitmaps/eject.xpm"
41 #include "bitmaps/slow.xpm"
42 #include "bitmaps/fast.xpm"
43 #include "bitmaps/playlist.xpm"
44 #include "bitmaps/speaker.xpm"
45
46 #define TOOLBAR_BMP_WIDTH 16
47 #define TOOLBAR_BMP_HEIGHT 16
48
49 /* include the icon graphic */
50 #include "../../../share/vlc32x32.xpm"
51
52 /*****************************************************************************
53  * Local class declarations.
54  *****************************************************************************/
55 class wxMenuExt: public wxMenu
56 {
57 public:
58     /* Constructor */
59     wxMenuExt( wxMenu* parentMenu, int id, const wxString& text,
60                    const wxString& helpString, wxItemKind kind,
61                    char *_psz_var, int _i_object_id, vlc_value_t _val,
62                    int _i_val_type );
63
64     virtual ~wxMenuExt() {};
65
66     char *psz_var;
67     int  i_val_type;
68     int  i_object_id;
69     vlc_value_t val;
70
71 private:
72
73 };
74
75 class wxVolCtrl: public wxGauge
76 {
77 public:
78     /* Constructor */
79     wxVolCtrl( intf_thread_t *_p_intf, wxWindow* parent, wxWindowID id,
80                wxPoint = wxDefaultPosition, wxSize = wxSize( 20, -1 ) );
81     virtual ~wxVolCtrl() {};
82
83     void UpdateVolume();
84
85     void OnChange( wxMouseEvent& event );
86
87 private:
88     intf_thread_t *p_intf;
89
90     DECLARE_EVENT_TABLE();
91 };
92
93 BEGIN_EVENT_TABLE(wxVolCtrl, wxWindow)
94     /* Mouse events */
95     EVT_LEFT_DOWN(wxVolCtrl::OnChange)
96     EVT_MOTION(wxVolCtrl::OnChange)
97 END_EVENT_TABLE()
98
99 /*****************************************************************************
100  * Event Table.
101  *****************************************************************************/
102
103 DEFINE_LOCAL_EVENT_TYPE( wxEVT_INTF );
104
105 /* IDs for the controls and the menu commands */
106 enum
107 {
108     /* menu items */
109     MenuDummy_Event = wxID_HIGHEST + 1000,
110     Exit_Event = wxID_HIGHEST,
111     OpenFileSimple_Event,
112     OpenAdv_Event,
113     OpenFile_Event,
114     OpenDisc_Event,
115     OpenNet_Event,
116     OpenCapture_Event,
117     OpenSat_Event,
118     OpenOther_Event,
119     EjectDisc_Event,
120
121     Wizard_Event,
122
123     Playlist_Event,
124     Logs_Event,
125     FileInfo_Event,
126
127     Prefs_Event,
128     Extended_Event,
129 //    Undock_Event,
130     Bookmarks_Event,
131     Skins_Event,
132
133     SliderScroll_Event,
134     StopStream_Event,
135     PlayStream_Event,
136     PrevStream_Event,
137     NextStream_Event,
138     SlowStream_Event,
139     FastStream_Event,
140
141     /* it is important for the id corresponding to the "About" command to have
142      * this standard value as otherwise it won't be handled properly under Mac
143      * (where it is special and put into the "Apple" menu) */
144     About_Event = wxID_ABOUT
145 };
146
147 BEGIN_EVENT_TABLE(Interface, wxFrame)
148     /* Menu events */
149     EVT_MENU(Exit_Event, Interface::OnExit)
150     EVT_MENU(About_Event, Interface::OnAbout)
151
152     EVT_MENU(Playlist_Event, Interface::OnShowDialog)
153     EVT_MENU(Logs_Event, Interface::OnShowDialog)
154     EVT_MENU(FileInfo_Event, Interface::OnShowDialog)
155     EVT_MENU(Prefs_Event, Interface::OnShowDialog)
156
157     EVT_MENU_OPEN(Interface::OnMenuOpen)
158
159     EVT_MENU( Extended_Event, Interface::OnExtended )
160 //    EVT_MENU( Undock_Event, Interface::OnUndock )
161
162     EVT_MENU( Bookmarks_Event, Interface::OnShowDialog)
163
164 #if defined( __WXMSW__ ) || defined( __WXMAC__ )
165     EVT_CONTEXT_MENU(Interface::OnContextMenu2)
166 #endif
167     EVT_RIGHT_UP(Interface::OnContextMenu)
168
169     /* Toolbar events */
170     EVT_MENU(OpenFileSimple_Event, Interface::OnShowDialog)
171     EVT_MENU(OpenAdv_Event, Interface::OnShowDialog)
172     EVT_MENU(OpenFile_Event, Interface::OnShowDialog)
173     EVT_MENU(OpenDisc_Event, Interface::OnShowDialog)
174     EVT_MENU(OpenNet_Event, Interface::OnShowDialog)
175     EVT_MENU(OpenCapture_Event, Interface::OnShowDialog)
176     EVT_MENU(OpenSat_Event, Interface::OnShowDialog)
177     EVT_MENU(Wizard_Event, Interface::OnShowDialog)
178     EVT_MENU(StopStream_Event, Interface::OnStopStream)
179     EVT_MENU(PlayStream_Event, Interface::OnPlayStream)
180     EVT_MENU(PrevStream_Event, Interface::OnPrevStream)
181     EVT_MENU(NextStream_Event, Interface::OnNextStream)
182     EVT_MENU(SlowStream_Event, Interface::OnSlowStream)
183     EVT_MENU(FastStream_Event, Interface::OnFastStream)
184
185     /* Slider events */
186     EVT_COMMAND_SCROLL(SliderScroll_Event, Interface::OnSliderUpdate)
187
188     /* Custom events */
189     EVT_COMMAND(0, wxEVT_INTF, Interface::OnControlEvent)
190     EVT_COMMAND(1, wxEVT_INTF, Interface::OnControlEvent)
191
192 END_EVENT_TABLE()
193
194 /*****************************************************************************
195  * Constructor.
196  *****************************************************************************/
197 Interface::Interface( intf_thread_t *_p_intf ):
198     wxFrame( NULL, -1, wxT("VLC media player"),
199              wxDefaultPosition, wxSize(700,100), wxDEFAULT_FRAME_STYLE )
200 {
201     /* Initializations */
202     p_intf = _p_intf;
203     i_old_playing_status = PAUSE_S;
204     b_extra = VLC_FALSE;
205 //    b_undock = VLC_FALSE;
206
207     extra_window = NULL;
208
209     /* Give our interface a nice little icon */
210     SetIcon( wxIcon( vlc_xpm ) );
211
212     /* Create a sizer for the main frame */
213     frame_sizer = new wxBoxSizer( wxVERTICAL );
214     SetSizer( frame_sizer );
215
216     /* Create a dummy widget that can get the keyboard focus */
217     wxWindow *p_dummy = new wxWindow( this, 0, wxDefaultPosition,
218                                       wxSize(0,0) );
219     p_dummy->SetFocus();
220     frame_sizer->Add( p_dummy, 0, wxEXPAND );
221
222     /* Creation of the menu bar */
223     CreateOurMenuBar();
224
225     /* Creation of the tool bar */
226     CreateOurToolBar();
227
228     /* Create the extra panel */
229     extra_frame = new ExtraPanel( p_intf, this );
230     frame_sizer->Add( extra_frame, 0, wxEXPAND , 0 );
231     frame_sizer->Hide( extra_frame );
232
233     /* Creation of the status bar
234      * Helptext for menu items and toolbar tools will automatically get
235      * displayed here. */
236     int i_status_width[3] = {-6, -2, -9};
237     statusbar = CreateStatusBar( 3 );                            /* 2 fields */
238     statusbar->SetStatusWidths( 3, i_status_width );
239     statusbar->SetStatusText( wxString::Format(wxT("x%.2f"), 1.0), 1 );
240
241     /* Video window */
242     if( config_GetInt( p_intf, "wxwin-embed" ) )
243     {
244         VideoWindow( p_intf, this );
245         frame_sizer->Add( p_intf->p_sys->p_video_sizer, 1, wxEXPAND , 0 );
246     }
247
248     /* Creation of the slider sub-window */
249     CreateOurSlider();
250     frame_sizer->Add( slider_frame, 0, wxEXPAND , 0 );
251     frame_sizer->Hide( slider_frame );
252
253     /* Make sure we've got the right background colour */
254     SetBackgroundColour( slider_frame->GetBackgroundColour() );
255
256     /* Layout everything */
257     frame_sizer->Layout();
258     frame_sizer->Fit(this);
259
260 #if wxUSE_DRAG_AND_DROP
261     /* Associate drop targets with the main interface */
262     SetDropTarget( new DragAndDrop( p_intf ) );
263 #endif
264
265     SetupHotkeys();
266
267     /* Start timer */
268     timer = new Timer( p_intf, this );
269 }
270
271 Interface::~Interface()
272 {
273     if( p_intf->p_sys->p_wxwindow )
274     {
275         delete p_intf->p_sys->p_wxwindow;
276     }
277
278     /* Clean up */
279     delete timer;
280 }
281
282 void Interface::Update()
283 {
284     /* Misc updates */
285     ((wxVolCtrl *)volctrl)->UpdateVolume();
286 }
287
288 void Interface::OnControlEvent( wxCommandEvent& event )
289 {
290     switch( event.GetId() )
291     {
292     case 0:
293         frame_sizer->Layout();
294         frame_sizer->Fit(this);
295         break;
296
297     case 1:
298         long i_style = GetWindowStyle();
299         if( event.GetInt() ) i_style |= wxSTAY_ON_TOP;
300         else i_style &= ~wxSTAY_ON_TOP;
301         SetWindowStyle( i_style );
302         break;
303     }
304 }
305
306 /*****************************************************************************
307  * Private methods.
308  *****************************************************************************/
309 void Interface::CreateOurMenuBar()
310 {
311     /* Create the "File" menu */
312     wxMenu *file_menu = new wxMenu;
313     file_menu->Append( OpenFileSimple_Event,
314                        wxU(_("Quick &Open File...\tCtrl-O")) );
315
316     file_menu->AppendSeparator();
317     file_menu->Append( OpenFile_Event, wxU(_("Open &File...\tCtrl-F")) );
318     file_menu->Append( OpenDisc_Event, wxU(_("Open &Disc...\tCtrl-D")) );
319     file_menu->Append( OpenNet_Event,
320                        wxU(_("Open &Network Stream...\tCtrl-N")) );
321     file_menu->Append( OpenCapture_Event,
322                        wxU(_("Open &Capture Device...\tCtrl-C")) );
323
324     file_menu->AppendSeparator();
325     file_menu->Append( Wizard_Event, wxU(_("&Wizard...\tCtrl-W")) );
326     file_menu->AppendSeparator();
327     file_menu->Append( Exit_Event, wxU(_("E&xit\tCtrl-X")) );
328
329     /* Create the "View" menu */
330     wxMenu *view_menu = new wxMenu;
331     view_menu->Append( Playlist_Event, wxU(_("&Playlist...\tCtrl-P")) );
332     view_menu->Append( Logs_Event, wxU(_("&Messages...\tCtrl-M")) );
333     view_menu->Append( FileInfo_Event,
334                        wxU(_("Stream and Media &info...\tCtrl-I")) );
335
336     /* Create the "Auto-generated" menus */
337     p_settings_menu = SettingsMenu( p_intf, this );
338     p_audio_menu = AudioMenu( p_intf, this );
339     p_video_menu = VideoMenu( p_intf, this );
340     p_navig_menu = NavigMenu( p_intf, this );
341
342     /* Create the "Help" menu */
343     wxMenu *help_menu = new wxMenu;
344     help_menu->Append( About_Event, wxU(_("About VLC media player")) );
345
346     /* Append the freshly created menus to the menu bar... */
347     wxMenuBar *menubar = new wxMenuBar( wxMB_DOCKABLE );
348     menubar->Append( file_menu, wxU(_("&File")) );
349     menubar->Append( view_menu, wxU(_("&View")) );
350     menubar->Append( p_settings_menu, wxU(_("&Settings")) );
351     menubar->Append( p_audio_menu, wxU(_("&Audio")) );
352     menubar->Append( p_video_menu, wxU(_("&Video")) );
353     menubar->Append( p_navig_menu, wxU(_("&Navigation")) );
354     menubar->Append( help_menu, wxU(_("&Help")) );
355
356     /* Attach the menu bar to the frame */
357     SetMenuBar( menubar );
358
359     /* Find out size of menu bar */
360     int i_size = 0;
361     for( unsigned int i = 0; i < menubar->GetMenuCount(); i++ )
362     {
363         int i_width, i_height;
364         menubar->GetTextExtent( menubar->GetLabelTop(i), &i_width, &i_height );
365         i_size += i_width +
366 #if defined(__WXGTK__)
367             22 /* approximate margin */;
368 #else
369             4 /* approximate margin */;
370 #endif
371     }
372     frame_sizer->SetMinSize( i_size, -1 );
373
374     /* Intercept all menu events in our custom event handler */
375     PushEventHandler( new MenuEvtHandler( p_intf, this ) );
376
377 #if wxUSE_DRAG_AND_DROP
378     /* Associate drop targets with the menubar */
379     menubar->SetDropTarget( new DragAndDrop( p_intf ) );
380 #endif
381 }
382
383 class VLCVolCtrl : public wxControl
384 {
385 public:
386     VLCVolCtrl( intf_thread_t *p_intf, wxWindow *p_parent, wxGauge ** );
387     virtual ~VLCVolCtrl() {};
388
389     virtual void OnPaint( wxPaintEvent &event );
390
391   private:
392     DECLARE_EVENT_TABLE()
393     int i_y_offset;
394 };
395
396 BEGIN_EVENT_TABLE(VLCVolCtrl, wxControl)
397    EVT_PAINT(VLCVolCtrl::OnPaint)
398 END_EVENT_TABLE()
399
400 #if defined(__WXGTK__)
401 #define VLCVOL_HEIGHT p_parent->GetSize().GetHeight()
402 #else
403 #define VLCVOL_HEIGHT TOOLBAR_BMP_HEIGHT
404 #endif
405 VLCVolCtrl::VLCVolCtrl( intf_thread_t *p_intf, wxWindow *p_parent,
406                         wxGauge **pp_volctrl )
407   :wxControl( p_parent, -1, wxDefaultPosition, wxSize(64, VLCVOL_HEIGHT ),
408               wxBORDER_NONE ),
409    i_y_offset((VLCVOL_HEIGHT - TOOLBAR_BMP_HEIGHT) / 2)
410 {
411     *pp_volctrl = new wxVolCtrl( p_intf, this, -1, wxPoint( 18, i_y_offset ),
412                                  wxSize( 44, TOOLBAR_BMP_HEIGHT ) );
413 }
414
415 void VLCVolCtrl::OnPaint( wxPaintEvent &evt )
416 {
417     wxPaintDC dc( this );
418     wxBitmap mPlayBitmap( speaker_xpm );
419     dc.DrawBitmap( mPlayBitmap, 0, i_y_offset, TRUE );
420 }
421
422 void Interface::CreateOurToolBar()
423 {
424 #define HELP_OPEN N_("Open")
425 #define HELP_STOP N_("Stop")
426 #define HELP_PLAY N_("Play")
427 #define HELP_PAUSE N_("Pause")
428 #define HELP_PLO N_("Playlist")
429 #define HELP_PLP N_("Previous playlist item")
430 #define HELP_PLN N_("Next playlist item")
431 #define HELP_SLOW N_("Play slower")
432 #define HELP_FAST N_("Play faster")
433
434     wxLogNull LogDummy; /* Hack to suppress annoying log message on the win32
435                          * version because we don't include wx.rc */
436
437     wxToolBar *toolbar =
438         CreateToolBar( wxTB_HORIZONTAL | wxTB_FLAT | wxTB_DOCKABLE );
439
440     toolbar->SetToolBitmapSize( wxSize(TOOLBAR_BMP_WIDTH,TOOLBAR_BMP_HEIGHT) );
441
442     toolbar->AddTool( OpenFile_Event, wxT(""),
443                       wxBitmap( eject_xpm ), wxU(_(HELP_OPEN)) );
444     toolbar->AddSeparator();
445     toolbar->AddTool( PlayStream_Event, wxT(""), wxBitmap( play_xpm ),
446                       wxU(_(HELP_PLAY)) );
447 #if 0
448     toolbar->AddTool( PlayStream_Event, wxT(""), wxBitmap( pause_xpm ),
449                       wxU(_(HELP_PAUSE)) );
450 #endif
451     toolbar->AddTool( StopStream_Event, wxT(""), wxBitmap( stop_xpm ),
452                       wxU(_(HELP_STOP)) );
453     toolbar->AddSeparator();
454     toolbar->AddTool( PrevStream_Event, wxT(""),
455                       wxBitmap( prev_xpm ), wxU(_(HELP_PLP)) );
456     toolbar->AddTool( SlowStream_Event, wxT(""),
457                       wxBitmap( slow_xpm ), wxU(_(HELP_SLOW)) );
458     toolbar->AddTool( FastStream_Event, wxT(""),
459                       wxBitmap( fast_xpm ), wxU(_(HELP_FAST)) );
460     toolbar->AddTool( NextStream_Event, wxT(""), wxBitmap( next_xpm ),
461                       wxU(_(HELP_PLN)) );
462     toolbar->AddSeparator();
463     toolbar->AddTool( Playlist_Event, wxT(""), wxBitmap( playlist_xpm ),
464                       wxU(_(HELP_PLO)) );
465
466     wxControl *p_dummy_ctrl =
467         new wxControl( toolbar, -1, wxDefaultPosition,
468                        wxSize(35, 16 ), wxBORDER_NONE );
469
470     toolbar->AddControl( p_dummy_ctrl );
471
472     VLCVolCtrl *sound_control = new VLCVolCtrl( p_intf, toolbar, &volctrl );
473     toolbar->AddControl( sound_control );
474
475     toolbar->Realize();
476
477 #if wxUSE_DRAG_AND_DROP
478     /* Associate drop targets with the toolbar */
479     toolbar->SetDropTarget( new DragAndDrop( p_intf ) );
480 #endif
481 }
482
483 void Interface::CreateOurSlider()
484 {
485     /* Create a new frame and sizer containing the slider */
486     slider_frame = new wxPanel( this, -1, wxDefaultPosition, wxDefaultSize );
487     slider_frame->SetAutoLayout( TRUE );
488     wxBoxSizer *frame_sizer = new wxBoxSizer( wxHORIZONTAL );
489     //frame_sizer->SetMinSize( -1, 50 );
490
491     /* Create slider */
492     slider = new wxSlider( slider_frame, SliderScroll_Event, 0, 0,
493                            SLIDER_MAX_POS, wxDefaultPosition, wxDefaultSize );
494
495     /* Add everything to the frame */
496     frame_sizer->Add( slider, 1, wxEXPAND | wxALL, 5 );
497     slider_frame->SetSizer( frame_sizer );
498     frame_sizer->Layout();
499     frame_sizer->SetSizeHints(slider_frame);
500
501     /* Hide the slider by default */
502     slider_frame->Hide();
503 }
504
505
506 static int ConvertHotkeyModifiers( int i_hotkey )
507 {
508     int i_accel_flags = 0;
509     if( i_hotkey & KEY_MODIFIER_ALT ) i_accel_flags |= wxACCEL_ALT;
510     if( i_hotkey & KEY_MODIFIER_CTRL ) i_accel_flags |= wxACCEL_CTRL;
511     if( i_hotkey & KEY_MODIFIER_SHIFT ) i_accel_flags |= wxACCEL_SHIFT;
512     if( !i_accel_flags ) i_accel_flags = wxACCEL_NORMAL;
513     return i_accel_flags;
514 }
515
516 static int ConvertHotkey( int i_hotkey )
517 {
518     int i_key = i_hotkey & ~KEY_MODIFIER;
519     if( i_key & KEY_ASCII ) return i_key & KEY_ASCII;
520     else if( i_key & KEY_SPECIAL )
521     {
522         switch ( i_key )
523         {
524         case KEY_LEFT: return WXK_LEFT;
525         case KEY_RIGHT: return WXK_RIGHT;
526         case KEY_UP: return WXK_UP;
527         case KEY_DOWN: return WXK_DOWN;
528         case KEY_SPACE: return WXK_SPACE;
529         case KEY_ENTER: return WXK_RETURN;
530         case KEY_F1: return WXK_F1;
531         case KEY_F2: return WXK_F2;
532         case KEY_F3: return WXK_F3;
533         case KEY_F4: return WXK_F4;
534         case KEY_F5: return WXK_F5;
535         case KEY_F6: return WXK_F6;
536         case KEY_F7: return WXK_F7;
537         case KEY_F8: return WXK_F8;
538         case KEY_F9: return WXK_F9;
539         case KEY_F10: return WXK_F10;
540         case KEY_F11: return WXK_F11;
541         case KEY_F12: return WXK_F12;
542         case KEY_HOME: return WXK_HOME;
543         case KEY_END: return WXK_HOME;
544         case KEY_MENU: return WXK_MENU;
545         case KEY_ESC: return WXK_ESCAPE;
546         case KEY_PAGEUP: return WXK_PRIOR;
547         case KEY_PAGEDOWN: return WXK_NEXT;
548         case KEY_TAB: return WXK_TAB;
549         case KEY_BACKSPACE: return WXK_BACK;
550         }
551     }
552     return WXK_F24;
553 }
554
555 void Interface::SetupHotkeys()
556 {
557     struct vlc_t::hotkey *p_hotkeys = p_intf->p_vlc->p_hotkeys;
558     int i_hotkeys;
559
560     /* Count number of hoteys */
561     for( i_hotkeys = 0; p_hotkeys[i_hotkeys].psz_action != NULL; i_hotkeys++ );
562
563     p_intf->p_sys->i_first_hotkey_event = wxID_HIGHEST + 7000;
564     p_intf->p_sys->i_hotkeys = i_hotkeys;
565
566     wxAcceleratorEntry p_entries[i_hotkeys];
567
568     /* Setup the hotkeys as accelerators */
569     for( int i = 0; i < i_hotkeys; i++ )
570     {
571         p_entries[i].Set( ConvertHotkeyModifiers( p_hotkeys[i].i_key ),
572                           ConvertHotkey( p_hotkeys[i].i_key ),
573                           p_intf->p_sys->i_first_hotkey_event + i );
574     }
575
576     wxAcceleratorTable accel( i_hotkeys, p_entries );
577
578     if( !accel.Ok() )
579     {
580         msg_Err( p_intf, "invalid accelerator table" );
581     }
582     else
583     {
584         SetAcceleratorTable( accel );
585         msg_Dbg( p_intf, "accelerator table loaded" );
586     }
587 }
588
589 /*****************************************************************************
590  * Event Handlers.
591  *****************************************************************************/
592
593 void Interface::OnMenuOpen(wxMenuEvent& event)
594 {
595 #if defined( __WXMSW__ )
596 #   define GetEventObject GetMenu
597 #endif
598
599     if( event.GetEventObject() == p_settings_menu )
600     {
601         p_settings_menu = SettingsMenu( p_intf, this, p_settings_menu );
602
603         /* Add static items */
604         p_settings_menu->AppendCheckItem( Extended_Event,
605             wxU(_("&Extended GUI") ) );
606         if( b_extra ) p_settings_menu->Check( Extended_Event, TRUE );
607 #if 0
608         p_settings_menu->AppendCheckItem( Undock_Event,
609             wxU(_("&Undock Ext. GUI") ) );
610         if( b_undock ) p_settings_menu->Check( Undock_Event, TRUE );
611 #endif
612         p_settings_menu->Append( Bookmarks_Event, wxU(_("&Bookmarks...") ) );
613         p_settings_menu->Append( Prefs_Event, wxU(_("&Preferences...")) );
614     }
615
616     else if( event.GetEventObject() == p_audio_menu )
617     {
618         p_audio_menu = AudioMenu( p_intf, this, p_audio_menu );
619     }
620
621     else if( event.GetEventObject() == p_video_menu )
622     {
623         p_video_menu = VideoMenu( p_intf, this, p_video_menu );
624     }
625
626     else if( event.GetEventObject() == p_navig_menu )
627     {
628         p_navig_menu = NavigMenu( p_intf, this, p_navig_menu );
629     }
630
631 #if defined( __WXMSW__ )
632 #   undef GetEventObject
633 #endif
634 }
635
636 #if defined( __WXMSW__ ) || defined( __WXMAC__ )
637 void Interface::OnContextMenu2(wxContextMenuEvent& event)
638 {
639     /* Only show the context menu for the main interface */
640     if( GetId() != event.GetId() )
641     {
642         event.Skip();
643         return;
644     }
645
646     if( p_intf->p_sys->pf_show_dialog )
647         p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU, 1, 0 );
648 }
649 #endif
650 void Interface::OnContextMenu(wxMouseEvent& event)
651 {
652     if( p_intf->p_sys->pf_show_dialog )
653         p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU, 1, 0 );
654 }
655
656 void Interface::OnExit( wxCommandEvent& WXUNUSED(event) )
657 {
658     /* TRUE is to force the frame to close. */
659     Close(TRUE);
660 }
661
662 void Interface::OnAbout( wxCommandEvent& WXUNUSED(event) )
663 {
664     wxString msg;
665     msg.Printf( wxString(wxT("VLC media player " PACKAGE_VERSION)) +
666         wxU(_(" (wxWindows interface)\n\n")) +
667         wxU(_("(c) 1996-2004 - the VideoLAN Team\n\n")) +
668         wxU( vlc_wraptext(INTF_ABOUT_MSG,WRAPCOUNT,ISUTF8) ) + wxT("\n\n") +
669         wxU(_("The VideoLAN team <videolan@videolan.org>\n"
670               "http://www.videolan.org/\n\n")) );
671
672     wxMessageBox( msg, wxString::Format(wxU(_("About %s")),
673                   wxT("VLC media player")), wxOK | wxICON_INFORMATION, this );
674 }
675
676 void Interface::OnShowDialog( wxCommandEvent& event )
677 {
678     if( p_intf->p_sys->pf_show_dialog )
679     {
680         int i_id;
681
682         switch( event.GetId() )
683         {
684         case OpenFileSimple_Event:
685             i_id = INTF_DIALOG_FILE_SIMPLE;
686             break;
687         case OpenAdv_Event:
688             i_id = INTF_DIALOG_FILE;
689         case OpenFile_Event:
690             i_id = INTF_DIALOG_FILE;
691             break;
692         case OpenDisc_Event:
693             i_id = INTF_DIALOG_DISC;
694             break;
695         case OpenNet_Event:
696             i_id = INTF_DIALOG_NET;
697             break;
698         case OpenCapture_Event:
699             i_id = INTF_DIALOG_CAPTURE;
700             break;
701         case OpenSat_Event:
702             i_id = INTF_DIALOG_SAT;
703             break;
704         case Playlist_Event:
705             i_id = INTF_DIALOG_PLAYLIST;
706             break;
707         case Logs_Event:
708             i_id = INTF_DIALOG_MESSAGES;
709             break;
710         case FileInfo_Event:
711             i_id = INTF_DIALOG_FILEINFO;
712             break;
713         case Prefs_Event:
714             i_id = INTF_DIALOG_PREFS;
715             break;
716         case Wizard_Event:
717             i_id = INTF_DIALOG_WIZARD;
718             break;
719         case Bookmarks_Event:
720             i_id = INTF_DIALOG_BOOKMARKS;
721             break;
722         default:
723             i_id = INTF_DIALOG_FILE;
724             break;
725         }
726
727         p_intf->p_sys->pf_show_dialog( p_intf, i_id, 1, 0 );
728     }
729 }
730
731 void Interface::OnExtended(wxCommandEvent& event)
732 {
733     b_extra = (b_extra == VLC_TRUE ? VLC_FALSE : VLC_TRUE );
734
735     if( b_extra == VLC_FALSE )
736     {
737         extra_frame->Hide();
738         frame_sizer->Hide( extra_frame );
739     }
740     else
741     {
742         extra_frame->Show();
743         frame_sizer->Show( extra_frame );
744     }
745     frame_sizer->Layout();
746     frame_sizer->Fit(this);
747 }
748
749 #if 0
750         if( b_undock == VLC_TRUE )
751         {
752                 fprintf(stderr,"Deleting window\n");
753             if( extra_window )
754             {
755                 delete extra_window;
756                 extra_window = NULL;
757             }
758         }
759         else
760         {
761             extra_frame->Hide();
762             frame_sizer->Hide( extra_frame );
763             frame_sizer->Layout();
764             frame_sizer->Fit(this);
765         }
766     }
767     else
768     {
769         if( b_undock == VLC_TRUE )
770         {
771                 fprintf(stderr,"Creating window\n");
772             extra_frame->Hide();
773             frame_sizer->Hide( extra_frame );
774             frame_sizer->Detach( extra_frame );
775             frame_sizer->Layout();
776             frame_sizer->Fit(this);
777             extra_window = new ExtraWindow( p_intf, this, extra_frame );
778         }
779         else
780         {
781                 fprintf(stderr,"Deleting window\n");
782             if( extra_window )
783             {
784                 delete extra_window;
785             }
786             extra_frame->Show();
787             frame_sizer->Show( extra_frame );
788             frame_sizer->Layout();
789             frame_sizer->Fit(this);
790         }
791     }
792 }
793
794 void Interface::OnUndock(wxCommandEvent& event)
795 {
796     b_undock = (b_undock == VLC_TRUE ? VLC_FALSE : VLC_TRUE );
797
798     if( b_extra == VLC_TRUE )
799     {
800         if( b_undock == VLC_FALSE )
801         {
802                 fprintf(stderr,"Deleting window\n");
803             if( extra_window )
804             {
805                 delete extra_window;
806                 extra_window = NULL;
807             }
808             extra_frame->Show();
809             frame_sizer->Show( extra_frame );
810             frame_sizer->Layout();
811             frame_sizer->Fit(this);
812         }
813         else
814         {
815                 fprintf(stderr,"Creating window\n");
816             extra_frame->Hide();
817             frame_sizer->Hide( extra_frame );
818             frame_sizer->Detach( extra_frame );
819             frame_sizer->Layout();
820             frame_sizer->Fit(this);
821             extra_window = new ExtraWindow( p_intf, this, extra_frame );
822         }
823     }
824 }
825 #endif
826
827 void Interface::OnPlayStream( wxCommandEvent& WXUNUSED(event) )
828 {
829     wxCommandEvent dummy;
830     playlist_t *p_playlist =
831         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
832                                        FIND_ANYWHERE );
833     if( p_playlist == NULL ) return;
834
835     if( p_playlist->i_size && p_playlist->i_enabled )
836     {
837         vlc_value_t state;
838
839         input_thread_t *p_input = (input_thread_t *)vlc_object_find( p_intf,
840                                                        VLC_OBJECT_INPUT,
841                                                        FIND_ANYWHERE );
842         if( p_input == NULL )
843         {
844             /* No stream was playing, start one */
845             playlist_Play( p_playlist );
846             TogglePlayButton( PLAYING_S );
847             vlc_object_release( p_playlist );
848             return;
849         }
850
851         var_Get( p_input, "state", &state );
852
853         if( state.i_int != PAUSE_S )
854         {
855             /* A stream is being played, pause it */
856             state.i_int = PAUSE_S;
857         }
858         else
859         {
860             /* Stream is paused, resume it */
861             state.i_int = PLAYING_S;
862         }
863         var_Set( p_input, "state", state );
864
865         TogglePlayButton( state.i_int );
866         vlc_object_release( p_input );
867         vlc_object_release( p_playlist );
868     }
869     else
870     {
871         /* If the playlist is empty, open a file requester instead */
872         vlc_object_release( p_playlist );
873         OnShowDialog( dummy );
874     }
875 }
876
877 void Interface::OnStopStream( wxCommandEvent& WXUNUSED(event) )
878 {
879     playlist_t * p_playlist =
880         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
881                                        FIND_ANYWHERE );
882     if( p_playlist == NULL )
883     {
884         return;
885     }
886
887     playlist_Stop( p_playlist );
888     TogglePlayButton( PAUSE_S );
889     vlc_object_release( p_playlist );
890 }
891
892 void Interface::OnSliderUpdate( wxScrollEvent& event )
893 {
894     vlc_mutex_lock( &p_intf->change_lock );
895
896 #ifdef WIN32
897     if( event.GetEventType() == wxEVT_SCROLL_THUMBRELEASE
898         || event.GetEventType() == wxEVT_SCROLL_ENDSCROLL )
899     {
900 #endif
901         if( p_intf->p_sys->i_slider_pos != event.GetPosition()
902             && p_intf->p_sys->p_input )
903         {
904             vlc_value_t pos;
905             pos.f_float = (float)event.GetPosition() / (float)SLIDER_MAX_POS;
906
907             var_Set( p_intf->p_sys->p_input, "position", pos );
908         }
909
910 #ifdef WIN32
911         p_intf->p_sys->b_slider_free = VLC_TRUE;
912     }
913     else
914     {
915         p_intf->p_sys->b_slider_free = VLC_FALSE;
916
917         if( p_intf->p_sys->p_input )
918         {
919             /* Update stream date */
920             char psz_time[ MSTRTIME_MAX_SIZE ], psz_total[ MSTRTIME_MAX_SIZE ];
921             mtime_t i_seconds;
922             vlc_value_t val;
923
924             i_seconds = var_GetTime( p_intf->p_sys->p_input, "length" ) / I64C(1000000 );
925             secstotimestr( psz_total, i_seconds );
926
927             i_seconds = var_GetTime( p_intf->p_sys->p_input, "time" ) / I64C(1000000 );
928             secstotimestr( psz_time, i_seconds );
929
930             statusbar->SetStatusText( wxU(psz_time)+ wxString(wxT(" / ")) + wxU(psz_total), 0 );
931         }
932     }
933 #endif
934
935 #undef WIN32
936     vlc_mutex_unlock( &p_intf->change_lock );
937 }
938
939 void Interface::OnPrevStream( wxCommandEvent& WXUNUSED(event) )
940 {
941     playlist_t * p_playlist =
942         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
943                                        FIND_ANYWHERE );
944     if( p_playlist == NULL )
945     {
946         return;
947     }
948
949     /* FIXME --fenrir */
950 #if 0
951     if( p_playlist->p_input != NULL )
952     {
953         vlc_mutex_lock( &p_playlist->p_input->stream.stream_lock );
954         if( p_playlist->p_input->stream.p_selected_area->i_id > 1 )
955         {
956             vlc_value_t val; val.b_bool = VLC_TRUE;
957             vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
958             var_Set( p_playlist->p_input, "prev-title", val );
959         } else
960             vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
961     }
962     vlc_mutex_unlock( &p_playlist->object_lock );
963 #endif
964
965     playlist_Prev( p_playlist );
966     vlc_object_release( p_playlist );
967 }
968
969 void Interface::OnNextStream( wxCommandEvent& WXUNUSED(event) )
970 {
971     playlist_t * p_playlist =
972         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
973                                        FIND_ANYWHERE );
974     if( p_playlist == NULL )
975     {
976         return;
977     }
978
979     /* FIXME --fenrir */
980 #if 0
981     var_Change( p_input, "title", VLC_VAR_CHOICESCOUNT, &val, NULL );
982     vlc_mutex_lock( &p_playlist->object_lock );
983     if( p_playlist->p_input != NULL )
984     {
985         vlc_mutex_lock( &p_playlist->p_input->stream.stream_lock );
986         if( p_playlist->p_input->stream.i_area_nb > 1 &&
987             p_playlist->p_input->stream.p_selected_area->i_id <
988               p_playlist->p_input->stream.i_area_nb - 1 )
989         {
990             vlc_value_t val; val.b_bool = VLC_TRUE;
991             vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
992             var_Set( p_playlist->p_input, "next-title", val );
993         } else
994             vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
995     }
996     vlc_mutex_unlock( &p_playlist->object_lock );
997 #endif
998     playlist_Next( p_playlist );
999     vlc_object_release( p_playlist );
1000 }
1001
1002 void Interface::OnSlowStream( wxCommandEvent& WXUNUSED(event) )
1003 {
1004     input_thread_t *p_input =
1005         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
1006                                            FIND_ANYWHERE );
1007     if( p_input )
1008     {
1009         vlc_value_t val; val.b_bool = VLC_TRUE;
1010
1011         var_Set( p_input, "rate-slower", val );
1012         vlc_object_release( p_input );
1013     }
1014 }
1015
1016 void Interface::OnFastStream( wxCommandEvent& WXUNUSED(event) )
1017 {
1018     input_thread_t *p_input =
1019         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
1020                                            FIND_ANYWHERE );
1021     if( p_input )
1022     {
1023         vlc_value_t val; val.b_bool = VLC_TRUE;
1024
1025         var_Set( p_input, "rate-faster", val );
1026         vlc_object_release( p_input );
1027     }
1028 }
1029
1030 void Interface::TogglePlayButton( int i_playing_status )
1031 {
1032     if( i_playing_status == i_old_playing_status )
1033         return;
1034
1035     GetToolBar()->DeleteTool( PlayStream_Event );
1036
1037     if( i_playing_status == PLAYING_S )
1038     {
1039         GetToolBar()->InsertTool( 2, PlayStream_Event, wxU(_("Pause")),
1040                                   wxBitmap( pause_xpm ), wxNullBitmap,
1041                                   wxITEM_NORMAL, wxU(_(HELP_PAUSE)) );
1042     }
1043     else
1044     {
1045         GetToolBar()->InsertTool( 2, PlayStream_Event, wxU(_("Play")),
1046                                   wxBitmap( play_xpm ), wxNullBitmap,
1047                                   wxITEM_NORMAL, wxU(_(HELP_PLAY)) );
1048     }
1049
1050     GetToolBar()->Realize();
1051
1052     i_old_playing_status = i_playing_status;
1053 }
1054
1055 #if wxUSE_DRAG_AND_DROP
1056 /*****************************************************************************
1057  * Definition of DragAndDrop class.
1058  *****************************************************************************/
1059 DragAndDrop::DragAndDrop( intf_thread_t *_p_intf, vlc_bool_t _b_enqueue )
1060 {
1061     p_intf = _p_intf;
1062     b_enqueue = _b_enqueue;
1063 }
1064
1065 bool DragAndDrop::OnDropFiles( wxCoord, wxCoord,
1066                                const wxArrayString& filenames )
1067 {
1068     /* Add dropped files to the playlist */
1069
1070     playlist_t *p_playlist =
1071         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
1072                                        FIND_ANYWHERE );
1073     if( p_playlist == NULL )
1074     {
1075         return FALSE;
1076     }
1077
1078     for( size_t i = 0; i < filenames.GetCount(); i++ )
1079         playlist_Add( p_playlist, (const char *)filenames[i].mb_str(),
1080                       (const char *)filenames[i].mb_str(),
1081                       PLAYLIST_APPEND | ((i | b_enqueue) ? 0 : PLAYLIST_GO),
1082                       PLAYLIST_END );
1083
1084     vlc_object_release( p_playlist );
1085
1086     return TRUE;
1087 }
1088 #endif
1089
1090 /*****************************************************************************
1091  * Definition of VolCtrl class.
1092  *****************************************************************************/
1093 wxVolCtrl::wxVolCtrl( intf_thread_t *_p_intf, wxWindow* parent, wxWindowID id,
1094                       wxPoint point, wxSize size )
1095   : wxGauge( parent, id, 200, point, size, wxGA_HORIZONTAL | wxGA_SMOOTH )
1096 {
1097     p_intf = _p_intf;
1098     UpdateVolume();
1099 }
1100
1101 void wxVolCtrl::OnChange( wxMouseEvent& event )
1102 {
1103     if( !event.LeftDown() && !event.LeftIsDown() ) return;
1104
1105     int i_volume = event.GetX() * 200 / GetClientSize().GetWidth();
1106     aout_VolumeSet( p_intf, i_volume * AOUT_VOLUME_MAX / 200 / 2 );
1107     UpdateVolume();
1108 }
1109
1110 void wxVolCtrl::UpdateVolume()
1111 {
1112     audio_volume_t i_volume;
1113     aout_VolumeGet( p_intf, &i_volume );
1114
1115     int i_gauge_volume = i_volume * 200 * 2 / AOUT_VOLUME_MAX;
1116     if( i_gauge_volume == GetValue() ) return;
1117
1118     SetValue( i_gauge_volume );
1119     SetToolTip( wxString::Format((wxString)wxU(_("Volume")) + wxT(" %d"),
1120                 i_gauge_volume / 2 ) );
1121 }