* modules/gui/wxwindows/*: added demuxdump support to the open dialog.
[vlc.git] / modules / gui / wxwindows / preferences.cpp
1 /*****************************************************************************
2  * preferences.cpp : wxWindows plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2001 VideoLAN
5  * $Id: preferences.cpp,v 1.2 2003/03/29 01:50:12 gbazin 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
34 #ifdef WIN32                                                 /* mingw32 hack */
35 #undef Yield
36 #undef CreateDialog
37 #endif
38
39 /* Let vlc take care of the i18n stuff */
40 #define WXINTL_NO_GETTEXT_MACRO
41
42 #include <wx/wxprec.h>
43 #include <wx/wx.h>
44 #include <wx/window.h>
45 #include <wx/notebook.h>
46 #include <wx/textctrl.h>
47 #include <wx/combobox.h>
48 #include <wx/spinctrl.h>
49 #include <wx/statline.h>
50 #include <wx/treectrl.h>
51 #include <wx/clntdata.h>
52 #include <wx/dynarray.h>
53
54 #include <vlc/intf.h>
55
56 #include "wxwindows.h"
57
58 #ifndef wxRB_SINGLE
59 #   define wxRB_SINGLE 0
60 #endif
61
62 /*****************************************************************************
63  * Classes declarations.
64  *****************************************************************************/
65 class PrefsTreeCtrl : public wxTreeCtrl
66 {
67 public:
68
69     PrefsTreeCtrl() { }
70     PrefsTreeCtrl( wxWindow *parent, intf_thread_t *_p_intf,
71                    PrefsDialog *p_prefs_dialog, wxBoxSizer *_p_sizer );
72     virtual ~PrefsTreeCtrl();
73
74 private:
75     /* Event handlers (these functions should _not_ be virtual) */
76     void OnSelectTreeItem( wxTreeEvent& event );
77
78     DECLARE_EVENT_TABLE()
79
80     intf_thread_t *p_intf;
81     PrefsDialog *p_prefs_dialog;
82     wxBoxSizer *p_sizer;
83     wxWindow *p_parent;
84 };
85
86 WX_DEFINE_ARRAY(wxEvtHandler *, ArrayOfControls);
87
88 class PrefsPanel : public wxScrolledWindow
89 {
90 public:
91
92     PrefsPanel() { }
93     PrefsPanel( wxWindow *parent, intf_thread_t *_p_intf,
94                 module_t *p_module, char * );
95     virtual ~PrefsPanel() {}
96
97 private:
98     void OnFileBrowse( wxCommandEvent& WXUNUSED(event) );
99     void OnDirectoryBrowse( wxCommandEvent& WXUNUSED(event) );
100     DECLARE_EVENT_TABLE()
101
102     intf_thread_t *p_intf;
103     ArrayOfControls controls_array;
104 };
105
106 class ConfigTreeData : public wxTreeItemData
107 {
108 public:
109
110     ConfigTreeData() { panel == NULL; }
111     virtual ~ConfigTreeData() { if( panel ) delete panel; }
112
113     wxWindow *panel;
114     wxBoxSizer *sizer;
115 };
116
117 class ConfigData : public wxClientData
118 {
119 public:
120     ConfigData() { b_advanced = VLC_FALSE; }
121     ConfigData( vlc_bool_t _b_advanced ) { b_advanced = _b_advanced; }
122     virtual ~ConfigData() { }
123
124     vlc_bool_t IsAdvanced() { return b_advanced; }
125
126 private:
127     vlc_bool_t b_advanced;
128 };
129
130 /*****************************************************************************
131  * Event Table.
132  *****************************************************************************/
133
134 /* IDs for the controls and the menu commands */
135 enum
136 {
137     Notebook_Event = wxID_HIGHEST,
138     MRL_Event,
139
140 };
141
142 BEGIN_EVENT_TABLE(PrefsDialog, wxDialog)
143     /* Button events */
144     EVT_BUTTON(wxID_OK, PrefsDialog::OnOk)
145     EVT_BUTTON(wxID_CANCEL, PrefsDialog::OnCancel)
146
147 END_EVENT_TABLE()
148
149 // menu and control ids
150 enum
151 {
152     PrefsTree_Ctrl = wxID_HIGHEST
153 };
154
155 BEGIN_EVENT_TABLE(PrefsTreeCtrl, wxTreeCtrl)
156     EVT_TREE_SEL_CHANGED(PrefsTree_Ctrl, PrefsTreeCtrl::OnSelectTreeItem)
157 END_EVENT_TABLE()
158
159 enum
160 {
161     FileBrowse_Event = wxID_HIGHEST,
162     DirectoryBrowse_Event,
163
164 };
165
166 BEGIN_EVENT_TABLE(PrefsPanel, wxScrolledWindow)
167     /* Button events */
168     EVT_BUTTON(FileBrowse_Event, PrefsPanel::OnFileBrowse)
169     EVT_BUTTON(DirectoryBrowse_Event, PrefsPanel::OnDirectoryBrowse)
170
171 END_EVENT_TABLE()
172
173 /*****************************************************************************
174  * Constructor.
175  *****************************************************************************/
176 PrefsDialog::PrefsDialog( intf_thread_t *_p_intf, Interface *_p_main_interface)
177   :  wxDialog( _p_main_interface, -1, _("Preferences"), wxDefaultPosition,
178                wxSize(600,400), wxDEFAULT_FRAME_STYLE )
179 {
180     /* Initializations */
181     p_intf = _p_intf;
182     p_main_interface = _p_main_interface;
183
184     /* Create a panel to put everything in */
185     wxPanel *panel = new wxPanel( this, -1 );
186     panel->SetAutoLayout( TRUE );
187
188     /* Create the preferences tree control */
189     wxBoxSizer *controls_sizer = new wxBoxSizer( wxHORIZONTAL );
190     PrefsTreeCtrl *prefs_tree =
191         new PrefsTreeCtrl( panel, p_intf, this, controls_sizer );
192
193     /* Separation */
194     wxStaticLine *static_line = new wxStaticLine( panel, wxID_OK );
195
196     /* Create the buttons */
197     wxButton *ok_button = new wxButton( panel, wxID_OK, _("OK") );
198     ok_button->SetDefault();
199     wxButton *cancel_button = new wxButton( panel, wxID_CANCEL, _("Cancel") );
200
201     /* Place everything in sizers */
202     wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
203     button_sizer->Add( ok_button, 0, wxALL, 5 );
204     button_sizer->Add( cancel_button, 0, wxALL, 5 );
205     button_sizer->Layout();
206
207     wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
208     wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
209     panel_sizer->Add( controls_sizer, 1, wxEXPAND | wxALL, 5 );
210     panel_sizer->Add( static_line, 0, wxEXPAND | wxALL, 5 );
211     panel_sizer->Add( button_sizer, 0, wxALIGN_LEFT | wxALIGN_BOTTOM |
212                       wxALL, 5 );
213     panel_sizer->Layout();
214     panel->SetSizer( panel_sizer );
215     main_sizer->Add( panel, 1, wxEXPAND, 0 );
216     main_sizer->Layout();
217     SetSizer( main_sizer );
218 }
219
220 PrefsDialog::~PrefsDialog()
221 {
222 }
223
224 /*****************************************************************************
225  * Private methods.
226  *****************************************************************************/
227
228
229 /*****************************************************************************
230  * Events methods.
231  *****************************************************************************/
232 void PrefsDialog::OnOk( wxCommandEvent& WXUNUSED(event) )
233 {
234     this->Hide();
235 }
236
237 void PrefsDialog::OnCancel( wxCommandEvent& WXUNUSED(event) )
238 {
239     this->Hide();
240 }
241
242 void PrefsTreeCtrl::OnSelectTreeItem( wxTreeEvent& event )
243 {
244     ConfigTreeData *config_data;
245
246     config_data = (ConfigTreeData *)GetItemData( event.GetOldItem() );
247     if( config_data && config_data->panel )
248     {
249         config_data->panel->Hide();
250         p_sizer->Remove( config_data->panel );
251     }
252
253     config_data = (ConfigTreeData *)GetItemData( event.GetItem() );
254     if( config_data && config_data->panel )
255     {
256         config_data->panel->Show();
257         config_data->panel->FitInside();
258         p_sizer->Add( config_data->panel, 2, wxEXPAND | wxALL, 0 );
259         p_sizer->Layout();
260     }
261 }
262
263 void PrefsPanel::OnFileBrowse( wxCommandEvent& WXUNUSED(event) )
264 {
265     wxFileDialog dialog( this, _("Open file"), "", "", "*.*",
266                          wxOPEN );
267
268     if( dialog.ShowModal() == wxID_OK )
269     {
270 #if 0
271         file_combo->SetValue( dialog.GetPath() );      
272 #endif
273     }
274 }
275
276 void PrefsPanel::OnDirectoryBrowse( wxCommandEvent& WXUNUSED(event) )
277 {
278     wxFileDialog dialog( this, _("Open file"), "", "", "*.*",
279                          wxOPEN );
280
281     if( dialog.ShowModal() == wxID_OK )
282     {
283 #if 0
284         file_combo->SetValue( dialog.GetPath() );      
285 #endif
286     }
287 }
288
289 /*****************************************************************************
290  * PrefsTreeCtrl class definition.
291  *****************************************************************************/
292 PrefsTreeCtrl::PrefsTreeCtrl( wxWindow *_p_parent, intf_thread_t *_p_intf,
293                               PrefsDialog *_p_prefs_dialog,
294                               wxBoxSizer *_p_sizer )
295   : wxTreeCtrl( _p_parent, PrefsTree_Ctrl, wxDefaultPosition, wxDefaultSize,
296                 wxTR_NO_LINES | wxTR_FULL_ROW_HIGHLIGHT |
297                 wxTR_LINES_AT_ROOT | wxTR_HIDE_ROOT |
298                 wxTR_HAS_BUTTONS | wxTR_TWIST_BUTTONS | wxSUNKEN_BORDER )
299 {
300     vlc_list_t      *p_list;
301     module_t        *p_module;
302     module_config_t *p_item;
303     int i_index;
304
305     /* Initializations */
306     p_intf = _p_intf;
307     p_prefs_dialog = _p_prefs_dialog;
308     p_sizer = _p_sizer;
309     p_parent = _p_parent;
310
311     wxTreeItemId root_item = AddRoot( "" );
312
313     /* List the plugins */
314     p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
315     if( !p_list ) return;
316
317     /*
318      * Build a tree of the main options
319      */
320     for( i_index = 0; i_index < p_list->i_count; i_index++ )
321     {
322         p_module = (module_t *)p_list->p_values[i_index].p_object;
323         if( !strcmp( p_module->psz_object_name, "main" ) )
324             break;
325     }
326     if( i_index < p_list->i_count )
327     {
328         /* We found the main module */
329
330         /* Enumerate config options and add corresponding config boxes */
331         p_item = p_module->p_config;
332
333         if( p_item ) do
334         {
335             if( p_item->b_advanced && !config_GetInt( p_intf, "advanced" ))
336             {
337                 continue;
338             }
339             switch( p_item->i_type )
340             {
341             case CONFIG_HINT_CATEGORY:
342                 ConfigTreeData *config_data = new ConfigTreeData;
343                 config_data->panel =
344                     new PrefsPanel( p_parent, p_intf,
345                                     p_module, p_item->psz_text );
346                 config_data->panel->Hide();
347
348                 /* Add the category to the tree */
349                 AppendItem( root_item, p_item->psz_text, -1, -1, config_data );
350                 break;
351             }
352         }
353         while( p_item->i_type != CONFIG_HINT_END && p_item++ );
354
355         SortChildren( root_item );
356     }
357
358     /*
359      * Build a tree of all the plugins
360      */
361
362     wxTreeItemId plugins_item = AppendItem( root_item, _("Plugins") );
363
364     for( i_index = 0; i_index < p_list->i_count; i_index++ )
365     {
366         p_module = (module_t *)p_list->p_values[i_index].p_object;
367
368         /* Find the capabiltiy child item */
369         long cookie; size_t i_child_index;
370         wxTreeItemId capability_item = GetFirstChild( plugins_item, cookie);
371         for( i_child_index = 0;
372              i_child_index < GetChildrenCount( plugins_item, FALSE );
373              i_child_index++ )
374         {
375             if( !GetItemText(capability_item).Cmp(p_module->psz_capability) )
376             {
377                 break;
378             }
379             capability_item = GetNextChild( plugins_item, cookie );
380         }
381
382         if( i_child_index == GetChildrenCount( plugins_item, FALSE ) )
383         {
384             /* We didn't find it, add it */
385             capability_item = AppendItem( plugins_item,
386                                           p_module->psz_capability );
387         }
388
389         /* Add the plugin to the tree */
390         ConfigTreeData *config_data = new ConfigTreeData;
391         config_data->panel =
392             new PrefsPanel( p_parent, p_intf, p_module, NULL );
393         config_data->panel->Hide();
394         AppendItem( capability_item, p_module->psz_object_name, -1, -1,
395                     config_data );
396     }
397
398     /* Sort all this mess */
399     long cookie; size_t i_child_index;
400     SortChildren( plugins_item );
401     wxTreeItemId capability_item = GetFirstChild( plugins_item, cookie);
402     for( i_child_index = 0;
403          i_child_index < GetChildrenCount( plugins_item, FALSE );
404          i_child_index++ )
405     {
406         capability_item = GetNextChild( plugins_item, cookie );
407         SortChildren( capability_item );
408     }
409
410     /* Clean-up everything */
411     vlc_list_release( p_list );
412
413     p_sizer->Add( this, 1, wxEXPAND | wxALL, 0 );
414     p_sizer->Layout();
415
416 }
417
418 PrefsTreeCtrl::~PrefsTreeCtrl()
419 {
420 }
421
422 /*****************************************************************************
423  * PrefsPanel class definition.
424  *****************************************************************************/
425 PrefsPanel::PrefsPanel( wxWindow* parent, intf_thread_t *_p_intf,
426                         module_t *p_module, char *psz_section )
427   :  wxScrolledWindow( parent, -1, wxDefaultPosition, wxDefaultSize )
428 {
429     module_config_t *p_item;
430     vlc_list_t      *p_list;
431     module_t        *p_parser;
432
433     wxStaticText *label;
434     wxComboBox *combo;
435     wxRadioButton *radio;
436     wxSpinCtrl *spin;
437     wxCheckBox *checkbox;
438     wxTextCtrl *textctrl;
439     wxButton *button;
440     wxStaticLine *static_line;
441     wxBoxSizer *horizontal_sizer;
442     wxSortedArrayString sorted_array;
443     wxArrayString array;
444
445     /* Initializations */
446     p_intf = _p_intf;
447     SetAutoLayout( TRUE );
448     SetScrollRate( 5, 5 );
449
450     wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
451
452     /* Enumerate config options and add corresponding config boxes */
453     p_item = p_module->p_config;
454
455     /* Find the category if it has been specified */
456     if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY )
457     {
458         while( !p_item->i_type == CONFIG_HINT_CATEGORY ||
459                strcmp( psz_section, p_item->psz_text ) )
460         {
461             if( p_item->i_type == CONFIG_HINT_END )
462                 break;
463             p_item++;
464         }
465     }
466
467     /* Add a head title to the panel */
468     wxStaticBox *static_box = new wxStaticBox( this, -1, "" );
469     wxStaticBoxSizer *box_sizer = new wxStaticBoxSizer( static_box,
470                                                         wxHORIZONTAL );
471     label = new wxStaticText( this, -1,
472                               psz_section ? p_item->psz_text :
473                               p_module->psz_longname );
474
475     box_sizer->Add( label, 1, wxALL, 5 );
476     sizer->Add( box_sizer, 0, wxEXPAND | wxALL, 5 );
477
478     if( p_item ) do
479     {
480         if( p_item->b_advanced && !config_GetInt( p_intf, "advanced" ) )
481         {
482             continue;
483         }
484
485         /* If a category has been specified, check we finished the job */
486         if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY &&
487             strcmp( psz_section, p_item->psz_text ) )
488             break;
489
490         switch( p_item->i_type )
491         {
492         case CONFIG_HINT_CATEGORY:
493 #if 0
494             label = new wxStaticText(this, -1, p_item->psz_text);
495             sizer->Add( label, 0, wxALL, 5 );
496 #endif
497             break;
498
499         case CONFIG_ITEM_MODULE:
500             label = new wxStaticText(this, -1, p_item->psz_text);
501             combo = new wxComboBox( this, -1, p_item->psz_value,
502                                     wxDefaultPosition, wxSize(200,-1),
503                                     0, NULL );
504
505             /* build a list of available modules */
506             p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
507             for( int i_index = 0; i_index < p_list->i_count; i_index++ )
508             {
509                 p_parser = (module_t *)p_list->p_values[i_index].p_object ;
510
511                 if( !strcmp( p_parser->psz_capability,
512                              p_item->psz_type ) )
513                 {
514                     combo->Append( p_parser->psz_longname );
515                 }
516             }
517
518             combo->SetToolTip( p_item->psz_longtext );
519             horizontal_sizer = new wxBoxSizer( wxHORIZONTAL );
520             horizontal_sizer->Add( label, 0, wxALL, 5 );
521             horizontal_sizer->Add( combo, 0, wxALL, 5 );
522             sizer->Add( horizontal_sizer, 0, wxALL, 5 );
523             break;
524
525         case CONFIG_ITEM_STRING:
526         case CONFIG_ITEM_FILE:
527             label = new wxStaticText(this, -1, p_item->psz_text);
528             textctrl = new wxTextCtrl( this, -1, p_item->psz_value,
529                                        wxDefaultPosition, wxDefaultSize,
530                                        wxTE_PROCESS_ENTER);
531             textctrl->SetToolTip( p_item->psz_longtext );
532             horizontal_sizer = new wxBoxSizer( wxHORIZONTAL );
533             horizontal_sizer->Add( label, 0, wxALL, 5 );
534             horizontal_sizer->Add( textctrl, 0, wxALL, 5 );
535             if( p_item->i_type == CONFIG_ITEM_FILE )
536             {
537                 button = new wxButton( this, -1, _("Browse...") );
538                 horizontal_sizer->Add( button, 0, wxALL, 5 );
539             }
540             sizer->Add( horizontal_sizer, 0, wxALL, 5 );
541             break;
542
543         case CONFIG_ITEM_INTEGER:
544             label = new wxStaticText(this, -1, p_item->psz_text);
545             spin = new wxSpinCtrl( this, -1,
546                                    wxString::Format(_("%d"), p_item->i_value),
547                                    wxDefaultPosition, wxDefaultSize,
548                                    wxSP_ARROW_KEYS,
549                                    0, 16000, p_item->i_value);
550             spin->SetToolTip( p_item->psz_longtext );
551             horizontal_sizer = new wxBoxSizer( wxHORIZONTAL );
552             horizontal_sizer->Add( label, 0, wxALL, 5 );
553             horizontal_sizer->Add( spin, 0, wxALL, 5 );
554             sizer->Add( horizontal_sizer, 0, wxALL, 5 );
555             break;
556
557         case CONFIG_ITEM_FLOAT:
558             label = new wxStaticText(this, -1, p_item->psz_text);
559             spin = new wxSpinCtrl( this, -1,
560                                    wxString::Format(_("%d"), p_item->i_value),
561                                    wxDefaultPosition, wxDefaultSize,
562                                    wxSP_ARROW_KEYS,
563                                    0, 16000, p_item->i_value);
564             spin->SetToolTip( p_item->psz_longtext );
565             horizontal_sizer = new wxBoxSizer( wxHORIZONTAL );
566             horizontal_sizer->Add( label, 0, wxALL, 5 );
567             horizontal_sizer->Add( spin, 0, wxALL, 5 );
568             sizer->Add( horizontal_sizer, 0, wxALL, 5 );
569             break;
570
571         case CONFIG_ITEM_BOOL:
572             checkbox = new wxCheckBox( this, -1, p_item->psz_text );
573             if( p_item->i_value ) checkbox->SetValue(TRUE);
574             checkbox->SetToolTip( p_item->psz_longtext );
575             horizontal_sizer = new wxBoxSizer( wxHORIZONTAL );
576             horizontal_sizer->Add( checkbox, 0, wxALL, 5 );
577             sizer->Add( horizontal_sizer, 0, wxALL, 5 );
578             break;
579         }
580     }
581     while( p_item->i_type != CONFIG_HINT_END && p_item++ );
582
583
584     sizer->Layout();
585     SetSizer( sizer );
586 }