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