]> git.sesse.net Git - vlc/blob - modules/gui/wxwindows/open.cpp
* renamed --spu-track to --sub-track
[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 <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                                 0, NULL );
397     mrl_combo->SetToolTip( wxU(_("You can use this field directly by typing "
398         "the full MRL you want to open.\n""Alternatively, the field will be "
399         "filled automatically when you use the controls below.")) );
400
401     mrl_sizer->Add( mrl_label, 0, wxALL | wxALIGN_CENTER, 5 );
402     mrl_sizer->Add( mrl_combo, 1, wxALL | wxALIGN_CENTER, 5 );
403     mrl_sizer_sizer->Add( mrl_sizer, 1, wxEXPAND | wxALL, 5 );
404
405
406     /* Create Static Text */
407     wxStaticText *label = new wxStaticText( panel, -1,
408         wxU(_("Alternatively, you can build an MRL using one of the "
409               "following predefined targets:")) );
410
411     wxFlexGridSizer *common_opt_sizer = new wxFlexGridSizer( 5, 1, 20 );
412
413     if( i_method == OPEN_NORMAL )
414     {
415         /* Create Stream Output checkox */
416         sout_checkbox = new wxCheckBox( panel, SoutEnable_Event,
417                                          wxU(_("Stream output")) );
418         sout_checkbox->SetToolTip( wxU(_("Use VLC as a server of streams")) );
419         common_opt_sizer->Add( sout_checkbox, 0,
420                                wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
421
422         sout_button = new wxButton( panel, SoutSettings_Event,
423                                     wxU(_("Settings...")) );
424         sout_button->Disable();
425
426         char *psz_sout = config_GetPsz( p_intf, "sout" );
427         if( psz_sout && *psz_sout )
428         {
429             sout_checkbox->SetValue(TRUE);
430             sout_button->Enable();
431             subsfile_mrl.Add( wxString(wxT("sout=")) + wxL2U(psz_sout) );
432         }
433         if( psz_sout ) free( psz_sout );
434
435         common_opt_sizer->Add( sout_button, 1, wxALIGN_LEFT |
436                                wxALIGN_CENTER_VERTICAL );
437
438         common_opt_sizer->Add( new wxPanel( this, -1 ), 1,
439                                wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
440     }
441
442     /* Create caching options */
443     caching_checkbox = new wxCheckBox( panel, CachingEnable_Event,
444                                        wxU(_("Caching")) );
445     caching_checkbox->SetToolTip( wxU(_("Change the default caching value "
446                                         "(in milliseconds)")) );
447     common_opt_sizer->Add( caching_checkbox, 0,
448                            wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
449     caching_value = new wxSpinCtrl( panel, CachingChange_Event );
450 #ifdef WIN32  /* WIN32 uses 16 bit integer */
451     caching_value->SetRange( 0, 32767 );
452 #else
453     caching_value->SetRange( 0, 1000000 );
454 #endif
455     caching_value->Disable();
456     common_opt_sizer->Add( caching_value, 0,
457                            wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
458
459     /* Separation */
460     wxStaticLine *static_line = new wxStaticLine( panel, wxID_OK );
461
462     /* Create the buttons */
463     wxButton *ok_button = new wxButton( panel, wxID_OK, wxU(_("OK")) );
464     ok_button->SetDefault();
465     wxButton *cancel_button = new wxButton( panel, wxID_CANCEL,
466                                             wxU(_("Cancel")) );
467
468     /* Create notebook */
469     notebook = new wxNotebook( panel, Notebook_Event );
470     wxNotebookSizer *notebook_sizer = new wxNotebookSizer( notebook );
471
472     notebook->AddPage( FilePanel( notebook ), wxU(_("File")),
473                        i_access_method == FILE_ACCESS );
474     notebook->AddPage( DiscPanel( notebook ), wxU(_("Disc")),
475                        i_access_method == DISC_ACCESS );
476     notebook->AddPage( NetPanel( notebook ), wxU(_("Network")),
477                        i_access_method == NET_ACCESS );
478
479     module_t *p_module = config_FindModule( VLC_OBJECT(p_intf), "v4l" );
480     if( p_module )
481     {
482         AutoBuiltPanel *autopanel =
483             new AutoBuiltPanel( notebook, this, p_intf, p_module );
484         input_tab_array.Add( autopanel );
485         notebook->AddPage( autopanel, wxU( p_module->psz_shortname ?
486                         p_module->psz_shortname : p_module->psz_object_name ),
487                            i_access_method == CAPTURE_ACCESS );
488     }
489
490     p_module = config_FindModule( VLC_OBJECT(p_intf), "pvr" );
491     if( p_module )
492     {
493         AutoBuiltPanel *autopanel =
494             new AutoBuiltPanel( notebook, this, p_intf, p_module );
495         input_tab_array.Add( autopanel );
496         notebook->AddPage( autopanel, wxU( p_module->psz_shortname ?
497                         p_module->psz_shortname : p_module->psz_object_name ),
498                            i_access_method == CAPTURE_ACCESS );
499     }
500
501     p_module = config_FindModule( VLC_OBJECT(p_intf), "dvb" );
502     if( p_module )
503     {
504         AutoBuiltPanel *autopanel =
505             new AutoBuiltPanel( notebook, this, p_intf, p_module );
506         input_tab_array.Add( autopanel );
507         notebook->AddPage( autopanel, wxU( p_module->psz_shortname ?
508                         p_module->psz_shortname : p_module->psz_object_name ),
509                            i_access_method == CAPTURE_ACCESS );
510     }
511
512     p_module = config_FindModule( VLC_OBJECT(p_intf), "dshow" );
513     if( p_module )
514     {
515         AutoBuiltPanel *autopanel =
516             new AutoBuiltPanel( notebook, this, p_intf, p_module );
517         input_tab_array.Add( autopanel );
518         notebook->AddPage( autopanel, wxU( p_module->psz_shortname ?
519                         p_module->psz_shortname : p_module->psz_object_name ),
520                            i_access_method == CAPTURE_ACCESS );
521     }
522
523     /* Update Disc panel */
524     wxCommandEvent dummy_event;
525     OnDiscTypeChange( dummy_event );
526
527     /* Update Net panel */
528     dummy_event.SetId( NetRadio1_Event );
529     OnNetTypeChange( dummy_event );
530
531     /* Update MRL */
532     wxNotebookEvent event( wxEVT_NULL, 0, i_access_method );
533     OnPageChange( event );
534
535     /* Place everything in sizers */
536     wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
537     button_sizer->Add( ok_button, 0, wxALL, 5 );
538     button_sizer->Add( cancel_button, 0, wxALL, 5 );
539     button_sizer->Layout();
540     wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
541     wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
542     panel_sizer->Add( mrl_sizer_sizer, 0, wxEXPAND, 5 );
543     panel_sizer->Add( label, 0, wxEXPAND | wxALL, 5 );
544     panel_sizer->Add( notebook_sizer, 1, wxEXPAND | wxALL, 5 );
545     panel_sizer->Add( common_opt_sizer, 0, wxALIGN_LEFT | wxALL, 5 );
546     panel_sizer->Add( static_line, 0, wxEXPAND | wxALL, 5 );
547     panel_sizer->Add( button_sizer, 0, wxALIGN_LEFT | wxALL, 5 );
548     panel_sizer->Layout();
549     panel->SetSizerAndFit( panel_sizer );
550     main_sizer->Add( panel, 1, wxGROW, 0 );
551     main_sizer->Layout();
552     SetSizerAndFit( main_sizer );
553 }
554
555 OpenDialog::~OpenDialog()
556 {
557     /* Clean up */
558     if( file_dialog ) delete file_dialog;
559     if( sout_dialog ) delete sout_dialog;
560     if( subsfile_dialog ) delete subsfile_dialog;
561 }
562
563 int OpenDialog::Show( int i_access_method, int i_arg )
564 {
565     notebook->SetSelection( i_access_method );
566     int i_ret = wxDialog::Show();
567     Raise();
568     SetFocus();
569     i_open_arg = i_arg;
570     return i_ret;
571 }
572
573 int OpenDialog::Show()
574 {
575     int i_ret = wxDialog::Show();
576     Raise();
577     SetFocus();
578     return i_ret;
579 }
580
581 /*****************************************************************************
582  * Private methods.
583  *****************************************************************************/
584 wxPanel *OpenDialog::FilePanel( wxWindow* parent )
585 {
586     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
587                                   wxSize(200, 200) );
588
589     wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
590
591     /* Create browse file line */
592     wxBoxSizer *file_sizer = new wxBoxSizer( wxHORIZONTAL );
593
594     file_combo = new wxComboBox( panel, FileName_Event, wxT(""),
595                                  wxPoint(20,25), wxSize(200, -1), 0, NULL );
596     wxButton *browse_button = new wxButton( panel, FileBrowse_Event,
597                                             wxU(_("Browse...")) );
598     file_sizer->Add( file_combo, 1, wxALL, 5 );
599     file_sizer->Add( browse_button, 0, wxALL, 5 );
600
601     /* Create Subtitles File checkox */
602     wxFlexGridSizer *subsfile_sizer = new wxFlexGridSizer( 2, 1, 20 );
603     subsfile_checkbox = new wxCheckBox( panel, SubsFileEnable_Event,
604                                         wxU(_("Subtitle options")) );
605     subsfile_checkbox->SetToolTip( wxU(_("Force options for separate subtitle files.")) );
606     subsfile_sizer->Add( subsfile_checkbox, 0,
607                          wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
608     subsfile_button = new wxButton( panel, SubsFileSettings_Event,
609                                     wxU(_("Settings...")) );
610     subsfile_button->Disable();
611
612     char *psz_subsfile = config_GetPsz( p_intf, "sub-file" );
613     if( psz_subsfile && *psz_subsfile )
614     {
615         subsfile_checkbox->SetValue(TRUE);
616         subsfile_button->Enable();
617         subsfile_mrl.Add( wxString(wxT("sub-file=")) + wxL2U(psz_subsfile) );
618     }
619     if( psz_subsfile ) free( psz_subsfile );
620
621     subsfile_sizer->Add( subsfile_button, 1,
622                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
623
624     sizer->Add( file_sizer, 0, wxEXPAND | wxALL, 5 );
625     sizer->Add( subsfile_sizer, 0, wxEXPAND | wxALL, 5 );
626     panel->SetSizerAndFit( sizer );
627     return panel;
628 }
629
630 wxPanel *OpenDialog::DiscPanel( wxWindow* parent )
631 {
632     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
633                                   wxSize(200, 200) );
634
635     wxBoxSizer *sizer_row = new wxBoxSizer( wxVERTICAL );
636     wxFlexGridSizer *sizer = new wxFlexGridSizer( 2, 3, 20 );
637
638     static const wxString disc_type_array[] =
639     {
640         wxU(_("DVD (menus)")),
641         wxU(_("DVD")),
642         wxU(_("VCD")),
643         wxU(_("Audio CD")),
644     };
645
646     disc_type = new wxRadioBox( panel, DiscType_Event, wxU(_("Disc type")),
647                                 wxDefaultPosition, wxDefaultSize,
648                                 WXSIZEOF(disc_type_array), disc_type_array,
649                                 WXSIZEOF(disc_type_array), wxRA_SPECIFY_COLS );
650
651     sizer_row->Add( disc_type, i_disc_type_selection, wxEXPAND | wxALL, 5 );
652
653     wxStaticText *label = new wxStaticText( panel, -1, wxU(_("Device name")) );
654     disc_device = new wxTextCtrl( panel, DiscDevice_Event, wxT(""),
655                                   wxDefaultPosition, wxDefaultSize,
656                                   wxTE_PROCESS_ENTER);
657
658     sizer->Add( label, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
659     sizer->Add( disc_device, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
660
661     disc_title_label = new wxStaticText( panel, -1, wxU(_("Title")) );
662     disc_title = new wxSpinCtrl( panel, DiscTitle_Event );
663     sizer->Add( disc_title_label, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
664     sizer->Add( disc_title, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
665
666     disc_chapter_label = new wxStaticText( panel, -1, wxU(_("Chapter")) );
667     disc_chapter = new wxSpinCtrl( panel, DiscChapter_Event );
668     sizer->Add( disc_chapter_label, 0,
669                 wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
670     sizer->Add( disc_chapter, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
671
672     disc_sub_label = new wxStaticText( panel, -1, wxU(_("Subtitles track")) );
673     disc_sub = new wxSpinCtrl( panel, DiscSub_Event );
674     sizer->Add( disc_sub_label, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
675     sizer->Add( disc_sub, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
676     disc_sub->SetRange( -1, 255 );
677     i_disc_sub = config_GetInt( p_intf, "sub-track" );
678     disc_sub->SetValue( i_disc_sub );
679
680     sizer_row->Add( sizer, 0, wxEXPAND | wxALL, 5 );
681
682     panel->SetSizerAndFit( sizer_row );
683     return panel;
684 }
685
686 wxPanel *OpenDialog::NetPanel( wxWindow* parent )
687 {
688     int i;
689     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
690                                   wxSize(200, 200) );
691
692     wxBoxSizer *sizer_row = new wxBoxSizer( wxVERTICAL );
693     wxFlexGridSizer *sizer = new wxFlexGridSizer( 2, 4, 20 );
694
695     static const wxString net_type_array[] =
696     {
697         wxU(_("UDP/RTP")),
698         wxU(_("UDP/RTP Multicast")),
699         wxU(_("HTTP/FTP/MMS")),
700         wxU(_("RTSP"))
701     };
702
703     for( i=0; i<4; i++ )
704     {
705         net_radios[i] = new wxRadioButton( panel, NetRadio1_Event + i,
706                                            net_type_array[i],
707                                            wxDefaultPosition, wxDefaultSize,
708                                            wxRB_SINGLE );
709
710         net_subpanels[i] = new wxPanel( panel, -1,
711                                         wxDefaultPosition, wxDefaultSize );
712     }
713
714     /* UDP/RTP row */
715     wxFlexGridSizer *subpanel_sizer;
716     wxStaticText *label;
717     i_net_ports[0] = config_GetInt( p_intf, "server-port" );
718     subpanel_sizer = new wxFlexGridSizer( 3, 1, 20 );
719     label = new wxStaticText( net_subpanels[0], -1, wxU(_("Port")) );
720     net_ports[0] = new wxSpinCtrl( net_subpanels[0], NetPort1_Event,
721                                    wxString::Format(wxT("%d"), i_net_ports[0]),
722                                    wxDefaultPosition, wxDefaultSize,
723                                    wxSP_ARROW_KEYS,
724                                    0, 16000, i_net_ports[0] );
725
726     subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
727     subpanel_sizer->Add( net_ports[0], 1,
728                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
729     net_ipv6 = new wxCheckBox( net_subpanels[0], NetForceIPv6_Event,
730                                wxU(_("Force IPv6")));
731     subpanel_sizer->Add( net_ipv6, 0,
732                          wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
733     net_subpanels[0]->SetSizerAndFit( subpanel_sizer );
734     net_radios[0]->SetValue( TRUE );
735
736     /* UDP/RTP Multicast row */
737     subpanel_sizer = new wxFlexGridSizer( 4, 1, 20 );
738     label = new wxStaticText( net_subpanels[1], -1, wxU(_("Address")) );
739     net_addrs[1] = new wxTextCtrl( net_subpanels[1], NetAddr2_Event, wxT(""),
740                                    wxDefaultPosition, wxDefaultSize,
741                                    wxTE_PROCESS_ENTER);
742     subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
743     subpanel_sizer->Add( net_addrs[1], 1,
744                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
745
746     label = new wxStaticText( net_subpanels[1], -1, wxU(_("Port")) );
747     i_net_ports[1] = i_net_ports[0];
748     net_ports[1] = new wxSpinCtrl( net_subpanels[1], NetPort2_Event,
749                                    wxString::Format(wxT("%d"), i_net_ports[1]),
750                                    wxDefaultPosition, wxDefaultSize,
751                                    wxSP_ARROW_KEYS,
752                                    0, 16000, i_net_ports[1] );
753
754     subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
755     subpanel_sizer->Add( net_ports[1], 1,
756                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
757     net_subpanels[1]->SetSizerAndFit( subpanel_sizer );
758
759     /* HTTP and RTSP rows */
760     for( i=2; i<4; i++ )
761     {
762         subpanel_sizer = new wxFlexGridSizer( 2, 1, 20 );
763         label = new wxStaticText( net_subpanels[i], -1, wxU(_("URL")) );
764         net_addrs[i] = new wxTextCtrl( net_subpanels[i], NetAddr1_Event + i,
765                                        (i == 2) ? wxT("") : wxT("rtsp://"),
766                                        wxDefaultPosition, wxSize( 200, -1 ),
767                                        wxTE_PROCESS_ENTER);
768         subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
769         subpanel_sizer->Add( net_addrs[i], 1,
770                              wxEXPAND | wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
771         net_subpanels[i]->SetSizerAndFit( subpanel_sizer );
772     }
773
774     /* Stuff everything into the main panel */
775     for( i=0; i<4; i++ )
776     {
777         sizer->Add( net_radios[i], 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL |
778                     wxALL, 5 );
779         sizer->Add( net_subpanels[i], 1, wxEXPAND | wxALIGN_LEFT |
780                     wxALIGN_CENTER_VERTICAL | wxALL, 5  );
781     }
782
783     sizer_row->Add( sizer, 0, wxEXPAND | wxALL, 5 );
784
785     panel->SetSizerAndFit( sizer_row );
786     return panel;
787 }
788
789 void OpenDialog::UpdateMRL()
790 {
791     UpdateMRL( i_current_access_method );
792 }
793
794 void OpenDialog::UpdateMRL( int i_access_method )
795 {
796     wxString mrltemp, caching_name;
797
798     i_current_access_method = i_access_method;
799
800     switch( i_access_method )
801     {
802     case FILE_ACCESS:
803         mrltemp = file_combo->GetValue();
804         caching_name = wxT("file-caching");
805         break;
806
807     case DISC_ACCESS:
808         i_disc_type_selection = disc_type->GetSelection();
809
810         switch ( i_disc_type_selection )
811         {
812         case 0: /* DVD with menus */
813         case 1: /* DVD without menus */
814             if( i_disc_type_selection == 0 )
815             {
816                 mrltemp = wxT("dvd://") + disc_device->GetValue();
817                 caching_name = wxT("dvdnav-caching");
818             }
819             else
820             {
821                 mrltemp = wxT("dvdsimple://") + disc_device->GetValue();
822                 caching_name = wxT("dvdread-caching");
823             }
824
825             if( i_disc_title > 0 )
826             {
827                 mrltemp += wxString::Format( wxT("@%d"), i_disc_title );
828
829                 if( i_disc_chapter > 0 )
830                     mrltemp += wxString::Format( wxT(":%d"), i_disc_chapter );
831             }
832
833             if( i_disc_sub >= 0 )
834                 mrltemp += wxString::Format( wxT("  :sub-track=%d"),
835                                              i_disc_sub );
836             break;
837
838         case 2:  /* VCD of some sort */
839 #ifdef HAVE_VCDX
840             mrltemp = wxT("vcdx://") + disc_device->GetValue();
841             if( i_disc_title > 0 )
842                 mrltemp += wxString::Format( wxT("@%c%d"),
843                                   config_GetInt( p_intf, "vcdx-PBC"  )
844                                   ? 'P' : 'E', i_disc_title );
845 #else
846             mrltemp = wxT("vcd://") + disc_device->GetValue();
847             if( i_disc_title > 0 )
848                 mrltemp += wxString::Format( wxT("@%d"), i_disc_title );
849 #endif
850
851             if( i_disc_sub >= 0 )
852                 mrltemp += wxString::Format( wxT("  :sub-track=%d"),
853                                              i_disc_sub );
854
855             caching_name = wxT("vcd-caching");
856             break;
857
858         case 3: /* CD-DA */
859             mrltemp = 
860 #ifdef HAVE_CDDAX
861               wxT("cddax://") 
862 #else
863               wxT("cdda://") 
864 #endif
865               + disc_device->GetValue();
866             if( i_disc_title > 0 )
867                 mrltemp += wxString::Format( wxT("@%d"), i_disc_title );
868
869             caching_name = wxT("cdda-caching");
870             break;
871
872         default:
873             msg_Err( p_intf, "invalid selection (%d)",
874                      disc_type->GetSelection() );
875         }
876
877         break;
878
879     case NET_ACCESS:
880         switch( i_net_type )
881         {
882         case 0:
883             mrltemp = wxT("udp://");
884             if ( net_ipv6->GetValue() )
885             {
886                 mrltemp += wxT("@[::]");
887             }
888             if( i_net_ports[0] !=
889                 config_GetInt( p_intf, "server-port" ) )
890             {
891                 mrltemp += wxString::Format( wxT("@:%d"), i_net_ports[0] );
892             }
893
894             caching_name = wxT("udp-caching");
895             break;
896
897         case 1:
898             mrltemp = wxT("udp://@");
899             if ((net_addrs[1]->GetLineText(0).Find (':') != -1)
900                 && (net_addrs[1]->GetLineText(0)[0u] != '['))
901             {
902                 /* automatically adds '[' and ']' to IPv6 addresses */
903                 mrltemp += wxT("[") + net_addrs[1]->GetLineText(0)
904                          + wxT("]");
905             }
906             else
907             {
908                 mrltemp += net_addrs[1]->GetLineText(0);
909             }
910             if( i_net_ports[1] != config_GetInt( p_intf, "server-port" ) )
911             {
912                 mrltemp += wxString::Format( wxT(":%d"), i_net_ports[1] );
913             }
914
915             caching_name = wxT("udp-caching");
916             break;
917
918         case 2:
919             /* http access */
920             if( net_addrs[2]->GetLineText(0).Find(wxT("://")) == -1 )
921                 mrltemp = wxT("http://");
922
923             mrltemp += net_addrs[2]->GetLineText(0);
924
925             caching_name = wxT("http-caching");
926             break;
927
928         case 3:
929             /* RTSP access */
930             if( net_addrs[3]->GetLineText(0).Find(wxT("rtsp://")) != 0 )
931             {
932                 mrltemp = wxT("rtsp://");
933             }
934             mrltemp += net_addrs[3]->GetLineText(0);
935
936             caching_name = wxT("rtsp-caching");
937             break;
938         }
939         break;
940
941     default:
942         {
943             int i_item = i_access_method - MAX_ACCESS;
944
945             if( i_item < 0 || i_item >= (int)input_tab_array.GetCount() )
946                 break;
947
948             AutoBuiltPanel *input_panel = input_tab_array.Item( i_item );
949
950             mrltemp = input_panel->name + wxT("://");
951
952             for( int i=0; i < (int)input_panel->config_array.GetCount(); i++ )
953             {
954                 ConfigControl *control = input_panel->config_array.Item(i);
955
956                 mrltemp += wxT(" :");
957
958                 if( control->GetType() == CONFIG_ITEM_BOOL &&
959                     !control->GetIntValue() ) mrltemp += wxT("no-");
960
961                 mrltemp += control->GetName();
962
963                 switch( control->GetType() )
964                 {
965                 case CONFIG_ITEM_STRING:
966                 case CONFIG_ITEM_FILE:
967                 case CONFIG_ITEM_DIRECTORY:
968                 case CONFIG_ITEM_MODULE:
969                     mrltemp += wxT("=\"") + control->GetPszValue() + wxT("\"");
970                     break;
971                 case CONFIG_ITEM_INTEGER:
972                     mrltemp +=
973                         wxString::Format( wxT("=%i"), control->GetIntValue() );
974                     break;
975                 case CONFIG_ITEM_FLOAT:
976                     mrltemp +=
977                         wxString::Format(wxT("=%f"), control->GetFloatValue());
978                     break;
979                 }
980             }
981
982             if( input_panel->p_advanced_mrl_combo &&
983                 input_panel->p_advanced_mrl_combo->GetValue() )
984             {
985                 mrltemp += wxT(" ") +
986                     input_panel->p_advanced_mrl_combo->GetValue();
987             }
988         }
989         break;
990     }
991
992     if( caching_name.size() )
993     {
994         if( caching_value->IsEnabled() )
995         {
996             mrltemp += wxT("  :") + caching_name +
997                 wxString::Format( wxT("=%d"), i_caching );
998         }
999         else
1000         {
1001             int i_value = config_GetInt( p_intf, caching_name.mb_str() );
1002             caching_value->SetValue( i_value );
1003         }
1004     }
1005
1006     mrl_combo->SetValue( mrltemp );
1007 }
1008
1009 /*****************************************************************************
1010  * Events methods.
1011  *****************************************************************************/
1012 void OpenDialog::OnOk( wxCommandEvent& WXUNUSED(event) )
1013 {
1014     mrl = SeparateEntries( mrl_combo->GetValue() );
1015     mrl_combo->Append( mrl_combo->GetValue() );
1016     if( mrl_combo->GetCount() > 10 ) mrl_combo->Delete( 0 );
1017     mrl_combo->SetSelection( mrl_combo->GetCount() - 1 );
1018
1019     if( i_method == OPEN_STREAM )
1020     {
1021         if( IsModal() ) EndModal( wxID_OK );
1022         Hide();
1023         return;
1024     }
1025
1026     /* Update the playlist */
1027     playlist_t *p_playlist =
1028         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
1029                                        FIND_ANYWHERE );
1030     if( p_playlist == NULL ) return;
1031
1032     for( int i = 0; i < (int)mrl.GetCount(); i++ )
1033     {
1034         vlc_bool_t b_start = !i && i_open_arg;
1035         playlist_item_t *p_item =
1036             playlist_ItemNew( p_intf, (const char*)mrl[i].mb_str(),
1037                               (const char *)mrl[i].mb_str() );
1038
1039         /* Insert options */
1040         while( i + 1 < (int)mrl.GetCount() &&
1041                ((const char *)mrl[i + 1].mb_str())[0] == ':' )
1042         {
1043             playlist_ItemAddOption( p_item, mrl[i + 1].mb_str() );
1044             i++;
1045         }
1046
1047         /* Get the options from the subtitles dialog */
1048         if( subsfile_checkbox->IsChecked() && subsfile_mrl.GetCount() )
1049         {
1050             for( int j = 0; j < (int)subsfile_mrl.GetCount(); j++ )
1051             {
1052                 playlist_ItemAddOption( p_item, subsfile_mrl[j].mb_str() );
1053             }
1054         }
1055
1056         /* Get the options from the stream output dialog */
1057         if( sout_checkbox->IsChecked() && sout_mrl.GetCount() )
1058         {
1059             for( int j = 0; j < (int)sout_mrl.GetCount(); j++ )
1060             {
1061                 playlist_ItemAddOption( p_item, sout_mrl[j].mb_str() );
1062             }
1063         }
1064
1065         int i_id = playlist_AddItem( p_playlist, p_item,
1066                                      PLAYLIST_APPEND, PLAYLIST_END );
1067
1068         if( b_start )
1069         {
1070             playlist_Control( p_playlist, PLAYLIST_ITEMPLAY , p_item );
1071         }
1072     }
1073
1074     vlc_object_release( p_playlist );
1075
1076     Hide();
1077
1078     if( IsModal() ) EndModal( wxID_OK );
1079 }
1080
1081 void OpenDialog::OnCancel( wxCommandEvent& WXUNUSED(event) )
1082 {
1083     Hide();
1084
1085     if( IsModal() ) EndModal( wxID_CANCEL );
1086 }
1087
1088 void OpenDialog::OnPageChange( wxNotebookEvent& event )
1089 {
1090     UpdateMRL( event.GetSelection() );
1091 }
1092
1093 void OpenDialog::OnMRLChange( wxCommandEvent& event )
1094 {
1095     //mrl = SeparateEntries( event.GetString() );
1096 }
1097
1098 /*****************************************************************************
1099  * File panel event methods.
1100  *****************************************************************************/
1101 void OpenDialog::OnFilePanelChange( wxCommandEvent& WXUNUSED(event) )
1102 {
1103     UpdateMRL( FILE_ACCESS );
1104 }
1105
1106 void OpenDialog::OnFileBrowse( wxCommandEvent& WXUNUSED(event) )
1107 {
1108     if( file_dialog == NULL )
1109         file_dialog = new wxFileDialog( this, wxU(_("Open File")),
1110             wxT(""), wxT(""), wxT("*"), wxOPEN | wxMULTIPLE );
1111
1112     if( file_dialog && file_dialog->ShowModal() == wxID_OK )
1113     {
1114         wxArrayString paths;
1115         wxString path;
1116
1117         file_dialog->GetPaths( paths );
1118
1119         for( size_t i = 0; i < paths.GetCount(); i++ )
1120         {
1121             if( paths[i].Find( wxT(' ') ) >= 0 )
1122                 path += wxT("\"") + paths[i] + wxT("\" ");
1123             else
1124                 path += paths[i] + wxT(" ");
1125         }
1126
1127         file_combo->SetValue( path );
1128         file_combo->Append( path );
1129         if( file_combo->GetCount() > 10 ) file_combo->Delete( 0 );
1130         UpdateMRL( FILE_ACCESS );
1131     }
1132 }
1133
1134 /*****************************************************************************
1135  * Disc panel event methods.
1136  *****************************************************************************/
1137 void OpenDialog::OnDiscPanelChange( wxCommandEvent& event )
1138 {
1139     if( event.GetId() == DiscTitle_Event ) i_disc_title = event.GetInt();
1140     if( event.GetId() == DiscChapter_Event ) i_disc_chapter = event.GetInt();
1141     if( event.GetId() == DiscSub_Event ) i_disc_sub = event.GetInt();
1142
1143     UpdateMRL( DISC_ACCESS );
1144 }
1145
1146 void OpenDialog::OnDiscDeviceChange( wxCommandEvent& event )
1147 {
1148     char *psz_device;
1149
1150     switch( disc_type->GetSelection() )
1151     {
1152         case 3:
1153             psz_device = config_GetPsz( p_intf, "cd-audio" );
1154             break;
1155
1156         case 2:
1157             psz_device = config_GetPsz( p_intf, "vcd" );
1158             break;
1159
1160         default:
1161             psz_device = config_GetPsz( p_intf, "dvd" );
1162             break;
1163     }
1164
1165     if ( !psz_device ) psz_device = "";
1166
1167     if( disc_device->GetValue().Cmp( wxL2U( psz_device ) ) )
1168     {
1169         b_disc_device_changed = true;
1170     }
1171
1172     UpdateMRL( DISC_ACCESS );
1173 }
1174
1175 void OpenDialog::OnDiscTypeChange( wxCommandEvent& WXUNUSED(event) )
1176 {
1177     char *psz_device = NULL;
1178
1179     switch( disc_type->GetSelection() )
1180     {
1181
1182     case 0: /* DVD with menus */
1183     case 1: /* DVD without menus */
1184         disc_sub->Enable(); disc_sub_label->Enable();
1185         disc_chapter->Enable(); disc_chapter_label->Enable();
1186         disc_title_label->SetLabel ( wxU(_("Title")) );
1187         psz_device = config_GetPsz( p_intf, "dvd" );
1188         if( !b_disc_device_changed )
1189         {
1190             if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
1191             else disc_device->SetValue( wxT("") );
1192         }
1193         disc_title->SetRange( 0, 255 );
1194         disc_chapter->SetRange( 0, 255 );
1195         break;
1196
1197     case 2:  /* VCD of some sort */
1198         disc_sub->Enable(); disc_sub_label->Enable();
1199         disc_chapter->Disable(); disc_chapter_label->Disable();
1200         psz_device = config_GetPsz( p_intf, "vcd" );
1201         if( !b_disc_device_changed )
1202         {
1203             if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
1204             else disc_device->SetValue( wxT("") );
1205         }
1206
1207 #ifdef HAVE_VCDX
1208         disc_title_label->SetLabel ( config_GetInt( p_intf, "vcdx-PBC"  )
1209                                      ? wxT("Playback LID") : wxT("Entry") );
1210 #else
1211         disc_title_label->SetLabel ( wxU(_("Track")) );
1212 #endif
1213         disc_title->SetRange( 0, 999 );
1214         break;
1215
1216     case 3: /* CD-DA */
1217         disc_sub->Disable(); disc_sub_label->Disable();
1218         disc_chapter->Disable(); disc_chapter_label->Disable();
1219         disc_title_label->SetLabel ( wxU(_("Track")) );
1220         psz_device = config_GetPsz( p_intf, "cd-audio" );
1221         if( !b_disc_device_changed )
1222         {
1223             if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
1224             else disc_device->SetValue( wxT("") );
1225         }
1226
1227         /* There are at most 99 tracks in a CD-DA */
1228         disc_title->SetRange( 0, 99 );
1229         break;
1230
1231     default:
1232         msg_Err( p_intf, "invalid Disc type selection (%d)",
1233                  disc_type->GetSelection() );
1234         break;
1235     }
1236
1237     disc_title->SetValue( 0 ); i_disc_title = 0;
1238     disc_chapter->SetValue( 0 ); i_disc_chapter = 0;
1239
1240     if( psz_device ) free( psz_device );
1241
1242     UpdateMRL( DISC_ACCESS );
1243 }
1244
1245 /*****************************************************************************
1246  * Net panel event methods.
1247  *****************************************************************************/
1248 void OpenDialog::OnNetPanelChange( wxCommandEvent& event )
1249 {
1250     if( event.GetId() >= NetPort1_Event && event.GetId() <= NetPort3_Event )
1251     {
1252         i_net_ports[event.GetId() - NetPort1_Event] = event.GetInt();
1253     }
1254
1255     UpdateMRL( NET_ACCESS );
1256 }
1257
1258 void OpenDialog::OnNetTypeChange( wxCommandEvent& event )
1259 {
1260     int i;
1261
1262     i_net_type = event.GetId() - NetRadio1_Event;
1263
1264     for(i=0; i<4; i++)
1265     {
1266         net_radios[i]->SetValue( event.GetId() == (NetRadio1_Event+i) );
1267         net_subpanels[i]->Enable( event.GetId() == (NetRadio1_Event+i) );
1268     }
1269
1270     UpdateMRL( NET_ACCESS );
1271 }
1272
1273 /*****************************************************************************
1274  * Subtitles file event methods.
1275  *****************************************************************************/
1276 void OpenDialog::OnSubsFileEnable( wxCommandEvent& event )
1277 {
1278     subsfile_button->Enable( event.GetInt() != 0 );
1279 }
1280
1281 void OpenDialog::OnSubsFileSettings( wxCommandEvent& WXUNUSED(event) )
1282 {
1283     /* Show/hide the open dialog */
1284     if( subsfile_dialog == NULL )
1285         subsfile_dialog = new SubsFileDialog( p_intf, this );
1286
1287     if( subsfile_dialog && subsfile_dialog->ShowModal() == wxID_OK )
1288     {
1289         subsfile_mrl.Empty();
1290         subsfile_mrl.Add( wxString(wxT("sub-file=")) +
1291                           subsfile_dialog->file_combo->GetValue() );
1292         if( subsfile_dialog->encoding_combo )
1293             subsfile_mrl.Add( wxString(wxT("subsdec-encoding=")) +
1294                               subsfile_dialog->encoding_combo->GetValue() );
1295         subsfile_mrl.Add( wxString::Format(wxT("subsdec-align=%i"),
1296                            (int)subsfile_dialog->align_combo->GetClientData(
1297                            subsfile_dialog->align_combo->GetSelection()) ) );
1298
1299         subsfile_mrl.Add( wxString::Format( wxT("freetype-rel-fontsize=%i"),
1300                           (int)subsfile_dialog->size_combo->GetClientData(
1301                           subsfile_dialog->size_combo->GetSelection()) ) );
1302         subsfile_mrl.Add( wxString::Format( wxT("sub-fps=%i"),
1303                           subsfile_dialog->fps_spinctrl->GetValue() ) );
1304         subsfile_mrl.Add( wxString::Format( wxT("sub-delay=%i"),
1305                           subsfile_dialog->delay_spinctrl->GetValue() ) );
1306     }
1307 }
1308
1309 /*****************************************************************************
1310  * Stream output event methods.
1311  *****************************************************************************/
1312 void OpenDialog::OnSoutEnable( wxCommandEvent& event )
1313 {
1314     sout_button->Enable( event.GetInt() != 0 );
1315 }
1316
1317 void OpenDialog::OnSoutSettings( wxCommandEvent& WXUNUSED(event) )
1318 {
1319     /* Show/hide the open dialog */
1320     if( sout_dialog == NULL )
1321         sout_dialog = new SoutDialog( p_intf, this );
1322
1323     if( sout_dialog && sout_dialog->ShowModal() == wxID_OK )
1324     {
1325         sout_mrl = sout_dialog->GetOptions();
1326     }
1327 }
1328
1329 /*****************************************************************************
1330  * Caching event methods.
1331  *****************************************************************************/
1332 void OpenDialog::OnCachingEnable( wxCommandEvent& event )
1333 {
1334     caching_value->Enable( event.GetInt() != 0 );
1335     i_caching = caching_value->GetValue();
1336     UpdateMRL();
1337 }
1338
1339 void OpenDialog::OnCachingChange( wxCommandEvent& event )
1340 {
1341     i_caching = event.GetInt();
1342     UpdateMRL();
1343 }
1344
1345 /*****************************************************************************
1346  * Utility functions.
1347  *****************************************************************************/
1348 wxArrayString SeparateEntries( wxString entries )
1349 {
1350     vlc_bool_t b_quotes_mode = VLC_FALSE;
1351
1352     wxArrayString entries_array;
1353     wxString entry;
1354
1355     wxStringTokenizer token( entries, wxT(" \t\r\n\""), wxTOKEN_RET_DELIMS );
1356
1357     while( token.HasMoreTokens() )
1358     {
1359         entry += token.GetNextToken();
1360
1361         if( entry.IsEmpty() ) continue;
1362
1363         if( !b_quotes_mode && entry.Last() == wxT('\"') )
1364         {
1365             /* Enters quotes mode */
1366             entry.RemoveLast();
1367             b_quotes_mode = VLC_TRUE;
1368         }
1369         else if( b_quotes_mode && entry.Last() == wxT('\"') )
1370         {
1371             /* Finished the quotes mode */
1372             entry.RemoveLast();
1373             b_quotes_mode = VLC_FALSE;
1374         }
1375         else if( !b_quotes_mode && entry.Last() != wxT('\"') )
1376         {
1377             /* we found a non-quoted standalone string */
1378             if( token.HasMoreTokens() ||
1379                 entry.Last() == wxT(' ') || entry.Last() == wxT('\t') ||
1380                 entry.Last() == wxT('\r') || entry.Last() == wxT('\n') )
1381                 entry.RemoveLast();
1382             if( !entry.IsEmpty() ) entries_array.Add( entry );
1383             entry.Empty();
1384         }
1385         else
1386         {;}
1387     }
1388
1389     if( !entry.IsEmpty() ) entries_array.Add( entry );
1390
1391     return entries_array;
1392 }