]> git.sesse.net Git - vlc/blob - modules/gui/wxwindows/interface.cpp
0ee1c8d4cabbc882536ccc246bbf5ac6d8f55134
[vlc] / modules / gui / wxwindows / interface.cpp
1 /*****************************************************************************
2  * interface.cpp : wxWindows plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2001 VideoLAN
5  * $Id: interface.cpp,v 1.64 2003/10/08 12:18:50 zorglub Exp $
6  *
7  * Authors: Gildas Bazin <gbazin@netcourrier.com>
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 <stdlib.h>                                      /* malloc(), free() */
28 #include <errno.h>                                                 /* ENOMEM */
29 #include <string.h>                                            /* strerror() */
30 #include <stdio.h>
31
32 #include <vlc/vlc.h>
33 #include <vlc/aout.h>
34 #include <vlc/vout.h>
35 #include <vlc/intf.h>
36 #include "stream_control.h"
37
38 #include "wxwindows.h"
39
40 /* include the toolbar graphics */
41 #include "bitmaps/file.xpm"
42 #include "bitmaps/disc.xpm"
43 #include "bitmaps/net.xpm"
44 #if 0
45 #include "bitmaps/sat.xpm"
46 #endif
47 #include "bitmaps/play.xpm"
48 #include "bitmaps/pause.xpm"
49 #include "bitmaps/stop.xpm"
50 #include "bitmaps/previous.xpm"
51 #include "bitmaps/next.xpm"
52 #include "bitmaps/playlist.xpm"
53 #include "bitmaps/fast.xpm"
54 #include "bitmaps/slow.xpm"
55
56 #define TOOLBAR_BMP_WIDTH 36
57 #define TOOLBAR_BMP_HEIGHT 36
58
59 /* include the icon graphic */
60 #include "../../../share/vlc32x32.xpm"
61
62 /*****************************************************************************
63  * Local class declarations.
64  *****************************************************************************/
65 class wxMenuExt: public wxMenu
66 {
67 public:
68     /* Constructor */
69     wxMenuExt( wxMenu* parentMenu, int id, const wxString& text,
70                    const wxString& helpString, wxItemKind kind,
71                    char *_psz_var, int _i_object_id, vlc_value_t _val,
72                    int _i_val_type );
73
74     virtual ~wxMenuExt() {};
75
76     char *psz_var;
77     int  i_val_type;
78     int  i_object_id;
79     vlc_value_t val;
80
81 private:
82
83 };
84
85 class wxVolCtrl: public wxGauge
86 {
87 public:
88     /* Constructor */
89     wxVolCtrl( intf_thread_t *_p_intf, wxWindow* parent, wxWindowID id );
90     virtual ~wxVolCtrl() {};
91
92     void Change( int i_volume );
93
94     void OnChange( wxMouseEvent& event );
95
96 private:
97     intf_thread_t *p_intf;
98
99     DECLARE_EVENT_TABLE();
100 };
101
102 BEGIN_EVENT_TABLE(wxVolCtrl, wxWindow)
103     /* Mouse events */
104     EVT_LEFT_DOWN(wxVolCtrl::OnChange)
105     EVT_MOTION(wxVolCtrl::OnChange)
106 END_EVENT_TABLE()
107
108 /*****************************************************************************
109  * Event Table.
110  *****************************************************************************/
111
112 /* IDs for the controls and the menu commands */
113 enum
114 {
115     /* menu items */
116     Exit_Event = wxID_HIGHEST,
117     OpenFileSimple_Event,
118     OpenFile_Event,
119     OpenDisc_Event,
120     OpenNet_Event,
121     OpenSat_Event,
122     EjectDisc_Event,
123
124     Playlist_Event,
125     Logs_Event,
126     FileInfo_Event,
127
128     Prefs_Event,
129     Extra_Event,
130
131     SliderScroll_Event,
132     StopStream_Event,
133     PlayStream_Event,
134     PrevStream_Event,
135     NextStream_Event,
136     SlowStream_Event,
137     FastStream_Event,
138
139     Adjust_Event,
140     Hue_Event,
141     Contrast_Event,
142     Brightness_Event,
143     Saturation_Event,
144
145     Ratio_Event,
146     /* it is important for the id corresponding to the "About" command to have
147      * this standard value as otherwise it won't be handled properly under Mac
148      * (where it is special and put into the "Apple" menu) */
149     About_Event = wxID_ABOUT
150 };
151
152 BEGIN_EVENT_TABLE(Interface, wxFrame)
153     /* Menu events */
154     EVT_MENU(Exit_Event, Interface::OnExit)
155     EVT_MENU(About_Event, Interface::OnAbout)
156
157     EVT_MENU(Playlist_Event, Interface::OnShowDialog)
158     EVT_MENU(Logs_Event, Interface::OnShowDialog)
159     EVT_MENU(FileInfo_Event, Interface::OnShowDialog)
160     EVT_MENU(Prefs_Event, Interface::OnShowDialog)
161
162     EVT_MENU_OPEN(Interface::OnMenuOpen)
163
164     EVT_MENU( Extra_Event, Interface::OnExtra)
165     EVT_CHECKBOX( Adjust_Event, Interface::OnEnableAdjust)
166
167     EVT_COMBOBOX( Ratio_Event, Interface::OnRatio)
168
169 #if defined( __WXMSW__ ) || defined( __WXMAC__ )
170     EVT_CONTEXT_MENU(Interface::OnContextMenu2)
171 #endif
172     EVT_RIGHT_UP(Interface::OnContextMenu)
173
174     /* Toolbar events */
175     EVT_MENU(OpenFileSimple_Event, Interface::OnShowDialog)
176     EVT_MENU(OpenFile_Event, Interface::OnShowDialog)
177     EVT_MENU(OpenDisc_Event, Interface::OnShowDialog)
178     EVT_MENU(OpenNet_Event, Interface::OnShowDialog)
179     EVT_MENU(OpenSat_Event, Interface::OnShowDialog)
180     EVT_MENU(StopStream_Event, Interface::OnStopStream)
181     EVT_MENU(PlayStream_Event, Interface::OnPlayStream)
182     EVT_MENU(PrevStream_Event, Interface::OnPrevStream)
183     EVT_MENU(NextStream_Event, Interface::OnNextStream)
184     EVT_MENU(SlowStream_Event, Interface::OnSlowStream)
185     EVT_MENU(FastStream_Event, Interface::OnFastStream)
186
187     /* Slider events */
188     EVT_COMMAND_SCROLL(SliderScroll_Event, Interface::OnSliderUpdate)
189
190     EVT_COMMAND_SCROLL(Hue_Event, Interface::OnHueUpdate)
191     EVT_COMMAND_SCROLL(Contrast_Event, Interface::OnContrastUpdate)
192     EVT_COMMAND_SCROLL(Brightness_Event, Interface::OnBrightnessUpdate)
193     EVT_COMMAND_SCROLL(Saturation_Event, Interface::OnSaturationUpdate)
194
195 END_EVENT_TABLE()
196
197 /*****************************************************************************
198  * Constructor.
199  *****************************************************************************/
200 Interface::Interface( intf_thread_t *_p_intf ):
201     wxFrame( NULL, -1, wxT("VLC media player"),
202              wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE )
203 {
204     /* Initializations */
205     p_intf = _p_intf;
206     i_old_playing_status = PAUSE_S;
207     b_extra = VLC_FALSE;
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 wxFlexGridSizer( 1, 0, 0);
214     frame_sizer = new wxBoxSizer( wxVERTICAL );
215     SetSizer( frame_sizer );
216
217     /* Create a dummy widget that can get the keyboard focus */
218     wxWindow *p_dummy = new wxWindow( this, 0, wxDefaultPosition,
219                                       wxSize(0,0) );
220     p_dummy->SetFocus();
221     frame_sizer->Add( p_dummy );
222
223     /* Creation of the menu bar */
224     CreateOurMenuBar();
225
226     /* Creation of the tool bar */
227     CreateOurToolBar();
228
229     /* Creation of the slider sub-window */
230     CreateOurSlider();
231     frame_sizer->Add( slider_frame, 0, wxEXPAND , 0 );
232     frame_sizer->Hide( slider_frame );
233
234     /* Create the extra panel */
235     CreateOurExtraPanel();
236     frame_sizer->Add( extra_frame, 0, wxEXPAND , 0 );
237     frame_sizer->Hide( extra_frame );
238
239     /* Creation of the status bar
240      * Helptext for menu items and toolbar tools will automatically get
241      * displayed here. */
242     int i_status_width[3] = {-6, -2, -9};
243     statusbar = CreateStatusBar( 3 );                            /* 2 fields */
244     statusbar->SetStatusWidths( 3, i_status_width );
245     statusbar->SetStatusText( wxString::Format(wxT("x%.2f"), 1.0), 1 );
246
247     /* Make sure we've got the right background colour */
248     SetBackgroundColour( slider_frame->GetBackgroundColour() );
249
250     /* Layout everything */
251     SetAutoLayout( TRUE );
252     frame_sizer->Layout();
253     frame_sizer->Fit(this);
254
255 #if !defined(__WXX11__)
256     /* Associate drop targets with the main interface */
257     SetDropTarget( new DragAndDrop( p_intf ) );
258 #endif
259
260     UpdateAcceleratorTable();
261 }
262
263 Interface::~Interface()
264 {
265     if( p_intf->p_sys->p_wxwindow )
266     {
267         delete p_intf->p_sys->p_wxwindow;
268     }
269     /* Clean up */
270 }
271
272 /*****************************************************************************
273  * Private methods.
274  *****************************************************************************/
275 void Interface::CreateOurMenuBar()
276 {
277 #define HELP_FILE  N_("Open a file")
278 #define HELP_DISC  N_("Open a DVD or (S)VCD")
279 #define HELP_NET   N_("Open a network stream")
280 #define HELP_SAT   N_("Open a satellite stream")
281 #define HELP_EJECT N_("Eject the DVD/CD")
282 #define HELP_EXIT  N_("Exit this program")
283
284 #define HELP_PLAYLIST   N_("Open the playlist")
285 #define HELP_LOGS       N_("Show the program logs")
286 #define HELP_FILEINFO       N_("Show information about the file being played")
287
288 #define HELP_PREFS N_("Go to the preferences menu")
289 #define EXTRA_PREFS N_("Shows the extended GUI")
290
291 #define HELP_ABOUT N_("About this program")
292
293     /* Create the "File" menu */
294     wxMenu *file_menu = new wxMenu;
295     file_menu->Append( OpenFileSimple_Event, wxU(_("Simple &Open ...")),
296                        wxU(_(HELP_FILE)) );
297     file_menu->Append( OpenFile_Event, wxU(_("Open &File...")),
298                        wxU(_(HELP_FILE)) );
299     file_menu->Append( OpenDisc_Event, wxU(_("Open &Disc...")),
300                        wxU(_(HELP_DISC)) );
301     file_menu->Append( OpenNet_Event, wxU(_("Open &Network Stream...")),
302                        wxU(_(HELP_NET)) );
303 #if 0
304     file_menu->Append( OpenSat_Event, wxU(_("Open &Satellite Stream...")),
305                        wxU(_(HELP_NET)) );
306 #endif
307 #if 0
308     file_menu->AppendSeparator();
309     file_menu->Append( EjectDisc_Event, wxU(_("&Eject Disc")),
310                        wxU(_(HELP_EJECT)) );
311 #endif
312     file_menu->AppendSeparator();
313     file_menu->Append( Exit_Event, wxU(_("E&xit")), wxU(_(HELP_EXIT)) );
314
315     /* Create the "View" menu */
316     wxMenu *view_menu = new wxMenu;
317     view_menu->Append( Playlist_Event, wxU(_("&Playlist...")),
318                        wxU(_(HELP_PLAYLIST)) );
319     view_menu->Append( Logs_Event, wxU(_("&Messages...")), wxU(_(HELP_LOGS)) );
320     view_menu->Append( FileInfo_Event, wxU(_("&File info...")),
321                        wxU(_(HELP_FILEINFO)) );
322
323     /* Create the "Settings" menu */
324     wxMenu *settings_menu = new wxMenu;
325     settings_menu->Append( Prefs_Event, wxU(_("&Preferences...")),
326                            wxU(_(HELP_PREFS)) );
327     settings_menu->AppendCheckItem( Extra_Event, wxU(_("&Extended GUI") ),
328                                     wxU(_(EXTRA_PREFS)) );
329
330
331     /* Create the "Audio" menu */
332     p_audio_menu = new wxMenu;
333     b_audio_menu = 1;
334
335     /* Create the "Video" menu */
336     p_video_menu = new wxMenu;
337     b_video_menu = 1;
338
339     /* Create the "Navigation" menu */
340     p_navig_menu = new wxMenu;
341     b_navig_menu = 1;
342
343     /* Create the "Help" menu */
344     wxMenu *help_menu = new wxMenu;
345     help_menu->Append( About_Event, wxU(_("&About...")), wxU(_(HELP_ABOUT)) );
346
347     /* Append the freshly created menus to the menu bar... */
348     wxMenuBar *menubar = new wxMenuBar( wxMB_DOCKABLE );
349     menubar->Append( file_menu, wxU(_("&File")) );
350     menubar->Append( view_menu, wxU(_("&View")) );
351     menubar->Append( settings_menu, wxU(_("&Settings")) );
352     menubar->Append( p_audio_menu, wxU(_("&Audio")) );
353     menubar->Append( p_video_menu, wxU(_("&Video")) );
354     menubar->Append( p_navig_menu, wxU(_("&Navigation")) );
355     menubar->Append( help_menu, wxU(_("&Help")) );
356
357     /* Attach the menu bar to the frame */
358     SetMenuBar( menubar );
359
360     /* Intercept all menu events in our custom event handler */
361     PushEventHandler( new MenuEvtHandler( p_intf, this ) );
362
363 #if !defined(__WXX11__)
364     /* Associate drop targets with the menubar */
365     menubar->SetDropTarget( new DragAndDrop( p_intf ) );
366 #endif
367 }
368
369 void Interface::CreateOurToolBar()
370 {
371 #define HELP_STOP N_("Stop current playlist item")
372 #define HELP_PLAY N_("Play current playlist item")
373 #define HELP_PAUSE N_("Pause current playlist item")
374 #define HELP_PLO N_("Open playlist")
375 #define HELP_PLP N_("Previous playlist item")
376 #define HELP_PLN N_("Next playlist item")
377 #define HELP_SLOW N_("Play slower")
378 #define HELP_FAST N_("Play faster")
379
380     wxLogNull LogDummy; /* Hack to suppress annoying log message on the win32
381                          * version because we don't include wx.rc */
382
383     wxToolBar *toolbar = CreateToolBar(
384                                        wxTB_HORIZONTAL | wxTB_FLAT | wxTB_DOCKABLE );
385
386     toolbar->SetToolBitmapSize( wxSize(TOOLBAR_BMP_WIDTH,TOOLBAR_BMP_HEIGHT) );
387
388     toolbar->AddTool( OpenFile_Event, wxU(_("File")), wxBitmap( file_xpm ),
389                       wxU(_(HELP_FILE)) );
390     toolbar->AddTool( OpenDisc_Event, wxU(_("Disc")), wxBitmap( disc_xpm ),
391                       wxU(_(HELP_DISC)) );
392     toolbar->AddTool( OpenNet_Event, wxU(_("Net")), wxBitmap( net_xpm ),
393                       wxU(_(HELP_NET)) );
394 #if 0
395     toolbar->AddTool( OpenSat_Event, wxU(_("Sat")), wxBitmap( sat_xpm ),
396                       wxU(_(HELP_SAT)) );
397 #endif
398     toolbar->AddSeparator();
399     toolbar->AddTool( StopStream_Event, wxU(_("Stop")), wxBitmap( stop_xpm ),
400                       wxU(_(HELP_STOP)) );
401     toolbar->AddTool( PlayStream_Event, wxU(_("Play")), wxBitmap( play_xpm ),
402                       wxU(_(HELP_PLAY)) );
403     toolbar->AddSeparator();
404     toolbar->AddTool( Playlist_Event, wxU(_("Playlist")),
405                       wxBitmap( playlist_xpm ), wxU(_(HELP_PLO)) );
406     toolbar->AddTool( PrevStream_Event, wxU(_("Prev")),
407                       wxBitmap( previous_xpm ), wxU(_(HELP_PLP)) );
408     toolbar->AddTool( NextStream_Event, wxU(_("Next")), wxBitmap( next_xpm ),
409                       wxU(_(HELP_PLN)) );
410     toolbar->AddTool( SlowStream_Event, wxU(_("Slower")), wxBitmap( slow_xpm ),
411                       wxU(_(HELP_SLOW)) );
412     toolbar->AddTool( FastStream_Event, wxU(_("Faster")), wxBitmap( fast_xpm ),
413                       wxU(_(HELP_FAST)) );
414
415     toolbar->Realize();
416
417     /* Place the toolbar in a sizer, so we can calculate the width of the
418      * toolbar and set this as the minimum for the main frame size. */
419     wxBoxSizer *toolbar_sizer = new wxBoxSizer( wxHORIZONTAL );
420     toolbar_sizer->Add( toolbar, 0, 0, 0 );
421
422     toolbar_sizer->Layout();
423
424 #ifndef WIN32
425     frame_sizer->SetMinSize( toolbar_sizer->GetMinSize().GetWidth(), -1 );
426 #else
427     frame_sizer->SetMinSize( toolbar->GetToolSize().GetWidth() *
428                              toolbar->GetToolsCount(), -1 );
429 #endif
430
431 #if !defined(__WXX11__)
432     /* Associate drop targets with the toolbar */
433     toolbar->SetDropTarget( new DragAndDrop( p_intf ) );
434 #endif
435 }
436
437 void Interface::CreateOurSlider()
438 {
439     /* Create a new frame and sizer containing the slider */
440     slider_frame = new wxPanel( this, -1, wxDefaultPosition, wxDefaultSize );
441     slider_frame->SetAutoLayout( TRUE );
442     wxBoxSizer *frame_sizer =
443         new wxBoxSizer( wxHORIZONTAL );
444
445     /* Create static box to surround the slider */
446     slider_box = new wxStaticBox( slider_frame, -1, wxT("") );
447
448     /* Create sizer for slider frame */
449     wxStaticBoxSizer *slider_sizer =
450         new wxStaticBoxSizer( slider_box, wxHORIZONTAL );
451     slider_sizer->SetMinSize( -1, 50 );
452
453     /* Create slider */
454     slider = new wxSlider( slider_frame, SliderScroll_Event, 0, 0,
455                            SLIDER_MAX_POS, wxDefaultPosition, wxDefaultSize );
456     slider_sizer->Add( slider, 1, wxEXPAND | wxALL, 5 );
457
458
459     volctrl = new wxVolCtrl( p_intf, slider_frame, -1 );
460
461     /* Add everything to the frame */
462     frame_sizer->Add( slider_sizer, 1, wxEXPAND | wxBOTTOM, 5 );
463     frame_sizer->Add( volctrl, 0, wxEXPAND | wxALL, 5 );
464     slider_frame->SetSizer( frame_sizer );
465     frame_sizer->Layout();
466     frame_sizer->SetSizeHints(slider_frame);
467
468     /* Hide the slider by default */
469     slider_frame->Hide();
470 }
471
472
473 void Interface::CreateOurExtraPanel()
474 {
475     char *psz_filters;
476
477     extra_frame = new wxPanel( this, -1, wxDefaultPosition, wxDefaultSize );
478     extra_frame->SetAutoLayout( TRUE );
479     wxBoxSizer *extra_sizer = new wxBoxSizer( wxHORIZONTAL );
480
481     /* Create static box to surround the adjust controls */
482     adjust_box = new wxStaticBox( extra_frame, -1, wxU(_("Image adjust")) );
483
484     /* Create the size for the frame */
485     wxStaticBoxSizer *adjust_sizer =
486         new wxStaticBoxSizer( adjust_box, wxVERTICAL );
487     adjust_sizer->SetMinSize( -1, 50 );
488
489     /* Create every controls */
490
491     /* Create the adjust button */
492     wxCheckBox * adjust_check = new wxCheckBox( extra_frame, Adjust_Event,
493                                                  wxU(_("Enable")));
494
495
496     wxBoxSizer *hue_sizer = new wxBoxSizer( wxHORIZONTAL );
497     wxStaticText *hue_text = new wxStaticText( extra_frame, -1,
498                                        wxU(_("Hue")) );
499     hue_slider = new wxSlider ( extra_frame, Hue_Event, 0, 0,
500                                 360, wxDefaultPosition, wxDefaultSize );
501
502     hue_sizer->Add(hue_text,1, 0 ,0);
503     hue_sizer->Add(hue_slider,1, 0 ,0);
504     hue_sizer->Layout();
505
506     wxBoxSizer *contrast_sizer = new wxBoxSizer( wxHORIZONTAL );
507     wxStaticText *contrast_text = new wxStaticText( extra_frame, -1,
508                                        wxU(_("Contrast")) );
509     contrast_slider = new wxSlider ( extra_frame, Contrast_Event, 0, 0,
510                                 200, wxDefaultPosition, wxDefaultSize);
511     contrast_sizer->Add(contrast_text,1, 0 ,0);
512     contrast_sizer->Add(contrast_slider,1, 0 ,0);
513     contrast_sizer->Layout();
514
515     wxBoxSizer *brightness_sizer = new wxBoxSizer( wxHORIZONTAL );
516     wxStaticText *brightness_text = new wxStaticText( extra_frame, -1,
517                                        wxU(_("Brightness")) );
518     brightness_slider = new wxSlider ( extra_frame, Brightness_Event, 0, 0,
519                            200, wxDefaultPosition, wxDefaultSize) ;
520     brightness_sizer->Add(brightness_text,1,0,0);
521     brightness_sizer->Add(brightness_slider,1,0,0);
522     brightness_sizer->Layout();
523
524     wxBoxSizer *saturation_sizer = new wxBoxSizer( wxHORIZONTAL );
525     wxStaticText *saturation_text = new wxStaticText( extra_frame, -1,
526                                           wxU(_("Saturation")) );
527     saturation_slider = new wxSlider ( extra_frame, Saturation_Event, 0, 0,
528                            300, wxDefaultPosition, wxDefaultSize );
529     saturation_sizer->Add(saturation_text,1,0,0);
530     saturation_sizer->Add(saturation_slider,1,0,0);
531     saturation_sizer->Layout();
532
533     adjust_sizer->Add(adjust_check, 1, wxEXPAND, 0);
534     adjust_sizer->Add(hue_sizer, 1, wxEXPAND, 0);
535     adjust_sizer->Add(contrast_sizer, 1, wxEXPAND, 0);
536     adjust_sizer->Add(brightness_sizer, 1, wxEXPAND, 0);
537     adjust_sizer->Add(saturation_sizer, 1, wxEXPAND, 0);
538
539     extra_sizer->Add(adjust_sizer,1,wxBOTTOM,5);
540
541
542     /* Create static box to surround the other controls */
543     other_box = new wxStaticBox( extra_frame, -1, wxU(_("Video Options")) );
544
545     /* Create the sizer for the frame */
546     wxStaticBoxSizer *other_sizer =
547         new wxStaticBoxSizer( other_box, wxVERTICAL );
548     other_sizer->SetMinSize( -1, 50 );
549
550     static const wxString ratio_array[] =
551     {
552         wxT("4:3"),
553         wxT("16:9"),
554     };
555
556     wxBoxSizer *ratio_sizer = new wxBoxSizer( wxHORIZONTAL );
557     wxStaticText *ratio_text = new wxStaticText( extra_frame, -1,
558                                           wxU(_("Ratio")) );
559
560     ratio_combo = new wxComboBox( extra_frame, Ratio_Event, wxT(""),
561                                   wxDefaultPosition, wxSize(120,-1),
562                                   WXSIZEOF(ratio_array), ratio_array,
563                                   0 );
564
565     ratio_sizer->Add( ratio_text, 0, wxALL, 2 );
566     ratio_sizer->Add( ratio_combo, 0, wxALL, 2 );
567     ratio_sizer->Layout();
568
569     other_sizer->Add(ratio_sizer,0,wxALL,0 );
570
571     extra_sizer->Add(other_sizer,0,wxBOTTOM,5);
572
573     extra_frame->SetSizer( extra_sizer );
574
575     /* Layout the whole panel */
576     extra_sizer->Layout();
577
578     extra_sizer->SetSizeHints(extra_frame);
579
580     /* Write down initial values */
581     psz_filters = config_GetPsz( p_intf, "filter" );
582
583     if(psz_filters == NULL) psz_filters=strdup("");
584
585     if( strstr(psz_filters,"adjust") )
586     {
587         adjust_check->SetValue( 1 );
588         saturation_slider->Enable();
589         contrast_slider->Enable();
590         brightness_slider->Enable();
591         hue_slider->Enable();
592     }
593     else
594     {
595         adjust_check->SetValue( 0 );
596         saturation_slider->Disable();
597         contrast_slider->Disable();
598         brightness_slider->Disable();
599         hue_slider->Disable();
600     }
601
602     int i_value = config_GetInt( p_intf, "hue" );
603     if( i_value > 0 && i_value < 360 )
604         hue_slider->SetValue( i_value );
605
606     float f_value;
607     f_value = config_GetFloat( p_intf, "saturation" );
608     if( f_value > 0 && f_value < 5 )
609         saturation_slider->SetValue( (int)(100 * f_value) );
610     f_value = config_GetFloat( p_intf, "contrast" );
611     if( f_value > 0 && f_value < 4 )
612         contrast_slider->SetValue( (int)(100 * f_value) );
613     f_value = config_GetFloat( p_intf, "brightness" );
614     if( f_value > 0 && f_value < 2 )
615         brightness_slider->SetValue( (int)(100 * f_value) );
616
617     extra_frame->Hide();
618     free(psz_filters);
619 }
620
621 void Interface::UpdateAcceleratorTable()
622 {
623     /* Set some hotkeys */
624     wxAcceleratorEntry entries[7];
625     int i_key = config_GetInt( p_intf, "quit-key" );
626     int i = 0;
627     entries[i++].Set( ConvertHotkeyModifiers( i_key ), ConvertHotkey( i_key ),
628                     Exit_Event );
629     i_key = config_GetInt( p_intf, "stop-key" );
630     entries[i++].Set( ConvertHotkeyModifiers( i_key ), ConvertHotkey( i_key ),
631                     StopStream_Event );
632     i_key = config_GetInt( p_intf, "play-pause-key" );
633     entries[i++].Set( ConvertHotkeyModifiers( i_key ), ConvertHotkey( i_key ),
634                     PlayStream_Event );
635     i_key = config_GetInt( p_intf, "next-key" );
636     entries[i++].Set( ConvertHotkeyModifiers( i_key ), ConvertHotkey( i_key ),
637                     NextStream_Event );
638     i_key = config_GetInt( p_intf, "prev-key" );
639     entries[i++].Set( ConvertHotkeyModifiers( i_key ), ConvertHotkey( i_key ),
640                     PrevStream_Event );
641     i_key = config_GetInt( p_intf, "faster-key" );
642     entries[i++].Set( ConvertHotkeyModifiers( i_key ), ConvertHotkey( i_key ),
643                     FastStream_Event );
644     i_key = config_GetInt( p_intf, "slower-key" );
645     entries[i++].Set( ConvertHotkeyModifiers( i_key ), ConvertHotkey( i_key ),
646                     SlowStream_Event );
647
648     wxAcceleratorTable accel( 7, entries );
649
650     if( !accel.Ok() )
651         msg_Err( p_intf, "invalid accelerator table" );
652
653     SetAcceleratorTable( accel );
654     msg_Dbg( p_intf, "accelerator table loaded" );
655
656 }
657
658
659
660 /*****************************************************************************
661  * Event Handlers.
662  *****************************************************************************/
663 /* Work-around helper for buggy wxGTK */
664 void RecursiveDestroy( wxMenu *menu )
665 {
666     wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
667     for( ; node; )
668     {
669         wxMenuItem *item = node->GetData();
670         node = node->GetNext();
671
672         /* Delete the submenus */
673         wxMenu *submenu = item->GetSubMenu();
674         if( submenu )
675         {
676             RecursiveDestroy( submenu );
677         }
678         menu->Delete( item );
679     }
680 }
681
682 void Interface::OnMenuOpen(wxMenuEvent& event)
683 {
684 #if !defined( __WXMSW__ )
685     if( event.GetEventObject() == p_audio_menu )
686     {
687         if( b_audio_menu )
688         {
689             p_audio_menu = AudioMenu( p_intf, this );
690
691             /* Work-around for buggy wxGTK */
692             wxMenu *menu = GetMenuBar()->GetMenu( 3 );
693             RecursiveDestroy( menu );
694             /* End work-around */
695
696             menu =
697                 GetMenuBar()->Replace( 3, p_audio_menu, wxU(_("&Audio")) );
698             if( menu ) delete menu;
699
700             b_audio_menu = 0;
701         }
702         else b_audio_menu = 1;
703     }
704     else if( event.GetEventObject() == p_video_menu )
705     {
706         if( b_video_menu )
707         {
708             p_video_menu = VideoMenu( p_intf, this );
709
710             /* Work-around for buggy wxGTK */
711             wxMenu *menu = GetMenuBar()->GetMenu( 4 );
712             RecursiveDestroy( menu );
713             /* End work-around */
714
715             menu =
716                 GetMenuBar()->Replace( 4, p_video_menu, wxU(_("&Video")) );
717             if( menu ) delete menu;
718
719             b_video_menu = 0;
720         }
721         else b_video_menu = 1;
722     }
723     else if( event.GetEventObject() == p_navig_menu )
724     {
725         if( b_navig_menu )
726         {
727             p_navig_menu = NavigMenu( p_intf, this );
728
729             /* Work-around for buggy wxGTK */
730             wxMenu *menu = GetMenuBar()->GetMenu( 5 );
731             RecursiveDestroy( menu );
732             /* End work-around */
733
734             menu =
735                 GetMenuBar()->Replace( 5, p_navig_menu, wxU(_("&Navigation")));
736             if( menu ) delete menu;
737
738             b_navig_menu = 0;
739         }
740         else b_navig_menu = 1;
741     }
742
743 #else
744     p_audio_menu = AudioMenu( p_intf, this );
745     wxMenu *menu = GetMenuBar()->Replace( 3, p_audio_menu, wxU(_("&Audio")) );
746     if( menu ) delete menu;
747
748     p_video_menu = VideoMenu( p_intf, this );
749     menu = GetMenuBar()->Replace( 4, p_video_menu, wxU(_("&Video")) );
750     if( menu ) delete menu;
751
752     p_navig_menu = NavigMenu( p_intf, this );
753     menu = GetMenuBar()->Replace( 5, p_navig_menu, wxU(_("&Navigation")) );
754     if( menu ) delete menu;
755
756 #endif
757 }
758
759 #if defined( __WXMSW__ ) || defined( __WXMAC__ )
760 void Interface::OnContextMenu2(wxContextMenuEvent& event)
761 {
762     /* Only show the context menu for the main interface */
763     if( GetId() != event.GetId() )
764     {
765         event.Skip();
766         return;
767     }
768
769     if( p_intf->p_sys->pf_show_dialog )
770         p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU, 1, 0 );
771 }
772 #endif
773 void Interface::OnContextMenu(wxMouseEvent& event)
774 {
775     if( p_intf->p_sys->pf_show_dialog )
776         p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU, 1, 0 );
777 }
778
779 void Interface::OnExit( wxCommandEvent& WXUNUSED(event) )
780 {
781     /* TRUE is to force the frame to close. */
782     Close(TRUE);
783 }
784
785 void Interface::OnAbout( wxCommandEvent& WXUNUSED(event) )
786 {
787     wxString msg;
788     msg.Printf( wxString(wxT("VLC media player " VERSION)) +
789         wxU(_(" (wxWindows interface)\n\n")) +
790         wxU(_("(C) 1996-2003 - the VideoLAN Team\n\n")) +
791         wxU( INTF_ABOUT_MSG ) + wxT("\n\n") +
792         wxU(_("The VideoLAN team <videolan@videolan.org>\n"
793               "http://www.videolan.org/\n\n")) );
794
795     wxMessageBox( msg, wxString::Format(wxU(_("About %s")),
796                   wxT("VLC media player")), wxOK | wxICON_INFORMATION, this );
797 }
798
799 void Interface::OnShowDialog( wxCommandEvent& event )
800 {
801     if( p_intf->p_sys->pf_show_dialog )
802     {
803         int i_id;
804
805         switch( event.GetId() )
806         {
807         case OpenFileSimple_Event:
808             i_id = INTF_DIALOG_FILE_SIMPLE;
809             break;
810         case OpenFile_Event:
811             i_id = INTF_DIALOG_FILE;
812             break;
813         case OpenDisc_Event:
814             i_id = INTF_DIALOG_DISC;
815             break;
816         case OpenNet_Event:
817             i_id = INTF_DIALOG_NET;
818             break;
819         case OpenSat_Event:
820             i_id = INTF_DIALOG_SAT;
821             break;
822         case Playlist_Event:
823             i_id = INTF_DIALOG_PLAYLIST;
824             break;
825         case Logs_Event:
826             i_id = INTF_DIALOG_MESSAGES;
827             break;
828         case FileInfo_Event:
829             i_id = INTF_DIALOG_FILEINFO;
830             break;
831         case Prefs_Event:
832             i_id = INTF_DIALOG_PREFS;
833             break;
834         default:
835             i_id = INTF_DIALOG_FILE;
836             break;
837
838         }
839
840         p_intf->p_sys->pf_show_dialog( p_intf, i_id, 1, 0 );
841     }
842 }
843
844 void Interface::OnExtra(wxCommandEvent& event)
845 {
846     if( b_extra == VLC_FALSE)
847     {
848         extra_frame->Show();
849         frame_sizer->Show( extra_frame );
850         b_extra = VLC_TRUE;
851     }
852     else
853     {
854         extra_frame->Hide();
855         frame_sizer->Hide( extra_frame );
856         b_extra = VLC_FALSE;
857     }
858     frame_sizer->Layout();
859     frame_sizer->Fit(this);
860 }
861
862 void Interface::OnEnableAdjust(wxCommandEvent& event)
863 {
864     char *psz_filters=config_GetPsz( p_intf, "filter");
865     char *psz_new = NULL;
866     if( event.IsChecked() )
867     {
868         if(psz_filters == NULL)
869         {
870             psz_new = strdup( "adjust" );
871         }
872         else
873         {
874             psz_new= (char *) malloc(strlen(psz_filters) + 8 );
875             sprintf( psz_new, "%s:adjust", psz_filters);
876         }
877         config_PutPsz( p_intf, "filter", psz_new );
878         vlc_value_t val;
879         vout_thread_t *p_vout =
880            (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
881                                        FIND_ANYWHERE );
882         if( p_vout != NULL )
883         {
884             val.psz_string = strdup( psz_new );
885             var_Set( p_vout, "filter", val);
886             vlc_object_release( p_vout );
887         }
888         if( val.psz_string ) free( val.psz_string );
889         brightness_slider->Enable();
890         saturation_slider->Enable();
891         contrast_slider->Enable();
892         hue_slider->Enable();
893     }
894     else
895     {
896         if( psz_filters != NULL )
897         {
898
899             char *psz_current;
900             unsigned int i=0;
901             for( i = 0; i< strlen(psz_filters ); i++)
902             {
903                 if ( !strncasecmp( &psz_filters[i],"adjust",6 ))
904                 {
905                     if(i > 0)
906                         if( psz_filters[i-1] == ':' ) i--;
907                     psz_current = strchr( &psz_filters[i+1] , ':' );
908                     if( !psz_current )
909                         psz_filters[i] = '\0';
910                     else
911                     {
912                        memmove( &psz_filters[i] , psz_current,
913                                 &psz_filters[strlen(psz_filters)]-psz_current
914                                 +1);
915                     }
916                 }
917             }
918             config_PutPsz( p_intf, "filter", psz_filters);
919             vlc_value_t val;
920             val.psz_string = strdup( psz_filters );
921             vout_thread_t *p_vout =
922                (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
923                                        FIND_ANYWHERE );
924             if( p_vout != NULL )
925             {
926                 var_Set( p_vout, "filter", val);
927                 vlc_object_release( p_vout );
928             }
929             if( val.psz_string ) free( val.psz_string );
930         }
931         brightness_slider->Disable();
932         saturation_slider->Disable();
933         contrast_slider->Disable();
934         hue_slider->Disable();
935     }
936     if(psz_filters) free(psz_filters);
937     if(psz_new) free(psz_new);
938 }
939
940 void Interface::OnHueUpdate( wxScrollEvent& event)
941 {
942    config_PutInt( p_intf , "hue" , event.GetPosition() );
943 }
944
945 void Interface::OnSaturationUpdate( wxScrollEvent& event)
946 {
947    config_PutFloat( p_intf , "saturation" , (float)event.GetPosition()/100 );
948 }
949
950 void Interface::OnBrightnessUpdate( wxScrollEvent& event)
951 {
952    config_PutFloat( p_intf , "brightness", (float)event.GetPosition()/100 );
953 }
954
955 void Interface::OnContrastUpdate(wxScrollEvent& event)
956 {
957    config_PutFloat( p_intf , "contrast" , (float)event.GetPosition()/100 );
958
959 }
960
961 void Interface::OnRatio( wxCommandEvent& event )
962 {
963    config_PutPsz( p_intf, "aspect-ratio", ratio_combo->GetValue().mb_str() );
964 }
965
966 void Interface::OnPlayStream( wxCommandEvent& WXUNUSED(event) )
967 {
968     wxCommandEvent dummy;
969     playlist_t *p_playlist =
970         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
971                                        FIND_ANYWHERE );
972     if( p_playlist == NULL ) return;
973
974     if( p_playlist->i_size && p_playlist->i_enabled )
975     {
976         vlc_value_t state;
977
978         input_thread_t *p_input = (input_thread_t *)vlc_object_find( p_intf,
979                                                        VLC_OBJECT_INPUT,
980                                                        FIND_ANYWHERE );
981         if( p_input == NULL )
982         {
983             /* No stream was playing, start one */
984             playlist_Play( p_playlist );
985             TogglePlayButton( PLAYING_S );
986             vlc_object_release( p_playlist );
987             return;
988         }
989
990         var_Get( p_input, "state", &state );
991
992         if( state.i_int != PAUSE_S )
993         {
994             /* A stream is being played, pause it */
995             state.i_int = PAUSE_S;
996         }
997         else
998         {
999             /* Stream is paused, resume it */
1000             state.i_int = PLAYING_S;
1001         }
1002         var_Set( p_input, "state", state );
1003
1004         TogglePlayButton( state.i_int );
1005         vlc_object_release( p_input );
1006         vlc_object_release( p_playlist );
1007     }
1008     else
1009     {
1010         /* If the playlist is empty, open a file requester instead */
1011         vlc_object_release( p_playlist );
1012         OnShowDialog( dummy );
1013     }
1014 }
1015
1016 void Interface::OnStopStream( wxCommandEvent& WXUNUSED(event) )
1017 {
1018     playlist_t * p_playlist =
1019         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
1020                                        FIND_ANYWHERE );
1021     if( p_playlist == NULL )
1022     {
1023         return;
1024     }
1025
1026     playlist_Stop( p_playlist );
1027     TogglePlayButton( PAUSE_S );
1028     vlc_object_release( p_playlist );
1029 }
1030
1031 void Interface::OnSliderUpdate( wxScrollEvent& event )
1032 {
1033     vlc_mutex_lock( &p_intf->change_lock );
1034
1035 #ifdef WIN32
1036     if( event.GetEventType() == wxEVT_SCROLL_THUMBRELEASE
1037         || event.GetEventType() == wxEVT_SCROLL_ENDSCROLL )
1038     {
1039 #endif
1040         if( p_intf->p_sys->i_slider_pos != event.GetPosition()
1041             && p_intf->p_sys->p_input )
1042         {
1043             vlc_value_t pos;
1044             pos.f_float = (float)event.GetPosition() / (float)SLIDER_MAX_POS;
1045
1046             var_Set( p_intf->p_sys->p_input, "position", pos );
1047         }
1048
1049 #ifdef WIN32
1050         p_intf->p_sys->b_slider_free = VLC_TRUE;
1051     }
1052     else
1053     {
1054         p_intf->p_sys->b_slider_free = VLC_FALSE;
1055
1056         if( p_intf->p_sys->p_input )
1057         {
1058             /* Update stream date */
1059 #define p_area p_intf->p_sys->p_input->stream.p_selected_area
1060             char psz_time[ OFFSETTOTIME_MAX_SIZE ];
1061
1062             slider_box->SetLabel(
1063                 wxU(input_OffsetToTime( p_intf->p_sys->p_input,
1064                                         psz_time,
1065                                         p_area->i_size * event.GetPosition()
1066                                         / SLIDER_MAX_POS )) );
1067 #undef p_area
1068         }
1069     }
1070 #endif
1071
1072     vlc_mutex_unlock( &p_intf->change_lock );
1073 }
1074
1075 void Interface::OnPrevStream( wxCommandEvent& WXUNUSED(event) )
1076 {
1077     playlist_t * p_playlist =
1078         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
1079                                        FIND_ANYWHERE );
1080     if( p_playlist == NULL )
1081     {
1082         return;
1083     }
1084
1085     vlc_mutex_lock( &p_playlist->object_lock );
1086     if( p_playlist->p_input != NULL )
1087     {
1088         vlc_mutex_lock( &p_playlist->p_input->stream.stream_lock );
1089         if( p_playlist->p_input->stream.p_selected_area->i_id > 1 )
1090         {
1091             vlc_value_t val; val.b_bool = VLC_TRUE;
1092             vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
1093             var_Set( p_playlist->p_input, "prev-title", val );
1094             vlc_mutex_unlock( &p_playlist->object_lock );
1095             vlc_object_release( p_playlist );  
1096             return;
1097         }
1098         vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
1099     }
1100     vlc_mutex_unlock( &p_playlist->object_lock );
1101
1102     playlist_Prev( p_playlist );
1103     vlc_object_release( p_playlist );
1104 }
1105
1106 void Interface::OnNextStream( wxCommandEvent& WXUNUSED(event) )
1107 {
1108     playlist_t * p_playlist =
1109         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
1110                                        FIND_ANYWHERE );
1111     if( p_playlist == NULL )
1112     {
1113         return;
1114     }
1115
1116     vlc_mutex_lock( &p_playlist->object_lock );
1117     if( p_playlist->p_input != NULL )
1118     {
1119         vlc_mutex_lock( &p_playlist->p_input->stream.stream_lock );
1120         if( p_playlist->p_input->stream.i_area_nb > 1 &&
1121             p_playlist->p_input->stream.p_selected_area->i_id <
1122               p_playlist->p_input->stream.i_area_nb - 1 )
1123         {
1124             vlc_value_t val; val.b_bool = VLC_TRUE;
1125             vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
1126             var_Set( p_playlist->p_input, "next-title", val );
1127             vlc_mutex_unlock( &p_playlist->object_lock );
1128             vlc_object_release( p_playlist );  
1129             return;
1130         }
1131         vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
1132     }
1133     vlc_mutex_unlock( &p_playlist->object_lock );
1134
1135     playlist_Next( p_playlist );
1136     vlc_object_release( p_playlist );
1137 }
1138
1139 void Interface::OnSlowStream( wxCommandEvent& WXUNUSED(event) )
1140 {
1141     input_thread_t *p_input =
1142         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
1143                                            FIND_ANYWHERE );
1144     if( p_input )
1145     {
1146         vlc_value_t val; val.b_bool = VLC_TRUE;
1147
1148         var_Set( p_input, "rate-slower", val );
1149         vlc_object_release( p_input );
1150     }
1151 }
1152
1153 void Interface::OnFastStream( wxCommandEvent& WXUNUSED(event) )
1154 {
1155     input_thread_t *p_input =
1156         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
1157                                            FIND_ANYWHERE );
1158     if( p_input )
1159     {
1160         vlc_value_t val; val.b_bool = VLC_TRUE;
1161
1162         var_Set( p_input, "rate-faster", val );
1163         vlc_object_release( p_input );
1164     }
1165 }
1166
1167 void Interface::TogglePlayButton( int i_playing_status )
1168 {
1169     if( i_playing_status == i_old_playing_status )
1170         return;
1171
1172     GetToolBar()->DeleteTool( PlayStream_Event );
1173
1174     if( i_playing_status == PLAYING_S )
1175     {
1176         GetToolBar()->InsertTool( 5, PlayStream_Event, wxU(_("Pause")),
1177                                   wxBitmap( pause_xpm ), wxNullBitmap,
1178                                   wxITEM_NORMAL, wxU(_(HELP_PAUSE)) );
1179     }
1180     else
1181     {
1182         GetToolBar()->InsertTool( 5, PlayStream_Event, wxU(_("Play")),
1183                                   wxBitmap( play_xpm ), wxNullBitmap,
1184                                   wxITEM_NORMAL, wxU(_(HELP_PLAY)) );
1185     }
1186
1187     GetToolBar()->Realize();
1188
1189     i_old_playing_status = i_playing_status;
1190 }
1191
1192 #if !defined(__WXX11__)
1193 /*****************************************************************************
1194  * Definition of DragAndDrop class.
1195  *****************************************************************************/
1196 DragAndDrop::DragAndDrop( intf_thread_t *_p_intf )
1197 {
1198     p_intf = _p_intf;
1199 }
1200
1201 bool DragAndDrop::OnDropFiles( wxCoord, wxCoord,
1202                                const wxArrayString& filenames )
1203 {
1204     /* Add dropped files to the playlist */
1205
1206     playlist_t *p_playlist =
1207         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
1208                                        FIND_ANYWHERE );
1209     if( p_playlist == NULL )
1210     {
1211         return FALSE;
1212     }
1213
1214     for( size_t i = 0; i < filenames.GetCount(); i++ )
1215         playlist_Add( p_playlist, (const char *)filenames[i].mb_str(), 0, 0,
1216                       PLAYLIST_APPEND | (i ? 0 : PLAYLIST_GO), PLAYLIST_END );
1217
1218     vlc_object_release( p_playlist );
1219
1220     return TRUE;
1221 }
1222 #endif
1223
1224 /*****************************************************************************
1225  * Definition of wxVolCtrl class.
1226  *****************************************************************************/
1227 wxVolCtrl::wxVolCtrl( intf_thread_t *_p_intf, wxWindow* parent, wxWindowID id )
1228   : wxGauge( parent, id, 200, wxDefaultPosition, wxDefaultSize,
1229              wxGA_VERTICAL | wxGA_SMOOTH )
1230 {
1231     p_intf = _p_intf;
1232 }
1233
1234 void wxVolCtrl::OnChange( wxMouseEvent& event )
1235 {
1236     if( !event.LeftDown() && !event.LeftIsDown() ) return;
1237
1238     int i_volume = (GetClientSize().GetHeight() - event.GetY()) * 200 /
1239                     GetClientSize().GetHeight();
1240     Change( i_volume );
1241 }
1242
1243 void wxVolCtrl::Change( int i_volume )
1244 {
1245     aout_VolumeSet( p_intf, i_volume * AOUT_VOLUME_MAX / 200 );
1246     SetValue( i_volume );
1247     SetToolTip( wxString::Format((wxString)wxU(_("Volume")) + wxT(" %d"),
1248                 i_volume ) );
1249 }