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