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