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