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