]> git.sesse.net Git - vlc/blob - modules/gui/wxwidgets/dialogs/open.cpp
375c8d52eea9e10e90ee4ab2b27ae7276f3727ad
[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             input_ItemAddOption( 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                 input_ItemAddOption( 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                 input_ItemAddOption( p_input, psz_utf8 );
1203                 wxLocaleFree( psz_utf8 );
1204             }
1205         }
1206
1207         if( b_start )
1208         {
1209             playlist_PlaylistAddInput( p_playlist, p_input,
1210                                        PLAYLIST_APPEND | PLAYLIST_GO,
1211                                        PLAYLIST_END );
1212         }
1213         else
1214         {
1215             playlist_PlaylistAddInput( p_playlist, p_input,
1216                                        PLAYLIST_APPEND|PLAYLIST_PREPARSE,
1217                                        PLAYLIST_END );
1218         }
1219     }
1220
1221     vlc_object_release( p_playlist );
1222
1223     Hide();
1224
1225     if( IsModal() ) EndModal( wxID_OK );
1226 }
1227
1228 void OpenDialog::OnCancel( wxCommandEvent& WXUNUSED(event) )
1229 {
1230     wxCloseEvent cevent;
1231     OnClose(cevent);
1232 }
1233
1234 void OpenDialog::OnClose( wxCloseEvent& WXUNUSED(event) )
1235 {
1236     Hide();
1237
1238     if( IsModal() ) EndModal( wxID_CANCEL );
1239 }
1240
1241 void OpenDialog::OnPageChange( wxNotebookEvent& event )
1242 {
1243     UpdateMRL( event.GetSelection() );
1244 }
1245
1246 void OpenDialog::OnMRLChange( wxCommandEvent& event )
1247 {
1248     //mrl = SeparateEntries( event.GetString() );
1249 }
1250
1251 /*****************************************************************************
1252  * File panel event methods.
1253  *****************************************************************************/
1254 void OpenDialog::OnFilePanelChange( wxCommandEvent& WXUNUSED(event) )
1255 {
1256     UpdateMRL( FILE_ACCESS );
1257 }
1258
1259 void OpenDialog::OnFileBrowse( wxCommandEvent& WXUNUSED(event) )
1260 {
1261     if( file_dialog == NULL )
1262         file_dialog = new wxFileDialog( this, wxU(_("Open File")),
1263             wxT(""), wxT(""), wxT("*"), wxOPEN | wxMULTIPLE );
1264
1265     file_dialog->SetWildcard(wxU(_("All Files (*.*)|*"
1266         "|Sound Files (*.mp3, *.ogg, etc.)|" EXTENSIONS_AUDIO
1267         "|Video Files (*.avi, *.mpg, etc.)|" EXTENSIONS_VIDEO
1268         "|Playlist Files (*.m3u, *.pls, etc.)|" EXTENSIONS_PLAYLIST
1269         "|Subtitle Files (*.srt, *.sub, etc.)|" EXTENSIONS_SUBTITLE)));
1270
1271     if( file_dialog && file_dialog->ShowModal() == wxID_OK )
1272     {
1273         wxArrayString paths;
1274         wxString path;
1275
1276         file_dialog->GetPaths( paths );
1277
1278         for( size_t i = 0; i < paths.GetCount(); i++ )
1279         {
1280             if( paths[i].Find( wxT(' ') ) >= 0 )
1281                 path += wxT("\"") + paths[i] + wxT("\" ");
1282             else
1283                 path += paths[i] + wxT(" ");
1284         }
1285
1286         file_combo->SetValue( path );
1287         file_combo->Append( path );
1288         if( file_combo->GetCount() > 10 ) file_combo->Delete( 0 );
1289         UpdateMRL( FILE_ACCESS );
1290     }
1291 }
1292
1293 void OpenDialog::OnSubFileBrowse( wxCommandEvent& WXUNUSED(event) )
1294 {
1295     wxFileDialog dialog( this, wxU(_("Open subtitles file")),
1296                          wxT(""), wxT(""), wxT("*"), wxOPEN );
1297
1298     if( dialog.ShowModal() == wxID_OK )
1299     {
1300         subfile_combo->SetValue( dialog.GetPath() );
1301     }
1302     wxCommandEvent event; OnSubFileChange( event );
1303 }
1304
1305 void OpenDialog::OnSubFileChange( wxCommandEvent& WXUNUSED(event) )
1306 {
1307     if( subsfile_mrl.GetCount() != 0 )
1308     {
1309         subsfile_mrl.RemoveAt( 0 );
1310         subsfile_mrl.Insert( wxString(wxT("sub-file=")) + subfile_combo->GetValue() , 0 );
1311     }
1312     else
1313     {
1314         subsfile_mrl.Add( wxString(wxT("sub-file=")) + subfile_combo->GetValue() );
1315     }
1316 }
1317
1318 /*****************************************************************************
1319  * Disc panel event methods.
1320  *****************************************************************************/
1321 void OpenDialog::OnDiscPanelChangeSpin( wxSpinEvent& event )
1322 {
1323     wxCommandEvent cevent;
1324     cevent.SetId(event.GetId());
1325     cevent.SetInt(event.GetPosition());
1326     OnDiscPanelChange(cevent);
1327 }
1328
1329 void OpenDialog::OnDiscPanelChange( wxCommandEvent& event )
1330 {
1331     if( event.GetId() == DiscTitle_Event ) i_disc_title = event.GetInt();
1332     if( event.GetId() == DiscChapter_Event ) i_disc_chapter = event.GetInt();
1333     if( event.GetId() == DiscSub_Event ) i_disc_sub = event.GetInt();
1334     if( event.GetId() == DiscAudio_Event ) i_disc_audio = event.GetInt();
1335
1336     UpdateMRL( DISC_ACCESS );
1337 }
1338
1339 void OpenDialog::OnDiscDeviceChange( wxCommandEvent& event )
1340 {
1341     char *psz_device;
1342
1343     switch( disc_type->GetSelection() )
1344     {
1345         case 3:
1346             psz_device = config_GetPsz( p_intf, "cd-audio" );
1347             break;
1348
1349         case 2:
1350             psz_device = config_GetPsz( p_intf, "vcd" );
1351             break;
1352
1353         default:
1354             psz_device = config_GetPsz( p_intf, "dvd" );
1355             break;
1356     }
1357
1358     if ( !psz_device ) psz_device = "";
1359
1360     if( disc_device->GetValue().Cmp( wxL2U( psz_device ) ) )
1361     {
1362         b_disc_device_changed = true;
1363     }
1364
1365     UpdateMRL( DISC_ACCESS );
1366 }
1367
1368 #ifdef HAVE_LIBCDIO
1369
1370 /* Return true if *psz_drive is a drive with a DVD in it. A more complete
1371    check would see if the media looks like a *playable* DVD. This should
1372    go into libcdio.
1373  */
1374 static bool IsDVD(const char *psz_drive)
1375 {
1376   CdIo_t *p_cdio = cdio_open (psz_drive, DRIVER_UNKNOWN);
1377   if (p_cdio)
1378   {
1379       discmode_t discmode = cdio_get_discmode(p_cdio);
1380       cdio_destroy(p_cdio);
1381       return cdio_is_discmode_dvd(discmode);
1382   }
1383   return false;
1384 }
1385
1386
1387 /* Return a device that has a DVD in it. The caller needs to free
1388    the returned string.
1389 */
1390 static char * ProbeDVD(const wxChar *device)
1391 {
1392         /*
1393   char **ppsz_cd_drives;
1394   const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(device);
1395   char *psz_device = (char *) tmp_buf;
1396
1397   if( IsDVD(psz_device) )
1398   {
1399       return strdup(psz_device);
1400   }
1401
1402   ppsz_cd_drives = cdio_get_devices(DRIVER_DEVICE);
1403   if( ppsz_cd_drives )
1404   {
1405       char **c;
1406       for( c = ppsz_cd_drives; *c != NULL; c++ )
1407       {
1408       if( IsDVD(*c) )
1409       {
1410           char *psz_drive = strdup(*c);
1411           cdio_free_device_list(ppsz_cd_drives);
1412           return strdup(psz_drive);
1413           }
1414       }
1415       cdio_free_device_list(ppsz_cd_drives);
1416   }*/
1417   return NULL;
1418 }
1419
1420
1421 static char * ProbeDevice(char **ppsz_search_devices, cdio_fs_anal_t mask,
1422               bool b_any)
1423 {
1424     char **ppsz_devices;
1425
1426     if( ppsz_search_devices && !ppsz_search_devices[0] )
1427         ppsz_search_devices = NULL;
1428
1429     /* Start out trying the device that has been entered so far. */
1430     ppsz_devices = cdio_get_devices_with_cap(ppsz_search_devices, mask,
1431                          b_any);
1432
1433     if (ppsz_devices && *ppsz_devices)
1434     {
1435         char *psz_device = strdup(*ppsz_devices);
1436         cdio_free_device_list(ppsz_devices);
1437         return psz_device;
1438     }
1439
1440     /* If there was no device specified on the first try, then give up
1441        now. Otherwise accept any CD-ROM in the class (e.g. VCD or DVD).
1442     */
1443     if( !ppsz_search_devices ) return NULL;
1444
1445     ppsz_devices = cdio_get_devices_with_cap(NULL, mask, true);
1446
1447     if (ppsz_devices && *ppsz_devices)
1448     {
1449         char *psz_device = strdup(*ppsz_devices);
1450         cdio_free_device_list(ppsz_devices);
1451         return psz_device;
1452     }
1453
1454     return NULL;
1455 }
1456
1457
1458 /* Return a device that has a CD-DA in it. The caller needs to free
1459    the returned string.
1460 */
1461 static char * ProbeCDDA(const wxChar *device)
1462 {
1463         /*
1464    char *ppsz_device[2];
1465    const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(device);
1466    char *psz_device = (char *) tmp_buf;
1467    ppsz_device[0] = (device && *device) ? psz_device : NULL;
1468    ppsz_device[1] = NULL;
1469    return ProbeDevice(ppsz_device, CDIO_FS_AUDIO, false);
1470    */ return NULL;
1471 }
1472
1473 /* Return a device that has a VCD in it. The caller needs to free
1474    the returned string.
1475 */
1476 static char * ProbeVCD(const wxChar *device)
1477 {/*
1478    char *ppsz_device[2];
1479    const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(device);
1480    char *psz_device = (char *) tmp_buf;
1481    ppsz_device[0] = (device && *device) ? psz_device : NULL;
1482    ppsz_device[1] = NULL;
1483    return ProbeDevice(ppsz_device,
1484                       (CDIO_FS_ANAL_SVCD|CDIO_FS_ANAL_CVD|CDIO_FS_ANAL_VIDEOCD
1485                        |CDIO_FS_UNKNOWN), true);
1486                        */ return NULL;
1487 }
1488
1489
1490 /*
1491    Probe (find anywhere) a CD-DA, VCD, or a DVD.
1492    First try the device name that may have been entered for the "disc type"
1493    selected. If that doesn't work we try any device for the disc type.
1494    If that doesn't work, try looking for CD-ROMs or DVD drives. the
1495    disc type, device name and paramter ranges are set to whatever we find.
1496 */
1497 void OpenDialog::OnDiscProbe( wxCommandEvent& WXUNUSED(event) )
1498 {
1499     wxCommandEvent dummy_event;
1500     char *psz_device = NULL;
1501     bool b_probed_DVD = false;
1502     bool b_probed_VCD = false;
1503     const int i_selection = disc_type->GetSelection();
1504
1505     /* Reduce verbosity of cdio errors. */
1506     cdio_loglevel_default = CDIO_LOG_ERROR;
1507
1508  retry:
1509     switch( disc_type->GetSelection() )
1510     {
1511
1512     case SELECTION_DISC_TYPE_DVD_MENUS:
1513     case SELECTION_DISC_TYPE_DVD:
1514       /* If not a DVD then try for a VCD. If VCD fails it will
1515          try for a CD-DA. */
1516       if (!psz_device) psz_device = ProbeDVD(disc_device->GetValue());
1517       if (!psz_device)
1518       {
1519           b_probed_DVD = true;
1520           disc_type->SetSelection(SELECTION_DISC_TYPE_VCD);
1521           OnDiscTypeChange( dummy_event );
1522           goto retry;
1523       }
1524       disc_device->SetValue( wxL2U(psz_device) );
1525       break;
1526
1527     case SELECTION_DISC_TYPE_VCD:  /* VCD probe of some sort */
1528       if(!psz_device) psz_device = ProbeVCD(disc_device->GetValue());
1529       if( psz_device  )
1530       {
1531 #ifdef HAVE_VCDX
1532 #if LIBVCD_VERSION_NUM > 23
1533       vcdinfo_obj_t *p_vcdinfo;
1534
1535           /* Set LID or entry range accurately if possible. */
1536       if( vcdinfo_open(&p_vcdinfo, &psz_device, DRIVER_DEVICE,
1537                 NULL) == VCDINFO_OPEN_VCD)
1538       {
1539           if (config_GetInt( p_intf, "vcdx-PBC"  ))
1540           {
1541           /* Set largest LID. */;
1542           disc_title->SetRange( 0, vcdinfo_get_num_LIDs(p_vcdinfo) );
1543
1544           }
1545           else
1546           {
1547           /* Set largest Entry */
1548           disc_title->SetRange( 0,
1549                     vcdinfo_get_num_entries(p_vcdinfo)-1 );
1550           }
1551           vcdinfo_close(p_vcdinfo);
1552       }
1553 #endif /* LIBVCD_VERSION_NUM > 23 */
1554           disc_device->SetValue( wxL2U(psz_device) );
1555 #else
1556           CdIo_t *p_cdio = cdio_open (psz_device, DRIVER_UNKNOWN);
1557           disc_device->SetValue( wxL2U(psz_device) );
1558
1559           /* Set track range accurately if possible. */
1560           if (p_cdio)
1561           {
1562               track_t i_last_track = cdio_get_last_track_num(p_cdio);
1563               disc_title->SetRange( 0, i_last_track-1 );
1564           }
1565           cdio_destroy(p_cdio);
1566 #endif
1567           break;
1568       }
1569
1570       b_probed_VCD = true;
1571
1572       /* Not a VCD. Try for a DVD unless we've been there before. */
1573       if( !b_probed_DVD && (psz_device = ProbeDVD(disc_device->GetValue())) )
1574       {
1575           disc_type->SetSelection(SELECTION_DISC_TYPE_DVD_MENUS);
1576           OnDiscTypeChange( dummy_event );
1577           goto retry;
1578       }
1579       b_probed_DVD = true;
1580
1581       /* Couldn't find a VCD or DVD. See if we can find a CD-DA. */
1582       psz_device = ProbeCDDA(disc_device->GetValue());
1583       if( psz_device  )
1584       {
1585           disc_type->SetSelection(SELECTION_DISC_TYPE_CDDA);
1586           OnDiscTypeChange( dummy_event );
1587           goto retry;
1588       }
1589
1590       /* Couldn't find a VCD, DVD or CD-DA. Null out the Device name and
1591      set to original selection.
1592        */
1593       disc_device->SetValue( wxL2U("") );
1594       disc_type->SetSelection(i_selection);
1595       OnDiscTypeChange( dummy_event );
1596       break;
1597
1598     case SELECTION_DISC_TYPE_CDDA:
1599       if(!psz_device) psz_device = ProbeCDDA(disc_device->GetValue());
1600       if( psz_device  )
1601       {
1602           CdIo_t *p_cdio = cdio_open (psz_device, DRIVER_UNKNOWN);
1603           disc_device->SetValue( wxL2U(psz_device) );
1604           if (p_cdio)
1605           {
1606               track_t i_last_track = cdio_get_last_track_num(p_cdio);
1607               disc_title->SetRange( 0, i_last_track );
1608 #if 0
1609           MediaInsertCDDA( p_intf,  p_cdio, i_last_track );
1610 #endif
1611           }
1612           cdio_destroy(p_cdio);
1613           break;
1614       }
1615
1616       /* Not a CD-DA. Try for a DVD unless we've been there before. */
1617       if( !b_probed_DVD && (psz_device = ProbeDVD(disc_device->GetValue())) )
1618       {
1619           disc_type->SetSelection(SELECTION_DISC_TYPE_DVD_MENUS);
1620           OnDiscTypeChange( dummy_event );
1621           goto retry;
1622       }
1623
1624       /* Couldn't find a CD-DA or DVD. See if we can find a VCD, unless
1625          we've tried that before. */
1626       if (!b_probed_VCD) psz_device = ProbeVCD(disc_device->GetValue());
1627       if( psz_device  )
1628       {
1629           disc_type->SetSelection(SELECTION_DISC_TYPE_VCD);
1630           OnDiscTypeChange( dummy_event );
1631           goto retry;
1632       }
1633       disc_device->SetValue( wxL2U("") );
1634       break;
1635
1636     default:
1637         msg_Err( p_intf, "invalid Disc type selection (%d)",
1638                  disc_type->GetSelection() );
1639         break;
1640     }
1641
1642     free(psz_device);
1643     disc_probe->SetValue(FALSE);
1644
1645     UpdateMRL( DISC_ACCESS );
1646 }
1647 #endif /* HAVE_LIBCDIO */
1648
1649 void OpenDialog::OnDiscTypeChange( wxCommandEvent& WXUNUSED(event) )
1650 {
1651     char *psz_device = NULL;
1652
1653     switch( disc_type->GetSelection() )
1654     {
1655
1656     case SELECTION_DISC_TYPE_DVD_MENUS:
1657     case SELECTION_DISC_TYPE_DVD:
1658         disc_sub->Enable(); disc_sub_label->Enable();
1659         disc_audio->Enable(); disc_audio_label->Enable();
1660         disc_chapter->Enable(); disc_chapter_label->Enable();
1661         disc_title_label->SetLabel ( wxU(_("Title")) );
1662         psz_device = config_GetPsz( p_intf, "dvd" );
1663         if( !b_disc_device_changed )
1664         {
1665             if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
1666             else disc_device->SetValue( wxT("") );
1667         }
1668         disc_title->SetRange( 0, 255 );
1669         disc_sub->SetRange( -1, 31 );  // up to 32 subtitles -1: no subtitle
1670         disc_audio->SetRange( 0, 7 );  // up to 8 audio channels
1671         disc_chapter->SetRange( 0, 255 );
1672         disc_title->SetToolTip( wxU(_("Title number.")) );
1673         // \bug [string] needs to be DVDs instead of DVD's
1674         disc_sub->SetToolTip( wxU(_(
1675           "DVD's can have up to 32 subtitles numbered 0..31. "
1676           "Note this is not the same thing as a subtitle name (e.g. 'en'). "
1677           "If a value -1 is used, no subtitle will be shown." )) );
1678         // \bug [string] needs to be DVDs instead of DVD's
1679         disc_audio->SetToolTip( wxU(_("Audio track number. "
1680           "DVD's can have up to 8 audio tracks numbered 0..7."
1681         )) );
1682         break;
1683
1684     case SELECTION_DISC_TYPE_VCD:
1685         disc_sub->Enable(); disc_sub_label->Enable();
1686         disc_audio->Enable(); disc_audio_label->Enable();
1687         disc_chapter->Disable(); disc_chapter_label->Disable();
1688         psz_device = config_GetPsz( p_intf, "vcd" );
1689         if( !b_disc_device_changed )
1690         {
1691             if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
1692             else disc_device->SetValue( wxT("") );
1693         }
1694
1695 #ifdef HAVE_VCDX
1696         if (config_GetInt( p_intf, "vcdx-PBC"  ))
1697         {
1698           disc_title_label->SetLabel ( wxT("Playback LID") );
1699           disc_title->SetToolTip( wxU(_(
1700           "Playback control (PBC) usually starts with number 1." )) );
1701         }
1702         else
1703         {
1704           disc_title_label->SetLabel ( wxT("Entry") );
1705           disc_title->SetToolTip( wxU(_(
1706           "The first entry (the beginning of the first MPEG track) is 0." )) );
1707         }
1708
1709 #else
1710         disc_title_label->SetLabel ( wxU(_("Track")) );
1711         disc_title->SetToolTip( wxU(_("Track number.")) );
1712 #endif
1713         disc_title->SetRange( 0, 99 );  // only 100 tracks allowed on VCDs
1714         disc_sub->SetRange( -1, 3 );    // up to 4 subtitles -1 = no subtitle
1715         disc_audio->SetRange( 0, 1 );   // up to 2 audio tracks
1716         // \bug [string] needs to be SVCDs instead of SVCD's
1717         disc_sub->SetToolTip( wxU(_(
1718           "SVCD's can have up to 4 subtitles numbered 0..3. "
1719           "If a value -1 is used, no subtitle will be shown." )) );
1720         // \bug [string] needs to be SVCDs instead of SVCD's
1721         disc_audio->SetToolTip( wxU(_("Audio track number. "
1722           "VCD's can have up to 2 audio tracks numbered 0 or 1. "
1723         )) );
1724         break;
1725
1726     case SELECTION_DISC_TYPE_CDDA:
1727         disc_sub->Disable(); disc_sub_label->Disable();
1728         disc_chapter->Disable(); disc_chapter_label->Disable();
1729         disc_audio->Disable(); disc_audio_label->Disable();
1730         disc_title_label->SetLabel ( wxU(_("Track")) );
1731 #ifdef HAVE_CDDAX
1732         disc_title->SetToolTip( wxU(_(
1733         "Audio CDs can have up to 100 tracks, the first track is usually 1. "
1734         "If 0 is given, then all tracks are played.")) );
1735 #else
1736         disc_title->SetToolTip( wxU(_(
1737         "Audio CDs can have up to 100 tracks, the first track is usually 1."
1738         )) );
1739 #endif
1740         psz_device = config_GetPsz( p_intf, "cd-audio" );
1741         if( !b_disc_device_changed )
1742         {
1743             if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
1744             else disc_device->SetValue( wxT("") );
1745         }
1746
1747         /* There are at most 100 tracks in a CD-DA */
1748         disc_title->SetRange( 0, 100 );
1749         break;
1750
1751     default:
1752         msg_Err( p_intf, "invalid Disc type selection (%d)",
1753                  disc_type->GetSelection() );
1754         break;
1755     }
1756
1757     disc_title->SetValue( 0 ); i_disc_title = 0;
1758     disc_chapter->SetValue( 0 ); i_disc_chapter = 0;
1759
1760     if( psz_device ) free( psz_device );
1761
1762     UpdateMRL( DISC_ACCESS );
1763 }
1764
1765 /*****************************************************************************
1766  * Net panel event methods.
1767  *****************************************************************************/
1768 void OpenDialog::OnNetPanelChangeSpin( wxSpinEvent& event )
1769 {
1770     wxCommandEvent cevent;
1771     cevent.SetId(event.GetId());
1772     cevent.SetInt(event.GetPosition());
1773     OnNetPanelChange(cevent);
1774 }
1775
1776 void OpenDialog::OnNetPanelChange( wxCommandEvent& event )
1777 {
1778     if( event.GetId() >= NetPort1_Event && event.GetId() <= NetPort3_Event )
1779     {
1780         i_net_ports[event.GetId() - NetPort1_Event] = event.GetInt();
1781     }
1782
1783     UpdateMRL( NET_ACCESS );
1784 }
1785
1786 void OpenDialog::OnNetTypeChange( wxCommandEvent& event )
1787 {
1788     int i;
1789
1790     i_net_type = event.GetId() - NetRadio1_Event;
1791
1792     for(i=0; i<4; i++)
1793     {
1794         net_radios[i]->SetValue( event.GetId() == (NetRadio1_Event+i) );
1795         net_subpanels[i]->Enable( event.GetId() == (NetRadio1_Event+i) );
1796     }
1797     /* UDP Unicast or multicast -> timeshift */
1798     if( i_net_type == 0 || i_net_type == 1 )
1799         net_timeshift->Enable();
1800     else
1801         net_timeshift->Disable();
1802
1803     UpdateMRL( NET_ACCESS );
1804 }
1805
1806 /*****************************************************************************
1807  * Subtitles file event methods.
1808  *****************************************************************************/
1809 void OpenDialog::OnSubsFileEnable( wxCommandEvent& event )
1810 {
1811     subsfile_button->Enable( event.GetInt() != 0 );
1812     subbrowse_button->Enable( event.GetInt() != 0 );
1813     subfile_combo->Enable( event.GetInt() != 0 );
1814 }
1815
1816 void OpenDialog::OnSubsFileSettings( wxCommandEvent& WXUNUSED(event) )
1817 {
1818     /* Show/hide the open dialog */
1819     if( subsfile_dialog == NULL )
1820         subsfile_dialog = new SubsFileDialog( p_intf, this );
1821
1822     if( subsfile_dialog && subsfile_dialog->ShowModal() == wxID_OK )
1823     {
1824         subsfile_mrl.Empty();
1825         subsfile_mrl.Add( wxString(wxT("sub-file="))  + subfile_combo->GetValue() );
1826         if( subsfile_dialog->encoding_combo )
1827         {
1828             subsfile_mrl.Add( wxString(wxT("subsdec-encoding=")) +
1829                               subsfile_dialog->encoding_combo->GetValue() );
1830         }
1831         if( subsfile_dialog->align_combo )
1832         {
1833             subsfile_mrl.Add( wxString::Format(wxT("subsdec-align=%i"),
1834                         (int)subsfile_dialog->align_combo->GetClientData(
1835                         subsfile_dialog->align_combo->GetSelection()) ) );
1836         }
1837         if( subsfile_dialog->size_combo )
1838         {
1839             subsfile_mrl.Add( wxString::Format( wxT("freetype-rel-fontsize=%i"),
1840                         (int)subsfile_dialog->size_combo->GetClientData(
1841                         subsfile_dialog->size_combo->GetSelection()) ) );
1842         }
1843         subsfile_mrl.Add( wxString::Format( wxT("sub-fps=%i"),
1844                           subsfile_dialog->fps_spinctrl->GetValue() ) );
1845         subsfile_mrl.Add( wxString::Format( wxT("sub-delay=%i"),
1846                           subsfile_dialog->delay_spinctrl->GetValue() ) );
1847     }
1848 }
1849
1850 /*****************************************************************************
1851  * Stream output event methods.
1852  *****************************************************************************/
1853 void OpenDialog::OnSoutEnable( wxCommandEvent& event )
1854 {
1855     sout_button->Enable( event.GetInt() != 0 );
1856 }
1857
1858 void OpenDialog::OnSoutSettings( wxCommandEvent& WXUNUSED(event) )
1859 {
1860     /* Show/hide the open dialog */
1861     if( sout_dialog == NULL )
1862         sout_dialog = new SoutDialog( p_intf, this );
1863
1864     if( sout_dialog && sout_dialog->ShowModal() == wxID_OK )
1865     {
1866         sout_mrl = sout_dialog->GetOptions();
1867     }
1868 }
1869
1870 /*****************************************************************************
1871  * Caching event methods.
1872  *****************************************************************************/
1873 void OpenDialog::OnCachingEnable( wxCommandEvent& event )
1874 {
1875     caching_value->Enable( event.GetInt() != 0 );
1876     i_caching = caching_value->GetValue();
1877     UpdateMRL();
1878 }
1879
1880 void OpenDialog::OnCachingChangeSpin( wxSpinEvent& event )
1881 {
1882     wxCommandEvent cevent;
1883     OnCachingChange(cevent);
1884 }
1885
1886 void OpenDialog::OnCachingChange( wxCommandEvent& event )
1887 {
1888     i_caching = event.GetInt();
1889     UpdateMRL();
1890 }
1891
1892 /*****************************************************************************
1893  * Utility functions.
1894  *****************************************************************************/
1895 wxArrayString SeparateEntries( wxString entries )
1896 {
1897     vlc_bool_t b_quotes_mode = VLC_FALSE;
1898
1899     wxArrayString entries_array;
1900     wxString entry;
1901
1902     wxStringTokenizer token( entries, wxT(" \t\r\n\""), wxTOKEN_RET_DELIMS );
1903
1904     while( token.HasMoreTokens() )
1905     {
1906         entry += token.GetNextToken();
1907
1908         if( entry.IsEmpty() ) continue;
1909
1910         if( !b_quotes_mode && entry.Last() == wxT('\"') )
1911         {
1912             /* Enters quotes mode */
1913             entry.RemoveLast();
1914             b_quotes_mode = VLC_TRUE;
1915         }
1916         else if( b_quotes_mode && entry.Last() == wxT('\"') )
1917         {
1918             /* Finished the quotes mode */
1919             entry.RemoveLast();
1920             b_quotes_mode = VLC_FALSE;
1921         }
1922         else if( !b_quotes_mode && entry.Last() != wxT('\"') )
1923         {
1924             /* we found a non-quoted standalone string */
1925             if( token.HasMoreTokens() ||
1926                 entry.Last() == wxT(' ') || entry.Last() == wxT('\t') ||
1927                 entry.Last() == wxT('\r') || entry.Last() == wxT('\n') )
1928                 entry.RemoveLast();
1929             if( !entry.IsEmpty() ) entries_array.Add( entry );
1930             entry.Empty();
1931         }
1932         else
1933         {;}
1934     }
1935
1936     if( !entry.IsEmpty() ) entries_array.Add( entry );
1937
1938     return entries_array;
1939 }