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