]> git.sesse.net Git - vlc/blob - modules/gui/wxwidgets/dialogs/open.cpp
FSF address change.
[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-cruft
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, wxU(_("OK")) );
321         ok_button->SetDefault();
322         wxButton *cancel_button =
323             new wxButton( p_advanced_dialog, wxID_CANCEL, wxU(_("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, wxU(_("OK")) );
491     ok_button->SetDefault();
492     wxButton *cancel_button = new wxButton( panel, wxID_CANCEL,
493                                             wxU(_("Cancel")) );
494
495     /* Create notebook */
496     notebook = new wxNotebook( panel, Notebook_Event );
497
498 #if (!wxCHECK_VERSION(2,5,2))
499     wxNotebookSizer *notebook_sizer = new wxNotebookSizer( notebook );
500 #endif
501
502     notebook->AddPage( FilePanel( notebook ), wxU(_("File")),
503                        i_access_method == FILE_ACCESS );
504     notebook->AddPage( DiscPanel( notebook ), wxU(_("Disc")),
505                        i_access_method == DISC_ACCESS );
506     notebook->AddPage( NetPanel( notebook ), wxU(_("Network")),
507                        i_access_method == NET_ACCESS );
508
509     module_t *p_module = config_FindModule( VLC_OBJECT(p_intf), "v4l" );
510     if( p_module )
511     {
512         AutoBuiltPanel *autopanel =
513             new AutoBuiltPanel( notebook, this, p_intf, p_module );
514         input_tab_array.Add( autopanel );
515         notebook->AddPage( autopanel, wxU( p_module->psz_shortname ?
516                         p_module->psz_shortname : p_module->psz_object_name ),
517                            i_access_method == CAPTURE_ACCESS );
518     }
519
520     p_module = config_FindModule( VLC_OBJECT(p_intf), "pvr" );
521     if( p_module )
522     {
523         AutoBuiltPanel *autopanel =
524             new AutoBuiltPanel( notebook, this, p_intf, p_module );
525         input_tab_array.Add( autopanel );
526         notebook->AddPage( autopanel, wxU( p_module->psz_shortname ?
527                         p_module->psz_shortname : p_module->psz_object_name ),
528                            i_access_method == CAPTURE_ACCESS );
529     }
530
531     p_module = config_FindModule( VLC_OBJECT(p_intf), "dvb" );
532     if( p_module )
533     {
534         AutoBuiltPanel *autopanel =
535             new AutoBuiltPanel( notebook, this, p_intf, p_module );
536         input_tab_array.Add( autopanel );
537         notebook->AddPage( autopanel, wxU( p_module->psz_shortname ?
538                         p_module->psz_shortname : p_module->psz_object_name ),
539                            i_access_method == CAPTURE_ACCESS );
540     }
541
542     p_module = config_FindModule( VLC_OBJECT(p_intf), "dshow" );
543     if( p_module )
544     {
545         AutoBuiltPanel *autopanel =
546             new AutoBuiltPanel( notebook, this, p_intf, p_module );
547         input_tab_array.Add( autopanel );
548         notebook->AddPage( autopanel, wxU( p_module->psz_shortname ?
549                         p_module->psz_shortname : p_module->psz_object_name ),
550                            i_access_method == CAPTURE_ACCESS );
551     }
552
553     /* Update Disc panel */
554     wxCommandEvent dummy_event;
555     OnDiscTypeChange( dummy_event );
556
557     /* Update Net panel */
558     dummy_event.SetId( NetRadio1_Event );
559     OnNetTypeChange( dummy_event );
560
561     /* Update MRL */
562     wxNotebookEvent event( wxEVT_NULL, 0, i_access_method );
563     OnPageChange( event );
564
565     /* Place everything in sizers */
566     wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
567     button_sizer->Add( ok_button, 0, wxALL, 5 );
568     button_sizer->Add( cancel_button, 0, wxALL, 5 );
569     button_sizer->Layout();
570     wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
571     wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
572 #if (!wxCHECK_VERSION(2,5,2))
573     panel_sizer->Add( notebook_sizer, 1, wxEXPAND | wxALL, 5 );
574 #else
575     panel_sizer->Add( notebook, 1, wxEXPAND | wxALL, 5 );
576 #endif
577     panel_sizer->Add( adv_sizer, 0, wxEXPAND | wxALL, 5 );
578     panel_sizer->Add( static_line, 0, wxEXPAND | wxALL, 5 );
579     panel_sizer->Add( button_sizer, 0, wxALIGN_LEFT | wxALL, 5 );
580     panel_sizer->Layout();
581     panel->SetSizerAndFit( panel_sizer );
582     main_sizer->Add( panel, 1, wxGROW, 0 );
583     main_sizer->Layout();
584     SetSizerAndFit( main_sizer );
585 }
586
587 OpenDialog::~OpenDialog()
588 {
589     /* Clean up */
590     if( file_dialog ) delete file_dialog;
591     if( sout_dialog ) delete sout_dialog;
592     if( subsfile_dialog ) delete subsfile_dialog;
593 }
594
595 int OpenDialog::Show( int i_access_method, int i_arg )
596 {
597     notebook->SetSelection( i_access_method );
598     int i_ret = wxDialog::Show();
599     Raise();
600     SetFocus();
601     i_open_arg = i_arg;
602     return i_ret;
603 }
604
605 int OpenDialog::Show()
606 {
607     int i_ret = wxDialog::Show();
608     Raise();
609     SetFocus();
610     return i_ret;
611 }
612
613 /*****************************************************************************
614  * Private methods.
615  *****************************************************************************/
616 wxPanel *OpenDialog::FilePanel( wxWindow* parent )
617 {
618     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
619                                   wxSize(200, 200) );
620
621     wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
622
623     /* Create browse file line */
624     wxBoxSizer *file_sizer = new wxBoxSizer( wxHORIZONTAL );
625
626     file_sizer->Add( new wxStaticText( panel, -1, wxU(_("Open:") ) ), 0,
627                      wxALL | wxALIGN_CENTER_VERTICAL, 5 );
628
629     file_combo = new wxComboBox( panel, FileName_Event, wxT("") );
630     wxButton *browse_button = new wxButton( panel, FileBrowse_Event,
631                                             wxU(_("Browse...")) );
632     file_sizer->Add( file_combo, 1, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
633     file_sizer->Add( browse_button, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
634
635     /* Create Subtitles File checkox - button  */
636     wxFlexGridSizer *subtitles_sizer = new wxFlexGridSizer( 2, 1, 20 );
637     subsfile_checkbox = new wxCheckBox( panel, SubsFileEnable_Event,
638                                         wxU(_("Use a subtitles file")) );
639     subsfile_checkbox->SetToolTip( wxU(_("Use an external subtitles file.")) );
640     subtitles_sizer->Add( subsfile_checkbox, 0,  wxALIGN_CENTER_VERTICAL |
641                           wxALL, 5 );
642     subsfile_button = new wxButton( panel, SubsFileSettings_Event,
643                                     wxU(_("Advanced Settings...")) );
644     subsfile_button->Disable();
645     subtitles_sizer->Add( subsfile_button, 1, wxALIGN_CENTER_VERTICAL |
646                            wxALL, 5 );
647
648     /* Create subtitles file line */
649     wxBoxSizer *subfile_sizer = new wxBoxSizer( wxHORIZONTAL );
650
651     char *psz_subsfile = config_GetPsz( p_intf, "sub-file" );
652     if( psz_subsfile && *psz_subsfile )
653     {
654         subsfile_checkbox->SetValue(TRUE);
655         subsfile_button->Enable();
656         subsfile_mrl.Add( wxString(wxT("sub-file=")) + wxL2U(psz_subsfile) );
657     }
658     if( !psz_subsfile )  psz_subsfile = strdup("");
659     subfile_sizer->Add( new wxStaticText( panel, -1, wxU(_("File:") ) ),
660                         0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
661     subfile_combo = new wxComboBox( panel, SubFileName_Event,
662                                     wxL2U( psz_subsfile ) );
663     if( psz_subsfile ) free( psz_subsfile );
664     subbrowse_button = new wxButton( panel, SubFileBrowse_Event,
665                                      wxU(_("Browse...")) );
666     subfile_sizer->Add( subfile_combo, 1, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
667     subfile_sizer->Add( subbrowse_button, 0, wxALL |wxALIGN_CENTER_VERTICAL, 5 );
668
669     subfile_combo->Disable();
670     subbrowse_button->Disable();
671
672     psz_subsfile = config_GetPsz( p_intf, "sub-file" );
673     if( psz_subsfile && *psz_subsfile )
674     {
675         subfile_combo->Enable();
676         subbrowse_button->Enable();
677     }
678
679     sizer->Add( file_sizer, 0, wxEXPAND | wxALL, 5 );
680     sizer->Add( subtitles_sizer, 0, wxLEFT | wxRIGHT | wxTOP, 5 );
681     sizer->Add( subfile_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT| wxBOTTOM, 5 );
682     panel->SetSizerAndFit( sizer );
683     return panel;
684 }
685
686 wxPanel *OpenDialog::DiscPanel( wxWindow* parent )
687 {
688     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
689                                   wxSize(200, 200) );
690
691     wxBoxSizer *sizer_row = new wxBoxSizer( wxVERTICAL );
692     wxFlexGridSizer *sizer = new wxFlexGridSizer( 2, 3, 20 );
693
694     static const wxString disc_type_array[] =
695     {
696         wxU(_("DVD (menus)")),
697         wxU(_("DVD")),
698         wxU(_("VCD")),
699         wxU(_("Audio CD")),
700     };
701
702     disc_type = new wxRadioBox( panel, DiscType_Event, wxU(_("Disc type")),
703                                 wxDefaultPosition, wxDefaultSize,
704                                 WXSIZEOF(disc_type_array), disc_type_array,
705                                 WXSIZEOF(disc_type_array), wxRA_SPECIFY_COLS );
706
707 #ifdef HAVE_LIBCDIO
708     disc_probe = new wxCheckBox( panel, DiscProbe_Event,
709                                  wxU(_("Probe Disc(s)")) );
710     disc_probe->SetToolTip( wxU(_("Probe for a DVD, VCD or audio CD. "
711 "First try the Device name entered for the selected Disc type "
712 "(DVD, DVD Menu, VCD, audio CD). If that doesn't find media, try any device "
713 "for the Disc type.  If that doesn't work, then try looking for CD-ROMs or "
714 "DVD drives. The Disc type, Device name, and some parameter ranges are set "
715 "based on media we find.")) );
716 #endif
717
718     sizer_row->Add( disc_type, i_disc_type_selection, wxEXPAND | wxALL, 5 );
719 #ifdef HAVE_LIBCDIO
720     sizer_row->Add( disc_probe, 0, wxEXPAND | wxALL );
721 #endif
722
723     wxStaticText *label = new wxStaticText( panel, -1, wxU(_("Device name")) );
724     disc_device = new wxTextCtrl( panel, DiscDevice_Event, wxT(""),
725                                   wxDefaultPosition, wxDefaultSize,
726                                   wxTE_PROCESS_ENTER);
727
728 #ifdef WIN32
729     char psz_default_device[3] = {0};
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
747     if( strlen(psz_default_device) > 0 )
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(_("Name of DVD device "
925             "to read from.")) );
926             if( i_disc_type_selection == 0 )
927             {
928                 mrltemp = wxT("dvd://") + disc_device->GetValue();
929                 caching_name = wxT("dvdnav-caching");
930             }
931             else
932             {
933                 mrltemp = wxT("dvdsimple://") + disc_device->GetValue();
934                 caching_name = wxT("dvdread-caching");
935             }
936
937             if( i_disc_title > 0 )
938             {
939                 mrltemp += wxString::Format( wxT("@%d"), i_disc_title );
940
941                 if( i_disc_chapter > 0 )
942                     mrltemp += wxString::Format( wxT(":%d"), i_disc_chapter );
943             }
944
945             if( i_disc_sub >= 0 )
946                 mrltemp += wxString::Format( wxT("  :sub-track=%d"),
947                                              i_disc_sub );
948             if( i_disc_audio >= 0 )
949                 mrltemp += wxString::Format( wxT("  :audio-track=%d"),
950                                              i_disc_audio );
951             break;
952
953         case 2:  /* VCD of some sort */
954 #ifdef HAVE_VCDX
955             disc_device->SetToolTip( wxU(_("Name of CD-ROM device "
956             "to read Video CD from. If this field is left empty, we will scan "
957             "for a CD-ROM with a VCD in it.")) );
958             mrltemp = wxT("vcdx://") + disc_device->GetValue();
959             if( i_disc_title > 0 )
960                 mrltemp += wxString::Format( wxT("@%c%d"),
961                                   config_GetInt( p_intf, "vcdx-PBC"  )
962                                   ? 'P' : 'E', i_disc_title );
963 #else
964             disc_device->SetToolTip( wxU(_("Name of CD-ROM device "
965             "to read Video CD from.")) );
966             mrltemp = wxT("vcd://") + disc_device->GetValue();
967             if( i_disc_title > 0 )
968                 mrltemp += wxString::Format( wxT("@%d"), i_disc_title );
969 #endif
970
971             if( i_disc_sub >= 0 )
972                 mrltemp += wxString::Format( wxT("  :sub-track=%d"),
973                                              i_disc_sub );
974
975             if( i_disc_audio >= 0 )
976                 mrltemp += wxString::Format( wxT("  :audio-track=%d"),
977                                              i_disc_audio );
978             caching_name = wxT("vcd-caching");
979             break;
980
981         case 3: /* CD-DA */
982 #ifdef HAVE_CDDAX
983             disc_device->SetToolTip( wxU(_("Name of CD-ROM device "
984             "to read audio CD from. If this field is left empty, we will scan "
985             "for a CD-ROM with an audio CD in it." )) );
986             mrltemp = wxT("cddax://")
987 #else
988             disc_device->SetToolTip( wxU(_("Name of CD-ROM device "
989             "to read audio CD from." )) );
990             mrltemp = wxT("cdda://")
991 #endif
992               + disc_device->GetValue();
993             if( i_disc_title > 0 )
994                 mrltemp += wxString::Format( wxT("@%d"), i_disc_title );
995
996             caching_name = wxT("cdda-caching");
997             break;
998
999         default:
1000             msg_Err( p_intf, "invalid selection (%d)",
1001                      disc_type->GetSelection() );
1002         }
1003
1004         break;
1005
1006     case NET_ACCESS:
1007         switch( i_net_type )
1008         {
1009         case 0:
1010             mrltemp = wxT("udp://@");
1011             if ( net_ipv6->GetValue() )
1012             {
1013                 mrltemp += wxT("[::]");
1014             }
1015             if( i_net_ports[0] !=
1016                 config_GetInt( p_intf, "server-port" ) )
1017             {
1018                 mrltemp += wxString::Format( wxT(":%d"), i_net_ports[0] );
1019             }
1020
1021             caching_name = wxT("udp-caching");
1022             break;
1023
1024         case 1:
1025             mrltemp = wxT("udp://@");
1026             if ((net_addrs[1]->GetLineText(0).Find (':') != -1)
1027                 && (net_addrs[1]->GetLineText(0)[0u] != '['))
1028             {
1029                 /* automatically adds '[' and ']' to IPv6 addresses */
1030                 mrltemp += wxT("[") + net_addrs[1]->GetLineText(0)
1031                          + wxT("]");
1032             }
1033             else
1034             {
1035                 mrltemp += net_addrs[1]->GetLineText(0);
1036             }
1037             if( i_net_ports[1] != config_GetInt( p_intf, "server-port" ) )
1038             {
1039                 mrltemp += wxString::Format( wxT(":%d"), i_net_ports[1] );
1040             }
1041
1042             caching_name = wxT("udp-caching");
1043             break;
1044
1045         case 2:
1046             /* http access */
1047             if( net_addrs[2]->GetLineText(0).Find(wxT("://")) == -1 )
1048                 mrltemp = wxT("http://");
1049
1050             mrltemp += net_addrs[2]->GetLineText(0);
1051
1052             caching_name = wxT("http-caching");
1053             break;
1054
1055         case 3:
1056             /* RTSP access */
1057             if( net_addrs[3]->GetLineText(0).Find(wxT("rtsp://")) != 0 )
1058             {
1059                 mrltemp = wxT("rtsp://");
1060             }
1061             mrltemp += net_addrs[3]->GetLineText(0);
1062
1063             caching_name = wxT("rtsp-caching");
1064             break;
1065         }
1066         if( net_timeshift->IsEnabled() && net_timeshift->IsChecked() )
1067             mrltemp += wxT(" :access-filter=timeshift");
1068         break;
1069
1070     default:
1071         {
1072             int i_item = i_access_method - MAX_ACCESS;
1073
1074             if( i_item < 0 || i_item >= (int)input_tab_array.GetCount() )
1075                 break;
1076
1077             AutoBuiltPanel *input_panel = input_tab_array.Item( i_item );
1078
1079             mrltemp = input_panel->name + wxT("://");
1080
1081             for( int i=0; i < (int)input_panel->config_array.GetCount(); i++ )
1082             {
1083                 ConfigControl *control = input_panel->config_array.Item(i);
1084
1085                 mrltemp += wxT(" :");
1086
1087                 if( control->GetType() == CONFIG_ITEM_BOOL &&
1088                     !control->GetIntValue() ) mrltemp += wxT("no-");
1089
1090                 mrltemp += control->GetName();
1091
1092                 switch( control->GetType() )
1093                 {
1094                 case CONFIG_ITEM_STRING:
1095                 case CONFIG_ITEM_FILE:
1096                 case CONFIG_ITEM_DIRECTORY:
1097                 case CONFIG_ITEM_MODULE:
1098                     mrltemp += wxT("=\"") + control->GetPszValue() + wxT("\"");
1099                     break;
1100                 case CONFIG_ITEM_INTEGER:
1101                     mrltemp +=
1102                         wxString::Format( wxT("=%i"), control->GetIntValue() );
1103                     break;
1104                 case CONFIG_ITEM_FLOAT:
1105                     mrltemp +=
1106                         wxString::Format(wxT("=%f"), control->GetFloatValue());
1107                     break;
1108                 }
1109             }
1110
1111             if( input_panel->p_advanced_mrl_combo &&
1112                 input_panel->p_advanced_mrl_combo->GetValue() )
1113             {
1114                 mrltemp += wxT(" ") +
1115                     input_panel->p_advanced_mrl_combo->GetValue();
1116             }
1117         }
1118         break;
1119     }
1120
1121     if( caching_name.size() )
1122     {
1123         if( caching_value->IsEnabled() )
1124         {
1125             mrltemp += wxT("  :") + caching_name +
1126                 wxString::Format( wxT("=%d"), i_caching );
1127         }
1128         else
1129         {
1130             int i_value = config_GetInt( p_intf, caching_name.mb_str() );
1131             caching_value->SetValue( i_value );
1132         }
1133     }
1134
1135     mrl_combo->SetValue( mrltemp );
1136 }
1137
1138 /*****************************************************************************
1139  * Events methods.
1140  *****************************************************************************/
1141 void OpenDialog::OnOk( wxCommandEvent& WXUNUSED(event) )
1142 {
1143     mrl = SeparateEntries( mrl_combo->GetValue() );
1144     mrl_combo->Append( mrl_combo->GetValue() );
1145     if( mrl_combo->GetCount() > 10 ) mrl_combo->Delete( 0 );
1146     mrl_combo->SetSelection( mrl_combo->GetCount() - 1 );
1147
1148     if( i_method == OPEN_STREAM )
1149     {
1150         if( IsModal() ) EndModal( wxID_OK );
1151         Hide();
1152         return;
1153     }
1154
1155     /* Update the playlist */
1156     playlist_t *p_playlist =
1157         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
1158                                        FIND_ANYWHERE );
1159     if( p_playlist == NULL ) return;
1160
1161     for( int i = 0; i < (int)mrl.GetCount(); i++ )
1162     {
1163         vlc_bool_t b_start = !i && i_open_arg;
1164         playlist_item_t *p_item;
1165         char *psz_utf8;
1166
1167         psz_utf8 = wxFromLocale( mrl[i] );
1168         p_item = playlist_ItemNew( p_intf, psz_utf8, psz_utf8 );
1169         wxLocaleFree( psz_utf8 );
1170
1171         /* Insert options */
1172         while( i + 1 < (int)mrl.GetCount() &&
1173                ((const char *)mrl[i + 1].mb_str())[0] == ':' )
1174         {
1175             psz_utf8 = wxFromLocale( mrl[i + 1] );
1176             playlist_ItemAddOption( p_item, psz_utf8 );
1177             wxLocaleFree( psz_utf8 );
1178             i++;
1179         }
1180
1181         /* Get the options from the subtitles dialog */
1182         if( subsfile_checkbox->IsChecked() && subsfile_mrl.GetCount() )
1183         {
1184             for( int j = 0; j < (int)subsfile_mrl.GetCount(); j++ )
1185             {
1186                 psz_utf8 = wxFromLocale( subsfile_mrl[j] );
1187                 playlist_ItemAddOption( p_item, psz_utf8 );
1188                 wxLocaleFree( psz_utf8 );
1189             }
1190         }
1191
1192         /* Get the options from the stream output dialog */
1193         if( sout_checkbox->IsChecked() && sout_mrl.GetCount() )
1194         {
1195             for( int j = 0; j < (int)sout_mrl.GetCount(); j++ )
1196             {
1197                 psz_utf8 = wxFromLocale( sout_mrl[j] );
1198                 playlist_ItemAddOption( p_item, psz_utf8 );
1199                 wxLocaleFree( psz_utf8 );
1200             }
1201         }
1202
1203         playlist_AddItem( p_playlist, p_item, PLAYLIST_APPEND, PLAYLIST_END );
1204
1205         if( b_start )
1206         {
1207             playlist_Control( p_playlist, PLAYLIST_ITEMPLAY, p_item );
1208         }
1209     }
1210
1211     vlc_object_release( p_playlist );
1212
1213     Hide();
1214
1215     if( IsModal() ) EndModal( wxID_OK );
1216 }
1217
1218 void OpenDialog::OnCancel( wxCommandEvent& WXUNUSED(event) )
1219 {
1220     wxCloseEvent cevent;
1221     OnClose(cevent);
1222 }
1223
1224 void OpenDialog::OnClose( wxCloseEvent& WXUNUSED(event) )
1225 {
1226     Hide();
1227
1228     if( IsModal() ) EndModal( wxID_CANCEL );
1229 }
1230
1231 void OpenDialog::OnPageChange( wxNotebookEvent& event )
1232 {
1233     UpdateMRL( event.GetSelection() );
1234 }
1235
1236 void OpenDialog::OnMRLChange( wxCommandEvent& event )
1237 {
1238     //mrl = SeparateEntries( event.GetString() );
1239 }
1240
1241 /*****************************************************************************
1242  * File panel event methods.
1243  *****************************************************************************/
1244 void OpenDialog::OnFilePanelChange( wxCommandEvent& WXUNUSED(event) )
1245 {
1246     UpdateMRL( FILE_ACCESS );
1247 }
1248
1249 void OpenDialog::OnFileBrowse( wxCommandEvent& WXUNUSED(event) )
1250 {
1251     if( file_dialog == NULL )
1252         file_dialog = new wxFileDialog( this, wxU(_("Open File")),
1253             wxT(""), wxT(""), wxT("*"), wxOPEN | wxMULTIPLE );
1254
1255     if( file_dialog && file_dialog->ShowModal() == wxID_OK )
1256     {
1257         wxArrayString paths;
1258         wxString path;
1259
1260         file_dialog->GetPaths( paths );
1261
1262         for( size_t i = 0; i < paths.GetCount(); i++ )
1263         {
1264             if( paths[i].Find( wxT(' ') ) >= 0 )
1265                 path += wxT("\"") + paths[i] + wxT("\" ");
1266             else
1267                 path += paths[i] + wxT(" ");
1268         }
1269
1270         file_combo->SetValue( path );
1271         file_combo->Append( path );
1272         if( file_combo->GetCount() > 10 ) file_combo->Delete( 0 );
1273         UpdateMRL( FILE_ACCESS );
1274     }
1275 }
1276
1277 void OpenDialog::OnSubFileBrowse( wxCommandEvent& WXUNUSED(event) )
1278 {
1279     wxFileDialog dialog( this, wxU(_("Open subtitles file")),
1280                          wxT(""), wxT(""), wxT("*"), wxOPEN );
1281
1282     if( dialog.ShowModal() == wxID_OK )
1283     {
1284         subfile_combo->SetValue( dialog.GetPath() );
1285     }
1286     wxCommandEvent event; OnSubFileChange( event );
1287 }
1288
1289 void OpenDialog::OnSubFileChange( wxCommandEvent& WXUNUSED(event) )
1290 {
1291     if( subsfile_mrl.GetCount() != 0 )
1292     {
1293         subsfile_mrl.RemoveAt( 0 );
1294         subsfile_mrl.Insert( wxString(wxT("sub-file=")) + subfile_combo->GetValue() , 0 );
1295     }
1296     else
1297     {
1298         subsfile_mrl.Add( wxString(wxT("sub-file=")) + subfile_combo->GetValue() );
1299     }
1300 }
1301
1302 /*****************************************************************************
1303  * Disc panel event methods.
1304  *****************************************************************************/
1305 void OpenDialog::OnDiscPanelChangeSpin( wxSpinEvent& event )
1306 {
1307     wxCommandEvent cevent;
1308     cevent.SetId(event.GetId());
1309     cevent.SetInt(event.GetPosition());
1310     OnDiscPanelChange(cevent);
1311 }
1312
1313 void OpenDialog::OnDiscPanelChange( wxCommandEvent& event )
1314 {
1315     if( event.GetId() == DiscTitle_Event ) i_disc_title = event.GetInt();
1316     if( event.GetId() == DiscChapter_Event ) i_disc_chapter = event.GetInt();
1317     if( event.GetId() == DiscSub_Event ) i_disc_sub = event.GetInt();
1318     if( event.GetId() == DiscAudio_Event ) i_disc_audio = event.GetInt();
1319
1320     UpdateMRL( DISC_ACCESS );
1321 }
1322
1323 void OpenDialog::OnDiscDeviceChange( wxCommandEvent& event )
1324 {
1325     char *psz_device;
1326
1327     switch( disc_type->GetSelection() )
1328     {
1329         case 3:
1330             psz_device = config_GetPsz( p_intf, "cd-audio" );
1331             break;
1332
1333         case 2:
1334             psz_device = config_GetPsz( p_intf, "vcd" );
1335             break;
1336
1337         default:
1338             psz_device = config_GetPsz( p_intf, "dvd" );
1339             break;
1340     }
1341
1342     if ( !psz_device ) psz_device = "";
1343
1344     if( disc_device->GetValue().Cmp( wxL2U( psz_device ) ) )
1345     {
1346         b_disc_device_changed = true;
1347     }
1348
1349     UpdateMRL( DISC_ACCESS );
1350 }
1351
1352 #ifdef HAVE_LIBCDIO
1353
1354 /* Return true if *psz_drive is a drive with a DVD in it. A more complete
1355    check would see if the media looks like a *playable* DVD. This should
1356    go into libcdio.
1357  */
1358 static bool IsDVD(const char *psz_drive)
1359 {
1360   CdIo_t *p_cdio = cdio_open (psz_drive, DRIVER_UNKNOWN);
1361   if (p_cdio)
1362   {
1363       discmode_t discmode = cdio_get_discmode(p_cdio);
1364       cdio_destroy(p_cdio);
1365       return cdio_is_discmode_dvd(discmode);
1366   }
1367   return false;
1368 }
1369
1370
1371 /* Return a device that has a DVD in it. The caller needs to free
1372    the returned string.
1373 */
1374 static char * ProbeDVD(const wxChar *device)
1375 {
1376         /*
1377   char **ppsz_cd_drives;
1378   const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(device);
1379   char *psz_device = (char *) tmp_buf;
1380
1381   if( IsDVD(psz_device) )
1382   {
1383       return strdup(psz_device);
1384   }
1385
1386   ppsz_cd_drives = cdio_get_devices(DRIVER_DEVICE);
1387   if( ppsz_cd_drives )
1388   {
1389       char **c;
1390       for( c = ppsz_cd_drives; *c != NULL; c++ )
1391       {
1392       if( IsDVD(*c) )
1393       {
1394           char *psz_drive = strdup(*c);
1395           cdio_free_device_list(ppsz_cd_drives);
1396           return strdup(psz_drive);
1397           }
1398       }
1399       cdio_free_device_list(ppsz_cd_drives);
1400   }*/
1401   return NULL;
1402 }
1403
1404
1405 static char * ProbeDevice(char **ppsz_search_devices, cdio_fs_anal_t mask,
1406               bool b_any)
1407 {
1408     char **ppsz_devices;
1409
1410     if( ppsz_search_devices && !ppsz_search_devices[0] )
1411         ppsz_search_devices = NULL;
1412
1413     /* Start out trying the device that has been entered so far. */
1414     ppsz_devices = cdio_get_devices_with_cap(ppsz_search_devices, mask,
1415                          b_any);
1416
1417     if (ppsz_devices && *ppsz_devices)
1418     {
1419         char *psz_device = strdup(*ppsz_devices);
1420         cdio_free_device_list(ppsz_devices);
1421         return psz_device;
1422     }
1423
1424     /* If there was no device specified on the first try, then give up
1425        now. Otherwise accept any CD-ROM in the class (e.g. VCD or DVD).
1426     */
1427     if( !ppsz_search_devices ) return NULL;
1428
1429     ppsz_devices = cdio_get_devices_with_cap(NULL, mask, true);
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     return NULL;
1439 }
1440
1441
1442 /* Return a device that has a CD-DA in it. The caller needs to free
1443    the returned string.
1444 */
1445 static char * ProbeCDDA(const wxChar *device)
1446 {
1447         /*
1448    char *ppsz_device[2];
1449    const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(device);
1450    char *psz_device = (char *) tmp_buf;
1451    ppsz_device[0] = (device && *device) ? psz_device : NULL;
1452    ppsz_device[1] = NULL;
1453    return ProbeDevice(ppsz_device, CDIO_FS_AUDIO, false);
1454    */ return NULL;
1455 }
1456
1457 /* Return a device that has a VCD in it. The caller needs to free
1458    the returned string.
1459 */
1460 static char * ProbeVCD(const wxChar *device)
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,
1468                       (CDIO_FS_ANAL_SVCD|CDIO_FS_ANAL_CVD|CDIO_FS_ANAL_VIDEOCD
1469                        |CDIO_FS_UNKNOWN), true);
1470                        */ return NULL;
1471 }
1472
1473
1474 /*
1475    Probe (find anywhere) a CD-DA, VCD, or a DVD.
1476    First try the device name that may have been entered for the "disc type"
1477    selected. If that doesn't work we try any device for the disc type.
1478    If that doesn't work, try looking for CD-ROMs or DVD drives. the
1479    disc type, device name and paramter ranges are set to whatever we find.
1480 */
1481 void OpenDialog::OnDiscProbe( wxCommandEvent& WXUNUSED(event) )
1482 {
1483     wxCommandEvent dummy_event;
1484     char *psz_device = NULL;
1485     bool b_probed_DVD = false;
1486     bool b_probed_VCD = false;
1487     const int i_selection = disc_type->GetSelection();
1488
1489     /* Reduce verbosity of cdio errors. */
1490     cdio_loglevel_default = CDIO_LOG_ERROR;
1491
1492  retry:
1493     switch( disc_type->GetSelection() )
1494     {
1495
1496     case SELECTION_DISC_TYPE_DVD_MENUS:
1497     case SELECTION_DISC_TYPE_DVD:
1498       /* If not a DVD then try for a VCD. If VCD fails it will
1499          try for a CD-DA. */
1500       if (!psz_device) psz_device = ProbeDVD(disc_device->GetValue());
1501       if (!psz_device)
1502       {
1503           b_probed_DVD = true;
1504           disc_type->SetSelection(SELECTION_DISC_TYPE_VCD);
1505           OnDiscTypeChange( dummy_event );
1506           goto retry;
1507       }
1508       disc_device->SetValue( wxL2U(psz_device) );
1509       break;
1510
1511     case SELECTION_DISC_TYPE_VCD:  /* VCD probe of some sort */
1512       if(!psz_device) psz_device = ProbeVCD(disc_device->GetValue());
1513       if( psz_device  )
1514       {
1515 #ifdef HAVE_VCDX
1516 #if LIBVCD_VERSION_NUM > 23
1517       vcdinfo_obj_t *p_vcdinfo;
1518
1519           /* Set LID or entry range accurately if possible. */
1520       if( vcdinfo_open(&p_vcdinfo, &psz_device, DRIVER_DEVICE,
1521                 NULL) == VCDINFO_OPEN_VCD)
1522       {
1523           if (config_GetInt( p_intf, "vcdx-PBC"  ))
1524           {
1525           /* Set largest LID. */;
1526           disc_title->SetRange( 0, vcdinfo_get_num_LIDs(p_vcdinfo) );
1527
1528           }
1529           else
1530           {
1531           /* Set largest Entry */
1532           disc_title->SetRange( 0,
1533                     vcdinfo_get_num_entries(p_vcdinfo)-1 );
1534           }
1535           vcdinfo_close(p_vcdinfo);
1536       }
1537 #endif /* LIBVCD_VERSION_NUM > 23 */
1538           disc_device->SetValue( wxL2U(psz_device) );
1539 #else
1540           CdIo_t *p_cdio = cdio_open (psz_device, DRIVER_UNKNOWN);
1541           disc_device->SetValue( wxL2U(psz_device) );
1542
1543           /* Set track range accurately if possible. */
1544           if (p_cdio)
1545           {
1546               track_t i_last_track = cdio_get_last_track_num(p_cdio);
1547               disc_title->SetRange( 0, i_last_track-1 );
1548           }
1549           cdio_destroy(p_cdio);
1550 #endif
1551           break;
1552       }
1553
1554       b_probed_VCD = true;
1555
1556       /* Not a VCD. Try for a DVD unless we've been there before. */
1557       if( !b_probed_DVD && (psz_device = ProbeDVD(disc_device->GetValue())) )
1558       {
1559           disc_type->SetSelection(SELECTION_DISC_TYPE_DVD_MENUS);
1560           OnDiscTypeChange( dummy_event );
1561           goto retry;
1562       }
1563       b_probed_DVD = true;
1564
1565       /* Couldn't find a VCD or DVD. See if we can find a CD-DA. */
1566       psz_device = ProbeCDDA(disc_device->GetValue());
1567       if( psz_device  )
1568       {
1569           disc_type->SetSelection(SELECTION_DISC_TYPE_CDDA);
1570           OnDiscTypeChange( dummy_event );
1571           goto retry;
1572       }
1573
1574       /* Couldn't find a VCD, DVD or CD-DA. Null out the Device name and
1575      set to original selection.
1576        */
1577       disc_device->SetValue( wxL2U("") );
1578       disc_type->SetSelection(i_selection);
1579       OnDiscTypeChange( dummy_event );
1580       break;
1581
1582     case SELECTION_DISC_TYPE_CDDA:
1583       if(!psz_device) psz_device = ProbeCDDA(disc_device->GetValue());
1584       if( psz_device  )
1585       {
1586           CdIo_t *p_cdio = cdio_open (psz_device, DRIVER_UNKNOWN);
1587           disc_device->SetValue( wxL2U(psz_device) );
1588           if (p_cdio)
1589           {
1590               track_t i_last_track = cdio_get_last_track_num(p_cdio);
1591               disc_title->SetRange( 0, i_last_track );
1592 #if 0
1593           MediaInsertCDDA( p_intf,  p_cdio, i_last_track );
1594 #endif
1595           }
1596           cdio_destroy(p_cdio);
1597           break;
1598       }
1599
1600       /* Not a CD-DA. Try for a DVD unless we've been there before. */
1601       if( !b_probed_DVD && (psz_device = ProbeDVD(disc_device->GetValue())) )
1602       {
1603           disc_type->SetSelection(SELECTION_DISC_TYPE_DVD_MENUS);
1604           OnDiscTypeChange( dummy_event );
1605           goto retry;
1606       }
1607
1608       /* Couldn't find a CD-DA or DVD. See if we can find a VCD, unless
1609          we've tried that before. */
1610       if (!b_probed_VCD) psz_device = ProbeVCD(disc_device->GetValue());
1611       if( psz_device  )
1612       {
1613           disc_type->SetSelection(SELECTION_DISC_TYPE_VCD);
1614           OnDiscTypeChange( dummy_event );
1615           goto retry;
1616       }
1617       disc_device->SetValue( wxL2U("") );
1618       break;
1619
1620     default:
1621         msg_Err( p_intf, "invalid Disc type selection (%d)",
1622                  disc_type->GetSelection() );
1623         break;
1624     }
1625
1626     free(psz_device);
1627     disc_probe->SetValue(FALSE);
1628
1629     UpdateMRL( DISC_ACCESS );
1630 }
1631 #endif /* HAVE_LIBCDIO */
1632
1633 void OpenDialog::OnDiscTypeChange( wxCommandEvent& WXUNUSED(event) )
1634 {
1635     char *psz_device = NULL;
1636
1637     switch( disc_type->GetSelection() )
1638     {
1639
1640     case SELECTION_DISC_TYPE_DVD_MENUS:
1641     case SELECTION_DISC_TYPE_DVD:
1642         disc_sub->Enable(); disc_sub_label->Enable();
1643         disc_audio->Enable(); disc_audio_label->Enable();
1644         disc_chapter->Enable(); disc_chapter_label->Enable();
1645         disc_title_label->SetLabel ( wxU(_("Title")) );
1646         psz_device = config_GetPsz( p_intf, "dvd" );
1647         if( !b_disc_device_changed )
1648         {
1649             if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
1650             else disc_device->SetValue( wxT("") );
1651         }
1652         disc_title->SetRange( 0, 255 );
1653         disc_sub->SetRange( -1, 31 );  // up to 32 subtitles -1: no subtitle
1654         disc_audio->SetRange( 0, 7 );  // up to 8 audio channels
1655         disc_chapter->SetRange( 0, 255 );
1656         disc_title->SetToolTip( wxU(_("Title number.")) );
1657         disc_sub->SetToolTip( wxU(_(
1658           "DVD's can have up to 32 subtitles numbered 0..31. "
1659           "Note this is not the same thing as a subtitle name e.g. 'en'. "
1660           "If a value -1 is used, no subtitle will be shown." )) );
1661         disc_audio->SetToolTip( wxU(_("Audio track number. "
1662           "DVD's can have up to 8 audio tracks numbered 0..7."
1663         )) );
1664         break;
1665
1666     case SELECTION_DISC_TYPE_VCD:
1667         disc_sub->Enable(); disc_sub_label->Enable();
1668         disc_audio->Enable(); disc_audio_label->Enable();
1669         disc_chapter->Disable(); disc_chapter_label->Disable();
1670         psz_device = config_GetPsz( p_intf, "vcd" );
1671         if( !b_disc_device_changed )
1672         {
1673             if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
1674             else disc_device->SetValue( wxT("") );
1675         }
1676
1677 #ifdef HAVE_VCDX
1678         if (config_GetInt( p_intf, "vcdx-PBC"  ))
1679         {
1680           disc_title_label->SetLabel ( wxT("Playback LID") );
1681           disc_title->SetToolTip( wxU(_(
1682           "Playback control (PBC) usually starts with number 1." )) );
1683         }
1684         else
1685         {
1686           disc_title_label->SetLabel ( wxT("Entry") );
1687           disc_title->SetToolTip( wxU(_(
1688           "The first entry (the beginning of the first MPEG track) is 0." )) );
1689         }
1690
1691 #else
1692         disc_title_label->SetLabel ( wxU(_("Track")) );
1693         disc_title->SetToolTip( wxU(_("Track number.")) );
1694 #endif
1695         disc_title->SetRange( 0, 99 );  // only 100 tracks allowed on VCDs
1696         disc_sub->SetRange( -1, 3 );    // up to 4 subtitles -1 = no subtitle
1697         disc_audio->SetRange( 0, 1 );   // up to 2 audio tracks
1698         disc_sub->SetToolTip( wxU(_(
1699           "SVCD's can have up to 4 subtitles numbered 0..3. "
1700           "If a value -1 is used, no subtitle will be shown." )) );
1701         disc_audio->SetToolTip( wxU(_("Audio track number. "
1702           "VCD's can have up to 2 audio tracks numbered 0 or 1. "
1703         )) );
1704         break;
1705
1706     case SELECTION_DISC_TYPE_CDDA:
1707         disc_sub->Disable(); disc_sub_label->Disable();
1708         disc_chapter->Disable(); disc_chapter_label->Disable();
1709         disc_audio->Disable(); disc_audio_label->Disable();
1710         disc_title_label->SetLabel ( wxU(_("Track")) );
1711 #ifdef HAVE_CDDAX
1712         disc_title->SetToolTip( wxU(_(
1713         "Audio CDs can have up to 100 tracks, the first track is usually 1. "
1714         "If 0 is given, then all tracks are played.")) );
1715 #else
1716         disc_title->SetToolTip( wxU(_(
1717         "Audio CDs can have up to 100 tracks, the first track is usually 1."
1718         )) );
1719 #endif
1720         psz_device = config_GetPsz( p_intf, "cd-audio" );
1721         if( !b_disc_device_changed )
1722         {
1723             if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
1724             else disc_device->SetValue( wxT("") );
1725         }
1726
1727         /* There are at most 100 tracks in a CD-DA */
1728         disc_title->SetRange( 0, 100 );
1729         break;
1730
1731     default:
1732         msg_Err( p_intf, "invalid Disc type selection (%d)",
1733                  disc_type->GetSelection() );
1734         break;
1735     }
1736
1737     disc_title->SetValue( 0 ); i_disc_title = 0;
1738     disc_chapter->SetValue( 0 ); i_disc_chapter = 0;
1739
1740     if( psz_device ) free( psz_device );
1741
1742     UpdateMRL( DISC_ACCESS );
1743 }
1744
1745 /*****************************************************************************
1746  * Net panel event methods.
1747  *****************************************************************************/
1748 void OpenDialog::OnNetPanelChangeSpin( wxSpinEvent& event )
1749 {
1750     wxCommandEvent cevent;
1751     cevent.SetId(event.GetId());
1752     cevent.SetInt(event.GetPosition());
1753     OnNetPanelChange(cevent);
1754 }
1755
1756 void OpenDialog::OnNetPanelChange( wxCommandEvent& event )
1757 {
1758     if( event.GetId() >= NetPort1_Event && event.GetId() <= NetPort3_Event )
1759     {
1760         i_net_ports[event.GetId() - NetPort1_Event] = event.GetInt();
1761     }
1762
1763     UpdateMRL( NET_ACCESS );
1764 }
1765
1766 void OpenDialog::OnNetTypeChange( wxCommandEvent& event )
1767 {
1768     int i;
1769
1770     i_net_type = event.GetId() - NetRadio1_Event;
1771
1772     for(i=0; i<4; i++)
1773     {
1774         net_radios[i]->SetValue( event.GetId() == (NetRadio1_Event+i) );
1775         net_subpanels[i]->Enable( event.GetId() == (NetRadio1_Event+i) );
1776     }
1777     /* UDP Unicast or multicast -> timeshift */
1778     if( i_net_type == 0 || i_net_type == 1 )
1779         net_timeshift->Enable();
1780     else
1781         net_timeshift->Disable();
1782
1783     UpdateMRL( NET_ACCESS );
1784 }
1785
1786 /*****************************************************************************
1787  * Subtitles file event methods.
1788  *****************************************************************************/
1789 void OpenDialog::OnSubsFileEnable( wxCommandEvent& event )
1790 {
1791     subsfile_button->Enable( event.GetInt() != 0 );
1792     subbrowse_button->Enable( event.GetInt() != 0 );
1793     subfile_combo->Enable( event.GetInt() != 0 );
1794 }
1795
1796 void OpenDialog::OnSubsFileSettings( wxCommandEvent& WXUNUSED(event) )
1797 {
1798     /* Show/hide the open dialog */
1799     if( subsfile_dialog == NULL )
1800         subsfile_dialog = new SubsFileDialog( p_intf, this );
1801
1802     if( subsfile_dialog && subsfile_dialog->ShowModal() == wxID_OK )
1803     {
1804         subsfile_mrl.Empty();
1805         subsfile_mrl.Add( wxString(wxT("sub-file="))  + subfile_combo->GetValue() );
1806         if( subsfile_dialog->encoding_combo )
1807         {
1808             subsfile_mrl.Add( wxString(wxT("subsdec-encoding=")) +
1809                               subsfile_dialog->encoding_combo->GetValue() );
1810         }
1811         if( subsfile_dialog->align_combo )
1812         {
1813             subsfile_mrl.Add( wxString::Format(wxT("subsdec-align=%i"),
1814                               (int)subsfile_dialog->align_combo->GetClientData(
1815                               subsfile_dialog->align_combo->GetSelection()) ) );
1816         }
1817         if( subsfile_dialog->size_combo )
1818         {
1819             subsfile_mrl.Add( wxString::Format( wxT("freetype-rel-fontsize=%i"),
1820                               (int)subsfile_dialog->size_combo->GetClientData(
1821                               subsfile_dialog->size_combo->GetSelection()) ) );
1822         }
1823         subsfile_mrl.Add( wxString::Format( wxT("sub-fps=%i"),
1824                           subsfile_dialog->fps_spinctrl->GetValue() ) );
1825         subsfile_mrl.Add( wxString::Format( wxT("sub-delay=%i"),
1826                           subsfile_dialog->delay_spinctrl->GetValue() ) );
1827     }
1828 }
1829
1830 /*****************************************************************************
1831  * Stream output event methods.
1832  *****************************************************************************/
1833 void OpenDialog::OnSoutEnable( wxCommandEvent& event )
1834 {
1835     sout_button->Enable( event.GetInt() != 0 );
1836 }
1837
1838 void OpenDialog::OnSoutSettings( wxCommandEvent& WXUNUSED(event) )
1839 {
1840     /* Show/hide the open dialog */
1841     if( sout_dialog == NULL )
1842         sout_dialog = new SoutDialog( p_intf, this );
1843
1844     if( sout_dialog && sout_dialog->ShowModal() == wxID_OK )
1845     {
1846         sout_mrl = sout_dialog->GetOptions();
1847     }
1848 }
1849
1850 /*****************************************************************************
1851  * Caching event methods.
1852  *****************************************************************************/
1853 void OpenDialog::OnCachingEnable( wxCommandEvent& event )
1854 {
1855     caching_value->Enable( event.GetInt() != 0 );
1856     i_caching = caching_value->GetValue();
1857     UpdateMRL();
1858 }
1859
1860 void OpenDialog::OnCachingChangeSpin( wxSpinEvent& event )
1861 {
1862     wxCommandEvent cevent;
1863     OnCachingChange(cevent);
1864 }
1865
1866 void OpenDialog::OnCachingChange( wxCommandEvent& event )
1867 {
1868     i_caching = event.GetInt();
1869     UpdateMRL();
1870 }
1871
1872 /*****************************************************************************
1873  * Utility functions.
1874  *****************************************************************************/
1875 wxArrayString SeparateEntries( wxString entries )
1876 {
1877     vlc_bool_t b_quotes_mode = VLC_FALSE;
1878
1879     wxArrayString entries_array;
1880     wxString entry;
1881
1882     wxStringTokenizer token( entries, wxT(" \t\r\n\""), wxTOKEN_RET_DELIMS );
1883
1884     while( token.HasMoreTokens() )
1885     {
1886         entry += token.GetNextToken();
1887
1888         if( entry.IsEmpty() ) continue;
1889
1890         if( !b_quotes_mode && entry.Last() == wxT('\"') )
1891         {
1892             /* Enters quotes mode */
1893             entry.RemoveLast();
1894             b_quotes_mode = VLC_TRUE;
1895         }
1896         else if( b_quotes_mode && entry.Last() == wxT('\"') )
1897         {
1898             /* Finished the quotes mode */
1899             entry.RemoveLast();
1900             b_quotes_mode = VLC_FALSE;
1901         }
1902         else if( !b_quotes_mode && entry.Last() != wxT('\"') )
1903         {
1904             /* we found a non-quoted standalone string */
1905             if( token.HasMoreTokens() ||
1906                 entry.Last() == wxT(' ') || entry.Last() == wxT('\t') ||
1907                 entry.Last() == wxT('\r') || entry.Last() == wxT('\n') )
1908                 entry.RemoveLast();
1909             if( !entry.IsEmpty() ) entries_array.Add( entry );
1910             entry.Empty();
1911         }
1912         else
1913         {;}
1914     }
1915
1916     if( !entry.IsEmpty() ) entries_array.Add( entry );
1917
1918     return entries_array;
1919 }