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