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