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