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