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