]> git.sesse.net Git - vlc/blob - modules/gui/wxwindows/open.cpp
Fix UDP unicast access when both IPv6 and non-default port are used
[vlc] / modules / gui / wxwindows / open.cpp
1 /*****************************************************************************
2  * open.cpp : wxWindows plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2005 VideoLAN
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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28 #include <errno.h>                                                 /* ENOMEM */
29 #include <string.h>                                            /* strerror() */
30 #include <stdio.h>
31
32 #include <vlc/vlc.h>
33
34 #include <wx/combobox.h>
35 #include <wx/statline.h>
36 #include <wx/tokenzr.h>
37
38 #include <vlc/intf.h>
39
40 #include <vector>
41
42 #include "wxwindows.h"
43 #include "preferences_widgets.h"
44
45 #ifndef wxRB_SINGLE
46 #   define wxRB_SINGLE 0
47 #endif
48
49 /*****************************************************************************
50  * Event Table.
51  *****************************************************************************/
52
53 /* IDs for the controls and the menu commands */
54 enum
55 {
56     Notebook_Event = wxID_HIGHEST,
57     MRL_Event,
58
59     FileBrowse_Event,
60     FileName_Event,
61
62     DiscType_Event,
63     DiscDevice_Event,
64     DiscTitle_Event,
65     DiscChapter_Event,
66     DiscSub_Event,
67
68     NetType_Event,
69     NetRadio1_Event, NetRadio2_Event, NetRadio3_Event, NetRadio4_Event,
70     NetPort1_Event, NetPort2_Event, NetPort3_Event,
71     NetAddr1_Event, NetAddr2_Event, NetAddr3_Event, NetAddr4_Event,
72     NetForceIPv6_Event,
73
74     SubsFileEnable_Event,
75     SubsFileSettings_Event,
76
77     SoutEnable_Event,
78     SoutSettings_Event,
79
80     CachingEnable_Event,
81     CachingChange_Event,
82
83     AdvancedOptions_Event
84 };
85
86 BEGIN_EVENT_TABLE(OpenDialog, wxDialog)
87     /* Button events */
88     EVT_BUTTON(wxID_OK, OpenDialog::OnOk)
89     EVT_BUTTON(wxID_CANCEL, OpenDialog::OnCancel)
90
91     EVT_NOTEBOOK_PAGE_CHANGED(Notebook_Event, OpenDialog::OnPageChange)
92
93     EVT_TEXT(MRL_Event, OpenDialog::OnMRLChange)
94
95     /* Events generated by the file panel */
96     EVT_TEXT(FileName_Event, OpenDialog::OnFilePanelChange)
97     EVT_BUTTON(FileBrowse_Event, OpenDialog::OnFileBrowse)
98
99     /* Events generated by the disc panel */
100     EVT_RADIOBOX(DiscType_Event, OpenDialog::OnDiscTypeChange)
101     EVT_TEXT(DiscDevice_Event, OpenDialog::OnDiscDeviceChange)
102     EVT_TEXT(DiscDevice_Event, OpenDialog::OnDiscPanelChange)
103     EVT_TEXT(DiscTitle_Event, OpenDialog::OnDiscPanelChange)
104     EVT_SPINCTRL(DiscTitle_Event, OpenDialog::OnDiscPanelChange)
105     EVT_TEXT(DiscChapter_Event, OpenDialog::OnDiscPanelChange)
106     EVT_SPINCTRL(DiscChapter_Event, OpenDialog::OnDiscPanelChange)
107     EVT_TEXT(DiscSub_Event, OpenDialog::OnDiscPanelChange)
108     EVT_SPINCTRL(DiscSub_Event, OpenDialog::OnDiscPanelChange)
109
110     /* Events generated by the net panel */
111     EVT_RADIOBUTTON(NetRadio1_Event, OpenDialog::OnNetTypeChange)
112     EVT_RADIOBUTTON(NetRadio2_Event, OpenDialog::OnNetTypeChange)
113     EVT_RADIOBUTTON(NetRadio3_Event, OpenDialog::OnNetTypeChange)
114     EVT_RADIOBUTTON(NetRadio4_Event, OpenDialog::OnNetTypeChange)
115     EVT_TEXT(NetPort1_Event, OpenDialog::OnNetPanelChange)
116     EVT_SPINCTRL(NetPort1_Event, OpenDialog::OnNetPanelChange)
117     EVT_TEXT(NetPort2_Event, OpenDialog::OnNetPanelChange)
118     EVT_SPINCTRL(NetPort2_Event, OpenDialog::OnNetPanelChange)
119     EVT_TEXT(NetPort3_Event, OpenDialog::OnNetPanelChange)
120     EVT_SPINCTRL(NetPort3_Event, OpenDialog::OnNetPanelChange)
121     EVT_TEXT(NetAddr2_Event, OpenDialog::OnNetPanelChange)
122     EVT_TEXT(NetAddr3_Event, OpenDialog::OnNetPanelChange)
123     EVT_TEXT(NetAddr4_Event, OpenDialog::OnNetPanelChange)
124     EVT_CHECKBOX(NetForceIPv6_Event, OpenDialog::OnNetPanelChange)
125
126     /* Events generated by the subtitle file buttons */
127     EVT_CHECKBOX(SubsFileEnable_Event, OpenDialog::OnSubsFileEnable)
128     EVT_BUTTON(SubsFileSettings_Event, OpenDialog::OnSubsFileSettings)
129
130     /* Events generated by the stream output buttons */
131     EVT_CHECKBOX(SoutEnable_Event, OpenDialog::OnSoutEnable)
132     EVT_BUTTON(SoutSettings_Event, OpenDialog::OnSoutSettings)
133
134     /* Events generated by the caching button */
135     EVT_CHECKBOX(CachingEnable_Event, OpenDialog::OnCachingEnable)
136     EVT_TEXT(CachingChange_Event, OpenDialog::OnCachingChange)
137     EVT_SPINCTRL(CachingChange_Event, OpenDialog::OnCachingChange)
138
139     /* Hide the window when the user closes the window */
140     EVT_CLOSE(OpenDialog::OnCancel)
141
142 END_EVENT_TABLE()
143
144 /*****************************************************************************
145  * AutoBuiltPanel.
146  *****************************************************************************/
147 WX_DEFINE_ARRAY(ConfigControl *, ArrayOfConfigControls);
148
149 class AutoBuiltPanel : public wxPanel
150 {
151 public:
152
153     AutoBuiltPanel() { }
154     AutoBuiltPanel( wxWindow *, OpenDialog *, intf_thread_t *,
155                     const module_t * );
156
157     virtual ~AutoBuiltPanel() {}
158
159     void UpdateAdvancedMRL();
160
161     wxString name;
162     ArrayOfConfigControls config_array;
163     ArrayOfConfigControls advanced_config_array;
164     wxComboBox *p_advanced_mrl_combo;
165
166 private:
167     intf_thread_t *p_intf;
168     OpenDialog *p_open_dialog;
169
170     void OnAdvanced( wxCommandEvent& event );
171     wxDialog *p_advanced_dialog;
172
173     DECLARE_EVENT_TABLE();
174 };
175
176 BEGIN_EVENT_TABLE(AutoBuiltPanel, wxPanel)
177     EVT_BUTTON(AdvancedOptions_Event, AutoBuiltPanel::OnAdvanced)
178 END_EVENT_TABLE()
179
180 static void AutoBuildCallback( void *p_data )
181 {
182     ((OpenDialog *)p_data)->UpdateMRL();
183 }
184
185 static void AutoBuildAdvancedCallback( void *p_data )
186 {
187     ((AutoBuiltPanel *)p_data)->UpdateAdvancedMRL();
188 }
189
190 AutoBuiltPanel::AutoBuiltPanel( wxWindow *parent, OpenDialog *dialog,
191                                 intf_thread_t *_p_intf,
192                                 const module_t *p_module )
193   : wxPanel( parent, -1, wxDefaultPosition, wxDefaultSize ),
194     name( wxU(p_module->psz_object_name) ),
195     p_advanced_mrl_combo( NULL ),
196     p_intf( _p_intf ), p_open_dialog( dialog ), p_advanced_dialog( NULL )
197 {
198     wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
199     module_config_t *p_item = p_module->p_config;
200     bool b_advanced = false;
201
202     if( p_item ) do
203     {
204         if( !(p_item->i_type & CONFIG_HINT) && p_item->b_advanced )
205             b_advanced = true;
206
207         if( p_item->i_type & CONFIG_HINT || p_item->b_advanced )
208             continue;
209
210         ConfigControl *control =
211             CreateConfigControl( VLC_OBJECT(p_intf), p_item, this );
212
213         config_array.Add( control );
214
215         /* Don't add items that were not recognized */
216         if( control == NULL ) continue;
217
218         control->SetUpdateCallback( AutoBuildCallback, (void *)dialog );
219
220         sizer->Add( control, 0, wxEXPAND | wxALL, 2 );
221     }
222     while( p_item->i_type != CONFIG_HINT_END && p_item++ );
223
224     if( b_advanced )
225     {
226         wxButton *button =
227             new wxButton( this, AdvancedOptions_Event,
228                           wxU(_("Advanced options...")) );
229         sizer->Add( button, 0, wxALL, 5 );
230
231         /* Build the advanced dialog */
232         p_advanced_dialog =
233             new wxDialog( this, -1, ((wxString)wxU(_("Advanced options"))) +
234                           wxT(" (") + wxU( p_module->psz_longname ) + wxT(")"),
235                           wxDefaultPosition, wxDefaultSize,
236                           wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER );
237
238         wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
239
240         /* Create MRL combobox */
241         wxBoxSizer *mrl_sizer_sizer = new wxBoxSizer( wxHORIZONTAL );
242         wxStaticBox *mrl_box =
243             new wxStaticBox( p_advanced_dialog, -1,
244                              wxU(_("Advanced options")) );
245         wxStaticBoxSizer *mrl_sizer =
246             new wxStaticBoxSizer( mrl_box, wxHORIZONTAL );
247         wxStaticText *mrl_label =
248             new wxStaticText( p_advanced_dialog, -1, wxU(_("Options:")) );
249         p_advanced_mrl_combo =
250             new wxComboBox( p_advanced_dialog, MRL_Event, wxT(""),
251                             wxDefaultPosition, wxDefaultSize );
252         mrl_sizer->Add( mrl_label, 0, wxALL | wxALIGN_CENTER, 5 );
253         mrl_sizer->Add( p_advanced_mrl_combo, 1, wxALL | wxALIGN_CENTER, 5 );
254         mrl_sizer_sizer->Add( mrl_sizer, 1, wxEXPAND | wxALL, 5 );
255         sizer->Add( mrl_sizer_sizer, 0, wxEXPAND | wxALL, 2 );
256
257         /* Add advanced options to panel */
258         module_config_t *p_item = p_module->p_config;
259         if( p_item ) do
260         {
261             if( p_item->i_type & CONFIG_HINT || !p_item->b_advanced )
262                 continue;
263
264             ConfigControl *control =
265                 CreateConfigControl( VLC_OBJECT(p_intf), p_item,
266                                      p_advanced_dialog );
267
268             advanced_config_array.Add( control );
269
270             /* Don't add items that were not recognized */
271             if( control == NULL ) continue;
272
273             control->SetUpdateCallback( AutoBuildAdvancedCallback,
274                                         (void *)this );
275
276             sizer->Add( control, 0, wxEXPAND | wxALL, 2 );
277         }
278         while( p_item->i_type != CONFIG_HINT_END && p_item++ );
279
280         /* Separation */
281         wxPanel *dummy_panel = new wxPanel( p_advanced_dialog, -1 );
282         sizer->Add( dummy_panel, 1 );
283         wxStaticLine *static_line =
284             new wxStaticLine( p_advanced_dialog, wxID_OK );
285         sizer->Add( static_line, 0, wxEXPAND | wxALL, 5 );
286
287         /* Create buttons */
288         wxButton *ok_button =
289             new wxButton( p_advanced_dialog, wxID_OK, wxU(_("OK")) );
290         ok_button->SetDefault();
291         wxButton *cancel_button =
292             new wxButton( p_advanced_dialog, wxID_CANCEL, wxU(_("Cancel")) );
293         wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
294         button_sizer->Add( ok_button, 0, wxALL, 5 );
295         button_sizer->Add( cancel_button, 0, wxALL, 5 );
296         button_sizer->Layout();
297         sizer->Add( button_sizer, 0, wxALL, 0 );
298
299         sizer->SetMinSize( 400, -1 );
300         p_advanced_dialog->SetSizerAndFit( sizer );
301     }
302
303     this->SetSizerAndFit( sizer );
304 }
305
306 void AutoBuiltPanel::OnAdvanced( wxCommandEvent& event )
307 {
308     if( p_advanced_dialog->ShowModal() == wxID_OK )
309     {
310         UpdateAdvancedMRL();
311         p_open_dialog->UpdateMRL();
312     }
313 }
314
315 void AutoBuiltPanel::UpdateAdvancedMRL()
316 {
317     wxString mrltemp;
318
319     for( int i = 0; i < (int)advanced_config_array.GetCount(); i++ )
320     {
321         ConfigControl *control = advanced_config_array.Item(i);
322
323         mrltemp += (i ? wxT(" :") : wxT(":"));
324
325         if( control->GetType() == CONFIG_ITEM_BOOL &&
326             !control->GetIntValue() ) mrltemp += wxT("no-");
327
328         mrltemp += control->GetName();
329
330         switch( control->GetType() )
331         {
332         case CONFIG_ITEM_STRING:
333         case CONFIG_ITEM_FILE:
334         case CONFIG_ITEM_DIRECTORY:
335         case CONFIG_ITEM_MODULE:
336             mrltemp += wxT("=\"") + control->GetPszValue() + wxT("\"");
337             break;
338         case CONFIG_ITEM_INTEGER:
339             mrltemp +=
340                 wxString::Format( wxT("=%i"), control->GetIntValue() );
341             break;
342         case CONFIG_ITEM_FLOAT:
343             mrltemp +=
344                 wxString::Format(wxT("=%f"), control->GetFloatValue());
345             break;
346         }
347     }
348
349     p_advanced_mrl_combo->SetValue( mrltemp );
350 }
351
352 /*****************************************************************************
353  * Constructor.
354  *****************************************************************************/
355 OpenDialog::OpenDialog( intf_thread_t *_p_intf, wxWindow *_p_parent,
356                         int i_access_method, int i_arg ):
357       wxDialog( _p_parent, -1, wxU(_("Open...")), wxDefaultPosition,
358              wxDefaultSize, wxDEFAULT_FRAME_STYLE )
359 {
360     OpenDialog( _p_intf, _p_parent, i_access_method, i_arg, OPEN_NORMAL );
361 }
362
363 OpenDialog::OpenDialog( intf_thread_t *_p_intf, wxWindow *_p_parent,
364                         int i_access_method, int i_arg, int _i_method ):
365       wxDialog( _p_parent, -1, wxU(_("Open...")), wxDefaultPosition,
366              wxDefaultSize, wxDEFAULT_FRAME_STYLE )
367 {
368     /* Initializations */
369     i_method = _i_method;
370     p_intf = _p_intf;
371     p_parent = _p_parent;
372     SetIcon( *p_intf->p_sys->p_icon );
373     file_dialog = NULL;
374     i_disc_type_selection = 0;
375     i_disc_title = 0;
376     i_open_arg = i_arg;
377
378     sout_dialog = NULL;
379     subsfile_dialog = NULL;
380     b_disc_device_changed = false;
381
382     /* Create a panel to put everything in */
383     wxPanel *panel = new wxPanel( this, -1 );
384     panel->SetAutoLayout( TRUE );
385
386     /* Create MRL combobox */
387     wxBoxSizer *mrl_sizer_sizer = new wxBoxSizer( wxHORIZONTAL );
388     wxStaticBox *mrl_box = new wxStaticBox( panel, -1,
389                                wxU(_("Media Resource Locator (MRL)")) );
390     wxStaticBoxSizer *mrl_sizer = new wxStaticBoxSizer( mrl_box,
391                                                         wxHORIZONTAL );
392     wxStaticText *mrl_label = new wxStaticText( panel, -1,
393                                                 wxU(_("Open:")) );
394     mrl_combo = new wxComboBox( panel, MRL_Event, wxT(""),
395                                 wxPoint(20,25), wxSize(120, -1) );
396     mrl_combo->SetToolTip( wxU(_("You can use this field directly by typing "
397         "the full MRL you want to open.\n""Alternatively, the field will be "
398         "filled automatically when you use the controls below.")) );
399
400     mrl_sizer->Add( mrl_label, 0, wxALL | wxALIGN_CENTER, 5 );
401     mrl_sizer->Add( mrl_combo, 1, wxALL | wxALIGN_CENTER, 5 );
402     mrl_sizer_sizer->Add( mrl_sizer, 1, wxEXPAND | wxALL, 5 );
403
404
405     /* Create Static Text */
406     wxStaticText *label = new wxStaticText( panel, -1,
407         wxU(_("Alternatively, you can build an MRL using one of the "
408               "following predefined targets:")) );
409
410     wxFlexGridSizer *common_opt_sizer = new wxFlexGridSizer( 5, 1, 20 );
411
412     if( i_method == OPEN_NORMAL )
413     {
414         /* Create Stream Output checkox */
415         sout_checkbox = new wxCheckBox( panel, SoutEnable_Event,
416                                          wxU(_("Stream output")) );
417         sout_checkbox->SetToolTip( wxU(_("Use VLC as a server of streams")) );
418         common_opt_sizer->Add( sout_checkbox, 0,
419                                wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
420
421         sout_button = new wxButton( panel, SoutSettings_Event,
422                                     wxU(_("Settings...")) );
423         sout_button->Disable();
424
425         char *psz_sout = config_GetPsz( p_intf, "sout" );
426         if( psz_sout && *psz_sout )
427         {
428             sout_checkbox->SetValue(TRUE);
429             sout_button->Enable();
430             subsfile_mrl.Add( wxString(wxT("sout=")) + wxL2U(psz_sout) );
431         }
432         if( psz_sout ) free( psz_sout );
433
434         common_opt_sizer->Add( sout_button, 1, wxALIGN_LEFT |
435                                wxALIGN_CENTER_VERTICAL );
436
437         common_opt_sizer->Add( new wxPanel( this, -1 ), 1,
438                                wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
439     }
440
441     /* Create caching options */
442     caching_checkbox = new wxCheckBox( panel, CachingEnable_Event,
443                                        wxU(_("Caching")) );
444     caching_checkbox->SetToolTip( wxU(_("Change the default caching value "
445                                         "(in milliseconds)")) );
446     common_opt_sizer->Add( caching_checkbox, 0,
447                            wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
448     caching_value = new wxSpinCtrl( panel, CachingChange_Event );
449 #ifdef WIN32  /* WIN32 uses 16 bit integer */
450     caching_value->SetRange( 0, 32767 );
451 #else
452     caching_value->SetRange( 0, 1000000 );
453 #endif
454     caching_value->Disable();
455     common_opt_sizer->Add( caching_value, 0,
456                            wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
457
458     /* Separation */
459     wxStaticLine *static_line = new wxStaticLine( panel, wxID_OK );
460
461     /* Create the buttons */
462     wxButton *ok_button = new wxButton( panel, wxID_OK, wxU(_("OK")) );
463     ok_button->SetDefault();
464     wxButton *cancel_button = new wxButton( panel, wxID_CANCEL,
465                                             wxU(_("Cancel")) );
466
467     /* Create notebook */
468     notebook = new wxNotebook( panel, Notebook_Event );
469     wxNotebookSizer *notebook_sizer = new wxNotebookSizer( notebook );
470
471     notebook->AddPage( FilePanel( notebook ), wxU(_("File")),
472                        i_access_method == FILE_ACCESS );
473     notebook->AddPage( DiscPanel( notebook ), wxU(_("Disc")),
474                        i_access_method == DISC_ACCESS );
475     notebook->AddPage( NetPanel( notebook ), wxU(_("Network")),
476                        i_access_method == NET_ACCESS );
477
478     module_t *p_module = config_FindModule( VLC_OBJECT(p_intf), "v4l" );
479     if( p_module )
480     {
481         AutoBuiltPanel *autopanel =
482             new AutoBuiltPanel( notebook, this, p_intf, p_module );
483         input_tab_array.Add( autopanel );
484         notebook->AddPage( autopanel, wxU( p_module->psz_shortname ?
485                         p_module->psz_shortname : p_module->psz_object_name ),
486                            i_access_method == CAPTURE_ACCESS );
487     }
488
489     p_module = config_FindModule( VLC_OBJECT(p_intf), "pvr" );
490     if( p_module )
491     {
492         AutoBuiltPanel *autopanel =
493             new AutoBuiltPanel( notebook, this, p_intf, p_module );
494         input_tab_array.Add( autopanel );
495         notebook->AddPage( autopanel, wxU( p_module->psz_shortname ?
496                         p_module->psz_shortname : p_module->psz_object_name ),
497                            i_access_method == CAPTURE_ACCESS );
498     }
499
500     p_module = config_FindModule( VLC_OBJECT(p_intf), "dvb" );
501     if( p_module )
502     {
503         AutoBuiltPanel *autopanel =
504             new AutoBuiltPanel( notebook, this, p_intf, p_module );
505         input_tab_array.Add( autopanel );
506         notebook->AddPage( autopanel, wxU( p_module->psz_shortname ?
507                         p_module->psz_shortname : p_module->psz_object_name ),
508                            i_access_method == CAPTURE_ACCESS );
509     }
510
511     p_module = config_FindModule( VLC_OBJECT(p_intf), "dshow" );
512     if( p_module )
513     {
514         AutoBuiltPanel *autopanel =
515             new AutoBuiltPanel( notebook, this, p_intf, p_module );
516         input_tab_array.Add( autopanel );
517         notebook->AddPage( autopanel, wxU( p_module->psz_shortname ?
518                         p_module->psz_shortname : p_module->psz_object_name ),
519                            i_access_method == CAPTURE_ACCESS );
520     }
521
522     /* Update Disc panel */
523     wxCommandEvent dummy_event;
524     OnDiscTypeChange( dummy_event );
525
526     /* Update Net panel */
527     dummy_event.SetId( NetRadio1_Event );
528     OnNetTypeChange( dummy_event );
529
530     /* Update MRL */
531     wxNotebookEvent event( wxEVT_NULL, 0, i_access_method );
532     OnPageChange( event );
533
534     /* Place everything in sizers */
535     wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
536     button_sizer->Add( ok_button, 0, wxALL, 5 );
537     button_sizer->Add( cancel_button, 0, wxALL, 5 );
538     button_sizer->Layout();
539     wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
540     wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
541     panel_sizer->Add( mrl_sizer_sizer, 0, wxEXPAND, 5 );
542     panel_sizer->Add( label, 0, wxEXPAND | wxALL, 5 );
543     panel_sizer->Add( notebook_sizer, 1, wxEXPAND | wxALL, 5 );
544     panel_sizer->Add( common_opt_sizer, 0, wxALIGN_LEFT | wxALL, 5 );
545     panel_sizer->Add( static_line, 0, wxEXPAND | wxALL, 5 );
546     panel_sizer->Add( button_sizer, 0, wxALIGN_LEFT | wxALL, 5 );
547     panel_sizer->Layout();
548     panel->SetSizerAndFit( panel_sizer );
549     main_sizer->Add( panel, 1, wxGROW, 0 );
550     main_sizer->Layout();
551     SetSizerAndFit( main_sizer );
552 }
553
554 OpenDialog::~OpenDialog()
555 {
556     /* Clean up */
557     if( file_dialog ) delete file_dialog;
558     if( sout_dialog ) delete sout_dialog;
559     if( subsfile_dialog ) delete subsfile_dialog;
560 }
561
562 int OpenDialog::Show( int i_access_method, int i_arg )
563 {
564     notebook->SetSelection( i_access_method );
565     int i_ret = wxDialog::Show();
566     Raise();
567     SetFocus();
568     i_open_arg = i_arg;
569     return i_ret;
570 }
571
572 int OpenDialog::Show()
573 {
574     int i_ret = wxDialog::Show();
575     Raise();
576     SetFocus();
577     return i_ret;
578 }
579
580 /*****************************************************************************
581  * Private methods.
582  *****************************************************************************/
583 wxPanel *OpenDialog::FilePanel( wxWindow* parent )
584 {
585     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
586                                   wxSize(200, 200) );
587
588     wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
589
590     /* Create browse file line */
591     wxBoxSizer *file_sizer = new wxBoxSizer( wxHORIZONTAL );
592
593     file_combo = new wxComboBox( panel, FileName_Event, wxT(""),
594                                  wxPoint(20,25), wxSize(200, -1) );
595     wxButton *browse_button = new wxButton( panel, FileBrowse_Event,
596                                             wxU(_("Browse...")) );
597     file_sizer->Add( file_combo, 1, wxALL, 5 );
598     file_sizer->Add( browse_button, 0, wxALL, 5 );
599
600     /* Create Subtitles File checkox */
601     wxFlexGridSizer *subsfile_sizer = new wxFlexGridSizer( 2, 1, 20 );
602     subsfile_checkbox = new wxCheckBox( panel, SubsFileEnable_Event,
603                                         wxU(_("Subtitle options")) );
604     subsfile_checkbox->SetToolTip( wxU(_("Force options for separate subtitle files.")) );
605     subsfile_sizer->Add( subsfile_checkbox, 0,
606                          wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
607     subsfile_button = new wxButton( panel, SubsFileSettings_Event,
608                                     wxU(_("Settings...")) );
609     subsfile_button->Disable();
610
611     char *psz_subsfile = config_GetPsz( p_intf, "sub-file" );
612     if( psz_subsfile && *psz_subsfile )
613     {
614         subsfile_checkbox->SetValue(TRUE);
615         subsfile_button->Enable();
616         subsfile_mrl.Add( wxString(wxT("sub-file=")) + wxL2U(psz_subsfile) );
617     }
618     if( psz_subsfile ) free( psz_subsfile );
619
620     subsfile_sizer->Add( subsfile_button, 1,
621                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
622
623     sizer->Add( file_sizer, 0, wxEXPAND | wxALL, 5 );
624     sizer->Add( subsfile_sizer, 0, wxEXPAND | wxALL, 5 );
625     panel->SetSizerAndFit( sizer );
626     return panel;
627 }
628
629 wxPanel *OpenDialog::DiscPanel( wxWindow* parent )
630 {
631     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
632                                   wxSize(200, 200) );
633
634     wxBoxSizer *sizer_row = new wxBoxSizer( wxVERTICAL );
635     wxFlexGridSizer *sizer = new wxFlexGridSizer( 2, 3, 20 );
636
637     static const wxString disc_type_array[] =
638     {
639         wxU(_("DVD (menus)")),
640         wxU(_("DVD")),
641         wxU(_("VCD")),
642         wxU(_("Audio CD")),
643     };
644
645     disc_type = new wxRadioBox( panel, DiscType_Event, wxU(_("Disc type")),
646                                 wxDefaultPosition, wxDefaultSize,
647                                 WXSIZEOF(disc_type_array), disc_type_array,
648                                 WXSIZEOF(disc_type_array), wxRA_SPECIFY_COLS );
649
650     sizer_row->Add( disc_type, i_disc_type_selection, wxEXPAND | wxALL, 5 );
651
652     wxStaticText *label = new wxStaticText( panel, -1, wxU(_("Device name")) );
653     disc_device = new wxTextCtrl( panel, DiscDevice_Event, wxT(""),
654                                   wxDefaultPosition, wxDefaultSize,
655                                   wxTE_PROCESS_ENTER);
656
657     sizer->Add( label, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
658     sizer->Add( disc_device, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
659
660     disc_title_label = new wxStaticText( panel, -1, wxU(_("Title")) );
661     disc_title = new wxSpinCtrl( panel, DiscTitle_Event );
662     sizer->Add( disc_title_label, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
663     sizer->Add( disc_title, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
664
665     disc_chapter_label = new wxStaticText( panel, -1, wxU(_("Chapter")) );
666     disc_chapter = new wxSpinCtrl( panel, DiscChapter_Event );
667     sizer->Add( disc_chapter_label, 0,
668                 wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
669     sizer->Add( disc_chapter, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
670
671     disc_sub_label = new wxStaticText( panel, -1, wxU(_("Subtitles track")) );
672     disc_sub = new wxSpinCtrl( panel, DiscSub_Event );
673     sizer->Add( disc_sub_label, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
674     sizer->Add( disc_sub, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
675     disc_sub->SetRange( -1, 255 );
676     i_disc_sub = config_GetInt( p_intf, "sub-track" );
677     disc_sub->SetValue( i_disc_sub );
678
679     sizer_row->Add( sizer, 0, wxEXPAND | wxALL, 5 );
680
681     panel->SetSizerAndFit( sizer_row );
682     return panel;
683 }
684
685 wxPanel *OpenDialog::NetPanel( wxWindow* parent )
686 {
687     int i;
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, 4, 20 );
693
694     static const wxString net_type_array[] =
695     {
696         wxU(_("UDP/RTP")),
697         wxU(_("UDP/RTP Multicast")),
698         wxU(_("HTTP/HTTPS/FTP/MMS")),
699         wxU(_("RTSP"))
700     };
701
702     for( i=0; i<4; i++ )
703     {
704         net_radios[i] = new wxRadioButton( panel, NetRadio1_Event + i,
705                                            net_type_array[i],
706                                            wxDefaultPosition, wxDefaultSize,
707                                            wxRB_SINGLE );
708
709         net_subpanels[i] = new wxPanel( panel, -1,
710                                         wxDefaultPosition, wxDefaultSize );
711     }
712
713     /* UDP/RTP row */
714     wxFlexGridSizer *subpanel_sizer;
715     wxStaticText *label;
716     i_net_ports[0] = config_GetInt( p_intf, "server-port" );
717     subpanel_sizer = new wxFlexGridSizer( 3, 1, 20 );
718     label = new wxStaticText( net_subpanels[0], -1, wxU(_("Port")) );
719     net_ports[0] = new wxSpinCtrl( net_subpanels[0], NetPort1_Event,
720                                    wxString::Format(wxT("%d"), i_net_ports[0]),
721                                    wxDefaultPosition, wxDefaultSize,
722                                    wxSP_ARROW_KEYS,
723                                    0, 16000, i_net_ports[0] );
724
725     subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
726     subpanel_sizer->Add( net_ports[0], 1,
727                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
728     net_ipv6 = new wxCheckBox( net_subpanels[0], NetForceIPv6_Event,
729                                wxU(_("Force IPv6")));
730     subpanel_sizer->Add( net_ipv6, 0,
731                          wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
732     net_subpanels[0]->SetSizerAndFit( subpanel_sizer );
733     net_radios[0]->SetValue( TRUE );
734
735     /* UDP/RTP Multicast row */
736     subpanel_sizer = new wxFlexGridSizer( 4, 1, 20 );
737     label = new wxStaticText( net_subpanels[1], -1, wxU(_("Address")) );
738     net_addrs[1] = new wxTextCtrl( net_subpanels[1], NetAddr2_Event, wxT(""),
739                                    wxDefaultPosition, wxDefaultSize,
740                                    wxTE_PROCESS_ENTER);
741     subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
742     subpanel_sizer->Add( net_addrs[1], 1,
743                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
744
745     label = new wxStaticText( net_subpanels[1], -1, wxU(_("Port")) );
746     i_net_ports[1] = i_net_ports[0];
747     net_ports[1] = new wxSpinCtrl( net_subpanels[1], NetPort2_Event,
748                                    wxString::Format(wxT("%d"), i_net_ports[1]),
749                                    wxDefaultPosition, wxDefaultSize,
750                                    wxSP_ARROW_KEYS,
751                                    0, 16000, i_net_ports[1] );
752
753     subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
754     subpanel_sizer->Add( net_ports[1], 1,
755                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
756     net_subpanels[1]->SetSizerAndFit( subpanel_sizer );
757
758     /* HTTP and RTSP rows */
759     for( i=2; i<4; i++ )
760     {
761         subpanel_sizer = new wxFlexGridSizer( 2, 1, 20 );
762         label = new wxStaticText( net_subpanels[i], -1, wxU(_("URL")) );
763         net_addrs[i] = new wxTextCtrl( net_subpanels[i], NetAddr1_Event + i,
764                                        (i == 2) ? wxT("") : wxT("rtsp://"),
765                                        wxDefaultPosition, wxSize( 200, -1 ),
766                                        wxTE_PROCESS_ENTER);
767         subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
768         subpanel_sizer->Add( net_addrs[i], 1,
769                              wxEXPAND | wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
770         net_subpanels[i]->SetSizerAndFit( subpanel_sizer );
771     }
772
773     /* Stuff everything into the main panel */
774     for( i=0; i<4; i++ )
775     {
776         sizer->Add( net_radios[i], 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL |
777                     wxALL, 5 );
778         sizer->Add( net_subpanels[i], 1, wxEXPAND | wxALIGN_LEFT |
779                     wxALIGN_CENTER_VERTICAL | wxALL, 5  );
780     }
781
782     sizer_row->Add( sizer, 0, wxEXPAND | wxALL, 5 );
783
784     panel->SetSizerAndFit( sizer_row );
785     return panel;
786 }
787
788 void OpenDialog::UpdateMRL()
789 {
790     UpdateMRL( i_current_access_method );
791 }
792
793 void OpenDialog::UpdateMRL( int i_access_method )
794 {
795     wxString mrltemp, caching_name;
796
797     i_current_access_method = i_access_method;
798
799     switch( i_access_method )
800     {
801     case FILE_ACCESS:
802         mrltemp = file_combo->GetValue();
803         caching_name = wxT("file-caching");
804         break;
805
806     case DISC_ACCESS:
807         i_disc_type_selection = disc_type->GetSelection();
808
809         switch ( i_disc_type_selection )
810         {
811         case 0: /* DVD with menus */
812         case 1: /* DVD without menus */
813             if( i_disc_type_selection == 0 )
814             {
815                 mrltemp = wxT("dvd://") + disc_device->GetValue();
816                 caching_name = wxT("dvdnav-caching");
817             }
818             else
819             {
820                 mrltemp = wxT("dvdsimple://") + disc_device->GetValue();
821                 caching_name = wxT("dvdread-caching");
822             }
823
824             if( i_disc_title > 0 )
825             {
826                 mrltemp += wxString::Format( wxT("@%d"), i_disc_title );
827
828                 if( i_disc_chapter > 0 )
829                     mrltemp += wxString::Format( wxT(":%d"), i_disc_chapter );
830             }
831
832             if( i_disc_sub >= 0 )
833                 mrltemp += wxString::Format( wxT("  :sub-track=%d"),
834                                              i_disc_sub );
835             break;
836
837         case 2:  /* VCD of some sort */
838 #ifdef HAVE_VCDX
839             mrltemp = wxT("vcdx://") + disc_device->GetValue();
840             if( i_disc_title > 0 )
841                 mrltemp += wxString::Format( wxT("@%c%d"),
842                                   config_GetInt( p_intf, "vcdx-PBC"  )
843                                   ? 'P' : 'E', i_disc_title );
844 #else
845             mrltemp = wxT("vcd://") + disc_device->GetValue();
846             if( i_disc_title > 0 )
847                 mrltemp += wxString::Format( wxT("@%d"), i_disc_title );
848 #endif
849
850             if( i_disc_sub >= 0 )
851                 mrltemp += wxString::Format( wxT("  :sub-track=%d"),
852                                              i_disc_sub );
853
854             caching_name = wxT("vcd-caching");
855             break;
856
857         case 3: /* CD-DA */
858             mrltemp = 
859 #ifdef HAVE_CDDAX
860               wxT("cddax://") 
861 #else
862               wxT("cdda://") 
863 #endif
864               + disc_device->GetValue();
865             if( i_disc_title > 0 )
866                 mrltemp += wxString::Format( wxT("@%d"), i_disc_title );
867
868             caching_name = wxT("cdda-caching");
869             break;
870
871         default:
872             msg_Err( p_intf, "invalid selection (%d)",
873                      disc_type->GetSelection() );
874         }
875
876         break;
877
878     case NET_ACCESS:
879         switch( i_net_type )
880         {
881         case 0:
882             mrltemp = wxT("udp://@");
883             if ( net_ipv6->GetValue() )
884             {
885                 mrltemp += wxT("[::]");
886             }
887             if( i_net_ports[0] !=
888                 config_GetInt( p_intf, "server-port" ) )
889             {
890                 mrltemp += wxString::Format( wxT(":%d"), i_net_ports[0] );
891             }
892
893             caching_name = wxT("udp-caching");
894             break;
895
896         case 1:
897             mrltemp = wxT("udp://@");
898             if ((net_addrs[1]->GetLineText(0).Find (':') != -1)
899                 && (net_addrs[1]->GetLineText(0)[0u] != '['))
900             {
901                 /* automatically adds '[' and ']' to IPv6 addresses */
902                 mrltemp += wxT("[") + net_addrs[1]->GetLineText(0)
903                          + wxT("]");
904             }
905             else
906             {
907                 mrltemp += net_addrs[1]->GetLineText(0);
908             }
909             if( i_net_ports[1] != config_GetInt( p_intf, "server-port" ) )
910             {
911                 mrltemp += wxString::Format( wxT(":%d"), i_net_ports[1] );
912             }
913
914             caching_name = wxT("udp-caching");
915             break;
916
917         case 2:
918             /* http access */
919             if( net_addrs[2]->GetLineText(0).Find(wxT("://")) == -1 )
920                 mrltemp = wxT("http://");
921
922             mrltemp += net_addrs[2]->GetLineText(0);
923
924             caching_name = wxT("http-caching");
925             break;
926
927         case 3:
928             /* RTSP access */
929             if( net_addrs[3]->GetLineText(0).Find(wxT("rtsp://")) != 0 )
930             {
931                 mrltemp = wxT("rtsp://");
932             }
933             mrltemp += net_addrs[3]->GetLineText(0);
934
935             caching_name = wxT("rtsp-caching");
936             break;
937         }
938         break;
939
940     default:
941         {
942             int i_item = i_access_method - MAX_ACCESS;
943
944             if( i_item < 0 || i_item >= (int)input_tab_array.GetCount() )
945                 break;
946
947             AutoBuiltPanel *input_panel = input_tab_array.Item( i_item );
948
949             mrltemp = input_panel->name + wxT("://");
950
951             for( int i=0; i < (int)input_panel->config_array.GetCount(); i++ )
952             {
953                 ConfigControl *control = input_panel->config_array.Item(i);
954
955                 mrltemp += wxT(" :");
956
957                 if( control->GetType() == CONFIG_ITEM_BOOL &&
958                     !control->GetIntValue() ) mrltemp += wxT("no-");
959
960                 mrltemp += control->GetName();
961
962                 switch( control->GetType() )
963                 {
964                 case CONFIG_ITEM_STRING:
965                 case CONFIG_ITEM_FILE:
966                 case CONFIG_ITEM_DIRECTORY:
967                 case CONFIG_ITEM_MODULE:
968                     mrltemp += wxT("=\"") + control->GetPszValue() + wxT("\"");
969                     break;
970                 case CONFIG_ITEM_INTEGER:
971                     mrltemp +=
972                         wxString::Format( wxT("=%i"), control->GetIntValue() );
973                     break;
974                 case CONFIG_ITEM_FLOAT:
975                     mrltemp +=
976                         wxString::Format(wxT("=%f"), control->GetFloatValue());
977                     break;
978                 }
979             }
980
981             if( input_panel->p_advanced_mrl_combo &&
982                 input_panel->p_advanced_mrl_combo->GetValue() )
983             {
984                 mrltemp += wxT(" ") +
985                     input_panel->p_advanced_mrl_combo->GetValue();
986             }
987         }
988         break;
989     }
990
991     if( caching_name.size() )
992     {
993         if( caching_value->IsEnabled() )
994         {
995             mrltemp += wxT("  :") + caching_name +
996                 wxString::Format( wxT("=%d"), i_caching );
997         }
998         else
999         {
1000             int i_value = config_GetInt( p_intf, caching_name.mb_str() );
1001             caching_value->SetValue( i_value );
1002         }
1003     }
1004
1005     mrl_combo->SetValue( mrltemp );
1006 }
1007
1008 /*****************************************************************************
1009  * Events methods.
1010  *****************************************************************************/
1011 void OpenDialog::OnOk( wxCommandEvent& WXUNUSED(event) )
1012 {
1013     mrl = SeparateEntries( mrl_combo->GetValue() );
1014     mrl_combo->Append( mrl_combo->GetValue() );
1015     if( mrl_combo->GetCount() > 10 ) mrl_combo->Delete( 0 );
1016     mrl_combo->SetSelection( mrl_combo->GetCount() - 1 );
1017
1018     if( i_method == OPEN_STREAM )
1019     {
1020         if( IsModal() ) EndModal( wxID_OK );
1021         Hide();
1022         return;
1023     }
1024
1025     /* Update the playlist */
1026     playlist_t *p_playlist =
1027         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
1028                                        FIND_ANYWHERE );
1029     if( p_playlist == NULL ) return;
1030
1031     for( int i = 0; i < (int)mrl.GetCount(); i++ )
1032     {
1033         vlc_bool_t b_start = !i && i_open_arg;
1034         playlist_item_t *p_item =
1035             playlist_ItemNew( p_intf, (const char*)mrl[i].mb_str(),
1036                               (const char *)mrl[i].mb_str() );
1037
1038         /* Insert options */
1039         while( i + 1 < (int)mrl.GetCount() &&
1040                ((const char *)mrl[i + 1].mb_str())[0] == ':' )
1041         {
1042             playlist_ItemAddOption( p_item, mrl[i + 1].mb_str() );
1043             i++;
1044         }
1045
1046         /* Get the options from the subtitles dialog */
1047         if( subsfile_checkbox->IsChecked() && subsfile_mrl.GetCount() )
1048         {
1049             for( int j = 0; j < (int)subsfile_mrl.GetCount(); j++ )
1050             {
1051                 playlist_ItemAddOption( p_item, subsfile_mrl[j].mb_str() );
1052             }
1053         }
1054
1055         /* Get the options from the stream output dialog */
1056         if( sout_checkbox->IsChecked() && sout_mrl.GetCount() )
1057         {
1058             for( int j = 0; j < (int)sout_mrl.GetCount(); j++ )
1059             {
1060                 playlist_ItemAddOption( p_item, sout_mrl[j].mb_str() );
1061             }
1062         }
1063
1064         int i_id = playlist_AddItem( p_playlist, p_item,
1065                                      PLAYLIST_APPEND, PLAYLIST_END );
1066
1067         if( b_start )
1068         {
1069             playlist_Control( p_playlist, PLAYLIST_ITEMPLAY , p_item );
1070         }
1071     }
1072
1073     vlc_object_release( p_playlist );
1074
1075     Hide();
1076
1077     if( IsModal() ) EndModal( wxID_OK );
1078 }
1079
1080 void OpenDialog::OnCancel( wxCommandEvent& WXUNUSED(event) )
1081 {
1082     Hide();
1083
1084     if( IsModal() ) EndModal( wxID_CANCEL );
1085 }
1086
1087 void OpenDialog::OnPageChange( wxNotebookEvent& event )
1088 {
1089     UpdateMRL( event.GetSelection() );
1090 }
1091
1092 void OpenDialog::OnMRLChange( wxCommandEvent& event )
1093 {
1094     //mrl = SeparateEntries( event.GetString() );
1095 }
1096
1097 /*****************************************************************************
1098  * File panel event methods.
1099  *****************************************************************************/
1100 void OpenDialog::OnFilePanelChange( wxCommandEvent& WXUNUSED(event) )
1101 {
1102     UpdateMRL( FILE_ACCESS );
1103 }
1104
1105 void OpenDialog::OnFileBrowse( wxCommandEvent& WXUNUSED(event) )
1106 {
1107     if( file_dialog == NULL )
1108         file_dialog = new wxFileDialog( this, wxU(_("Open File")),
1109             wxT(""), wxT(""), wxT("*"), wxOPEN | wxMULTIPLE );
1110
1111     if( file_dialog && file_dialog->ShowModal() == wxID_OK )
1112     {
1113         wxArrayString paths;
1114         wxString path;
1115
1116         file_dialog->GetPaths( paths );
1117
1118         for( size_t i = 0; i < paths.GetCount(); i++ )
1119         {
1120             if( paths[i].Find( wxT(' ') ) >= 0 )
1121                 path += wxT("\"") + paths[i] + wxT("\" ");
1122             else
1123                 path += paths[i] + wxT(" ");
1124         }
1125
1126         file_combo->SetValue( path );
1127         file_combo->Append( path );
1128         if( file_combo->GetCount() > 10 ) file_combo->Delete( 0 );
1129         UpdateMRL( FILE_ACCESS );
1130     }
1131 }
1132
1133 /*****************************************************************************
1134  * Disc panel event methods.
1135  *****************************************************************************/
1136 void OpenDialog::OnDiscPanelChange( wxCommandEvent& event )
1137 {
1138     if( event.GetId() == DiscTitle_Event ) i_disc_title = event.GetInt();
1139     if( event.GetId() == DiscChapter_Event ) i_disc_chapter = event.GetInt();
1140     if( event.GetId() == DiscSub_Event ) i_disc_sub = event.GetInt();
1141
1142     UpdateMRL( DISC_ACCESS );
1143 }
1144
1145 void OpenDialog::OnDiscDeviceChange( wxCommandEvent& event )
1146 {
1147     char *psz_device;
1148
1149     switch( disc_type->GetSelection() )
1150     {
1151         case 3:
1152             psz_device = config_GetPsz( p_intf, "cd-audio" );
1153             break;
1154
1155         case 2:
1156             psz_device = config_GetPsz( p_intf, "vcd" );
1157             break;
1158
1159         default:
1160             psz_device = config_GetPsz( p_intf, "dvd" );
1161             break;
1162     }
1163
1164     if ( !psz_device ) psz_device = "";
1165
1166     if( disc_device->GetValue().Cmp( wxL2U( psz_device ) ) )
1167     {
1168         b_disc_device_changed = true;
1169     }
1170
1171     UpdateMRL( DISC_ACCESS );
1172 }
1173
1174 void OpenDialog::OnDiscTypeChange( wxCommandEvent& WXUNUSED(event) )
1175 {
1176     char *psz_device = NULL;
1177
1178     switch( disc_type->GetSelection() )
1179     {
1180
1181     case 0: /* DVD with menus */
1182     case 1: /* DVD without menus */
1183         disc_sub->Enable(); disc_sub_label->Enable();
1184         disc_chapter->Enable(); disc_chapter_label->Enable();
1185         disc_title_label->SetLabel ( wxU(_("Title")) );
1186         psz_device = config_GetPsz( p_intf, "dvd" );
1187         if( !b_disc_device_changed )
1188         {
1189             if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
1190             else disc_device->SetValue( wxT("") );
1191         }
1192         disc_title->SetRange( 0, 255 );
1193         disc_chapter->SetRange( 0, 255 );
1194         break;
1195
1196     case 2:  /* VCD of some sort */
1197         disc_sub->Enable(); disc_sub_label->Enable();
1198         disc_chapter->Disable(); disc_chapter_label->Disable();
1199         psz_device = config_GetPsz( p_intf, "vcd" );
1200         if( !b_disc_device_changed )
1201         {
1202             if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
1203             else disc_device->SetValue( wxT("") );
1204         }
1205
1206 #ifdef HAVE_VCDX
1207         disc_title_label->SetLabel ( config_GetInt( p_intf, "vcdx-PBC"  )
1208                                      ? wxT("Playback LID") : wxT("Entry") );
1209 #else
1210         disc_title_label->SetLabel ( wxU(_("Track")) );
1211 #endif
1212         disc_title->SetRange( 0, 999 );
1213         break;
1214
1215     case 3: /* CD-DA */
1216         disc_sub->Disable(); disc_sub_label->Disable();
1217         disc_chapter->Disable(); disc_chapter_label->Disable();
1218         disc_title_label->SetLabel ( wxU(_("Track")) );
1219         psz_device = config_GetPsz( p_intf, "cd-audio" );
1220         if( !b_disc_device_changed )
1221         {
1222             if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
1223             else disc_device->SetValue( wxT("") );
1224         }
1225
1226         /* There are at most 99 tracks in a CD-DA */
1227         disc_title->SetRange( 0, 99 );
1228         break;
1229
1230     default:
1231         msg_Err( p_intf, "invalid Disc type selection (%d)",
1232                  disc_type->GetSelection() );
1233         break;
1234     }
1235
1236     disc_title->SetValue( 0 ); i_disc_title = 0;
1237     disc_chapter->SetValue( 0 ); i_disc_chapter = 0;
1238
1239     if( psz_device ) free( psz_device );
1240
1241     UpdateMRL( DISC_ACCESS );
1242 }
1243
1244 /*****************************************************************************
1245  * Net panel event methods.
1246  *****************************************************************************/
1247 void OpenDialog::OnNetPanelChange( wxCommandEvent& event )
1248 {
1249     if( event.GetId() >= NetPort1_Event && event.GetId() <= NetPort3_Event )
1250     {
1251         i_net_ports[event.GetId() - NetPort1_Event] = event.GetInt();
1252     }
1253
1254     UpdateMRL( NET_ACCESS );
1255 }
1256
1257 void OpenDialog::OnNetTypeChange( wxCommandEvent& event )
1258 {
1259     int i;
1260
1261     i_net_type = event.GetId() - NetRadio1_Event;
1262
1263     for(i=0; i<4; i++)
1264     {
1265         net_radios[i]->SetValue( event.GetId() == (NetRadio1_Event+i) );
1266         net_subpanels[i]->Enable( event.GetId() == (NetRadio1_Event+i) );
1267     }
1268
1269     UpdateMRL( NET_ACCESS );
1270 }
1271
1272 /*****************************************************************************
1273  * Subtitles file event methods.
1274  *****************************************************************************/
1275 void OpenDialog::OnSubsFileEnable( wxCommandEvent& event )
1276 {
1277     subsfile_button->Enable( event.GetInt() != 0 );
1278 }
1279
1280 void OpenDialog::OnSubsFileSettings( wxCommandEvent& WXUNUSED(event) )
1281 {
1282     /* Show/hide the open dialog */
1283     if( subsfile_dialog == NULL )
1284         subsfile_dialog = new SubsFileDialog( p_intf, this );
1285
1286     if( subsfile_dialog && subsfile_dialog->ShowModal() == wxID_OK )
1287     {
1288         subsfile_mrl.Empty();
1289         subsfile_mrl.Add( wxString(wxT("sub-file=")) +
1290                           subsfile_dialog->file_combo->GetValue() );
1291         if( subsfile_dialog->encoding_combo )
1292             subsfile_mrl.Add( wxString(wxT("subsdec-encoding=")) +
1293                               subsfile_dialog->encoding_combo->GetValue() );
1294         subsfile_mrl.Add( wxString::Format(wxT("subsdec-align=%i"),
1295                            (int)subsfile_dialog->align_combo->GetClientData(
1296                            subsfile_dialog->align_combo->GetSelection()) ) );
1297
1298         subsfile_mrl.Add( wxString::Format( wxT("freetype-rel-fontsize=%i"),
1299                           (int)subsfile_dialog->size_combo->GetClientData(
1300                           subsfile_dialog->size_combo->GetSelection()) ) );
1301         subsfile_mrl.Add( wxString::Format( wxT("sub-fps=%i"),
1302                           subsfile_dialog->fps_spinctrl->GetValue() ) );
1303         subsfile_mrl.Add( wxString::Format( wxT("sub-delay=%i"),
1304                           subsfile_dialog->delay_spinctrl->GetValue() ) );
1305     }
1306 }
1307
1308 /*****************************************************************************
1309  * Stream output event methods.
1310  *****************************************************************************/
1311 void OpenDialog::OnSoutEnable( wxCommandEvent& event )
1312 {
1313     sout_button->Enable( event.GetInt() != 0 );
1314 }
1315
1316 void OpenDialog::OnSoutSettings( wxCommandEvent& WXUNUSED(event) )
1317 {
1318     /* Show/hide the open dialog */
1319     if( sout_dialog == NULL )
1320         sout_dialog = new SoutDialog( p_intf, this );
1321
1322     if( sout_dialog && sout_dialog->ShowModal() == wxID_OK )
1323     {
1324         sout_mrl = sout_dialog->GetOptions();
1325     }
1326 }
1327
1328 /*****************************************************************************
1329  * Caching event methods.
1330  *****************************************************************************/
1331 void OpenDialog::OnCachingEnable( wxCommandEvent& event )
1332 {
1333     caching_value->Enable( event.GetInt() != 0 );
1334     i_caching = caching_value->GetValue();
1335     UpdateMRL();
1336 }
1337
1338 void OpenDialog::OnCachingChange( wxCommandEvent& event )
1339 {
1340     i_caching = event.GetInt();
1341     UpdateMRL();
1342 }
1343
1344 /*****************************************************************************
1345  * Utility functions.
1346  *****************************************************************************/
1347 wxArrayString SeparateEntries( wxString entries )
1348 {
1349     vlc_bool_t b_quotes_mode = VLC_FALSE;
1350
1351     wxArrayString entries_array;
1352     wxString entry;
1353
1354     wxStringTokenizer token( entries, wxT(" \t\r\n\""), wxTOKEN_RET_DELIMS );
1355
1356     while( token.HasMoreTokens() )
1357     {
1358         entry += token.GetNextToken();
1359
1360         if( entry.IsEmpty() ) continue;
1361
1362         if( !b_quotes_mode && entry.Last() == wxT('\"') )
1363         {
1364             /* Enters quotes mode */
1365             entry.RemoveLast();
1366             b_quotes_mode = VLC_TRUE;
1367         }
1368         else if( b_quotes_mode && entry.Last() == wxT('\"') )
1369         {
1370             /* Finished the quotes mode */
1371             entry.RemoveLast();
1372             b_quotes_mode = VLC_FALSE;
1373         }
1374         else if( !b_quotes_mode && entry.Last() != wxT('\"') )
1375         {
1376             /* we found a non-quoted standalone string */
1377             if( token.HasMoreTokens() ||
1378                 entry.Last() == wxT(' ') || entry.Last() == wxT('\t') ||
1379                 entry.Last() == wxT('\r') || entry.Last() == wxT('\n') )
1380                 entry.RemoveLast();
1381             if( !entry.IsEmpty() ) entries_array.Add( entry );
1382             entry.Empty();
1383         }
1384         else
1385         {;}
1386     }
1387
1388     if( !entry.IsEmpty() ) entries_array.Add( entry );
1389
1390     return entries_array;
1391 }