]> git.sesse.net Git - vlc/blob - modules/gui/wxwidgets/dialogs/open.cpp
f85150cac1d05e3d93043977c8afc5d1219b39ae
[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         if( psz_sout ) 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     if( file_dialog ) delete file_dialog;
592     if( sout_dialog ) delete sout_dialog;
593     if( subsfile_dialog ) 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     if( psz_subsfile ) 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         if( b_start )
1209         {
1210             playlist_AddInput( p_playlist, p_input,
1211                                PLAYLIST_APPEND | PLAYLIST_GO,
1212                                PLAYLIST_END, VLC_TRUE, VLC_FALSE );
1213         }
1214         else
1215         {
1216             playlist_AddInput( p_playlist, p_input,
1217                                        PLAYLIST_APPEND|PLAYLIST_PREPARSE,
1218                                        PLAYLIST_END, VLC_TRUE, VLC_FALSE );
1219         }
1220     }
1221
1222     vlc_object_release( p_playlist );
1223
1224     Hide();
1225
1226     if( IsModal() ) EndModal( wxID_OK );
1227 }
1228
1229 void OpenDialog::OnCancel( wxCommandEvent& WXUNUSED(event) )
1230 {
1231     wxCloseEvent cevent;
1232     OnClose(cevent);
1233 }
1234
1235 void OpenDialog::OnClose( wxCloseEvent& WXUNUSED(event) )
1236 {
1237     Hide();
1238
1239     if( IsModal() ) EndModal( wxID_CANCEL );
1240 }
1241
1242 void OpenDialog::OnPageChange( wxNotebookEvent& event )
1243 {
1244     UpdateMRL( event.GetSelection() );
1245 }
1246
1247 void OpenDialog::OnMRLChange( wxCommandEvent& event )
1248 {
1249     //mrl = SeparateEntries( event.GetString() );
1250 }
1251
1252 /*****************************************************************************
1253  * File panel event methods.
1254  *****************************************************************************/
1255 void OpenDialog::OnFilePanelChange( wxCommandEvent& WXUNUSED(event) )
1256 {
1257     UpdateMRL( FILE_ACCESS );
1258 }
1259
1260 void OpenDialog::OnFileBrowse( wxCommandEvent& WXUNUSED(event) )
1261 {
1262     if( file_dialog == NULL )
1263         file_dialog = new wxFileDialog( this, wxU(_("Open File")),
1264             wxT(""), wxT(""), wxT("*"), wxOPEN | wxMULTIPLE );
1265
1266     file_dialog->SetWildcard(wxU(_("All Files (*.*)|*"
1267         "|Sound Files (*.mp3, *.ogg, etc.)|" EXTENSIONS_AUDIO
1268         "|Video Files (*.avi, *.mpg, etc.)|" EXTENSIONS_VIDEO
1269         "|Playlist Files (*.m3u, *.pls, etc.)|" EXTENSIONS_PLAYLIST
1270         "|Subtitle Files (*.srt, *.sub, etc.)|" EXTENSIONS_SUBTITLE)));
1271
1272     if( file_dialog && file_dialog->ShowModal() == wxID_OK )
1273     {
1274         wxArrayString paths;
1275         wxString path;
1276
1277         file_dialog->GetPaths( paths );
1278
1279         for( size_t i = 0; i < paths.GetCount(); i++ )
1280         {
1281             if( paths[i].Find( wxT(' ') ) >= 0 )
1282                 path += wxT("\"") + paths[i] + wxT("\" ");
1283             else
1284                 path += paths[i] + wxT(" ");
1285         }
1286
1287         file_combo->SetValue( path );
1288         file_combo->Append( path );
1289         if( file_combo->GetCount() > 10 ) file_combo->Delete( 0 );
1290         UpdateMRL( FILE_ACCESS );
1291     }
1292 }
1293
1294 void OpenDialog::OnSubFileBrowse( wxCommandEvent& WXUNUSED(event) )
1295 {
1296     wxFileDialog dialog( this, wxU(_("Open subtitles file")),
1297                          wxT(""), wxT(""), wxT("*"), wxOPEN );
1298
1299     if( dialog.ShowModal() == wxID_OK )
1300     {
1301         subfile_combo->SetValue( dialog.GetPath() );
1302     }
1303     wxCommandEvent event; OnSubFileChange( event );
1304 }
1305
1306 void OpenDialog::OnSubFileChange( wxCommandEvent& WXUNUSED(event) )
1307 {
1308     if( subsfile_mrl.GetCount() != 0 )
1309     {
1310         subsfile_mrl.RemoveAt( 0 );
1311         subsfile_mrl.Insert( wxString(wxT("sub-file=")) + subfile_combo->GetValue() , 0 );
1312     }
1313     else
1314     {
1315         subsfile_mrl.Add( wxString(wxT("sub-file=")) + subfile_combo->GetValue() );
1316     }
1317 }
1318
1319 /*****************************************************************************
1320  * Disc panel event methods.
1321  *****************************************************************************/
1322 void OpenDialog::OnDiscPanelChangeSpin( wxSpinEvent& event )
1323 {
1324     wxCommandEvent cevent;
1325     cevent.SetId(event.GetId());
1326     cevent.SetInt(event.GetPosition());
1327     OnDiscPanelChange(cevent);
1328 }
1329
1330 void OpenDialog::OnDiscPanelChange( wxCommandEvent& event )
1331 {
1332     if( event.GetId() == DiscTitle_Event ) i_disc_title = event.GetInt();
1333     if( event.GetId() == DiscChapter_Event ) i_disc_chapter = event.GetInt();
1334     if( event.GetId() == DiscSub_Event ) i_disc_sub = event.GetInt();
1335     if( event.GetId() == DiscAudio_Event ) i_disc_audio = event.GetInt();
1336
1337     UpdateMRL( DISC_ACCESS );
1338 }
1339
1340 void OpenDialog::OnDiscDeviceChange( wxCommandEvent& event )
1341 {
1342     char *psz_device;
1343
1344     switch( disc_type->GetSelection() )
1345     {
1346         case 3:
1347             psz_device = config_GetPsz( p_intf, "cd-audio" );
1348             break;
1349
1350         case 2:
1351             psz_device = config_GetPsz( p_intf, "vcd" );
1352             break;
1353
1354         default:
1355             psz_device = config_GetPsz( p_intf, "dvd" );
1356             break;
1357     }
1358
1359     if ( !psz_device ) psz_device = "";
1360
1361     if( disc_device->GetValue().Cmp( wxL2U( psz_device ) ) )
1362     {
1363         b_disc_device_changed = true;
1364     }
1365
1366     UpdateMRL( DISC_ACCESS );
1367 }
1368
1369 #ifdef HAVE_LIBCDIO
1370
1371 /* Return true if *psz_drive is a drive with a DVD in it. A more complete
1372    check would see if the media looks like a *playable* DVD. This should
1373    go into libcdio.
1374  */
1375 static bool IsDVD(const char *psz_drive)
1376 {
1377   CdIo_t *p_cdio = cdio_open (psz_drive, DRIVER_UNKNOWN);
1378   if (p_cdio)
1379   {
1380       discmode_t discmode = cdio_get_discmode(p_cdio);
1381       cdio_destroy(p_cdio);
1382       return cdio_is_discmode_dvd(discmode);
1383   }
1384   return false;
1385 }
1386
1387
1388 /* Return a device that has a DVD in it. The caller needs to free
1389    the returned string.
1390 */
1391 static char * ProbeDVD(const wxChar *device)
1392 {
1393         /*
1394   char **ppsz_cd_drives;
1395   const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(device);
1396   char *psz_device = (char *) tmp_buf;
1397
1398   if( IsDVD(psz_device) )
1399   {
1400       return strdup(psz_device);
1401   }
1402
1403   ppsz_cd_drives = cdio_get_devices(DRIVER_DEVICE);
1404   if( ppsz_cd_drives )
1405   {
1406       char **c;
1407       for( c = ppsz_cd_drives; *c != NULL; c++ )
1408       {
1409       if( IsDVD(*c) )
1410       {
1411           char *psz_drive = strdup(*c);
1412           cdio_free_device_list(ppsz_cd_drives);
1413           return strdup(psz_drive);
1414           }
1415       }
1416       cdio_free_device_list(ppsz_cd_drives);
1417   }*/
1418   return NULL;
1419 }
1420
1421
1422 static char * ProbeDevice(char **ppsz_search_devices, cdio_fs_anal_t mask,
1423               bool b_any)
1424 {
1425     char **ppsz_devices;
1426
1427     if( ppsz_search_devices && !ppsz_search_devices[0] )
1428         ppsz_search_devices = NULL;
1429
1430     /* Start out trying the device that has been entered so far. */
1431     ppsz_devices = cdio_get_devices_with_cap(ppsz_search_devices, mask,
1432                          b_any);
1433
1434     if (ppsz_devices && *ppsz_devices)
1435     {
1436         char *psz_device = strdup(*ppsz_devices);
1437         cdio_free_device_list(ppsz_devices);
1438         return psz_device;
1439     }
1440
1441     /* If there was no device specified on the first try, then give up
1442        now. Otherwise accept any CD-ROM in the class (e.g. VCD or DVD).
1443     */
1444     if( !ppsz_search_devices ) return NULL;
1445
1446     ppsz_devices = cdio_get_devices_with_cap(NULL, mask, true);
1447
1448     if (ppsz_devices && *ppsz_devices)
1449     {
1450         char *psz_device = strdup(*ppsz_devices);
1451         cdio_free_device_list(ppsz_devices);
1452         return psz_device;
1453     }
1454
1455     return NULL;
1456 }
1457
1458
1459 /* Return a device that has a CD-DA in it. The caller needs to free
1460    the returned string.
1461 */
1462 static char * ProbeCDDA(const wxChar *device)
1463 {
1464         /*
1465    char *ppsz_device[2];
1466    const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(device);
1467    char *psz_device = (char *) tmp_buf;
1468    ppsz_device[0] = (device && *device) ? psz_device : NULL;
1469    ppsz_device[1] = NULL;
1470    return ProbeDevice(ppsz_device, CDIO_FS_AUDIO, false);
1471    */ return NULL;
1472 }
1473
1474 /* Return a device that has a VCD in it. The caller needs to free
1475    the returned string.
1476 */
1477 static char * ProbeVCD(const wxChar *device)
1478 {/*
1479    char *ppsz_device[2];
1480    const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(device);
1481    char *psz_device = (char *) tmp_buf;
1482    ppsz_device[0] = (device && *device) ? psz_device : NULL;
1483    ppsz_device[1] = NULL;
1484    return ProbeDevice(ppsz_device,
1485                       (CDIO_FS_ANAL_SVCD|CDIO_FS_ANAL_CVD|CDIO_FS_ANAL_VIDEOCD
1486                        |CDIO_FS_UNKNOWN), true);
1487                        */ return NULL;
1488 }
1489
1490
1491 /*
1492    Probe (find anywhere) a CD-DA, VCD, or a DVD.
1493    First try the device name that may have been entered for the "disc type"
1494    selected. If that doesn't work we try any device for the disc type.
1495    If that doesn't work, try looking for CD-ROMs or DVD drives. the
1496    disc type, device name and paramter ranges are set to whatever we find.
1497 */
1498 void OpenDialog::OnDiscProbe( wxCommandEvent& WXUNUSED(event) )
1499 {
1500     wxCommandEvent dummy_event;
1501     char *psz_device = NULL;
1502     bool b_probed_DVD = false;
1503     bool b_probed_VCD = false;
1504     const int i_selection = disc_type->GetSelection();
1505
1506     /* Reduce verbosity of cdio errors. */
1507     cdio_loglevel_default = CDIO_LOG_ERROR;
1508
1509  retry:
1510     switch( disc_type->GetSelection() )
1511     {
1512
1513     case SELECTION_DISC_TYPE_DVD_MENUS:
1514     case SELECTION_DISC_TYPE_DVD:
1515       /* If not a DVD then try for a VCD. If VCD fails it will
1516          try for a CD-DA. */
1517       if (!psz_device) psz_device = ProbeDVD(disc_device->GetValue());
1518       if (!psz_device)
1519       {
1520           b_probed_DVD = true;
1521           disc_type->SetSelection(SELECTION_DISC_TYPE_VCD);
1522           OnDiscTypeChange( dummy_event );
1523           goto retry;
1524       }
1525       disc_device->SetValue( wxL2U(psz_device) );
1526       break;
1527
1528     case SELECTION_DISC_TYPE_VCD:  /* VCD probe of some sort */
1529       if(!psz_device) psz_device = ProbeVCD(disc_device->GetValue());
1530       if( psz_device  )
1531       {
1532 #ifdef HAVE_VCDX
1533 #if LIBVCD_VERSION_NUM > 23
1534       vcdinfo_obj_t *p_vcdinfo;
1535
1536           /* Set LID or entry range accurately if possible. */
1537       if( vcdinfo_open(&p_vcdinfo, &psz_device, DRIVER_DEVICE,
1538                 NULL) == VCDINFO_OPEN_VCD)
1539       {
1540           if (config_GetInt( p_intf, "vcdx-PBC"  ))
1541           {
1542           /* Set largest LID. */;
1543           disc_title->SetRange( 0, vcdinfo_get_num_LIDs(p_vcdinfo) );
1544
1545           }
1546           else
1547           {
1548           /* Set largest Entry */
1549           disc_title->SetRange( 0,
1550                     vcdinfo_get_num_entries(p_vcdinfo)-1 );
1551           }
1552           vcdinfo_close(p_vcdinfo);
1553       }
1554 #endif /* LIBVCD_VERSION_NUM > 23 */
1555           disc_device->SetValue( wxL2U(psz_device) );
1556 #else
1557           CdIo_t *p_cdio = cdio_open (psz_device, DRIVER_UNKNOWN);
1558           disc_device->SetValue( wxL2U(psz_device) );
1559
1560           /* Set track range accurately if possible. */
1561           if (p_cdio)
1562           {
1563               track_t i_last_track = cdio_get_last_track_num(p_cdio);
1564               disc_title->SetRange( 0, i_last_track-1 );
1565           }
1566           cdio_destroy(p_cdio);
1567 #endif
1568           break;
1569       }
1570
1571       b_probed_VCD = true;
1572
1573       /* Not a VCD. Try for a DVD unless we've been there before. */
1574       if( !b_probed_DVD && (psz_device = ProbeDVD(disc_device->GetValue())) )
1575       {
1576           disc_type->SetSelection(SELECTION_DISC_TYPE_DVD_MENUS);
1577           OnDiscTypeChange( dummy_event );
1578           goto retry;
1579       }
1580       b_probed_DVD = true;
1581
1582       /* Couldn't find a VCD or DVD. See if we can find a CD-DA. */
1583       psz_device = ProbeCDDA(disc_device->GetValue());
1584       if( psz_device  )
1585       {
1586           disc_type->SetSelection(SELECTION_DISC_TYPE_CDDA);
1587           OnDiscTypeChange( dummy_event );
1588           goto retry;
1589       }
1590
1591       /* Couldn't find a VCD, DVD or CD-DA. Null out the Device name and
1592      set to original selection.
1593        */
1594       disc_device->SetValue( wxL2U("") );
1595       disc_type->SetSelection(i_selection);
1596       OnDiscTypeChange( dummy_event );
1597       break;
1598
1599     case SELECTION_DISC_TYPE_CDDA:
1600       if(!psz_device) psz_device = ProbeCDDA(disc_device->GetValue());
1601       if( psz_device  )
1602       {
1603           CdIo_t *p_cdio = cdio_open (psz_device, DRIVER_UNKNOWN);
1604           disc_device->SetValue( wxL2U(psz_device) );
1605           if (p_cdio)
1606           {
1607               track_t i_last_track = cdio_get_last_track_num(p_cdio);
1608               disc_title->SetRange( 0, i_last_track );
1609 #if 0
1610           MediaInsertCDDA( p_intf,  p_cdio, i_last_track );
1611 #endif
1612           }
1613           cdio_destroy(p_cdio);
1614           break;
1615       }
1616
1617       /* Not a CD-DA. Try for a DVD unless we've been there before. */
1618       if( !b_probed_DVD && (psz_device = ProbeDVD(disc_device->GetValue())) )
1619       {
1620           disc_type->SetSelection(SELECTION_DISC_TYPE_DVD_MENUS);
1621           OnDiscTypeChange( dummy_event );
1622           goto retry;
1623       }
1624
1625       /* Couldn't find a CD-DA or DVD. See if we can find a VCD, unless
1626          we've tried that before. */
1627       if (!b_probed_VCD) psz_device = ProbeVCD(disc_device->GetValue());
1628       if( psz_device  )
1629       {
1630           disc_type->SetSelection(SELECTION_DISC_TYPE_VCD);
1631           OnDiscTypeChange( dummy_event );
1632           goto retry;
1633       }
1634       disc_device->SetValue( wxL2U("") );
1635       break;
1636
1637     default:
1638         msg_Err( p_intf, "invalid Disc type selection (%d)",
1639                  disc_type->GetSelection() );
1640         break;
1641     }
1642
1643     free(psz_device);
1644     disc_probe->SetValue(FALSE);
1645
1646     UpdateMRL( DISC_ACCESS );
1647 }
1648 #endif /* HAVE_LIBCDIO */
1649
1650 void OpenDialog::OnDiscTypeChange( wxCommandEvent& WXUNUSED(event) )
1651 {
1652     char *psz_device = NULL;
1653
1654     switch( disc_type->GetSelection() )
1655     {
1656
1657     case SELECTION_DISC_TYPE_DVD_MENUS:
1658     case SELECTION_DISC_TYPE_DVD:
1659         disc_sub->Enable(); disc_sub_label->Enable();
1660         disc_audio->Enable(); disc_audio_label->Enable();
1661         disc_chapter->Enable(); disc_chapter_label->Enable();
1662         disc_title_label->SetLabel ( wxU(_("Title")) );
1663         psz_device = config_GetPsz( p_intf, "dvd" );
1664         if( !b_disc_device_changed )
1665         {
1666             if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
1667             else disc_device->SetValue( wxT("") );
1668         }
1669         disc_title->SetRange( 0, 255 );
1670         disc_sub->SetRange( -1, 31 );  // up to 32 subtitles -1: no subtitle
1671         disc_audio->SetRange( 0, 7 );  // up to 8 audio channels
1672         disc_chapter->SetRange( 0, 255 );
1673         disc_title->SetToolTip( wxU(_("Title number.")) );
1674         disc_sub->SetToolTip( wxU(_(
1675           "DVDs can have up to 32 subtitles numbered 0..31. "
1676           "Note this is not the same thing as a subtitle name (e.g. 'en'). "
1677           "If a value -1 is used, no subtitle will be shown." )) );
1678         disc_audio->SetToolTip( wxU(_("Audio track number. "
1679           "DVDs can have up to 8 audio tracks numbered 0..7."
1680         )) );
1681         break;
1682
1683     case SELECTION_DISC_TYPE_VCD:
1684         disc_sub->Enable(); disc_sub_label->Enable();
1685         disc_audio->Enable(); disc_audio_label->Enable();
1686         disc_chapter->Disable(); disc_chapter_label->Disable();
1687         psz_device = config_GetPsz( p_intf, "vcd" );
1688         if( !b_disc_device_changed )
1689         {
1690             if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
1691             else disc_device->SetValue( wxT("") );
1692         }
1693
1694 #ifdef HAVE_VCDX
1695         if (config_GetInt( p_intf, "vcdx-PBC"  ))
1696         {
1697           disc_title_label->SetLabel ( wxT("Playback LID") );
1698           disc_title->SetToolTip( wxU(_(
1699           "Playback control (PBC) usually starts with number 1." )) );
1700         }
1701         else
1702         {
1703           disc_title_label->SetLabel ( wxT("Entry") );
1704           disc_title->SetToolTip( wxU(_(
1705           "The first entry (the beginning of the first MPEG track) is 0." )) );
1706         }
1707
1708 #else
1709         disc_title_label->SetLabel ( wxU(_("Track")) );
1710         disc_title->SetToolTip( wxU(_("Track number.")) );
1711 #endif
1712         disc_title->SetRange( 0, 99 );  // only 100 tracks allowed on VCDs
1713         disc_sub->SetRange( -1, 3 );    // up to 4 subtitles -1 = no subtitle
1714         disc_audio->SetRange( 0, 1 );   // up to 2 audio tracks
1715         disc_sub->SetToolTip( wxU(_(
1716           "SVCDs can have up to 4 subtitles numbered 0..3. "
1717           "If a value -1 is used, no subtitle will be shown." )) );
1718         disc_audio->SetToolTip( wxU(_("Audio track number. "
1719           "VCDs can have up to 2 audio tracks numbered 0 or 1. "
1720         )) );
1721         break;
1722
1723     case SELECTION_DISC_TYPE_CDDA:
1724         disc_sub->Disable(); disc_sub_label->Disable();
1725         disc_chapter->Disable(); disc_chapter_label->Disable();
1726         disc_audio->Disable(); disc_audio_label->Disable();
1727         disc_title_label->SetLabel ( wxU(_("Track")) );
1728 #ifdef HAVE_CDDAX
1729         disc_title->SetToolTip( wxU(_(
1730         "Audio CDs can have up to 100 tracks, the first track is usually 1. "
1731         "If 0 is given, then all tracks are played.")) );
1732 #else
1733         disc_title->SetToolTip( wxU(_(
1734         "Audio CDs can have up to 100 tracks, the first track is usually 1."
1735         )) );
1736 #endif
1737         psz_device = config_GetPsz( p_intf, "cd-audio" );
1738         if( !b_disc_device_changed )
1739         {
1740             if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
1741             else disc_device->SetValue( wxT("") );
1742         }
1743
1744         /* There are at most 100 tracks in a CD-DA */
1745         disc_title->SetRange( 0, 100 );
1746         break;
1747
1748     default:
1749         msg_Err( p_intf, "invalid Disc type selection (%d)",
1750                  disc_type->GetSelection() );
1751         break;
1752     }
1753
1754     disc_title->SetValue( 0 ); i_disc_title = 0;
1755     disc_chapter->SetValue( 0 ); i_disc_chapter = 0;
1756
1757     if( psz_device ) free( psz_device );
1758
1759     UpdateMRL( DISC_ACCESS );
1760 }
1761
1762 /*****************************************************************************
1763  * Net panel event methods.
1764  *****************************************************************************/
1765 void OpenDialog::OnNetPanelChangeSpin( wxSpinEvent& event )
1766 {
1767     wxCommandEvent cevent;
1768     cevent.SetId(event.GetId());
1769     cevent.SetInt(event.GetPosition());
1770     OnNetPanelChange(cevent);
1771 }
1772
1773 void OpenDialog::OnNetPanelChange( wxCommandEvent& event )
1774 {
1775     if( event.GetId() >= NetPort1_Event && event.GetId() <= NetPort3_Event )
1776     {
1777         i_net_ports[event.GetId() - NetPort1_Event] = event.GetInt();
1778     }
1779
1780     UpdateMRL( NET_ACCESS );
1781 }
1782
1783 void OpenDialog::OnNetTypeChange( wxCommandEvent& event )
1784 {
1785     int i;
1786
1787     i_net_type = event.GetId() - NetRadio1_Event;
1788
1789     for(i=0; i<4; i++)
1790     {
1791         net_radios[i]->SetValue( event.GetId() == (NetRadio1_Event+i) );
1792         net_subpanels[i]->Enable( event.GetId() == (NetRadio1_Event+i) );
1793     }
1794     /* UDP Unicast or multicast -> timeshift */
1795     if( i_net_type == 0 || i_net_type == 1 )
1796         net_timeshift->Enable();
1797     else
1798         net_timeshift->Disable();
1799
1800     UpdateMRL( NET_ACCESS );
1801 }
1802
1803 /*****************************************************************************
1804  * Subtitles file event methods.
1805  *****************************************************************************/
1806 void OpenDialog::OnSubsFileEnable( wxCommandEvent& event )
1807 {
1808     subsfile_button->Enable( event.GetInt() != 0 );
1809     subbrowse_button->Enable( event.GetInt() != 0 );
1810     subfile_combo->Enable( event.GetInt() != 0 );
1811 }
1812
1813 void OpenDialog::OnSubsFileSettings( wxCommandEvent& WXUNUSED(event) )
1814 {
1815     /* Show/hide the open dialog */
1816     if( subsfile_dialog == NULL )
1817         subsfile_dialog = new SubsFileDialog( p_intf, this );
1818
1819     if( subsfile_dialog && subsfile_dialog->ShowModal() == wxID_OK )
1820     {
1821         subsfile_mrl.Empty();
1822         subsfile_mrl.Add( wxString(wxT("sub-file="))  + subfile_combo->GetValue() );
1823         if( subsfile_dialog->encoding_combo )
1824         {
1825             subsfile_mrl.Add( wxString(wxT("subsdec-encoding=")) +
1826                               subsfile_dialog->encoding_combo->GetValue() );
1827         }
1828         if( subsfile_dialog->align_combo )
1829         {
1830             subsfile_mrl.Add( wxString::Format(wxT("subsdec-align=%i"),
1831                         (int)subsfile_dialog->align_combo->GetClientData(
1832                         subsfile_dialog->align_combo->GetSelection()) ) );
1833         }
1834         if( subsfile_dialog->size_combo )
1835         {
1836             subsfile_mrl.Add( wxString::Format( wxT("freetype-rel-fontsize=%i"),
1837                         (int)subsfile_dialog->size_combo->GetClientData(
1838                         subsfile_dialog->size_combo->GetSelection()) ) );
1839         }
1840         subsfile_mrl.Add( wxString( wxT("sub-fps="))+
1841                                     subsfile_dialog->fps_ctrl->GetValue()  );
1842         subsfile_mrl.Add( wxString::Format( wxT("sub-delay=%i"),
1843                           subsfile_dialog->delay_spinctrl->GetValue() ) );
1844     }
1845 }
1846
1847 /*****************************************************************************
1848  * Stream output event methods.
1849  *****************************************************************************/
1850 void OpenDialog::OnSoutEnable( wxCommandEvent& event )
1851 {
1852     sout_button->Enable( event.GetInt() != 0 );
1853 }
1854
1855 void OpenDialog::OnSoutSettings( wxCommandEvent& WXUNUSED(event) )
1856 {
1857     /* Show/hide the open dialog */
1858     if( sout_dialog == NULL )
1859         sout_dialog = new SoutDialog( p_intf, this );
1860
1861     if( sout_dialog && sout_dialog->ShowModal() == wxID_OK )
1862     {
1863         sout_mrl = sout_dialog->GetOptions();
1864     }
1865 }
1866
1867 /*****************************************************************************
1868  * Caching event methods.
1869  *****************************************************************************/
1870 void OpenDialog::OnCachingEnable( wxCommandEvent& event )
1871 {
1872     caching_value->Enable( event.GetInt() != 0 );
1873     i_caching = caching_value->GetValue();
1874     UpdateMRL();
1875 }
1876
1877 void OpenDialog::OnCachingChangeSpin( wxSpinEvent& event )
1878 {
1879     wxCommandEvent cevent;
1880     OnCachingChange(cevent);
1881 }
1882
1883 void OpenDialog::OnCachingChange( wxCommandEvent& event )
1884 {
1885     i_caching = event.GetInt();
1886     UpdateMRL();
1887 }
1888
1889 /*****************************************************************************
1890  * Utility functions.
1891  *****************************************************************************/
1892 wxArrayString SeparateEntries( wxString entries )
1893 {
1894     vlc_bool_t b_quotes_mode = VLC_FALSE;
1895
1896     wxArrayString entries_array;
1897     wxString entry;
1898
1899     wxStringTokenizer token( entries, wxT(" \t\r\n\""), wxTOKEN_RET_DELIMS );
1900
1901     while( token.HasMoreTokens() )
1902     {
1903         entry += token.GetNextToken();
1904
1905         if( entry.IsEmpty() ) continue;
1906
1907         if( !b_quotes_mode && entry.Last() == wxT('\"') )
1908         {
1909             /* Enters quotes mode */
1910             entry.RemoveLast();
1911             b_quotes_mode = VLC_TRUE;
1912         }
1913         else if( b_quotes_mode && entry.Last() == wxT('\"') )
1914         {
1915             /* Finished the quotes mode */
1916             entry.RemoveLast();
1917             b_quotes_mode = VLC_FALSE;
1918         }
1919         else if( !b_quotes_mode && entry.Last() != wxT('\"') )
1920         {
1921             /* we found a non-quoted standalone string */
1922             if( token.HasMoreTokens() ||
1923                 entry.Last() == wxT(' ') || entry.Last() == wxT('\t') ||
1924                 entry.Last() == wxT('\r') || entry.Last() == wxT('\n') )
1925                 entry.RemoveLast();
1926             if( !entry.IsEmpty() ) entries_array.Add( entry );
1927             entry.Empty();
1928         }
1929         else
1930         {;}
1931     }
1932
1933     if( !entry.IsEmpty() ) entries_array.Add( entry );
1934
1935     return entries_array;
1936 }