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