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