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