* modules/gui/wxwindows/open.cpp: move the "open subtitles" line into the file panel.
[vlc.git] / modules / gui / wxwindows / open.cpp
1 /*****************************************************************************
2  * open.cpp : wxWindows plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2001 VideoLAN
5  * $Id: open.cpp,v 1.35 2003/07/26 14:19:04 gbazin Exp $
6  *
7  * Authors: Gildas Bazin <gbazin@netcourrier.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28 #include <errno.h>                                                 /* ENOMEM */
29 #include <string.h>                                            /* strerror() */
30 #include <stdio.h>
31
32 #include <vlc/vlc.h>
33
34 #ifdef WIN32                                                 /* mingw32 hack */
35 #undef Yield
36 #undef CreateDialog
37 #endif
38
39 /* Let vlc take care of the i18n stuff */
40 #define WXINTL_NO_GETTEXT_MACRO
41
42 #include <wx/wxprec.h>
43 #include <wx/wx.h>
44 #include <wx/notebook.h>
45 #include <wx/textctrl.h>
46 #include <wx/combobox.h>
47 #include <wx/spinctrl.h>
48 #include <wx/statline.h>
49 #include <wx/tokenzr.h>
50
51 #include <vlc/intf.h>
52
53 #include "wxwindows.h"
54
55 #ifndef wxRB_SINGLE
56 #   define wxRB_SINGLE 0
57 #endif
58
59 /*****************************************************************************
60  * Event Table.
61  *****************************************************************************/
62
63 /* IDs for the controls and the menu commands */
64 enum
65 {
66     Notebook_Event = wxID_HIGHEST,
67     MRL_Event,
68
69     FileBrowse_Event,
70     FileName_Event,
71
72     DiscType_Event,
73     DiscDevice_Event,
74     DiscTitle_Event,
75     DiscChapter_Event,
76
77     NetType_Event,
78     NetRadio1_Event, NetRadio2_Event, NetRadio3_Event,
79     NetPort1_Event, NetPort2_Event, NetPort3_Event,
80     NetAddr1_Event, NetAddr2_Event, NetAddr3_Event,
81
82     SubsFileEnable_Event,
83     SubsFileSettings_Event,
84
85     SoutEnable_Event,
86     SoutSettings_Event,
87
88     DemuxDump_Event,
89     DemuxDumpEnable_Event,
90     DemuxDumpBrowse_Event,
91 };
92
93 BEGIN_EVENT_TABLE(OpenDialog, wxFrame)
94     /* Button events */
95     EVT_BUTTON(wxID_OK, OpenDialog::OnOk)
96     EVT_BUTTON(wxID_CANCEL, OpenDialog::OnCancel)
97
98     EVT_NOTEBOOK_PAGE_CHANGED(Notebook_Event, OpenDialog::OnPageChange)
99
100     EVT_TEXT(MRL_Event, OpenDialog::OnMRLChange) 
101
102     /* Events generated by the file panel */
103     EVT_TEXT(FileName_Event, OpenDialog::OnFilePanelChange)
104     EVT_BUTTON(FileBrowse_Event, OpenDialog::OnFileBrowse)
105
106     /* Events generated by the disc panel */
107     EVT_RADIOBOX(DiscType_Event, OpenDialog::OnDiscTypeChange)
108     EVT_TEXT(DiscDevice_Event, OpenDialog::OnDiscPanelChange)
109     EVT_TEXT(DiscTitle_Event, OpenDialog::OnDiscPanelChange)
110     EVT_SPINCTRL(DiscTitle_Event, OpenDialog::OnDiscPanelChange)
111     EVT_TEXT(DiscChapter_Event, OpenDialog::OnDiscPanelChange)
112     EVT_SPINCTRL(DiscChapter_Event, OpenDialog::OnDiscPanelChange)
113
114     /* Events generated by the net panel */
115     EVT_RADIOBUTTON(NetRadio1_Event, OpenDialog::OnNetTypeChange)
116     EVT_RADIOBUTTON(NetRadio2_Event, OpenDialog::OnNetTypeChange)
117     EVT_RADIOBUTTON(NetRadio3_Event, OpenDialog::OnNetTypeChange)
118     EVT_TEXT(NetPort1_Event, OpenDialog::OnNetPanelChange)
119     EVT_SPINCTRL(NetPort1_Event, OpenDialog::OnNetPanelChange)
120     EVT_TEXT(NetPort2_Event, OpenDialog::OnNetPanelChange)
121     EVT_SPINCTRL(NetPort2_Event, OpenDialog::OnNetPanelChange)
122     EVT_TEXT(NetPort3_Event, OpenDialog::OnNetPanelChange)
123     EVT_SPINCTRL(NetPort3_Event, OpenDialog::OnNetPanelChange)
124     EVT_TEXT(NetAddr2_Event, OpenDialog::OnNetPanelChange)
125     EVT_TEXT(NetAddr3_Event, OpenDialog::OnNetPanelChange)
126
127     /* Events generated by the subtitle file buttons */
128     EVT_CHECKBOX(SubsFileEnable_Event, OpenDialog::OnSubsFileEnable)
129     EVT_BUTTON(SubsFileSettings_Event, OpenDialog::OnSubsFileSettings)
130
131     /* Events generated by the stream output buttons */
132     EVT_CHECKBOX(SoutEnable_Event, OpenDialog::OnSoutEnable)
133     EVT_BUTTON(SoutSettings_Event, OpenDialog::OnSoutSettings)
134
135     /* Events generated by the demux dump buttons */
136     EVT_CHECKBOX(DemuxDumpEnable_Event, OpenDialog::OnDemuxDumpEnable)
137     EVT_TEXT(DemuxDump_Event, OpenDialog::OnDemuxDumpChange)
138     EVT_BUTTON(DemuxDumpBrowse_Event, OpenDialog::OnDemuxDumpBrowse)
139
140     /* Hide the window when the user closes the window */
141     EVT_CLOSE(OpenDialog::OnCancel)
142
143 END_EVENT_TABLE()
144
145 /*****************************************************************************
146  * Constructor.
147  *****************************************************************************/
148 OpenDialog::OpenDialog( intf_thread_t *_p_intf, wxWindow *_p_parent,
149                         int i_access_method, int i_arg ):
150     wxFrame( _p_parent, -1, wxU(_("Open Target")), wxDefaultPosition,
151              wxDefaultSize, wxDEFAULT_FRAME_STYLE )
152 {
153     /* Initializations */
154     p_intf = _p_intf;
155     p_parent = _p_parent;
156     SetIcon( *p_intf->p_sys->p_icon );
157     file_dialog = NULL;
158     sout_dialog = NULL;
159     subsfile_dialog = NULL;
160     demuxdump_dialog = NULL;
161
162     /* Create a panel to put everything in */
163     wxPanel *panel = new wxPanel( this, -1 );
164     panel->SetAutoLayout( TRUE );
165
166     /* Create MRL combobox */
167     wxBoxSizer *mrl_sizer_sizer = new wxBoxSizer( wxHORIZONTAL );
168     wxStaticBox *mrl_box = new wxStaticBox( panel, -1,
169                                wxU(_("Media Resource Locator (MRL)")) );
170     wxStaticBoxSizer *mrl_sizer = new wxStaticBoxSizer( mrl_box,
171                                                         wxHORIZONTAL );
172     wxStaticText *mrl_label = new wxStaticText( panel, -1,
173                                                 wxU(_("Open Target:")) );
174     mrl_combo = new wxComboBox( panel, MRL_Event, wxT(""),
175                                 wxPoint(20,25), wxSize(120, -1),
176                                 0, NULL );
177     mrl_combo->SetToolTip( wxU(_("You can use this field directly by typing "
178         "the full MRL you want to open.\n""Alternatively, the field will be "
179         "filled automatically when you use the controls below.")) );
180
181     mrl_sizer->Add( mrl_label, 0, wxALL | wxALIGN_CENTER, 5 );
182     mrl_sizer->Add( mrl_combo, 1, wxALL | wxALIGN_CENTER, 5 );
183     mrl_sizer_sizer->Add( mrl_sizer, 1, wxEXPAND | wxALL, 5 );
184
185
186     /* Create Static Text */
187     wxStaticText *label = new wxStaticText( panel, -1,
188         wxU(_("Alternatively, you can build an MRL using one of the "
189               "following predefined targets:")) );
190
191     /* Create Stream Output checkox */
192     wxFlexGridSizer *sout_sizer = new wxFlexGridSizer( 2, 1, 20 );
193     sout_checkbox = new wxCheckBox( panel, SoutEnable_Event,
194                                     wxU(_("Stream output")) );
195     sout_checkbox->SetToolTip( wxU(_("Use VLC as a stream server")) );
196     sout_sizer->Add( sout_checkbox, 0,
197                      wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
198     sout_button = new wxButton( panel, SoutSettings_Event,
199                                 wxU(_("Settings...")) );
200     sout_button->Disable();
201
202     char *psz_sout = config_GetPsz( p_intf, "sout" );
203     if( psz_sout && *psz_sout )
204     {
205         sout_checkbox->SetValue(TRUE);
206         sout_button->Enable();
207         subsfile_mrl.Add( wxString(wxT("sout=")) + wxU(psz_sout) );
208     }
209     if( psz_sout ) free( psz_sout );
210
211     sout_sizer->Add( sout_button, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
212
213     /* Create Demux Dump checkox */
214     wxBoxSizer *demuxdump_sizer = new wxBoxSizer( wxHORIZONTAL );
215     demuxdump_checkbox = new wxCheckBox( panel, DemuxDumpEnable_Event,
216                                wxU(_("Capture input stream")) );
217     demuxdump_checkbox->SetToolTip(
218         wxU(_("Capture the stream you are playing to a file")) );
219     demuxdump_textctrl = new wxTextCtrl( panel, DemuxDump_Event, wxT(""),
220                                          wxDefaultPosition, wxDefaultSize,
221                                          wxTE_PROCESS_ENTER );
222     demuxdump_button = new wxButton( panel, DemuxDumpBrowse_Event,
223                                      wxU(_("Browse...")) );
224
225     char *psz_demuxdump = config_GetPsz( p_intf, "demuxdump-file" );
226     if( psz_demuxdump && *psz_demuxdump )
227     {
228         demuxdump_textctrl->SetValue( wxU(psz_demuxdump) );
229     }
230     if( psz_demuxdump ) free( psz_demuxdump );
231
232     demuxdump_textctrl->Disable();
233     demuxdump_button->Disable();
234     demuxdump_sizer->Add( demuxdump_checkbox, 0,
235                           wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
236     demuxdump_sizer->Add( demuxdump_button, 0,
237                           wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL, 10 );
238     demuxdump_sizer->Add( demuxdump_textctrl, 1, wxRIGHT, 10 );
239
240     /* Separation */
241     wxStaticLine *static_line = new wxStaticLine( panel, wxID_OK );
242
243     /* Create the buttons */
244     wxButton *ok_button = new wxButton( panel, wxID_OK, wxU(_("OK")) );
245     ok_button->SetDefault();
246     wxButton *cancel_button = new wxButton( panel, wxID_CANCEL,
247                                             wxU(_("Cancel")) );
248
249     /* Create notebook */
250     notebook = new wxNotebook( panel, Notebook_Event );
251     wxNotebookSizer *notebook_sizer = new wxNotebookSizer( notebook );
252
253     notebook->AddPage( FilePanel( notebook ), wxU(_("File")),
254                        i_access_method == FILE_ACCESS );
255     notebook->AddPage( DiscPanel( notebook ), wxU(_("Disc")),
256                        i_access_method == DISC_ACCESS );
257     notebook->AddPage( NetPanel( notebook ), wxU(_("Network")),
258                        i_access_method == NET_ACCESS );
259 #ifndef WIN32
260     notebook->AddPage( SatPanel( notebook ), wxU(_("Satellite")),
261                        i_access_method == SAT_ACCESS );
262 #endif
263
264     /* Update Disc panel */
265     wxCommandEvent dummy_event;
266     OnDiscTypeChange( dummy_event );
267
268     /* Update Net panel */
269     dummy_event.SetId( NetRadio1_Event );
270     OnNetTypeChange( dummy_event );
271
272     /* Update MRL */
273     wxNotebookEvent event( wxEVT_NULL, 0, i_access_method );
274     OnPageChange( event );
275
276     /* Place everything in sizers */
277     wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
278     button_sizer->Add( ok_button, 0, wxALL, 5 );
279     button_sizer->Add( cancel_button, 0, wxALL, 5 );
280     button_sizer->Layout();
281     wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
282     wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
283     panel_sizer->Add( mrl_sizer_sizer, 0, wxEXPAND, 5 );
284     panel_sizer->Add( label, 0, wxEXPAND | wxALL, 5 );
285     panel_sizer->Add( notebook_sizer, 1, wxEXPAND | wxALL, 5 );
286     panel_sizer->Add( sout_sizer, 0, wxALIGN_LEFT | wxALL, 5 );
287     panel_sizer->Add( demuxdump_sizer, 0, wxEXPAND | wxALIGN_LEFT | wxALL, 5 );
288     panel_sizer->Add( static_line, 0, wxEXPAND | wxALL, 5 );
289     panel_sizer->Add( button_sizer, 0, wxALIGN_LEFT | wxALL, 5 );
290     panel_sizer->Layout();
291     panel->SetSizerAndFit( panel_sizer );
292     main_sizer->Add( panel, 1, wxGROW, 0 );
293     main_sizer->Layout();
294     SetSizerAndFit( main_sizer );
295 }
296
297 OpenDialog::~OpenDialog()
298 {
299     /* Clean up */
300     if( file_dialog ) delete file_dialog;
301     if( sout_dialog ) delete sout_dialog;
302     if( subsfile_dialog ) delete subsfile_dialog;
303     if( demuxdump_dialog ) delete demuxdump_dialog;
304 }
305
306 int OpenDialog::Show( int i_access_method, int i_arg )
307 {
308     int i_ret;
309     notebook->SetSelection( i_access_method );
310     i_ret = wxFrame::Show();
311     Raise();
312     SetFocus();
313     return i_ret;
314 }
315
316 int OpenDialog::Show()
317 {
318     int i_ret;
319     i_ret = wxFrame::Show();
320     Raise();
321     SetFocus();
322     return i_ret;
323 }
324
325 /*****************************************************************************
326  * Private methods.
327  *****************************************************************************/
328 wxPanel *OpenDialog::FilePanel( wxWindow* parent )
329 {
330     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
331                                   wxSize(200, 200) );
332
333     wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
334
335     /* Create browse file line */
336     wxBoxSizer *file_sizer = new wxBoxSizer( wxHORIZONTAL );
337
338     file_combo = new wxComboBox( panel, FileName_Event, wxT(""),
339                                  wxPoint(20,25), wxSize(200, -1), 0, NULL );
340     wxButton *browse_button = new wxButton( panel, FileBrowse_Event,
341                                             wxU(_("Browse...")) );
342     file_sizer->Add( file_combo, 1, wxALL, 5 );
343     file_sizer->Add( browse_button, 0, wxALL, 5 );
344
345     /* Create Subtitles File checkox */
346     wxFlexGridSizer *subsfile_sizer = new wxFlexGridSizer( 2, 1, 20 );
347     subsfile_checkbox = new wxCheckBox( panel, SubsFileEnable_Event,
348                                         wxU(_("Subtitles file")) );
349     subsfile_checkbox->SetToolTip( wxU(_("Load an additional subtitles file. "
350                                    "Currently only works with AVI files.")) );
351     subsfile_sizer->Add( subsfile_checkbox, 0,
352                          wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
353     subsfile_button = new wxButton( panel, SubsFileSettings_Event,
354                                     wxU(_("Settings...")) );
355     subsfile_button->Disable();
356
357     char *psz_subsfile = config_GetPsz( p_intf, "sub-file" );
358     if( psz_subsfile && *psz_subsfile )
359     {
360         subsfile_checkbox->SetValue(TRUE);
361         subsfile_button->Enable();
362         subsfile_mrl.Add( wxString(wxT("sub-file=")) + wxU(psz_subsfile) );
363     }
364     if( psz_subsfile ) free( psz_subsfile );
365
366     subsfile_sizer->Add( subsfile_button, 1,
367                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
368
369     sizer->Add( file_sizer, 0, wxEXPAND | wxALL, 5 );
370     sizer->Add( subsfile_sizer, 0, wxEXPAND | wxALL, 5 );
371     panel->SetSizerAndFit( sizer );
372     return panel;
373 }
374
375 wxPanel *OpenDialog::DiscPanel( wxWindow* parent )
376 {
377     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
378                                   wxSize(200, 200) );
379
380     wxBoxSizer *sizer_row = new wxBoxSizer( wxVERTICAL );
381     wxFlexGridSizer *sizer = new wxFlexGridSizer( 2, 3, 20 );
382
383     static const wxString disc_type_array[] =
384     {
385         wxU(_("DVD (menus support)")),
386         wxU(_("DVD")),
387         wxU(_("VCD")),
388         wxU(_("CD Audio"))
389
390     };
391
392     disc_type = new wxRadioBox( panel, DiscType_Event, wxU(_("Disc type")),
393                                 wxDefaultPosition, wxDefaultSize,
394                                 WXSIZEOF(disc_type_array), disc_type_array,
395                                 WXSIZEOF(disc_type_array), wxRA_SPECIFY_COLS );
396     sizer_row->Add( disc_type, 0, wxEXPAND | wxALL, 5 );
397
398     wxStaticText *label = new wxStaticText( panel, -1, wxU(_("Device name")) );
399     disc_device = new wxTextCtrl( panel, DiscDevice_Event, wxT(""),
400                                   wxDefaultPosition, wxDefaultSize,
401                                   wxTE_PROCESS_ENTER);
402
403     sizer->Add( label, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
404     sizer->Add( disc_device, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
405
406     label = new wxStaticText( panel, -1, wxU(_("Title")) );
407     disc_title = new wxSpinCtrl( panel, DiscTitle_Event );
408
409     sizer->Add( label, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
410     sizer->Add( disc_title, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
411
412     label = new wxStaticText( panel, -1, wxU(_("Chapter")) );
413     disc_chapter = new wxSpinCtrl( panel, DiscChapter_Event );
414     sizer->Add( label, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
415     sizer->Add( disc_chapter, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
416     sizer_row->Add( sizer, 0, wxEXPAND | wxALL, 5 );
417
418     panel->SetSizerAndFit( sizer_row );
419     return panel;
420 }
421
422 wxPanel *OpenDialog::NetPanel( wxWindow* parent )
423 {
424     int i;
425     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
426                                   wxSize(200, 200) );
427
428     wxBoxSizer *sizer_row = new wxBoxSizer( wxVERTICAL );
429     wxFlexGridSizer *sizer = new wxFlexGridSizer( 2, 3, 20 );
430
431     static const wxString net_type_array[] =
432     {
433         wxU(_("UDP/RTP")),
434         wxU(_("UDP/RTP Multicast")),
435         wxU(_("HTTP/FTP/MMS"))
436     };
437
438     for( i=0; i<3; i++ )
439     {
440         net_radios[i] = new wxRadioButton( panel, NetRadio1_Event + i,
441                                            net_type_array[i],
442                                            wxDefaultPosition, wxDefaultSize,
443                                            wxRB_SINGLE );
444
445         net_subpanels[i] = new wxPanel( panel, -1,
446                                         wxDefaultPosition, wxDefaultSize );
447     }
448
449     /* UDP/RTP row */
450     wxFlexGridSizer *subpanel_sizer;
451     wxStaticText *label;
452     i_net_ports[0] = config_GetInt( p_intf, "server-port" );
453     subpanel_sizer = new wxFlexGridSizer( 2, 1, 20 );
454     label = new wxStaticText( net_subpanels[0], -1, wxU(_("Port")) );
455     net_ports[0] = new wxSpinCtrl( net_subpanels[0], NetPort1_Event,
456                                    wxString::Format(wxT("%d"), i_net_ports[0]),
457                                    wxDefaultPosition, wxDefaultSize,
458                                    wxSP_ARROW_KEYS,
459                                    0, 16000, i_net_ports[0] );
460
461     subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
462     subpanel_sizer->Add( net_ports[0], 1,
463                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
464     net_subpanels[0]->SetSizerAndFit( subpanel_sizer );
465     net_radios[0]->SetValue( TRUE );
466
467     /* UDP/RTP Multicast row */
468     subpanel_sizer = new wxFlexGridSizer( 4, 1, 20 );
469     label = new wxStaticText( net_subpanels[1], -1, wxU(_("Address")) );
470     net_addrs[1] = new wxTextCtrl( net_subpanels[1], NetAddr2_Event, wxT(""),
471                                    wxDefaultPosition, wxDefaultSize,
472                                    wxTE_PROCESS_ENTER);
473     subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
474     subpanel_sizer->Add( net_addrs[1], 1,
475                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
476
477     label = new wxStaticText( net_subpanels[1], -1, wxU(_("Port")) );
478     i_net_ports[1] = i_net_ports[0];
479     net_ports[1] = new wxSpinCtrl( net_subpanels[1], NetPort2_Event,
480                                    wxString::Format(wxT("%d"), i_net_ports[1]),
481                                    wxDefaultPosition, wxDefaultSize,
482                                    wxSP_ARROW_KEYS,
483                                    0, 16000, i_net_ports[1] );
484
485     subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
486     subpanel_sizer->Add( net_ports[1], 1,
487                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
488     net_subpanels[1]->SetSizerAndFit( subpanel_sizer );
489
490     /* HTTP row */
491     subpanel_sizer = new wxFlexGridSizer( 2, 1, 20 );
492     label = new wxStaticText( net_subpanels[2], -1, wxU(_("URL")) );
493     net_addrs[2] = new wxTextCtrl( net_subpanels[2], NetAddr3_Event, wxT(""),
494                                    wxDefaultPosition, wxSize( 200, -1 ),
495                                    wxTE_PROCESS_ENTER);
496     subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
497     subpanel_sizer->Add( net_addrs[2], 1,
498                          wxEXPAND | wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
499     net_subpanels[2]->SetSizerAndFit( subpanel_sizer );
500
501     /* Stuff everything into the main panel */
502     for( i=0; i<3; i++ )
503     {
504         sizer->Add( net_radios[i], 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL |
505                     wxALL, 5 );
506         sizer->Add( net_subpanels[i], 1, wxEXPAND | wxALIGN_LEFT |
507                     wxALIGN_CENTER_VERTICAL | wxALL, 5  );
508     }
509
510     sizer_row->Add( sizer, 0, wxEXPAND | wxALL, 5 );
511
512     panel->SetSizerAndFit( sizer_row );
513     return panel;
514 }
515
516 wxPanel *OpenDialog::SatPanel( wxWindow* parent )
517 {
518     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
519                                   wxSize(200, 200) );
520     return panel;
521 }
522
523 void OpenDialog::UpdateMRL( int i_access_method )
524 {
525     wxString demux, mrltemp;
526
527     i_current_access_method = i_access_method;
528
529     /* Check if the user asked for demuxdump */
530     if( demuxdump_checkbox->GetValue() )
531     {
532         demux = wxT("/demuxdump");
533     }
534
535     switch( i_access_method )
536     {
537     case FILE_ACCESS:
538         //mrltemp = wxT("file") + demux + wxT(":") + file_combo->GetValue();
539         mrltemp = file_combo->GetValue();
540         break;
541     case DISC_ACCESS:
542         mrltemp = ( disc_type->GetSelection() == 0 ? wxT("dvd") :
543                 disc_type->GetSelection() == 1 ? wxT("dvdsimple") :
544                 disc_type->GetSelection() == 2 ? wxT("vcd") : wxT("cdda") )
545                   + demux + wxT(":")
546                   + disc_device->GetLineText(0)
547                   + wxString::Format( wxT("@%d:%d"),
548                                       i_disc_title, i_disc_chapter );
549         break;
550     case NET_ACCESS:
551         switch( i_net_type )
552         {
553         case 0:
554             if( i_net_ports[0] !=
555                 config_GetInt( p_intf, "server-port" ) )
556             {
557                 mrltemp = wxT("udp") + demux +
558                           wxString::Format( wxT("://@:%d"),
559                                             i_net_ports[0] );
560             }
561             else
562             {
563                 mrltemp = wxT("udp") + demux + wxT("://");
564             }
565             break;
566
567         case 1:
568             mrltemp = wxT("udp") + demux + wxT("://@") +
569                       net_addrs[1]->GetLineText(0);
570             if( i_net_ports[1] !=
571                 config_GetInt( p_intf, "server-port" ) )
572             {
573                 mrltemp = mrltemp + wxString::Format( wxT(":%d"),
574                                               i_net_ports[1] );
575             }
576             break;
577
578         case 2:
579             /* http access */     
580             mrltemp = wxT("http") + demux + wxT("://") +
581                       net_addrs[2]->GetLineText(0);
582             break;
583         }
584         break;
585     case SAT_ACCESS:
586         mrltemp = wxT("satellite") + demux + wxT("://");
587         break;
588     default:
589         break;
590     }
591
592     mrl_combo->SetValue( mrltemp );
593 }
594
595 /*****************************************************************************
596  * Events methods.
597  *****************************************************************************/
598 void OpenDialog::OnOk( wxCommandEvent& WXUNUSED(event) )
599 {
600     mrl = SeparateEntries( mrl_combo->GetValue() );
601     mrl_combo->Append( mrl_combo->GetValue() );
602     if( mrl_combo->GetCount() > 10 ) mrl_combo->Delete( 0 );
603     mrl_combo->SetSelection( mrl_combo->GetCount() - 1 );
604
605     /* Update the playlist */
606     playlist_t *p_playlist =
607         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
608                                        FIND_ANYWHERE );
609     if( p_playlist == NULL ) return;
610
611     for( int i = 0; i < (int)mrl.GetCount(); i++ )
612     {
613         int i_options = 0, i_total_options;
614         char **ppsz_options = NULL;
615
616         /* Count the input options */
617         while( i + i_options + 1 < (int)mrl.GetCount() &&
618                ((const char *)mrl[i + i_options + 1].mb_str())[0] == ':' )
619         {
620             i_options++;
621         }
622
623         /* Allocate ppsz_options */
624         for( int j = 0; j < i_options; j++ )
625         {
626             if( !ppsz_options )
627                 ppsz_options = (char **)malloc( sizeof(char *) * i_options );
628
629             ppsz_options[j] = strdup( mrl[i + j  + 1].mb_str() );
630         }
631
632         i_total_options = i_options;
633
634         /* Get the options from the subtitles dialog */
635         if( subsfile_checkbox->IsChecked() && subsfile_mrl.GetCount() )
636         {
637             ppsz_options = (char **)realloc( ppsz_options, sizeof(char *) *
638                                (i_total_options + subsfile_mrl.GetCount()) );
639
640             for( int j = 0; j < (int)subsfile_mrl.GetCount(); j++ )
641             {
642                 ppsz_options[i_total_options + j] =
643                     strdup( subsfile_mrl[j].mb_str() );
644             }
645
646             i_total_options += subsfile_mrl.GetCount();
647         }
648
649         /* Get the options from the stream output dialog */
650         if( sout_checkbox->IsChecked() && sout_mrl.GetCount() )
651         {
652             ppsz_options = (char **)realloc( ppsz_options, sizeof(char *) *
653                                (i_total_options + sout_mrl.GetCount()) );
654
655             for( int j = 0; j < (int)sout_mrl.GetCount(); j++ )
656             {
657                 ppsz_options[i_total_options + j] =
658                     strdup( sout_mrl[j].mb_str() );
659             }
660
661             i_total_options += sout_mrl.GetCount();
662         }
663
664         playlist_Add( p_playlist, (const char *)mrl[i].mb_str(),
665                       (const char **)ppsz_options, i_total_options,
666                       PLAYLIST_APPEND | (i ? 0 : PLAYLIST_GO), PLAYLIST_END );
667
668         /* clean up */
669         for( int j = 0; j < i_total_options; j++ )
670             free( ppsz_options[j] );
671         if( ppsz_options ) free( ppsz_options );
672
673         i += i_options;
674    }
675
676     //TogglePlayButton( PLAYING_S );
677
678     vlc_object_release( p_playlist );
679
680     Hide();
681 }
682
683 void OpenDialog::OnCancel( wxCommandEvent& WXUNUSED(event) )
684 {
685     Hide();
686 }
687
688 void OpenDialog::OnPageChange( wxNotebookEvent& event )
689 {
690     UpdateMRL( event.GetSelection() );
691 }
692
693 void OpenDialog::OnMRLChange( wxCommandEvent& event )
694 {
695     //mrl = SeparateEntries( event.GetString() );
696 }
697
698 /*****************************************************************************
699  * File panel event methods.
700  *****************************************************************************/
701 void OpenDialog::OnFilePanelChange( wxCommandEvent& WXUNUSED(event) )
702 {
703     UpdateMRL( FILE_ACCESS );
704 }
705
706 void OpenDialog::OnFileBrowse( wxCommandEvent& WXUNUSED(event) )
707 {
708     if( file_dialog == NULL )
709         file_dialog = new wxFileDialog( this, wxU(_("Open file")),
710             wxT(""), wxT(""), wxT("*"), wxOPEN | wxMULTIPLE );
711
712     if( file_dialog && file_dialog->ShowModal() == wxID_OK )
713     {
714         wxArrayString paths;
715         wxString path;
716
717         file_dialog->GetPaths( paths );
718
719         for( size_t i = 0; i < paths.GetCount(); i++ )
720         {
721             if( paths[i].Find( wxT(' ') ) >= 0 )
722                 path += wxT("\"") + paths[i] + wxT("\" ");
723             else
724                 path += paths[i] + wxT(" ");
725         }
726
727         file_combo->SetValue( path );
728         file_combo->Append( path );
729         if( file_combo->GetCount() > 10 ) file_combo->Delete( 0 );
730         UpdateMRL( FILE_ACCESS );
731     }
732 }
733
734 /*****************************************************************************
735  * Disc panel event methods.
736  *****************************************************************************/
737 void OpenDialog::OnDiscPanelChange( wxCommandEvent& event )
738 {
739     if( event.GetId() == DiscTitle_Event )
740         i_disc_title = event.GetInt();
741     else if( event.GetId() == DiscChapter_Event )
742         i_disc_chapter = event.GetInt();
743
744     UpdateMRL( DISC_ACCESS );
745 }
746
747 void OpenDialog::OnDiscTypeChange( wxCommandEvent& WXUNUSED(event) )
748 {
749     char *psz_device;
750
751     switch( disc_type->GetSelection() )
752     {
753     case 2:
754         psz_device = config_GetPsz( p_intf, "vcd" );
755         disc_device->SetValue( psz_device ? wxU(psz_device) : wxT("") );
756         break;
757
758     default:
759         psz_device = config_GetPsz( p_intf, "dvd" );
760         disc_device->SetValue( psz_device ? wxU(psz_device) : wxT("") );
761         break;
762     }
763
764     if( psz_device ) free( psz_device );
765
766     switch( disc_type->GetSelection() )
767     {
768     case 0:
769         disc_title->SetRange( 0, 255 );
770         disc_title->SetValue( 0 );
771         i_disc_title = 0;
772         break;
773
774     default:
775         disc_title->SetRange( 1, 255 );
776         disc_title->SetValue( 1 );
777         i_disc_title = 1;
778         break;
779     }
780
781     i_disc_chapter = 1;
782     disc_chapter->SetRange( 1, 255 );
783     disc_chapter->SetValue( 1 );
784
785     UpdateMRL( DISC_ACCESS );
786 }
787
788 /*****************************************************************************
789  * Net panel event methods.
790  *****************************************************************************/
791 void OpenDialog::OnNetPanelChange( wxCommandEvent& event )
792 {
793     if( event.GetId() >= NetPort1_Event && event.GetId() <= NetPort3_Event )
794     {
795         i_net_ports[event.GetId() - NetPort1_Event] = event.GetInt();
796     }
797
798     UpdateMRL( NET_ACCESS );
799 }
800
801 void OpenDialog::OnNetTypeChange( wxCommandEvent& event )
802 {
803     int i;
804
805     i_net_type = event.GetId() - NetRadio1_Event;
806
807     for(i=0; i<3; i++)
808     {
809         net_radios[i]->SetValue( event.GetId() == (NetRadio1_Event+i) );
810         net_subpanels[i]->Enable( event.GetId() == (NetRadio1_Event+i) );
811     }
812
813     UpdateMRL( NET_ACCESS );
814 }
815
816 /*****************************************************************************
817  * Subtitles file event methods.
818  *****************************************************************************/
819 void OpenDialog::OnSubsFileEnable( wxCommandEvent& event )
820 {
821     subsfile_button->Enable( event.GetInt() != 0 );
822     if( event.GetInt() && demuxdump_checkbox->IsChecked() )
823     {
824         demuxdump_checkbox->SetValue( 0 );
825         wxCommandEvent event = wxCommandEvent( wxEVT_NULL );
826         event.SetInt( 0 );
827         OnDemuxDumpEnable( event );
828     }
829 }
830
831 void OpenDialog::OnSubsFileSettings( wxCommandEvent& WXUNUSED(event) )
832 {
833     /* Show/hide the open dialog */
834     if( subsfile_dialog == NULL )
835         subsfile_dialog = new SubsFileDialog( p_intf, this );
836
837     if( subsfile_dialog && subsfile_dialog->ShowModal() == wxID_OK )
838     {
839         subsfile_mrl.Empty();
840         subsfile_mrl.Add( wxString(wxT("sub-file=")) +
841                           subsfile_dialog->file_combo->GetValue() );
842         subsfile_mrl.Add( wxString::Format( wxT("sub-delay=%i"),
843                           subsfile_dialog->delay_spinctrl->GetValue() ) );
844         subsfile_mrl.Add( wxString::Format( wxT("sub-fps=%i"),
845                           subsfile_dialog->fps_spinctrl->GetValue() ) );
846     }
847 }
848
849 /*****************************************************************************
850  * Stream output event methods.
851  *****************************************************************************/
852 void OpenDialog::OnSoutEnable( wxCommandEvent& event )
853 {
854     sout_button->Enable( event.GetInt() != 0 );
855     if( event.GetInt() && demuxdump_checkbox->IsChecked() )
856     {
857         demuxdump_checkbox->SetValue( 0 );
858         wxCommandEvent event = wxCommandEvent( wxEVT_NULL );
859         event.SetInt( 0 );
860         OnDemuxDumpEnable( event );
861     }
862 }
863
864 void OpenDialog::OnSoutSettings( wxCommandEvent& WXUNUSED(event) )
865 {
866     /* Show/hide the open dialog */
867     if( sout_dialog == NULL )
868         sout_dialog = new SoutDialog( p_intf, this );
869
870     if( sout_dialog && sout_dialog->ShowModal() == wxID_OK )
871     {
872         sout_mrl = sout_dialog->GetOptions();
873     }
874 }
875
876 /*****************************************************************************
877  * Demux dump event methods.
878  *****************************************************************************/
879 void OpenDialog::OnDemuxDumpEnable( wxCommandEvent& event )
880 {
881     demuxdump_textctrl->Enable( event.GetInt() != 0 );
882     demuxdump_button->Enable( event.GetInt() != 0 );
883
884     if( event.GetInt() )
885     {
886         sout_checkbox->SetValue( 0 );
887         subsfile_checkbox->SetValue( 0 );
888         wxCommandEvent event = wxCommandEvent( wxEVT_NULL );
889         event.SetInt( 0 );
890         OnSoutEnable( event );
891         OnSubsFileEnable( event );
892     }
893
894     UpdateMRL( i_current_access_method );
895 }
896
897 void OpenDialog::OnDemuxDumpBrowse( wxCommandEvent& WXUNUSED(event) )
898 {
899     if( demuxdump_dialog == NULL )
900         demuxdump_dialog = new wxFileDialog( this, wxU(_("Save file")),
901                                wxT(""), wxT(""), wxT("*"), wxSAVE );
902
903     if( demuxdump_dialog && demuxdump_dialog->ShowModal() == wxID_OK )
904     {
905         demuxdump_textctrl->SetValue( demuxdump_dialog->GetPath() );
906         wxCommandEvent event = wxCommandEvent( wxEVT_NULL );
907         OnDemuxDumpChange( event );
908     }
909 }
910
911 void OpenDialog::OnDemuxDumpChange( wxCommandEvent& WXUNUSED(event) )
912 {
913     config_PutPsz( p_intf, "demuxdump-file",
914                    demuxdump_textctrl->GetValue().mb_str() );
915 }
916
917 /*****************************************************************************
918  * Utility functions.
919  *****************************************************************************/
920 wxArrayString SeparateEntries( wxString entries )
921 {
922     vlc_bool_t b_quotes_mode = VLC_FALSE;
923
924     wxArrayString entries_array;
925     wxString entry;
926
927     wxStringTokenizer token( entries, wxT(" \t\r\n\""), wxTOKEN_RET_DELIMS );
928
929     while( token.HasMoreTokens() )
930     {
931         entry += token.GetNextToken();
932
933         if( entry.IsEmpty() ) continue;
934
935         if( !b_quotes_mode && entry.Last() == wxT('\"') )
936         {
937             /* Enters quotes mode */
938             entry.RemoveLast();
939             b_quotes_mode = VLC_TRUE;
940         }
941         else if( b_quotes_mode && entry.Last() == wxT('\"') )
942         {
943             /* Finished the quotes mode */
944             entry.RemoveLast();
945             if( !entry.IsEmpty() ) entries_array.Add( entry );
946             entry.Empty();
947             b_quotes_mode = VLC_FALSE;
948         }
949         else if( !b_quotes_mode && entry.Last() != wxT('\"') )
950         {
951             /* we found a non-quoted standalone string */
952             if( token.HasMoreTokens() ||
953                 entry.Last() == wxT(' ') || entry.Last() == wxT('\t') ||
954                 entry.Last() == wxT('\r') || entry.Last() == wxT('\n') )
955                 entry.RemoveLast();
956             if( !entry.IsEmpty() ) entries_array.Add( entry );
957             entry.Empty();
958         }
959         else
960         {;}
961     }
962
963     if( !entry.IsEmpty() ) entries_array.Add( entry );
964
965     return entries_array;
966 }