]> git.sesse.net Git - vlc/blob - modules/gui/wxwidgets/dialogs/open.cpp
Remove useless test before free and delete.
[vlc] / modules / gui / wxwidgets / dialogs / open.cpp
1 /*****************************************************************************
2  * open.cpp : Open dialog box
3  *****************************************************************************
4  * Copyright (C) 2000-2005 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include "dialogs/open.hpp"
28 #include "dialogs/streamout.hpp"
29 #include "dialogs/preferences_widgets.h"
30 #include "dialogs/subtitles.hpp"
31
32 #include "vlc_charset.h"
33
34 #undef HAVE_LIBCDIO // Disable broken code
35
36 #ifdef HAVE_LIBCDIO
37 #include <cdio/cdio.h>
38 #include <cdio/cd_types.h>
39 #include <cdio/logging.h>
40 #endif /* HAVE_LIBCDIO */
41
42 #ifdef HAVE_VCDINFO
43 #include <libvcd/version.h>
44 /* There was a bug in libvcdinfo <= 23 which prevented C++ compilation */
45 #if LIBVCD_VERSION_NUM > 23
46 #include <libvcd/info.h>
47 #endif /* LIBVCD_VERSION_NUM > 23 */
48 #endif /* HAVE_VCDINFO */
49
50 #include <wx/combobox.h>
51 #include <wx/statline.h>
52 #include <wx/tokenzr.h>
53
54 #ifndef wxRB_SINGLE
55 #   define wxRB_SINGLE 0
56 #endif
57
58 #define SELECTION_DISC_TYPE_DVD_MENUS 0
59 #define SELECTION_DISC_TYPE_DVD       1
60 #define SELECTION_DISC_TYPE_VCD       2
61 #define SELECTION_DISC_TYPE_CDDA      3
62
63 /*****************************************************************************
64  * Event Table.
65  *****************************************************************************/
66
67 /* IDs for the controls and the menu commands */
68 enum
69 {
70     Notebook_Event = wxID_HIGHEST,
71     MRL_Event,
72
73     FileBrowse_Event,
74     SubFileBrowse_Event,
75     FileName_Event,
76     SubFileName_Event,
77
78     DiscType_Event,
79 #ifdef HAVE_LIBCDIO
80     DiscProbe_Event,
81 #endif
82     DiscDevice_Event,
83     DiscTitle_Event,
84     DiscChapter_Event,
85     DiscSub_Event,
86     DiscAudio_Event,
87
88     NetType_Event,
89     NetRadio1_Event, NetRadio2_Event, NetRadio3_Event, NetRadio4_Event,
90     NetPort1_Event, NetPort2_Event, NetPort3_Event,
91     NetAddr1_Event, NetAddr2_Event, NetAddr3_Event, NetAddr4_Event,
92     NetForceIPv6_Event, NetTimeshift_Event,
93
94     SubsFileEnable_Event,
95     SubsFileSettings_Event,
96
97     SoutEnable_Event,
98     SoutSettings_Event,
99
100     CachingEnable_Event,
101     CachingChange_Event,
102
103     AdvancedOptions_Event
104 };
105
106 BEGIN_EVENT_TABLE(OpenDialog, wxDialog)
107     /* Button events */
108     EVT_BUTTON(wxID_OK, OpenDialog::OnOk)
109     EVT_BUTTON(wxID_CANCEL, OpenDialog::OnCancel)
110
111     EVT_NOTEBOOK_PAGE_CHANGED(Notebook_Event, OpenDialog::OnPageChange)
112
113     EVT_TEXT(MRL_Event, OpenDialog::OnMRLChange)
114
115     /* Events generated by the file panel */
116     EVT_TEXT(FileName_Event, OpenDialog::OnFilePanelChange)
117     EVT_BUTTON(FileBrowse_Event, OpenDialog::OnFileBrowse)
118     EVT_TEXT(SubFileName_Event, OpenDialog::OnSubFileChange)
119     EVT_BUTTON(SubFileBrowse_Event, OpenDialog::OnSubFileBrowse)
120
121     /* Events generated by the disc panel */
122     EVT_RADIOBOX(DiscType_Event, OpenDialog::OnDiscTypeChange)
123 #ifdef HAVE_LIBCDIO
124     EVT_CHECKBOX(DiscProbe_Event, OpenDialog::OnDiscProbe)
125 #endif
126     EVT_TEXT(DiscDevice_Event, OpenDialog::OnDiscDeviceChange)
127     EVT_TEXT(DiscDevice_Event, OpenDialog::OnDiscPanelChange)
128     EVT_TEXT(DiscTitle_Event, OpenDialog::OnDiscPanelChange)
129     EVT_SPINCTRL(DiscTitle_Event, OpenDialog::OnDiscPanelChangeSpin)
130     EVT_TEXT(DiscChapter_Event, OpenDialog::OnDiscPanelChange)
131     EVT_SPINCTRL(DiscChapter_Event, OpenDialog::OnDiscPanelChangeSpin)
132     EVT_TEXT(DiscSub_Event, OpenDialog::OnDiscPanelChange)
133     EVT_TEXT(DiscAudio_Event, OpenDialog::OnDiscPanelChange)
134     EVT_SPINCTRL(DiscSub_Event, OpenDialog::OnDiscPanelChangeSpin)
135
136     /* Events generated by the net panel */
137     EVT_RADIOBUTTON(NetRadio1_Event, OpenDialog::OnNetTypeChange)
138     EVT_RADIOBUTTON(NetRadio2_Event, OpenDialog::OnNetTypeChange)
139     EVT_RADIOBUTTON(NetRadio3_Event, OpenDialog::OnNetTypeChange)
140     EVT_RADIOBUTTON(NetRadio4_Event, OpenDialog::OnNetTypeChange)
141     EVT_TEXT(NetPort1_Event, OpenDialog::OnNetPanelChange)
142     EVT_SPINCTRL(NetPort1_Event, OpenDialog::OnNetPanelChangeSpin)
143     EVT_TEXT(NetPort2_Event, OpenDialog::OnNetPanelChange)
144     EVT_SPINCTRL(NetPort2_Event, OpenDialog::OnNetPanelChangeSpin)
145     EVT_TEXT(NetPort3_Event, OpenDialog::OnNetPanelChange)
146     EVT_SPINCTRL(NetPort3_Event, OpenDialog::OnNetPanelChangeSpin)
147     EVT_TEXT(NetAddr2_Event, OpenDialog::OnNetPanelChange)
148     EVT_TEXT(NetAddr3_Event, OpenDialog::OnNetPanelChange)
149     EVT_TEXT(NetAddr4_Event, OpenDialog::OnNetPanelChange)
150     EVT_CHECKBOX(NetForceIPv6_Event, OpenDialog::OnNetPanelChange)
151     EVT_CHECKBOX(NetTimeshift_Event, OpenDialog::OnNetPanelChange)
152
153     /* Events generated by the subtitle file buttons */
154     EVT_CHECKBOX(SubsFileEnable_Event, OpenDialog::OnSubsFileEnable)
155     EVT_BUTTON(SubsFileSettings_Event, OpenDialog::OnSubsFileSettings)
156
157     /* Events generated by the stream output buttons */
158     EVT_CHECKBOX(SoutEnable_Event, OpenDialog::OnSoutEnable)
159     EVT_BUTTON(SoutSettings_Event, OpenDialog::OnSoutSettings)
160
161     /* Events generated by the caching button */
162     EVT_CHECKBOX(CachingEnable_Event, OpenDialog::OnCachingEnable)
163     EVT_TEXT(CachingChange_Event, OpenDialog::OnCachingChange)
164     EVT_SPINCTRL(CachingChange_Event, OpenDialog::OnCachingChangeSpin)
165
166     /* Hide the window when the user closes the window */
167     EVT_CLOSE(OpenDialog::OnClose)
168
169 END_EVENT_TABLE()
170
171
172 /*****************************************************************************
173  * AutoBuiltPanel.
174  *****************************************************************************/
175 WX_DEFINE_ARRAY(ConfigControl *, ArrayOfConfigControls);
176
177 class AutoBuiltPanel : public wxPanel
178 {
179 public:
180
181     AutoBuiltPanel() { }
182     AutoBuiltPanel( wxWindow *, OpenDialog *, intf_thread_t *,
183                     const module_t * );
184
185     virtual ~AutoBuiltPanel() {}
186
187     void UpdateAdvancedMRL();
188
189     wxString name;
190     ArrayOfConfigControls config_array;
191     ArrayOfConfigControls advanced_config_array;
192     wxComboBox *p_advanced_mrl_combo;
193
194 private:
195     intf_thread_t *p_intf;
196     OpenDialog *p_open_dialog;
197
198     void OnAdvanced( wxCommandEvent& event );
199     wxDialog *p_advanced_dialog;
200
201     DECLARE_EVENT_TABLE();
202 };
203
204 BEGIN_EVENT_TABLE(AutoBuiltPanel, wxPanel)
205     EVT_BUTTON(AdvancedOptions_Event, AutoBuiltPanel::OnAdvanced)
206 END_EVENT_TABLE()
207
208 static void AutoBuildCallback( void *p_data )
209 {
210     ((OpenDialog *)p_data)->UpdateMRL();
211 }
212
213 static void AutoBuildAdvancedCallback( void *p_data )
214 {
215     ((AutoBuiltPanel *)p_data)->UpdateAdvancedMRL();
216 }
217
218 AutoBuiltPanel::AutoBuiltPanel( wxWindow *parent, OpenDialog *dialog,
219                                 intf_thread_t *_p_intf,
220                                 const module_t *p_module )
221   : wxPanel( parent, -1, wxDefaultPosition, wxDefaultSize ),
222     name( wxU(module_GetObjName(p_module)) ),
223     p_advanced_mrl_combo( NULL ),
224     p_intf( _p_intf ), p_open_dialog( dialog ), p_advanced_dialog( NULL )
225 {
226     wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
227     bool b_advanced = false;
228     unsigned int i_confsize; 
229     module_config_t *p_config;
230     int n;
231
232     p_config = module_GetConfig (p_module, &i_confsize);
233     for( n = 0; n < i_confsize; n++ )
234     {
235         module_config_t *p_item = p_config + n;
236         if( !(p_item->i_type & CONFIG_HINT) && p_item->b_advanced )
237             b_advanced = true;
238
239         if( p_item->i_type & CONFIG_HINT || p_item->b_advanced )
240             continue;
241
242         ConfigControl *control =
243             CreateConfigControl( VLC_OBJECT(p_intf), p_item, this );
244
245         config_array.Add( control );
246
247         /* Don't add items that were not recognized */
248         if( control == NULL ) continue;
249
250         control->SetUpdateCallback( AutoBuildCallback, (void *)dialog );
251
252         sizer->Add( control, 0, wxEXPAND | wxALL, 2 );
253     }
254
255     if( b_advanced )
256     {
257         wxButton *button =
258             new wxButton( this, AdvancedOptions_Event,
259                           wxU(_("Advanced options...")) );
260         sizer->Add( button, 0, wxALL, 5 );
261
262         /* Build the advanced dialog */
263         p_advanced_dialog =
264             new wxDialog( this, -1, ((wxString)wxU(_("Advanced options"))) +
265                           wxT(" (") + wxU( module_GetLongName(p_module) ) +
266                           wxT(")"), wxDefaultPosition, wxDefaultSize,
267                           wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER );
268
269         wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
270
271         /* Create MRL combobox */
272         wxBoxSizer *mrl_sizer_sizer = new wxBoxSizer( wxHORIZONTAL );
273         wxStaticBox *mrl_box =
274             new wxStaticBox( p_advanced_dialog, -1,
275                              wxU(_("Advanced options")) );
276         wxStaticBoxSizer *mrl_sizer =
277             new wxStaticBoxSizer( mrl_box, wxHORIZONTAL );
278         wxStaticText *mrl_label =
279             new wxStaticText( p_advanced_dialog, -1, wxU(_("Options:")) );
280         p_advanced_mrl_combo =
281             new wxComboBox( p_advanced_dialog, MRL_Event, wxT(""),
282                             wxDefaultPosition, wxDefaultSize );
283         mrl_sizer->Add( mrl_label, 0, wxALL | wxALIGN_CENTER, 5 );
284         mrl_sizer->Add( p_advanced_mrl_combo, 1, wxALL | wxALIGN_CENTER, 5 );
285         mrl_sizer_sizer->Add( mrl_sizer, 1, wxEXPAND | wxALL, 5 );
286         sizer->Add( mrl_sizer_sizer, 0, wxEXPAND | wxALL, 2 );
287
288         /* Add advanced options to panel */
289         for( n = 0; n < i_confsize; n++ )
290         {
291             module_config_t *p_item = p_config + n;
292             if( p_item->i_type & CONFIG_HINT || !p_item->b_advanced )
293                 continue;
294
295             ConfigControl *control =
296                 CreateConfigControl( VLC_OBJECT(p_intf), p_item,
297                                      p_advanced_dialog );
298
299             advanced_config_array.Add( control );
300
301             /* Don't add items that were not recognized */
302             if( control == NULL ) continue;
303
304             control->SetUpdateCallback( AutoBuildAdvancedCallback,
305                                         (void *)this );
306
307             sizer->Add( control, 0, wxEXPAND | wxALL, 2 );
308         }
309
310         /* Separation */
311         wxPanel *dummy_panel = new wxPanel( p_advanced_dialog, -1 );
312         sizer->Add( dummy_panel, 1 );
313         wxStaticLine *static_line =
314             new wxStaticLine( p_advanced_dialog, wxID_OK );
315         sizer->Add( static_line, 0, wxEXPAND | wxALL, 5 );
316
317         /* Create buttons */
318         wxButton *ok_button =
319             new wxButton( p_advanced_dialog, wxID_OK, wxU(_("&OK")) );
320         ok_button->SetDefault();
321         wxButton *cancel_button =
322             new wxButton( p_advanced_dialog, wxID_CANCEL, wxU(_("&Cancel")) );
323         wxStdDialogButtonSizer *button_sizer = new wxStdDialogButtonSizer;
324         button_sizer->AddButton( ok_button );
325         button_sizer->AddButton( cancel_button );
326         button_sizer->Realize();
327         sizer->Add( button_sizer, 0, wxEXPAND|wxALL, 5 );
328
329         sizer->SetMinSize( 400, -1 );
330         p_advanced_dialog->SetSizerAndFit( sizer );
331     }
332
333     module_PutConfig (p_config);
334
335     this->SetSizerAndFit( sizer );
336 }
337
338 void AutoBuiltPanel::OnAdvanced( wxCommandEvent& event )
339 {
340     if( p_advanced_dialog->ShowModal() == wxID_OK )
341     {
342         UpdateAdvancedMRL();
343         p_open_dialog->UpdateMRL();
344     }
345 }
346
347 void AutoBuiltPanel::UpdateAdvancedMRL()
348 {
349     wxString mrltemp;
350
351     for( int i = 0; i < (int)advanced_config_array.GetCount(); i++ )
352     {
353         ConfigControl *control = advanced_config_array.Item(i);
354
355         mrltemp += (i ? wxT(" :") : wxT(":"));
356
357         if( control->GetType() == CONFIG_ITEM_BOOL &&
358             !control->GetIntValue() ) mrltemp += wxT("no-");
359
360         mrltemp += control->GetName();
361
362         switch( control->GetType() )
363         {
364         case CONFIG_ITEM_STRING:
365         case CONFIG_ITEM_FILE:
366         case CONFIG_ITEM_DIRECTORY:
367         case CONFIG_ITEM_MODULE:
368             mrltemp += wxT("=\"") + control->GetPszValue() + wxT("\"");
369             break;
370         case CONFIG_ITEM_INTEGER:
371             mrltemp +=
372                 wxString::Format( wxT("=%i"), control->GetIntValue() );
373             break;
374         case CONFIG_ITEM_FLOAT:
375             mrltemp +=
376                 wxString::Format(wxT("=%f"), control->GetFloatValue());
377             break;
378         }
379     }
380
381     p_advanced_mrl_combo->SetValue( mrltemp );
382 }
383
384 /*****************************************************************************
385  * Constructor.
386  *****************************************************************************/
387 OpenDialog::OpenDialog( intf_thread_t *_p_intf, wxWindow *_p_parent,
388                         int i_access_method, int i_arg ):
389       wxDialog( _p_parent, -1, wxU(_("Open...")), wxDefaultPosition,
390              wxDefaultSize, wxDEFAULT_FRAME_STYLE )
391 {
392     OpenDialog( _p_intf, _p_parent, i_access_method, i_arg, OPEN_NORMAL );
393 }
394
395 OpenDialog::OpenDialog( intf_thread_t *_p_intf, wxWindow *_p_parent,
396                         int i_access_method, int i_arg, int _i_method ):
397       wxDialog( _p_parent, -1, wxU(_("Open...")), wxDefaultPosition,
398              wxDefaultSize, wxDEFAULT_FRAME_STYLE )
399 {
400     /* Initializations */
401     i_method = _i_method;
402     p_intf = _p_intf;
403     p_parent = _p_parent;
404     SetIcon( *p_intf->p_sys->p_icon );
405     file_dialog = NULL;
406     i_disc_type_selection = 0;
407     i_disc_title = 0;
408     i_open_arg = i_arg;
409
410     sout_dialog = NULL;
411     subsfile_dialog = NULL;
412     b_disc_device_changed = false;
413
414     /* Create a panel to put everything in */
415     wxPanel *panel = new wxPanel( this, -1 );
416     panel->SetAutoLayout( TRUE );
417
418
419     /* Advanced options */
420     wxStaticBox *adv_box = new wxStaticBox( panel, -1,
421                                wxU(_("Advanced options")) );
422     wxStaticBoxSizer *adv_sizer = new wxStaticBoxSizer( adv_box,
423                                                         wxVERTICAL );
424
425
426     wxFlexGridSizer *common_opt_sizer = new wxFlexGridSizer( 5, 1, 20 );
427     if( i_method == OPEN_NORMAL )
428     {
429         /* Create Stream Output checkox */
430         sout_checkbox = new wxCheckBox( panel, SoutEnable_Event,
431                                          wxU(_("Stream/Save")) );
432         sout_checkbox->SetToolTip( wxU(_("Use VLC as a stream server")) );
433         common_opt_sizer->Add( sout_checkbox, 0,
434                                wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
435
436         sout_button = new wxButton( panel, SoutSettings_Event,
437                                     wxU(_("Settings...")) );
438         sout_button->Disable();
439
440         char *psz_sout = config_GetPsz( p_intf, "sout" );
441         if( psz_sout && *psz_sout )
442         {
443             sout_checkbox->SetValue(TRUE);
444             sout_button->Enable();
445             subsfile_mrl.Add( wxString(wxT("sout=")) + wxL2U(psz_sout) );
446         }
447         free( psz_sout );
448
449         common_opt_sizer->Add( sout_button, 1, wxALIGN_LEFT |
450                                wxALIGN_CENTER_VERTICAL );
451
452         common_opt_sizer->Add( new wxPanel( this, -1 ), 1,
453                                wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
454     }
455
456     /* Create caching options */
457     caching_checkbox = new wxCheckBox( panel, CachingEnable_Event,
458                                        wxU(_("Caching")) );
459     caching_checkbox->SetToolTip( wxU(_("Change the default caching value "
460                                         "(in milliseconds)")) );
461     common_opt_sizer->Add( caching_checkbox, 0,
462                            wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
463     caching_value = new wxSpinCtrl( panel, CachingChange_Event );
464     caching_value->SetRange( 0, 1000000 );
465     caching_value->Disable();
466     common_opt_sizer->Add( caching_value, 0,
467                            wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
468
469
470     wxBoxSizer *mrl_sizer = new wxBoxSizer( wxHORIZONTAL );
471     wxStaticText *mrl_label = new wxStaticText( panel, -1,
472                                                 wxU(_("Customize:")) );
473     mrl_combo = new wxComboBox( panel, MRL_Event, wxT(""),
474                                 wxDefaultPosition, wxDefaultSize );
475     //Point(20,25), wxSize(120, -1) );
476     mrl_combo->SetToolTip( wxU(_("You can use this field directly by typing "
477         "the full MRL you want to open.\n""Alternatively, the field will be "
478         "filled automatically when you use the controls above.")) );
479
480     mrl_sizer->Add( mrl_label, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
481     mrl_sizer->Add( mrl_combo, 1, wxALL | wxEXPAND | wxALIGN_CENTER_VERTICAL,
482                     5 );
483
484     adv_sizer->Add( common_opt_sizer, 0, wxTOP | wxLEFT|wxRIGHT | wxEXPAND, 5 );
485     adv_sizer->Add( mrl_sizer, 0, wxBOTTOM  | wxLEFT|wxRIGHT  | wxEXPAND, 5 );
486
487     /* Separation */
488     wxStaticLine *static_line = new wxStaticLine( panel, wxID_OK );
489
490     /* Create the buttons */
491     wxButton *ok_button = new wxButton( panel, wxID_OK, wxU(_("&OK")) );
492     ok_button->SetDefault();
493     wxButton *cancel_button = new wxButton( panel, wxID_CANCEL,
494                                             wxU(_("&Cancel")) );
495
496     /* Create notebook */
497     notebook = new wxNotebook( panel, Notebook_Event );
498
499 #if (!wxCHECK_VERSION(2,5,2))
500     wxNotebookSizer *notebook_sizer = new wxNotebookSizer( notebook );
501 #endif
502
503     notebook->AddPage( FilePanel( notebook ), wxU(_("File")),
504                        i_access_method == FILE_ACCESS );
505     notebook->AddPage( DiscPanel( notebook ), wxU(_("Disc")),
506                        i_access_method == DISC_ACCESS );
507     notebook->AddPage( NetPanel( notebook ), wxU(_("Network")),
508                        i_access_method == NET_ACCESS );
509
510     module_t *p_module = module_Find( VLC_OBJECT(p_intf), "v4l" );
511     if( p_module )
512     {
513         AutoBuiltPanel *autopanel =
514             new AutoBuiltPanel( notebook, this, p_intf, p_module );
515         input_tab_array.Add( autopanel );
516         notebook->AddPage( autopanel, wxU( module_GetName(p_module, 0) ),
517                            i_access_method == CAPTURE_ACCESS );
518         module_Put( p_module );
519     }
520
521     p_module = module_Find( VLC_OBJECT(p_intf), "pvr" );
522     if( p_module )
523     {
524         AutoBuiltPanel *autopanel =
525             new AutoBuiltPanel( notebook, this, p_intf, p_module );
526         input_tab_array.Add( autopanel );
527         notebook->AddPage( autopanel, wxU( module_GetName(p_module, 0) ),
528                            i_access_method == CAPTURE_ACCESS );
529         module_Put( p_module );
530     }
531
532     p_module = module_Find( VLC_OBJECT(p_intf), "dvb" );
533     if( p_module )
534     {
535         AutoBuiltPanel *autopanel =
536             new AutoBuiltPanel( notebook, this, p_intf, p_module );
537         input_tab_array.Add( autopanel );
538         notebook->AddPage( autopanel, wxU( module_GetName(p_module, 0) ),
539                            i_access_method == CAPTURE_ACCESS );
540         module_Put( p_module );
541     }
542
543     p_module = module_Find( VLC_OBJECT(p_intf), "dshow" );
544     if( p_module )
545     {
546         AutoBuiltPanel *autopanel =
547             new AutoBuiltPanel( notebook, this, p_intf, p_module );
548         input_tab_array.Add( autopanel );
549         notebook->AddPage( autopanel, wxU( module_GetName(p_module, 0) ),
550                            i_access_method == CAPTURE_ACCESS );
551         module_Put( p_module );
552     }
553
554     /* Update Disc panel */
555     wxCommandEvent dummy_event;
556     OnDiscTypeChange( dummy_event );
557
558     /* Update Net panel */
559     dummy_event.SetId( NetRadio1_Event );
560     OnNetTypeChange( dummy_event );
561
562     /* Update MRL */
563     wxNotebookEvent event( wxEVT_NULL, 0, i_access_method );
564     OnPageChange( event );
565
566     /* Place everything in sizers */
567     wxStdDialogButtonSizer *button_sizer = new wxStdDialogButtonSizer;
568     button_sizer->AddButton( cancel_button );
569     button_sizer->AddButton( ok_button );
570     button_sizer->Realize();
571     wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
572     wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
573 #if (!wxCHECK_VERSION(2,5,2))
574     panel_sizer->Add( notebook_sizer, 1, wxEXPAND | wxALL, 5 );
575 #else
576     panel_sizer->Add( notebook, 1, wxEXPAND | wxALL, 5 );
577 #endif
578     panel_sizer->Add( adv_sizer, 0, wxEXPAND | wxALL, 5 );
579     panel_sizer->Add( static_line, 0, wxEXPAND | wxALL, 5 );
580     panel_sizer->Add( button_sizer, 0, wxEXPAND | wxALL, 5 );
581     panel_sizer->Layout();
582     panel->SetSizerAndFit( panel_sizer );
583     main_sizer->Add( panel, 1, wxGROW, 0 );
584     main_sizer->Layout();
585     SetSizerAndFit( main_sizer );
586 }
587
588 OpenDialog::~OpenDialog()
589 {
590     /* Clean up */
591     delete file_dialog;
592     delete sout_dialog;
593     delete subsfile_dialog;
594 }
595
596 int OpenDialog::Show( int i_access_method, int i_arg )
597 {
598     notebook->SetSelection( i_access_method );
599     int i_ret = wxDialog::Show();
600     Raise();
601     SetFocus();
602     i_open_arg = i_arg;
603     return i_ret;
604 }
605
606 int OpenDialog::Show()
607 {
608     int i_ret = wxDialog::Show();
609     Raise();
610     SetFocus();
611     return i_ret;
612 }
613
614 /*****************************************************************************
615  * Private methods.
616  *****************************************************************************/
617 wxPanel *OpenDialog::FilePanel( wxWindow* parent )
618 {
619     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
620                                   wxSize(200, 200) );
621
622     wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
623
624     /* Create browse file line */
625     wxBoxSizer *file_sizer = new wxBoxSizer( wxHORIZONTAL );
626
627     file_sizer->Add( new wxStaticText( panel, -1, wxU(_("Open:") ) ), 0,
628                      wxALL | wxALIGN_CENTER_VERTICAL, 5 );
629
630     file_combo = new wxComboBox( panel, FileName_Event, wxT("") );
631     wxButton *browse_button = new wxButton( panel, FileBrowse_Event,
632                                             wxU(_("Browse...")) );
633     file_sizer->Add( file_combo, 1, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
634     file_sizer->Add( browse_button, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
635
636     /* Create Subtitles File checkox - button  */
637     wxFlexGridSizer *subtitles_sizer = new wxFlexGridSizer( 2, 1, 20 );
638     subsfile_checkbox = new wxCheckBox( panel, SubsFileEnable_Event,
639                                         wxU(_("Use a subtitles file")) );
640     subsfile_checkbox->SetToolTip( wxU(_("Use an external subtitles file.")) );
641     subtitles_sizer->Add( subsfile_checkbox, 0,  wxALIGN_CENTER_VERTICAL |
642                           wxALL, 5 );
643     subsfile_button = new wxButton( panel, SubsFileSettings_Event,
644                                     wxU(_("Advanced Settings...")) );
645     subsfile_button->Disable();
646     subtitles_sizer->Add( subsfile_button, 1, wxALIGN_CENTER_VERTICAL |
647                            wxALL, 5 );
648
649     /* Create subtitles file line */
650     wxBoxSizer *subfile_sizer = new wxBoxSizer( wxHORIZONTAL );
651
652     char *psz_subsfile = config_GetPsz( p_intf, "sub-file" );
653     if( psz_subsfile && *psz_subsfile )
654     {
655         subsfile_checkbox->SetValue(TRUE);
656         subsfile_button->Enable();
657         subsfile_mrl.Add( wxString(wxT("sub-file=")) + wxL2U(psz_subsfile) );
658     }
659     if( !psz_subsfile )  psz_subsfile = strdup("");
660     subfile_sizer->Add( new wxStaticText( panel, -1, wxU(_("File:") ) ),
661                         0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
662     subfile_combo = new wxComboBox( panel, SubFileName_Event,
663                                     wxL2U( psz_subsfile ) );
664     free( psz_subsfile );
665     subbrowse_button = new wxButton( panel, SubFileBrowse_Event,
666                                      wxU(_("Browse...")) );
667     subfile_sizer->Add( subfile_combo, 1, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
668     subfile_sizer->Add( subbrowse_button, 0, wxALL |wxALIGN_CENTER_VERTICAL, 5 );
669
670     subfile_combo->Disable();
671     subbrowse_button->Disable();
672
673     psz_subsfile = config_GetPsz( p_intf, "sub-file" );
674     if( psz_subsfile && *psz_subsfile )
675     {
676         subfile_combo->Enable();
677         subbrowse_button->Enable();
678     }
679
680     sizer->Add( file_sizer, 0, wxEXPAND | wxALL, 5 );
681     sizer->Add( subtitles_sizer, 0, wxLEFT | wxRIGHT | wxTOP, 5 );
682     sizer->Add( subfile_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT| wxBOTTOM, 5 );
683     panel->SetSizerAndFit( sizer );
684     return panel;
685 }
686
687 wxPanel *OpenDialog::DiscPanel( wxWindow* parent )
688 {
689     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
690                                   wxSize(200, 200) );
691
692     wxBoxSizer *sizer_row = new wxBoxSizer( wxVERTICAL );
693     wxFlexGridSizer *sizer = new wxFlexGridSizer( 2, 3, 20 );
694
695     static const wxString disc_type_array[] =
696     {
697         wxU(_("DVD (menus)")),
698         wxU(_("DVD")),
699         wxU(_("VCD")),
700         wxU(_("Audio CD")),
701     };
702
703     disc_type = new wxRadioBox( panel, DiscType_Event, wxU(_("Disc type")),
704                                 wxDefaultPosition, wxDefaultSize,
705                                 WXSIZEOF(disc_type_array), disc_type_array,
706                                 WXSIZEOF(disc_type_array), wxRA_SPECIFY_COLS );
707
708 #ifdef HAVE_LIBCDIO
709     disc_probe = new wxCheckBox( panel, DiscProbe_Event,
710                                  wxU(_("Probe Disc(s)")) );
711     disc_probe->SetToolTip( wxU(_("Probe for a DVD, VCD or audio CD. "
712 "First try the Device name entered for the selected Disc type "
713 "(DVD, DVD Menu, VCD, audio CD). If that doesn't find media, try any device "
714 "for the Disc type.  If that doesn't work, then try looking for CD-ROMs or "
715 "DVD drives. The Disc type, Device name, and some parameter ranges are set "
716 "based on media we find.")) );
717 #endif
718
719     sizer_row->Add( disc_type, i_disc_type_selection, wxEXPAND | wxALL, 5 );
720 #ifdef HAVE_LIBCDIO
721     sizer_row->Add( disc_probe, 0, wxEXPAND | wxALL );
722 #endif
723
724     wxStaticText *label = new wxStaticText( panel, -1, wxU(_("Device name")) );
725     disc_device = new wxTextCtrl( panel, DiscDevice_Event, wxT(""),
726                                   wxDefaultPosition, wxDefaultSize,
727                                   wxTE_PROCESS_ENTER);
728
729 #ifdef WIN32
730     char psz_default_device[3] = {0};
731     char *psz_forced;
732
733     /* find the drive_name for the first cdrom drive,
734      * which is probably "D:" and put the drive_name into
735      * psz_default_device... */
736     for( char drive_letter = 'A'; drive_letter <= 'Z'; ++drive_letter )
737     {
738         char drive_name[3] = {drive_letter, ':', 0};
739         UINT type = GetDriveTypeA( drive_name );
740         if( type == DRIVE_CDROM )
741         {
742             psz_default_device[0] = drive_letter;
743             psz_default_device[1] = ':';
744             break;
745         }
746     }
747
748     psz_forced = config_GetPsz( p_intf, "dvd" );
749
750     if( strlen(psz_default_device) > 0 &&
751         ( !psz_forced || psz_forced && !*psz_forced ) )
752     {
753         if(disc_device)
754             disc_device->SetValue( wxL2U(psz_default_device) );
755     }
756 #endif
757
758     sizer->Add( label, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
759     sizer->Add( disc_device, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
760
761     disc_title_label = new wxStaticText( panel, -1, wxU(_("Title")) );
762     disc_title = new wxSpinCtrl( panel, DiscTitle_Event );
763     sizer->Add( disc_title_label, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
764     sizer->Add( disc_title, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
765
766     disc_chapter_label = new wxStaticText( panel, -1, wxU(_("Chapter")) );
767     disc_chapter = new wxSpinCtrl( panel, DiscChapter_Event );
768     sizer->Add( disc_chapter_label, 0,
769                 wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
770     sizer->Add( disc_chapter, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
771
772     disc_sub_label = new wxStaticText( panel, -1, wxU(_("Subtitles track")) );
773     disc_sub = new wxSpinCtrl( panel, DiscSub_Event );
774     sizer->Add( disc_sub_label, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
775     sizer->Add( disc_sub, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
776     disc_sub->SetRange( -1, 255 );
777     i_disc_sub = config_GetInt( p_intf, "sub-track" );
778     disc_sub->SetValue( i_disc_sub );
779
780     disc_audio_label = new wxStaticText( panel, -1, wxU(_("Audio track")) );
781     disc_audio = new wxSpinCtrl( panel, DiscAudio_Event );
782     sizer->Add( disc_audio_label, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
783     sizer->Add( disc_audio, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
784     disc_audio->SetRange( -1, 255 );
785     i_disc_audio = config_GetInt( p_intf, "audio-track" );
786     disc_audio->SetValue( i_disc_audio );
787
788     sizer_row->Add( sizer, 0, wxEXPAND | wxALL, 5 );
789
790     panel->SetSizerAndFit( sizer_row );
791     return panel;
792 }
793
794 wxPanel *OpenDialog::NetPanel( wxWindow* parent )
795 {
796     int i;
797     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
798                                   wxSize(200, 200) );
799
800     wxBoxSizer *sizer_row = new wxBoxSizer( wxVERTICAL );
801     wxFlexGridSizer *sizer = new wxFlexGridSizer( 2, 4, 20 );
802
803     static const wxString net_type_array[] =
804     {
805         wxU(_("UDP/RTP")),
806         wxU(_("UDP/RTP Multicast")),
807         wxU(_("HTTP/HTTPS/FTP/MMS")),
808         wxU(_("RTSP"))
809     };
810
811     for( i=0; i<4; i++ )
812     {
813         net_radios[i] = new wxRadioButton( panel, NetRadio1_Event + i,
814                                            net_type_array[i],
815                                            wxDefaultPosition, wxDefaultSize,
816                                            wxRB_SINGLE );
817
818         net_subpanels[i] = new wxPanel( panel, -1,
819                                         wxDefaultPosition, wxDefaultSize );
820     }
821
822     /* Timeshift */
823     net_timeshift  = new wxCheckBox( panel, NetTimeshift_Event,
824                                      wxU(_("Allow timeshifting")) );
825
826     /* UDP/RTP row */
827     wxFlexGridSizer *subpanel_sizer;
828     wxStaticText *label;
829     i_net_ports[0] = config_GetInt( p_intf, "server-port" );
830     subpanel_sizer = new wxFlexGridSizer( 3, 1, 20 );
831     label = new wxStaticText( net_subpanels[0], -1, wxU(_("Port")) );
832     net_ports[0] = new wxSpinCtrl( net_subpanels[0], NetPort1_Event,
833                                    wxString::Format(wxT("%d"), i_net_ports[0]),
834                                    wxDefaultPosition, wxDefaultSize,
835                                    wxSP_ARROW_KEYS,
836                                    0, 65535, i_net_ports[0] );
837
838     subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
839     subpanel_sizer->Add( net_ports[0], 1,
840                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
841     net_ipv6 = new wxCheckBox( net_subpanels[0], NetForceIPv6_Event,
842                                wxU(_("Force IPv6")));
843     subpanel_sizer->Add( net_ipv6, 0,
844                          wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
845     net_subpanels[0]->SetSizerAndFit( subpanel_sizer );
846     net_radios[0]->SetValue( TRUE );
847
848     /* UDP/RTP Multicast row */
849     subpanel_sizer = new wxFlexGridSizer( 4, 1, 20 );
850     label = new wxStaticText( net_subpanels[1], -1, wxU(_("Address")) );
851     net_addrs[1] = new wxTextCtrl( net_subpanels[1], NetAddr2_Event, wxT(""),
852                                    wxDefaultPosition, wxDefaultSize,
853                                    wxTE_PROCESS_ENTER);
854     subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
855     subpanel_sizer->Add( net_addrs[1], 1,
856                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
857
858     label = new wxStaticText( net_subpanels[1], -1, wxU(_("Port")) );
859     i_net_ports[1] = i_net_ports[0];
860     net_ports[1] = new wxSpinCtrl( net_subpanels[1], NetPort2_Event,
861                                    wxString::Format(wxT("%d"), i_net_ports[1]),
862                                    wxDefaultPosition, wxDefaultSize,
863                                    wxSP_ARROW_KEYS,
864                                    0, 65535, i_net_ports[1] );
865
866     subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
867     subpanel_sizer->Add( net_ports[1], 1,
868                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
869     net_subpanels[1]->SetSizerAndFit( subpanel_sizer );
870
871     /* HTTP and RTSP rows */
872     for( i=2; i<4; i++ )
873     {
874         subpanel_sizer = new wxFlexGridSizer( 2, 1, 20 );
875         label = new wxStaticText( net_subpanels[i], -1, wxU(_("URL")) );
876         net_addrs[i] = new wxTextCtrl( net_subpanels[i], NetAddr1_Event + i,
877                                        (i == 2) ? wxT("") : wxT("rtsp://"),
878                                        wxDefaultPosition, wxSize( 200, -1 ),
879                                        wxTE_PROCESS_ENTER);
880         subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
881         subpanel_sizer->Add( net_addrs[i], 1,
882                              wxEXPAND | wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
883         net_subpanels[i]->SetSizerAndFit( subpanel_sizer );
884     }
885
886     /* Stuff everything into the main panel */
887     for( i=0; i<4; i++ )
888     {
889         sizer->Add( net_radios[i], 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL |
890                     wxALL, 5 );
891         sizer->Add( net_subpanels[i], 1, wxEXPAND | wxALIGN_LEFT |
892                     wxALIGN_CENTER_VERTICAL | wxALL, 5  );
893     }
894     sizer->Add( net_timeshift, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL |
895                 wxALL, 5 );
896
897     sizer_row->Add( sizer, 0, wxEXPAND | wxALL, 5 );
898
899     panel->SetSizerAndFit( sizer_row );
900     return panel;
901 }
902
903 void OpenDialog::UpdateMRL()
904 {
905     UpdateMRL( i_current_access_method );
906 }
907
908 void OpenDialog::UpdateMRL( int i_access_method )
909 {
910     wxString mrltemp, caching_name;
911
912     i_current_access_method = i_access_method;
913
914     switch( i_access_method )
915     {
916     case FILE_ACCESS:
917         mrltemp = file_combo->GetValue();
918         caching_name = wxT("file-caching");
919         break;
920
921     case DISC_ACCESS:
922         i_disc_type_selection = disc_type->GetSelection();
923
924         switch ( i_disc_type_selection )
925         {
926         case 0: /* DVD with menus */
927         case 1: /* DVD without menus */
928             disc_device->SetToolTip( wxU(_("DVD device to use" ) )  );
929             if( i_disc_type_selection == 0 )
930             {
931                 mrltemp = wxT("dvd://") + disc_device->GetValue();
932                 caching_name = wxT("dvdnav-caching");
933             }
934             else
935             {
936                 mrltemp = wxT("dvdsimple://") + disc_device->GetValue();
937                 caching_name = wxT("dvdread-caching");
938             }
939
940             if( i_disc_title > 0 )
941             {
942                 mrltemp += wxString::Format( wxT("@%d"), i_disc_title );
943
944                 if( i_disc_chapter > 0 )
945                     mrltemp += wxString::Format( wxT(":%d"), i_disc_chapter );
946             }
947
948             if( i_disc_sub >= 0 )
949                 mrltemp += wxString::Format( wxT("  :sub-track=%d"),
950                                              i_disc_sub );
951             if( i_disc_audio >= 0 )
952                 mrltemp += wxString::Format( wxT("  :audio-track=%d"),
953                                              i_disc_audio );
954             break;
955
956         case 2:  /* VCD of some sort */
957 #ifdef HAVE_VCDX
958             disc_device->SetToolTip( wxU(_("Name of CD-ROM device "
959             "to read Video CD from. If this field is left empty, we will scan "
960             "for a CD-ROM with a VCD in it.")) );
961             mrltemp = wxT("vcdx://") + disc_device->GetValue();
962             if( i_disc_title > 0 )
963                 mrltemp += wxString::Format( wxT("@%c%d"),
964                                   config_GetInt( p_intf, "vcdx-PBC"  )
965                                   ? 'P' : 'E', i_disc_title );
966 #else
967             disc_device->SetToolTip( wxU(_("CD-ROM device to use" ) ) );
968             mrltemp = wxT("vcd://") + disc_device->GetValue();
969             if( i_disc_title > 0 )
970                 mrltemp += wxString::Format( wxT("@%d"), i_disc_title );
971 #endif
972
973             if( i_disc_sub >= 0 )
974                 mrltemp += wxString::Format( wxT("  :sub-track=%d"),
975                                              i_disc_sub );
976
977             if( i_disc_audio >= 0 )
978                 mrltemp += wxString::Format( wxT("  :audio-track=%d"),
979                                              i_disc_audio );
980             caching_name = wxT("vcd-caching");
981             break;
982
983         case 3: /* CD-DA */
984 #ifdef HAVE_CDDAX
985             disc_device->SetToolTip( wxU(_("Name of CD-ROM device "
986             "to read audio CD from. If this field is left empty, we will scan "
987             "for a CD-ROM with an audio CD in it." )) );
988             mrltemp = wxT("cddax://")
989 #else
990             disc_device->SetToolTip( wxU(_("CD-ROM device to use" ) ) ) ;
991             mrltemp = wxT("cdda://")
992 #endif
993               + disc_device->GetValue();
994             if( i_disc_title > 0 )
995                 mrltemp += wxString::Format( wxT("@%d"), i_disc_title );
996
997             caching_name = wxT("cdda-caching");
998             break;
999
1000         default:
1001             msg_Err( p_intf, "invalid selection (%d)",
1002                      disc_type->GetSelection() );
1003         }
1004
1005         break;
1006
1007     case NET_ACCESS:
1008         switch( i_net_type )
1009         {
1010         case 0:
1011             mrltemp = wxT("udp://@");
1012             if ( net_ipv6->GetValue() )
1013             {
1014                 mrltemp += wxT("[::]");
1015             }
1016             if( i_net_ports[0] !=
1017                 config_GetInt( p_intf, "server-port" ) )
1018             {
1019                 mrltemp += wxString::Format( wxT(":%d"), i_net_ports[0] );
1020             }
1021
1022             caching_name = wxT("udp-caching");
1023             break;
1024
1025         case 1:
1026             mrltemp = wxT("udp://@");
1027             if ((net_addrs[1]->GetLineText(0).Find (':') != -1)
1028                 && (net_addrs[1]->GetLineText(0)[0u] != '['))
1029             {
1030                 /* automatically adds '[' and ']' to IPv6 addresses */
1031                 mrltemp += wxT("[") + net_addrs[1]->GetLineText(0)
1032                          + wxT("]");
1033             }
1034             else
1035             {
1036                 mrltemp += net_addrs[1]->GetLineText(0);
1037             }
1038             if( i_net_ports[1] != config_GetInt( p_intf, "server-port" ) )
1039             {
1040                 mrltemp += wxString::Format( wxT(":%d"), i_net_ports[1] );
1041             }
1042
1043             caching_name = wxT("udp-caching");
1044             break;
1045
1046         case 2:
1047             /* http access */
1048             if( net_addrs[2]->GetLineText(0).Find(wxT("://")) == -1 )
1049                 mrltemp = wxT("http://");
1050
1051             mrltemp += net_addrs[2]->GetLineText(0);
1052             if( ! mrltemp.Left(4).CmpNoCase(wxT("http")) )
1053                 caching_name = wxT("http-caching");
1054             else if( ! mrltemp.Left(3).CmpNoCase(wxT("mms")) )
1055                 caching_name = wxT("mms-caching");
1056             else
1057                 caching_name= wxT("ftp-caching");
1058             break;
1059
1060         case 3:
1061             /* RTSP access */
1062             if( net_addrs[3]->GetLineText(0).Find(wxT("rtsp://")) != 0 )
1063             {
1064                 mrltemp = wxT("rtsp://");
1065             }
1066             mrltemp += net_addrs[3]->GetLineText(0);
1067
1068             caching_name = wxT("rtsp-caching");
1069             break;
1070         }
1071         if( net_timeshift->IsEnabled() && net_timeshift->IsChecked() )
1072             mrltemp += wxT(" :access-filter=timeshift");
1073         break;
1074
1075     default:
1076         {
1077             int i_item = i_access_method - MAX_ACCESS;
1078
1079             if( i_item < 0 || i_item >= (int)input_tab_array.GetCount() )
1080                 break;
1081
1082             AutoBuiltPanel *input_panel = input_tab_array.Item( i_item );
1083
1084             mrltemp = input_panel->name + wxT("://");
1085
1086             for( int i=0; i < (int)input_panel->config_array.GetCount(); i++ )
1087             {
1088                 ConfigControl *control = input_panel->config_array.Item(i);
1089
1090                 mrltemp += wxT(" :");
1091
1092                 if( control->GetType() == CONFIG_ITEM_BOOL &&
1093                     !control->GetIntValue() ) mrltemp += wxT("no-");
1094
1095                 mrltemp += control->GetName();
1096
1097                 switch( control->GetType() )
1098                 {
1099                 case CONFIG_ITEM_STRING:
1100                 case CONFIG_ITEM_FILE:
1101                 case CONFIG_ITEM_DIRECTORY:
1102                 case CONFIG_ITEM_MODULE:
1103                     mrltemp += wxT("=\"") + control->GetPszValue() + wxT("\"");
1104                     break;
1105                 case CONFIG_ITEM_INTEGER:
1106                     mrltemp +=
1107                         wxString::Format( wxT("=%i"), control->GetIntValue() );
1108                     break;
1109                 case CONFIG_ITEM_FLOAT:
1110                     mrltemp +=
1111                         wxString::Format(wxT("=%f"), control->GetFloatValue());
1112                     break;
1113                 }
1114             }
1115
1116             if( input_panel->p_advanced_mrl_combo &&
1117                 input_panel->p_advanced_mrl_combo->GetValue() )
1118             {
1119                 mrltemp += wxT(" ") +
1120                     input_panel->p_advanced_mrl_combo->GetValue();
1121             }
1122         }
1123         break;
1124     }
1125
1126     if( caching_name.size() )
1127     {
1128         if( caching_value->IsEnabled() )
1129         {
1130             mrltemp += wxT("  :") + caching_name +
1131                 wxString::Format( wxT("=%d"), i_caching );
1132         }
1133         else
1134         {
1135             int i_value = config_GetInt( p_intf, caching_name.mb_str(wxConvUTF8) );
1136             caching_value->SetValue( i_value );
1137         }
1138     }
1139
1140     mrl_combo->SetValue( mrltemp );
1141 }
1142
1143 /*****************************************************************************
1144  * Events methods.
1145  *****************************************************************************/
1146 void OpenDialog::OnOk( wxCommandEvent& WXUNUSED(event) )
1147 {
1148     mrl = SeparateEntries( mrl_combo->GetValue() );
1149     mrl_combo->Append( mrl_combo->GetValue() );
1150     if( mrl_combo->GetCount() > 10 ) mrl_combo->Delete( 0 );
1151     mrl_combo->SetSelection( mrl_combo->GetCount() - 1 );
1152
1153     if( i_method == OPEN_STREAM )
1154     {
1155         if( IsModal() ) EndModal( wxID_OK );
1156         Hide();
1157         return;
1158     }
1159
1160     /* Update the playlist */
1161     playlist_t *p_playlist =
1162         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
1163                                        FIND_ANYWHERE );
1164     if( p_playlist == NULL ) return;
1165
1166     for( int i = 0; i < (int)mrl.GetCount(); i++ )
1167     {
1168         vlc_bool_t b_start = !i && i_open_arg;
1169         input_item_t *p_input;
1170         char *psz_utf8;
1171
1172         psz_utf8 = wxFromLocale( mrl[i] );
1173         p_input = input_ItemNew( p_intf, psz_utf8, NULL );
1174         wxLocaleFree( psz_utf8 );
1175
1176         /* Insert options */
1177         while( i + 1 < (int)mrl.GetCount() &&
1178                ((const char *)mrl[i + 1].mb_str(wxConvUTF8))[0] == ':' )
1179         {
1180             psz_utf8 = wxFromLocale( mrl[i + 1] );
1181             input_ItemAddOption( p_input, psz_utf8 );
1182             wxLocaleFree( psz_utf8 );
1183             i++;
1184         }
1185
1186         /* Get the options from the subtitles dialog */
1187         if( subsfile_checkbox->IsChecked() && subsfile_mrl.GetCount() )
1188         {
1189             for( int j = 0; j < (int)subsfile_mrl.GetCount(); j++ )
1190             {
1191                 psz_utf8 = wxFromLocale( subsfile_mrl[j] );
1192                 input_ItemAddOption( p_input, psz_utf8 );
1193                 wxLocaleFree( psz_utf8 );
1194             }
1195         }
1196
1197         /* Get the options from the stream output dialog */
1198         if( sout_checkbox->IsChecked() && sout_mrl.GetCount() )
1199         {
1200             for( int j = 0; j < (int)sout_mrl.GetCount(); j++ )
1201             {
1202                 psz_utf8 = wxFromLocale( sout_mrl[j] );
1203                 input_ItemAddOption( p_input, psz_utf8 );
1204                 wxLocaleFree( psz_utf8 );
1205             }
1206         }
1207
1208         /* FIXME: playlist_AddInput() can fail */
1209         playlist_AddInput( p_playlist, p_input,
1210                PLAYLIST_APPEND | ( b_start ? PLAYLIST_GO : PLAYLIST_PREPARSE ),
1211                PLAYLIST_END, VLC_TRUE, VLC_FALSE );
1212     }
1213
1214     vlc_object_release( p_playlist );
1215
1216     Hide();
1217
1218     if( IsModal() ) EndModal( wxID_OK );
1219 }
1220
1221 void OpenDialog::OnCancel( wxCommandEvent& WXUNUSED(event) )
1222 {
1223     wxCloseEvent cevent;
1224     OnClose(cevent);
1225 }
1226
1227 void OpenDialog::OnClose( wxCloseEvent& WXUNUSED(event) )
1228 {
1229     Hide();
1230
1231     if( IsModal() ) EndModal( wxID_CANCEL );
1232 }
1233
1234 void OpenDialog::OnPageChange( wxNotebookEvent& event )
1235 {
1236     UpdateMRL( event.GetSelection() );
1237 }
1238
1239 void OpenDialog::OnMRLChange( wxCommandEvent& event )
1240 {
1241     //mrl = SeparateEntries( event.GetString() );
1242 }
1243
1244 /*****************************************************************************
1245  * File panel event methods.
1246  *****************************************************************************/
1247 void OpenDialog::OnFilePanelChange( wxCommandEvent& WXUNUSED(event) )
1248 {
1249     UpdateMRL( FILE_ACCESS );
1250 }
1251
1252 void OpenDialog::OnFileBrowse( wxCommandEvent& WXUNUSED(event) )
1253 {
1254     if( file_dialog == NULL )
1255         file_dialog = new wxFileDialog( this, wxU(_("Open File")),
1256             wxT(""), wxT(""), wxT("*"), wxOPEN | wxMULTIPLE );
1257
1258     file_dialog->SetWildcard(wxU(_("All Files (*.*)|*"
1259         "|Sound Files (*.mp3, *.ogg, etc.)|" EXTENSIONS_AUDIO
1260         "|Video Files (*.avi, *.mpg, etc.)|" EXTENSIONS_VIDEO
1261         "|Playlist Files (*.m3u, *.pls, etc.)|" EXTENSIONS_PLAYLIST
1262         "|Subtitle Files (*.srt, *.sub, etc.)|" EXTENSIONS_SUBTITLE)));
1263
1264     if( file_dialog && file_dialog->ShowModal() == wxID_OK )
1265     {
1266         wxArrayString paths;
1267         wxString path;
1268
1269         file_dialog->GetPaths( paths );
1270
1271         for( size_t i = 0; i < paths.GetCount(); i++ )
1272         {
1273             if( paths[i].Find( wxT(' ') ) >= 0 )
1274                 path += wxT("\"") + paths[i] + wxT("\" ");
1275             else
1276                 path += paths[i] + wxT(" ");
1277         }
1278
1279         file_combo->SetValue( path );
1280         file_combo->Append( path );
1281         if( file_combo->GetCount() > 10 ) file_combo->Delete( 0 );
1282         UpdateMRL( FILE_ACCESS );
1283     }
1284 }
1285
1286 void OpenDialog::OnSubFileBrowse( wxCommandEvent& WXUNUSED(event) )
1287 {
1288     wxFileDialog dialog( this, wxU(_("Open subtitles file")),
1289                          wxT(""), wxT(""), wxT("*"), wxOPEN );
1290
1291     if( dialog.ShowModal() == wxID_OK )
1292     {
1293         subfile_combo->SetValue( dialog.GetPath() );
1294     }
1295     wxCommandEvent event; OnSubFileChange( event );
1296 }
1297
1298 void OpenDialog::OnSubFileChange( wxCommandEvent& WXUNUSED(event) )
1299 {
1300     if( subsfile_mrl.GetCount() != 0 )
1301     {
1302         subsfile_mrl.RemoveAt( 0 );
1303         subsfile_mrl.Insert( wxString(wxT("sub-file=")) + subfile_combo->GetValue() , 0 );
1304     }
1305     else
1306     {
1307         subsfile_mrl.Add( wxString(wxT("sub-file=")) + subfile_combo->GetValue() );
1308     }
1309 }
1310
1311 /*****************************************************************************
1312  * Disc panel event methods.
1313  *****************************************************************************/
1314 void OpenDialog::OnDiscPanelChangeSpin( wxSpinEvent& event )
1315 {
1316     wxCommandEvent cevent;
1317     cevent.SetId(event.GetId());
1318     cevent.SetInt(event.GetPosition());
1319     OnDiscPanelChange(cevent);
1320 }
1321
1322 void OpenDialog::OnDiscPanelChange( wxCommandEvent& event )
1323 {
1324     if( event.GetId() == DiscTitle_Event ) i_disc_title = event.GetInt();
1325     if( event.GetId() == DiscChapter_Event ) i_disc_chapter = event.GetInt();
1326     if( event.GetId() == DiscSub_Event ) i_disc_sub = event.GetInt();
1327     if( event.GetId() == DiscAudio_Event ) i_disc_audio = event.GetInt();
1328
1329     UpdateMRL( DISC_ACCESS );
1330 }
1331
1332 void OpenDialog::OnDiscDeviceChange( wxCommandEvent& event )
1333 {
1334     char *psz_device;
1335
1336     switch( disc_type->GetSelection() )
1337     {
1338         case 3:
1339             psz_device = config_GetPsz( p_intf, "cd-audio" );
1340             break;
1341
1342         case 2:
1343             psz_device = config_GetPsz( p_intf, "vcd" );
1344             break;
1345
1346         default:
1347             psz_device = config_GetPsz( p_intf, "dvd" );
1348             break;
1349     }
1350
1351     if ( !psz_device ) psz_device = "";
1352
1353     if( disc_device->GetValue().Cmp( wxL2U( psz_device ) ) )
1354     {
1355         b_disc_device_changed = true;
1356     }
1357
1358     UpdateMRL( DISC_ACCESS );
1359 }
1360
1361 #ifdef HAVE_LIBCDIO
1362
1363 /* Return true if *psz_drive is a drive with a DVD in it. A more complete
1364    check would see if the media looks like a *playable* DVD. This should
1365    go into libcdio.
1366  */
1367 static bool IsDVD(const char *psz_drive)
1368 {
1369   CdIo_t *p_cdio = cdio_open (psz_drive, DRIVER_UNKNOWN);
1370   if (p_cdio)
1371   {
1372       discmode_t discmode = cdio_get_discmode(p_cdio);
1373       cdio_destroy(p_cdio);
1374       return cdio_is_discmode_dvd(discmode);
1375   }
1376   return false;
1377 }
1378
1379
1380 /* Return a device that has a DVD in it. The caller needs to free
1381    the returned string.
1382 */
1383 static char * ProbeDVD(const wxChar *device)
1384 {
1385         /*
1386   char **ppsz_cd_drives;
1387   const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(device);
1388   char *psz_device = (char *) tmp_buf;
1389
1390   if( IsDVD(psz_device) )
1391   {
1392       return strdup(psz_device);
1393   }
1394
1395   ppsz_cd_drives = cdio_get_devices(DRIVER_DEVICE);
1396   if( ppsz_cd_drives )
1397   {
1398       char **c;
1399       for( c = ppsz_cd_drives; *c != NULL; c++ )
1400       {
1401       if( IsDVD(*c) )
1402       {
1403           char *psz_drive = strdup(*c);
1404           cdio_free_device_list(ppsz_cd_drives);
1405           return strdup(psz_drive);
1406           }
1407       }
1408       cdio_free_device_list(ppsz_cd_drives);
1409   }*/
1410   return NULL;
1411 }
1412
1413
1414 static char * ProbeDevice(char **ppsz_search_devices, cdio_fs_anal_t mask,
1415               bool b_any)
1416 {
1417     char **ppsz_devices;
1418
1419     if( ppsz_search_devices && !ppsz_search_devices[0] )
1420         ppsz_search_devices = NULL;
1421
1422     /* Start out trying the device that has been entered so far. */
1423     ppsz_devices = cdio_get_devices_with_cap(ppsz_search_devices, mask,
1424                          b_any);
1425
1426     if (ppsz_devices && *ppsz_devices)
1427     {
1428         char *psz_device = strdup(*ppsz_devices);
1429         cdio_free_device_list(ppsz_devices);
1430         return psz_device;
1431     }
1432
1433     /* If there was no device specified on the first try, then give up
1434        now. Otherwise accept any CD-ROM in the class (e.g. VCD or DVD).
1435     */
1436     if( !ppsz_search_devices ) return NULL;
1437
1438     ppsz_devices = cdio_get_devices_with_cap(NULL, mask, true);
1439
1440     if (ppsz_devices && *ppsz_devices)
1441     {
1442         char *psz_device = strdup(*ppsz_devices);
1443         cdio_free_device_list(ppsz_devices);
1444         return psz_device;
1445     }
1446
1447     return NULL;
1448 }
1449
1450
1451 /* Return a device that has a CD-DA in it. The caller needs to free
1452    the returned string.
1453 */
1454 static char * ProbeCDDA(const wxChar *device)
1455 {
1456         /*
1457    char *ppsz_device[2];
1458    const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(device);
1459    char *psz_device = (char *) tmp_buf;
1460    ppsz_device[0] = (device && *device) ? psz_device : NULL;
1461    ppsz_device[1] = NULL;
1462    return ProbeDevice(ppsz_device, CDIO_FS_AUDIO, false);
1463    */ return NULL;
1464 }
1465
1466 /* Return a device that has a VCD in it. The caller needs to free
1467    the returned string.
1468 */
1469 static char * ProbeVCD(const wxChar *device)
1470 {/*
1471    char *ppsz_device[2];
1472    const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(device);
1473    char *psz_device = (char *) tmp_buf;
1474    ppsz_device[0] = (device && *device) ? psz_device : NULL;
1475    ppsz_device[1] = NULL;
1476    return ProbeDevice(ppsz_device,
1477                       (CDIO_FS_ANAL_SVCD|CDIO_FS_ANAL_CVD|CDIO_FS_ANAL_VIDEOCD
1478                        |CDIO_FS_UNKNOWN), true);
1479                        */ return NULL;
1480 }
1481
1482
1483 /*
1484    Probe (find anywhere) a CD-DA, VCD, or a DVD.
1485    First try the device name that may have been entered for the "disc type"
1486    selected. If that doesn't work we try any device for the disc type.
1487    If that doesn't work, try looking for CD-ROMs or DVD drives. the
1488    disc type, device name and paramter ranges are set to whatever we find.
1489 */
1490 void OpenDialog::OnDiscProbe( wxCommandEvent& WXUNUSED(event) )
1491 {
1492     wxCommandEvent dummy_event;
1493     char *psz_device = NULL;
1494     bool b_probed_DVD = false;
1495     bool b_probed_VCD = false;
1496     const int i_selection = disc_type->GetSelection();
1497
1498     /* Reduce verbosity of cdio errors. */
1499     cdio_loglevel_default = CDIO_LOG_ERROR;
1500
1501  retry:
1502     switch( disc_type->GetSelection() )
1503     {
1504
1505     case SELECTION_DISC_TYPE_DVD_MENUS:
1506     case SELECTION_DISC_TYPE_DVD:
1507       /* If not a DVD then try for a VCD. If VCD fails it will
1508          try for a CD-DA. */
1509       if (!psz_device) psz_device = ProbeDVD(disc_device->GetValue());
1510       if (!psz_device)
1511       {
1512           b_probed_DVD = true;
1513           disc_type->SetSelection(SELECTION_DISC_TYPE_VCD);
1514           OnDiscTypeChange( dummy_event );
1515           goto retry;
1516       }
1517       disc_device->SetValue( wxL2U(psz_device) );
1518       break;
1519
1520     case SELECTION_DISC_TYPE_VCD:  /* VCD probe of some sort */
1521       if(!psz_device) psz_device = ProbeVCD(disc_device->GetValue());
1522       if( psz_device  )
1523       {
1524 #ifdef HAVE_VCDX
1525 #if LIBVCD_VERSION_NUM > 23
1526       vcdinfo_obj_t *p_vcdinfo;
1527
1528           /* Set LID or entry range accurately if possible. */
1529       if( vcdinfo_open(&p_vcdinfo, &psz_device, DRIVER_DEVICE,
1530                 NULL) == VCDINFO_OPEN_VCD)
1531       {
1532           if (config_GetInt( p_intf, "vcdx-PBC"  ))
1533           {
1534           /* Set largest LID. */;
1535           disc_title->SetRange( 0, vcdinfo_get_num_LIDs(p_vcdinfo) );
1536
1537           }
1538           else
1539           {
1540           /* Set largest Entry */
1541           disc_title->SetRange( 0,
1542                     vcdinfo_get_num_entries(p_vcdinfo)-1 );
1543           }
1544           vcdinfo_close(p_vcdinfo);
1545       }
1546 #endif /* LIBVCD_VERSION_NUM > 23 */
1547           disc_device->SetValue( wxL2U(psz_device) );
1548 #else
1549           CdIo_t *p_cdio = cdio_open (psz_device, DRIVER_UNKNOWN);
1550           disc_device->SetValue( wxL2U(psz_device) );
1551
1552           /* Set track range accurately if possible. */
1553           if (p_cdio)
1554           {
1555               track_t i_last_track = cdio_get_last_track_num(p_cdio);
1556               disc_title->SetRange( 0, i_last_track-1 );
1557           }
1558           cdio_destroy(p_cdio);
1559 #endif
1560           break;
1561       }
1562
1563       b_probed_VCD = true;
1564
1565       /* Not a VCD. Try for a DVD unless we've been there before. */
1566       if( !b_probed_DVD && (psz_device = ProbeDVD(disc_device->GetValue())) )
1567       {
1568           disc_type->SetSelection(SELECTION_DISC_TYPE_DVD_MENUS);
1569           OnDiscTypeChange( dummy_event );
1570           goto retry;
1571       }
1572       b_probed_DVD = true;
1573
1574       /* Couldn't find a VCD or DVD. See if we can find a CD-DA. */
1575       psz_device = ProbeCDDA(disc_device->GetValue());
1576       if( psz_device  )
1577       {
1578           disc_type->SetSelection(SELECTION_DISC_TYPE_CDDA);
1579           OnDiscTypeChange( dummy_event );
1580           goto retry;
1581       }
1582
1583       /* Couldn't find a VCD, DVD or CD-DA. Null out the Device name and
1584      set to original selection.
1585        */
1586       disc_device->SetValue( wxL2U("") );
1587       disc_type->SetSelection(i_selection);
1588       OnDiscTypeChange( dummy_event );
1589       break;
1590
1591     case SELECTION_DISC_TYPE_CDDA:
1592       if(!psz_device) psz_device = ProbeCDDA(disc_device->GetValue());
1593       if( psz_device  )
1594       {
1595           CdIo_t *p_cdio = cdio_open (psz_device, DRIVER_UNKNOWN);
1596           disc_device->SetValue( wxL2U(psz_device) );
1597           if (p_cdio)
1598           {
1599               track_t i_last_track = cdio_get_last_track_num(p_cdio);
1600               disc_title->SetRange( 0, i_last_track );
1601 #if 0
1602           MediaInsertCDDA( p_intf,  p_cdio, i_last_track );
1603 #endif
1604           }
1605           cdio_destroy(p_cdio);
1606           break;
1607       }
1608
1609       /* Not a CD-DA. Try for a DVD unless we've been there before. */
1610       if( !b_probed_DVD && (psz_device = ProbeDVD(disc_device->GetValue())) )
1611       {
1612           disc_type->SetSelection(SELECTION_DISC_TYPE_DVD_MENUS);
1613           OnDiscTypeChange( dummy_event );
1614           goto retry;
1615       }
1616
1617       /* Couldn't find a CD-DA or DVD. See if we can find a VCD, unless
1618          we've tried that before. */
1619       if (!b_probed_VCD) psz_device = ProbeVCD(disc_device->GetValue());
1620       if( psz_device  )
1621       {
1622           disc_type->SetSelection(SELECTION_DISC_TYPE_VCD);
1623           OnDiscTypeChange( dummy_event );
1624           goto retry;
1625       }
1626       disc_device->SetValue( wxL2U("") );
1627       break;
1628
1629     default:
1630         msg_Err( p_intf, "invalid Disc type selection (%d)",
1631                  disc_type->GetSelection() );
1632         break;
1633     }
1634
1635     free( psz_device );
1636     disc_probe->SetValue(FALSE);
1637
1638     UpdateMRL( DISC_ACCESS );
1639 }
1640 #endif /* HAVE_LIBCDIO */
1641
1642 void OpenDialog::OnDiscTypeChange( wxCommandEvent& WXUNUSED(event) )
1643 {
1644     char *psz_device = NULL;
1645
1646     switch( disc_type->GetSelection() )
1647     {
1648
1649     case SELECTION_DISC_TYPE_DVD_MENUS:
1650     case SELECTION_DISC_TYPE_DVD:
1651         disc_sub->Enable(); disc_sub_label->Enable();
1652         disc_audio->Enable(); disc_audio_label->Enable();
1653         disc_chapter->Enable(); disc_chapter_label->Enable();
1654         disc_title_label->SetLabel ( wxU(_("Title")) );
1655         psz_device = config_GetPsz( p_intf, "dvd" );
1656         if( !b_disc_device_changed )
1657         {
1658             if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
1659             else disc_device->SetValue( wxT("") );
1660         }
1661         disc_title->SetRange( 0, 255 );
1662         disc_sub->SetRange( -1, 31 );  // up to 32 subtitles -1: no subtitle
1663         disc_audio->SetRange( 0, 7 );  // up to 8 audio channels
1664         disc_chapter->SetRange( 0, 255 );
1665         disc_title->SetToolTip( wxU(_("Title number.")) );
1666         disc_sub->SetToolTip( wxU(_(
1667           "DVDs can have up to 32 subtitles numbered 0..31. "
1668           "Note this is not the same thing as a subtitle name (e.g. 'en'). "
1669           "If a value -1 is used, no subtitle will be shown." )) );
1670         disc_audio->SetToolTip( wxU(_("Audio track number. "
1671           "DVDs can have up to 8 audio tracks numbered 0..7."
1672         )) );
1673         break;
1674
1675     case SELECTION_DISC_TYPE_VCD:
1676         disc_sub->Enable(); disc_sub_label->Enable();
1677         disc_audio->Enable(); disc_audio_label->Enable();
1678         disc_chapter->Disable(); disc_chapter_label->Disable();
1679         psz_device = config_GetPsz( p_intf, "vcd" );
1680         if( !b_disc_device_changed )
1681         {
1682             if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
1683             else disc_device->SetValue( wxT("") );
1684         }
1685
1686 #ifdef HAVE_VCDX
1687         if (config_GetInt( p_intf, "vcdx-PBC"  ))
1688         {
1689           disc_title_label->SetLabel ( wxT("Playback LID") );
1690           disc_title->SetToolTip( wxU(_(
1691           "Playback control (PBC) usually starts with number 1." )) );
1692         }
1693         else
1694         {
1695           disc_title_label->SetLabel ( wxT("Entry") );
1696           disc_title->SetToolTip( wxU(_(
1697           "The first entry (the beginning of the first MPEG track) is 0." )) );
1698         }
1699
1700 #else
1701         disc_title_label->SetLabel ( wxU(_("Track")) );
1702         disc_title->SetToolTip( wxU(_("Track number.")) );
1703 #endif
1704         disc_title->SetRange( 0, 99 );  // only 100 tracks allowed on VCDs
1705         disc_sub->SetRange( -1, 3 );    // up to 4 subtitles -1 = no subtitle
1706         disc_audio->SetRange( 0, 1 );   // up to 2 audio tracks
1707         disc_sub->SetToolTip( wxU(_(
1708           "SVCDs can have up to 4 subtitles numbered 0..3. "
1709           "If a value -1 is used, no subtitle will be shown." )) );
1710         disc_audio->SetToolTip( wxU(_("Audio track number. "
1711           "VCDs can have up to 2 audio tracks numbered 0 or 1. "
1712         )) );
1713         break;
1714
1715     case SELECTION_DISC_TYPE_CDDA:
1716         disc_sub->Disable(); disc_sub_label->Disable();
1717         disc_chapter->Disable(); disc_chapter_label->Disable();
1718         disc_audio->Disable(); disc_audio_label->Disable();
1719         disc_title_label->SetLabel ( wxU(_("Track")) );
1720 #ifdef HAVE_CDDAX
1721         disc_title->SetToolTip( wxU(_(
1722         "Audio CDs can have up to 100 tracks, the first track is usually 1. "
1723         "If 0 is given, then all tracks are played.")) );
1724 #else
1725         disc_title->SetToolTip( wxU(_(
1726         "Audio CDs can have up to 100 tracks, the first track is usually 1."
1727         )) );
1728 #endif
1729         psz_device = config_GetPsz( p_intf, "cd-audio" );
1730         if( !b_disc_device_changed )
1731         {
1732             if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
1733             else disc_device->SetValue( wxT("") );
1734         }
1735
1736         /* There are at most 100 tracks in a CD-DA */
1737         disc_title->SetRange( 0, 100 );
1738         break;
1739
1740     default:
1741         msg_Err( p_intf, "invalid Disc type selection (%d)",
1742                  disc_type->GetSelection() );
1743         break;
1744     }
1745
1746     disc_title->SetValue( 0 ); i_disc_title = 0;
1747     disc_chapter->SetValue( 0 ); i_disc_chapter = 0;
1748
1749     free( psz_device );
1750
1751     UpdateMRL( DISC_ACCESS );
1752 }
1753
1754 /*****************************************************************************
1755  * Net panel event methods.
1756  *****************************************************************************/
1757 void OpenDialog::OnNetPanelChangeSpin( wxSpinEvent& event )
1758 {
1759     wxCommandEvent cevent;
1760     cevent.SetId(event.GetId());
1761     cevent.SetInt(event.GetPosition());
1762     OnNetPanelChange(cevent);
1763 }
1764
1765 void OpenDialog::OnNetPanelChange( wxCommandEvent& event )
1766 {
1767     if( event.GetId() >= NetPort1_Event && event.GetId() <= NetPort3_Event )
1768     {
1769         i_net_ports[event.GetId() - NetPort1_Event] = event.GetInt();
1770     }
1771
1772     UpdateMRL( NET_ACCESS );
1773 }
1774
1775 void OpenDialog::OnNetTypeChange( wxCommandEvent& event )
1776 {
1777     int i;
1778
1779     i_net_type = event.GetId() - NetRadio1_Event;
1780
1781     for(i=0; i<4; i++)
1782     {
1783         net_radios[i]->SetValue( event.GetId() == (NetRadio1_Event+i) );
1784         net_subpanels[i]->Enable( event.GetId() == (NetRadio1_Event+i) );
1785     }
1786     /* UDP Unicast or multicast -> timeshift */
1787     if( i_net_type == 0 || i_net_type == 1 )
1788         net_timeshift->Enable();
1789     else
1790         net_timeshift->Disable();
1791
1792     UpdateMRL( NET_ACCESS );
1793 }
1794
1795 /*****************************************************************************
1796  * Subtitles file event methods.
1797  *****************************************************************************/
1798 void OpenDialog::OnSubsFileEnable( wxCommandEvent& event )
1799 {
1800     subsfile_button->Enable( event.GetInt() != 0 );
1801     subbrowse_button->Enable( event.GetInt() != 0 );
1802     subfile_combo->Enable( event.GetInt() != 0 );
1803 }
1804
1805 void OpenDialog::OnSubsFileSettings( wxCommandEvent& WXUNUSED(event) )
1806 {
1807     /* Show/hide the open dialog */
1808     if( subsfile_dialog == NULL )
1809         subsfile_dialog = new SubsFileDialog( p_intf, this );
1810
1811     if( subsfile_dialog && subsfile_dialog->ShowModal() == wxID_OK )
1812     {
1813         subsfile_mrl.Empty();
1814         subsfile_mrl.Add( wxString(wxT("sub-file="))  + subfile_combo->GetValue() );
1815         if( subsfile_dialog->encoding_combo )
1816         {
1817             subsfile_mrl.Add( wxString(wxT("subsdec-encoding=")) +
1818                               subsfile_dialog->encoding_combo->GetValue() );
1819         }
1820         if( subsfile_dialog->align_combo )
1821         {
1822             subsfile_mrl.Add( wxString::Format(wxT("subsdec-align=%i"),
1823                         (int)subsfile_dialog->align_combo->GetClientData(
1824                         subsfile_dialog->align_combo->GetSelection()) ) );
1825         }
1826         if( subsfile_dialog->size_combo )
1827         {
1828             subsfile_mrl.Add( wxString::Format( wxT("freetype-rel-fontsize=%i"),
1829                         (int)subsfile_dialog->size_combo->GetClientData(
1830                         subsfile_dialog->size_combo->GetSelection()) ) );
1831         }
1832         subsfile_mrl.Add( wxString( wxT("sub-fps="))+
1833                                     subsfile_dialog->fps_ctrl->GetValue()  );
1834         subsfile_mrl.Add( wxString::Format( wxT("sub-delay=%i"),
1835                           subsfile_dialog->delay_spinctrl->GetValue() ) );
1836     }
1837 }
1838
1839 /*****************************************************************************
1840  * Stream output event methods.
1841  *****************************************************************************/
1842 void OpenDialog::OnSoutEnable( wxCommandEvent& event )
1843 {
1844     sout_button->Enable( event.GetInt() != 0 );
1845 }
1846
1847 void OpenDialog::OnSoutSettings( wxCommandEvent& WXUNUSED(event) )
1848 {
1849     /* Show/hide the open dialog */
1850     if( sout_dialog == NULL )
1851         sout_dialog = new SoutDialog( p_intf, this );
1852
1853     if( sout_dialog && sout_dialog->ShowModal() == wxID_OK )
1854     {
1855         sout_mrl = sout_dialog->GetOptions();
1856     }
1857 }
1858
1859 /*****************************************************************************
1860  * Caching event methods.
1861  *****************************************************************************/
1862 void OpenDialog::OnCachingEnable( wxCommandEvent& event )
1863 {
1864     caching_value->Enable( event.GetInt() != 0 );
1865     i_caching = caching_value->GetValue();
1866     UpdateMRL();
1867 }
1868
1869 void OpenDialog::OnCachingChangeSpin( wxSpinEvent& event )
1870 {
1871     wxCommandEvent cevent;
1872     OnCachingChange(cevent);
1873 }
1874
1875 void OpenDialog::OnCachingChange( wxCommandEvent& event )
1876 {
1877     i_caching = event.GetInt();
1878     UpdateMRL();
1879 }
1880
1881 /*****************************************************************************
1882  * Utility functions.
1883  *****************************************************************************/
1884 wxArrayString SeparateEntries( wxString entries )
1885 {
1886     vlc_bool_t b_quotes_mode = VLC_FALSE;
1887
1888     wxArrayString entries_array;
1889     wxString entry;
1890
1891     wxStringTokenizer token( entries, wxT(" \t\r\n\""), wxTOKEN_RET_DELIMS );
1892
1893     while( token.HasMoreTokens() )
1894     {
1895         entry += token.GetNextToken();
1896
1897         if( entry.IsEmpty() ) continue;
1898
1899         if( !b_quotes_mode && entry.Last() == wxT('\"') )
1900         {
1901             /* Enters quotes mode */
1902             entry.RemoveLast();
1903             b_quotes_mode = VLC_TRUE;
1904         }
1905         else if( b_quotes_mode && entry.Last() == wxT('\"') )
1906         {
1907             /* Finished the quotes mode */
1908             entry.RemoveLast();
1909             b_quotes_mode = VLC_FALSE;
1910         }
1911         else if( !b_quotes_mode && entry.Last() != wxT('\"') )
1912         {
1913             /* we found a non-quoted standalone string */
1914             if( token.HasMoreTokens() ||
1915                 entry.Last() == wxT(' ') || entry.Last() == wxT('\t') ||
1916                 entry.Last() == wxT('\r') || entry.Last() == wxT('\n') )
1917                 entry.RemoveLast();
1918             if( !entry.IsEmpty() ) entries_array.Add( entry );
1919             entry.Empty();
1920         }
1921         else
1922         {;}
1923     }
1924
1925     if( !entry.IsEmpty() ) entries_array.Add( entry );
1926
1927     return entries_array;
1928 }