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