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