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