1 /*****************************************************************************
2 * open.cpp : wxWindows plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2000-2005 the VideoLAN team
7 * Authors: Gildas Bazin <gbazin@videolan.org>
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
28 #include <stdlib.h> /* malloc(), free() */
29 #include <errno.h> /* ENOMEM */
30 #include <string.h> /* strerror() */
37 #include <cdio/cdio.h>
38 #include <cdio/cd_types.h>
39 #include <cdio/logging.h>
40 #endif /* HAVE_LIBCDIO */
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 */
50 #include <wx/combobox.h>
51 #include <wx/statline.h>
52 #include <wx/tokenzr.h>
58 #include "wxwidgets.h"
59 #include "preferences_widgets.h"
62 # define wxRB_SINGLE 0
65 #define SELECTION_DISC_TYPE_DVD_MENUS 0
66 #define SELECTION_DISC_TYPE_DVD 1
67 #define SELECTION_DISC_TYPE_VCD 2
68 #define SELECTION_DISC_TYPE_CDDA 3
70 /*****************************************************************************
72 *****************************************************************************/
74 /* IDs for the controls and the menu commands */
77 Notebook_Event = wxID_HIGHEST,
94 NetRadio1_Event, NetRadio2_Event, NetRadio3_Event, NetRadio4_Event,
95 NetPort1_Event, NetPort2_Event, NetPort3_Event,
96 NetAddr1_Event, NetAddr2_Event, NetAddr3_Event, NetAddr4_Event,
97 NetForceIPv6_Event, NetTimeshift_Event,
100 SubsFileSettings_Event,
108 AdvancedOptions_Event
111 BEGIN_EVENT_TABLE(OpenDialog, wxDialog)
113 EVT_BUTTON(wxID_OK, OpenDialog::OnOk)
114 EVT_BUTTON(wxID_CANCEL, OpenDialog::OnCancel)
116 EVT_NOTEBOOK_PAGE_CHANGED(Notebook_Event, OpenDialog::OnPageChange)
118 EVT_TEXT(MRL_Event, OpenDialog::OnMRLChange)
120 /* Events generated by the file panel */
121 EVT_TEXT(FileName_Event, OpenDialog::OnFilePanelChange)
122 EVT_BUTTON(FileBrowse_Event, OpenDialog::OnFileBrowse)
124 /* Events generated by the disc panel */
125 EVT_RADIOBOX(DiscType_Event, OpenDialog::OnDiscTypeChange)
127 EVT_CHECKBOX(DiscProbe_Event, OpenDialog::OnDiscProbe)
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)
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)
156 /* Events generated by the subtitle file buttons */
157 EVT_CHECKBOX(SubsFileEnable_Event, OpenDialog::OnSubsFileEnable)
158 EVT_BUTTON(SubsFileSettings_Event, OpenDialog::OnSubsFileSettings)
160 /* Events generated by the stream output buttons */
161 EVT_CHECKBOX(SoutEnable_Event, OpenDialog::OnSoutEnable)
162 EVT_BUTTON(SoutSettings_Event, OpenDialog::OnSoutSettings)
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)
169 /* Hide the window when the user closes the window */
170 EVT_CLOSE(OpenDialog::OnClose)
175 /* Perhaps someday we'll figure out how to add media information to
176 "Stream-and-Media info" when no input thread hasn't been initialized.
178 extern void MediaInsertCDDA( intf_thread_t *_p_intf, CdIo_t *p_cdio,
179 track_t i_last_track );
182 /*****************************************************************************
184 *****************************************************************************/
185 WX_DEFINE_ARRAY(ConfigControl *, ArrayOfConfigControls);
187 class AutoBuiltPanel : public wxPanel
192 AutoBuiltPanel( wxWindow *, OpenDialog *, intf_thread_t *,
195 virtual ~AutoBuiltPanel() {}
197 void UpdateAdvancedMRL();
200 ArrayOfConfigControls config_array;
201 ArrayOfConfigControls advanced_config_array;
202 wxComboBox *p_advanced_mrl_combo;
205 intf_thread_t *p_intf;
206 OpenDialog *p_open_dialog;
208 void OnAdvanced( wxCommandEvent& event );
209 wxDialog *p_advanced_dialog;
211 DECLARE_EVENT_TABLE();
214 BEGIN_EVENT_TABLE(AutoBuiltPanel, wxPanel)
215 EVT_BUTTON(AdvancedOptions_Event, AutoBuiltPanel::OnAdvanced)
218 static void AutoBuildCallback( void *p_data )
220 ((OpenDialog *)p_data)->UpdateMRL();
223 static void AutoBuildAdvancedCallback( void *p_data )
225 ((AutoBuiltPanel *)p_data)->UpdateAdvancedMRL();
228 AutoBuiltPanel::AutoBuiltPanel( wxWindow *parent, OpenDialog *dialog,
229 intf_thread_t *_p_intf,
230 const module_t *p_module )
231 : wxPanel( parent, -1, wxDefaultPosition, wxDefaultSize ),
232 name( wxU(p_module->psz_object_name) ),
233 p_advanced_mrl_combo( NULL ),
234 p_intf( _p_intf ), p_open_dialog( dialog ), p_advanced_dialog( NULL )
236 wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
237 module_config_t *p_item = p_module->p_config;
238 bool b_advanced = false;
242 if( !(p_item->i_type & CONFIG_HINT) && p_item->b_advanced )
245 if( p_item->i_type & CONFIG_HINT || p_item->b_advanced )
248 ConfigControl *control =
249 CreateConfigControl( VLC_OBJECT(p_intf), p_item, this );
251 config_array.Add( control );
253 /* Don't add items that were not recognized */
254 if( control == NULL ) continue;
256 control->SetUpdateCallback( AutoBuildCallback, (void *)dialog );
258 sizer->Add( control, 0, wxEXPAND | wxALL, 2 );
260 while( p_item->i_type != CONFIG_HINT_END && p_item++ );
265 new wxButton( this, AdvancedOptions_Event,
266 wxU(_("Advanced options...")) );
267 sizer->Add( button, 0, wxALL, 5 );
269 /* Build the advanced dialog */
271 new wxDialog( this, -1, ((wxString)wxU(_("Advanced options"))) +
272 wxT(" (") + wxU( p_module->psz_longname ) + wxT(")"),
273 wxDefaultPosition, wxDefaultSize,
274 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER );
276 wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
278 /* Create MRL combobox */
279 wxBoxSizer *mrl_sizer_sizer = new wxBoxSizer( wxHORIZONTAL );
280 wxStaticBox *mrl_box =
281 new wxStaticBox( p_advanced_dialog, -1,
282 wxU(_("Advanced options")) );
283 wxStaticBoxSizer *mrl_sizer =
284 new wxStaticBoxSizer( mrl_box, wxHORIZONTAL );
285 wxStaticText *mrl_label =
286 new wxStaticText( p_advanced_dialog, -1, wxU(_("Options:")) );
287 p_advanced_mrl_combo =
288 new wxComboBox( p_advanced_dialog, MRL_Event, wxT(""),
289 wxDefaultPosition, wxDefaultSize );
290 mrl_sizer->Add( mrl_label, 0, wxALL | wxALIGN_CENTER, 5 );
291 mrl_sizer->Add( p_advanced_mrl_combo, 1, wxALL | wxALIGN_CENTER, 5 );
292 mrl_sizer_sizer->Add( mrl_sizer, 1, wxEXPAND | wxALL, 5 );
293 sizer->Add( mrl_sizer_sizer, 0, wxEXPAND | wxALL, 2 );
295 /* Add advanced options to panel */
296 module_config_t *p_item = p_module->p_config;
299 if( p_item->i_type & CONFIG_HINT || !p_item->b_advanced )
302 ConfigControl *control =
303 CreateConfigControl( VLC_OBJECT(p_intf), p_item,
306 advanced_config_array.Add( control );
308 /* Don't add items that were not recognized */
309 if( control == NULL ) continue;
311 control->SetUpdateCallback( AutoBuildAdvancedCallback,
314 sizer->Add( control, 0, wxEXPAND | wxALL, 2 );
316 while( p_item->i_type != CONFIG_HINT_END && p_item++ );
319 wxPanel *dummy_panel = new wxPanel( p_advanced_dialog, -1 );
320 sizer->Add( dummy_panel, 1 );
321 wxStaticLine *static_line =
322 new wxStaticLine( p_advanced_dialog, wxID_OK );
323 sizer->Add( static_line, 0, wxEXPAND | wxALL, 5 );
326 wxButton *ok_button =
327 new wxButton( p_advanced_dialog, wxID_OK, wxU(_("OK")) );
328 ok_button->SetDefault();
329 wxButton *cancel_button =
330 new wxButton( p_advanced_dialog, wxID_CANCEL, wxU(_("Cancel")) );
331 wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
332 button_sizer->Add( ok_button, 0, wxALL, 5 );
333 button_sizer->Add( cancel_button, 0, wxALL, 5 );
334 button_sizer->Layout();
335 sizer->Add( button_sizer, 0, wxALL, 0 );
337 sizer->SetMinSize( 400, -1 );
338 p_advanced_dialog->SetSizerAndFit( sizer );
341 this->SetSizerAndFit( sizer );
344 void AutoBuiltPanel::OnAdvanced( wxCommandEvent& event )
346 if( p_advanced_dialog->ShowModal() == wxID_OK )
349 p_open_dialog->UpdateMRL();
353 void AutoBuiltPanel::UpdateAdvancedMRL()
357 for( int i = 0; i < (int)advanced_config_array.GetCount(); i++ )
359 ConfigControl *control = advanced_config_array.Item(i);
361 mrltemp += (i ? wxT(" :") : wxT(":"));
363 if( control->GetType() == CONFIG_ITEM_BOOL &&
364 !control->GetIntValue() ) mrltemp += wxT("no-");
366 mrltemp += control->GetName();
368 switch( control->GetType() )
370 case CONFIG_ITEM_STRING:
371 case CONFIG_ITEM_FILE:
372 case CONFIG_ITEM_DIRECTORY:
373 case CONFIG_ITEM_MODULE:
374 mrltemp += wxT("=\"") + control->GetPszValue() + wxT("\"");
376 case CONFIG_ITEM_INTEGER:
378 wxString::Format( wxT("=%i"), control->GetIntValue() );
380 case CONFIG_ITEM_FLOAT:
382 wxString::Format(wxT("=%f"), control->GetFloatValue());
387 p_advanced_mrl_combo->SetValue( mrltemp );
390 /*****************************************************************************
392 *****************************************************************************/
393 OpenDialog::OpenDialog( intf_thread_t *_p_intf, wxWindow *_p_parent,
394 int i_access_method, int i_arg ):
395 wxDialog( _p_parent, -1, wxU(_("Open...")), wxDefaultPosition,
396 wxDefaultSize, wxDEFAULT_FRAME_STYLE )
398 OpenDialog( _p_intf, _p_parent, i_access_method, i_arg, OPEN_NORMAL );
401 OpenDialog::OpenDialog( intf_thread_t *_p_intf, wxWindow *_p_parent,
402 int i_access_method, int i_arg, int _i_method ):
403 wxDialog( _p_parent, -1, wxU(_("Open...")), wxDefaultPosition,
404 wxDefaultSize, wxDEFAULT_FRAME_STYLE )
406 /* Initializations */
407 i_method = _i_method;
409 p_parent = _p_parent;
410 SetIcon( *p_intf->p_sys->p_icon );
412 i_disc_type_selection = 0;
417 subsfile_dialog = NULL;
418 b_disc_device_changed = false;
420 /* Create a panel to put everything in */
421 wxPanel *panel = new wxPanel( this, -1 );
422 panel->SetAutoLayout( TRUE );
424 /* Create MRL combobox */
425 wxBoxSizer *mrl_sizer_sizer = new wxBoxSizer( wxHORIZONTAL );
426 wxStaticBox *mrl_box = new wxStaticBox( panel, -1,
427 wxU(_("Media Resource Locator (MRL)")) );
428 wxStaticBoxSizer *mrl_sizer = new wxStaticBoxSizer( mrl_box,
430 wxStaticText *mrl_label = new wxStaticText( panel, -1,
432 mrl_combo = new wxComboBox( panel, MRL_Event, wxT(""),
433 wxPoint(20,25), wxSize(120, -1) );
434 mrl_combo->SetToolTip( wxU(_("You can use this field directly by typing "
435 "the full MRL you want to open.\n""Alternatively, the field will be "
436 "filled automatically when you use the controls below.")) );
438 mrl_sizer->Add( mrl_label, 0, wxALL | wxALIGN_CENTER, 5 );
439 mrl_sizer->Add( mrl_combo, 1, wxALL | wxALIGN_CENTER, 5 );
440 mrl_sizer_sizer->Add( mrl_sizer, 1, wxEXPAND | wxALL, 5 );
443 /* Create Static Text */
444 wxStaticText *label = new wxStaticText( panel, -1,
445 wxU(_("Alternatively, you can build an MRL using one of the "
446 "following predefined targets:")) );
448 wxFlexGridSizer *common_opt_sizer = new wxFlexGridSizer( 5, 1, 20 );
450 if( i_method == OPEN_NORMAL )
452 /* Create Stream Output checkox */
453 sout_checkbox = new wxCheckBox( panel, SoutEnable_Event,
454 wxU(_("Stream output")) );
455 sout_checkbox->SetToolTip( wxU(_("Use VLC as a server of streams")) );
456 common_opt_sizer->Add( sout_checkbox, 0,
457 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
459 sout_button = new wxButton( panel, SoutSettings_Event,
460 wxU(_("Settings...")) );
461 sout_button->Disable();
463 char *psz_sout = config_GetPsz( p_intf, "sout" );
464 if( psz_sout && *psz_sout )
466 sout_checkbox->SetValue(TRUE);
467 sout_button->Enable();
468 subsfile_mrl.Add( wxString(wxT("sout=")) + wxL2U(psz_sout) );
470 if( psz_sout ) free( psz_sout );
472 common_opt_sizer->Add( sout_button, 1, wxALIGN_LEFT |
473 wxALIGN_CENTER_VERTICAL );
475 common_opt_sizer->Add( new wxPanel( this, -1 ), 1,
476 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
479 /* Create caching options */
480 caching_checkbox = new wxCheckBox( panel, CachingEnable_Event,
482 caching_checkbox->SetToolTip( wxU(_("Change the default caching value "
483 "(in milliseconds)")) );
484 common_opt_sizer->Add( caching_checkbox, 0,
485 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
486 caching_value = new wxSpinCtrl( panel, CachingChange_Event );
487 caching_value->SetRange( 0, 1000000 );
488 caching_value->Disable();
489 common_opt_sizer->Add( caching_value, 0,
490 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
493 wxStaticLine *static_line = new wxStaticLine( panel, wxID_OK );
495 /* Create the buttons */
496 wxButton *ok_button = new wxButton( panel, wxID_OK, wxU(_("OK")) );
497 ok_button->SetDefault();
498 wxButton *cancel_button = new wxButton( panel, wxID_CANCEL,
501 /* Create notebook */
502 notebook = new wxNotebook( panel, Notebook_Event );
504 #if (!wxCHECK_VERSION(2,5,0))
505 wxNotebookSizer *notebook_sizer = new wxNotebookSizer( notebook );
508 notebook->AddPage( FilePanel( notebook ), wxU(_("File")),
509 i_access_method == FILE_ACCESS );
510 notebook->AddPage( DiscPanel( notebook ), wxU(_("Disc")),
511 i_access_method == DISC_ACCESS );
512 notebook->AddPage( NetPanel( notebook ), wxU(_("Network")),
513 i_access_method == NET_ACCESS );
515 module_t *p_module = config_FindModule( VLC_OBJECT(p_intf), "v4l" );
518 AutoBuiltPanel *autopanel =
519 new AutoBuiltPanel( notebook, this, p_intf, p_module );
520 input_tab_array.Add( autopanel );
521 notebook->AddPage( autopanel, wxU( p_module->psz_shortname ?
522 p_module->psz_shortname : p_module->psz_object_name ),
523 i_access_method == CAPTURE_ACCESS );
526 p_module = config_FindModule( VLC_OBJECT(p_intf), "pvr" );
529 AutoBuiltPanel *autopanel =
530 new AutoBuiltPanel( notebook, this, p_intf, p_module );
531 input_tab_array.Add( autopanel );
532 notebook->AddPage( autopanel, wxU( p_module->psz_shortname ?
533 p_module->psz_shortname : p_module->psz_object_name ),
534 i_access_method == CAPTURE_ACCESS );
537 p_module = config_FindModule( VLC_OBJECT(p_intf), "dvb" );
540 AutoBuiltPanel *autopanel =
541 new AutoBuiltPanel( notebook, this, p_intf, p_module );
542 input_tab_array.Add( autopanel );
543 notebook->AddPage( autopanel, wxU( p_module->psz_shortname ?
544 p_module->psz_shortname : p_module->psz_object_name ),
545 i_access_method == CAPTURE_ACCESS );
548 p_module = config_FindModule( VLC_OBJECT(p_intf), "dshow" );
551 AutoBuiltPanel *autopanel =
552 new AutoBuiltPanel( notebook, this, p_intf, p_module );
553 input_tab_array.Add( autopanel );
554 notebook->AddPage( autopanel, wxU( p_module->psz_shortname ?
555 p_module->psz_shortname : p_module->psz_object_name ),
556 i_access_method == CAPTURE_ACCESS );
559 /* Update Disc panel */
560 wxCommandEvent dummy_event;
561 OnDiscTypeChange( dummy_event );
563 /* Update Net panel */
564 dummy_event.SetId( NetRadio1_Event );
565 OnNetTypeChange( dummy_event );
568 wxNotebookEvent event( wxEVT_NULL, 0, i_access_method );
569 OnPageChange( event );
571 /* Place everything in sizers */
572 wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
573 button_sizer->Add( ok_button, 0, wxALL, 5 );
574 button_sizer->Add( cancel_button, 0, wxALL, 5 );
575 button_sizer->Layout();
576 wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
577 wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
578 panel_sizer->Add( mrl_sizer_sizer, 0, wxEXPAND, 5 );
579 panel_sizer->Add( label, 0, wxEXPAND | wxALL, 5 );
580 #if (!wxCHECK_VERSION(2,5,0))
581 panel_sizer->Add( notebook_sizer, 1, wxEXPAND | wxALL, 5 );
583 panel_sizer->Add( notebook, 1, wxEXPAND | wxALL, 5 );
585 panel_sizer->Add( common_opt_sizer, 0, wxALIGN_LEFT | wxALL, 5 );
586 panel_sizer->Add( static_line, 0, wxEXPAND | wxALL, 5 );
587 panel_sizer->Add( button_sizer, 0, wxALIGN_LEFT | wxALL, 5 );
588 panel_sizer->Layout();
589 panel->SetSizerAndFit( panel_sizer );
590 main_sizer->Add( panel, 1, wxGROW, 0 );
591 main_sizer->Layout();
592 SetSizerAndFit( main_sizer );
595 OpenDialog::~OpenDialog()
598 if( file_dialog ) delete file_dialog;
599 if( sout_dialog ) delete sout_dialog;
600 if( subsfile_dialog ) delete subsfile_dialog;
603 int OpenDialog::Show( int i_access_method, int i_arg )
605 notebook->SetSelection( i_access_method );
606 int i_ret = wxDialog::Show();
613 int OpenDialog::Show()
615 int i_ret = wxDialog::Show();
621 /*****************************************************************************
623 *****************************************************************************/
624 wxPanel *OpenDialog::FilePanel( wxWindow* parent )
626 wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
629 wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
631 /* Create browse file line */
632 wxBoxSizer *file_sizer = new wxBoxSizer( wxHORIZONTAL );
634 file_combo = new wxComboBox( panel, FileName_Event, wxT(""),
635 wxPoint(20,25), wxSize(200, -1) );
636 wxButton *browse_button = new wxButton( panel, FileBrowse_Event,
637 wxU(_("Browse...")) );
638 file_sizer->Add( file_combo, 1, wxALL, 5 );
639 file_sizer->Add( browse_button, 0, wxALL, 5 );
641 /* Create Subtitles File checkox */
642 wxFlexGridSizer *subsfile_sizer = new wxFlexGridSizer( 2, 1, 20 );
643 subsfile_checkbox = new wxCheckBox( panel, SubsFileEnable_Event,
644 wxU(_("Subtitle options")) );
645 subsfile_checkbox->SetToolTip( wxU(_("Force options for separate subtitle files.")) );
646 subsfile_sizer->Add( subsfile_checkbox, 0,
647 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
648 subsfile_button = new wxButton( panel, SubsFileSettings_Event,
649 wxU(_("Settings...")) );
650 subsfile_button->Disable();
652 char *psz_subsfile = config_GetPsz( p_intf, "sub-file" );
653 if( psz_subsfile && *psz_subsfile )
655 subsfile_checkbox->SetValue(TRUE);
656 subsfile_button->Enable();
657 subsfile_mrl.Add( wxString(wxT("sub-file=")) + wxL2U(psz_subsfile) );
659 if( psz_subsfile ) free( psz_subsfile );
661 subsfile_sizer->Add( subsfile_button, 1,
662 wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
664 sizer->Add( file_sizer, 0, wxEXPAND | wxALL, 5 );
665 sizer->Add( subsfile_sizer, 0, wxEXPAND | wxALL, 5 );
666 panel->SetSizerAndFit( sizer );
670 wxPanel *OpenDialog::DiscPanel( wxWindow* parent )
672 wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
675 wxBoxSizer *sizer_row = new wxBoxSizer( wxVERTICAL );
676 wxFlexGridSizer *sizer = new wxFlexGridSizer( 2, 3, 20 );
678 static const wxString disc_type_array[] =
680 wxU(_("DVD (menus)")),
686 disc_type = new wxRadioBox( panel, DiscType_Event, wxU(_("Disc type")),
687 wxDefaultPosition, wxDefaultSize,
688 WXSIZEOF(disc_type_array), disc_type_array,
689 WXSIZEOF(disc_type_array), wxRA_SPECIFY_COLS );
692 disc_probe = new wxCheckBox( panel, DiscProbe_Event,
693 wxU(_("Probe Disc(s)")) );
694 disc_probe->SetToolTip( wxU(_("Probe for a DVD, VCD or audio CD. "
695 "First try the Device name entered for the selected Disc type "
696 "(DVD, DVD Menu, VCD, audio CD). If that doesn't find media, try any device "
697 "for the Disc type. If that doesn't work, then try looking for CD-ROMs or "
698 "DVD drives. The Disc type, Device name, and some parameter ranges are set "
699 "based on media we find.")) );
702 sizer_row->Add( disc_type, i_disc_type_selection, wxEXPAND | wxALL, 5 );
704 sizer_row->Add( disc_probe, 0, wxEXPAND | wxALL );
707 wxStaticText *label = new wxStaticText( panel, -1, wxU(_("Device name")) );
708 disc_device = new wxTextCtrl( panel, DiscDevice_Event, wxT(""),
709 wxDefaultPosition, wxDefaultSize,
713 char psz_default_device[3] = {0};
715 /* find the drive_name for the first cdrom drive,
716 * which is probably "D:" and put the drive_name into
717 * psz_default_device... */
718 for( char drive_letter = 'A'; drive_letter <= 'Z'; ++drive_letter )
720 char drive_name[3] = {drive_letter, ':', 0};
721 UINT type = GetDriveTypeA( drive_name );
722 if( type == DRIVE_CDROM )
724 psz_default_device[0] = drive_letter;
725 psz_default_device[1] = ':';
731 if( strlen(psz_default_device) > 0 )
734 disc_device->SetValue( wxL2U(psz_default_device) );
738 sizer->Add( label, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
739 sizer->Add( disc_device, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
741 disc_title_label = new wxStaticText( panel, -1, wxU(_("Title")) );
742 disc_title = new wxSpinCtrl( panel, DiscTitle_Event );
743 sizer->Add( disc_title_label, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
744 sizer->Add( disc_title, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
746 disc_chapter_label = new wxStaticText( panel, -1, wxU(_("Chapter")) );
747 disc_chapter = new wxSpinCtrl( panel, DiscChapter_Event );
748 sizer->Add( disc_chapter_label, 0,
749 wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
750 sizer->Add( disc_chapter, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
752 disc_sub_label = new wxStaticText( panel, -1, wxU(_("Subtitles track")) );
753 disc_sub = new wxSpinCtrl( panel, DiscSub_Event );
754 sizer->Add( disc_sub_label, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
755 sizer->Add( disc_sub, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
756 disc_sub->SetRange( -1, 255 );
757 i_disc_sub = config_GetInt( p_intf, "sub-track" );
758 disc_sub->SetValue( i_disc_sub );
760 disc_audio_label = new wxStaticText( panel, -1, wxU(_("Audio track")) );
761 disc_audio = new wxSpinCtrl( panel, DiscAudio_Event );
762 sizer->Add( disc_audio_label, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
763 sizer->Add( disc_audio, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
764 disc_audio->SetRange( -1, 255 );
765 i_disc_audio = config_GetInt( p_intf, "audio-track" );
766 disc_audio->SetValue( i_disc_audio );
768 sizer_row->Add( sizer, 0, wxEXPAND | wxALL, 5 );
770 panel->SetSizerAndFit( sizer_row );
774 wxPanel *OpenDialog::NetPanel( wxWindow* parent )
777 wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
780 wxBoxSizer *sizer_row = new wxBoxSizer( wxVERTICAL );
781 wxFlexGridSizer *sizer = new wxFlexGridSizer( 2, 4, 20 );
783 static const wxString net_type_array[] =
786 wxU(_("UDP/RTP Multicast")),
787 wxU(_("HTTP/HTTPS/FTP/MMS")),
793 net_radios[i] = new wxRadioButton( panel, NetRadio1_Event + i,
795 wxDefaultPosition, wxDefaultSize,
798 net_subpanels[i] = new wxPanel( panel, -1,
799 wxDefaultPosition, wxDefaultSize );
803 net_timeshift = new wxCheckBox( panel, NetTimeshift_Event,
804 wxU(_("Allow timeshifting")) );
807 wxFlexGridSizer *subpanel_sizer;
809 i_net_ports[0] = config_GetInt( p_intf, "server-port" );
810 subpanel_sizer = new wxFlexGridSizer( 3, 1, 20 );
811 label = new wxStaticText( net_subpanels[0], -1, wxU(_("Port")) );
812 net_ports[0] = new wxSpinCtrl( net_subpanels[0], NetPort1_Event,
813 wxString::Format(wxT("%d"), i_net_ports[0]),
814 wxDefaultPosition, wxDefaultSize,
816 0, 65535, i_net_ports[0] );
818 subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
819 subpanel_sizer->Add( net_ports[0], 1,
820 wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
821 net_ipv6 = new wxCheckBox( net_subpanels[0], NetForceIPv6_Event,
822 wxU(_("Force IPv6")));
823 subpanel_sizer->Add( net_ipv6, 0,
824 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
825 net_subpanels[0]->SetSizerAndFit( subpanel_sizer );
826 net_radios[0]->SetValue( TRUE );
828 /* UDP/RTP Multicast row */
829 subpanel_sizer = new wxFlexGridSizer( 4, 1, 20 );
830 label = new wxStaticText( net_subpanels[1], -1, wxU(_("Address")) );
831 net_addrs[1] = new wxTextCtrl( net_subpanels[1], NetAddr2_Event, wxT(""),
832 wxDefaultPosition, wxDefaultSize,
834 subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
835 subpanel_sizer->Add( net_addrs[1], 1,
836 wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
838 label = new wxStaticText( net_subpanels[1], -1, wxU(_("Port")) );
839 i_net_ports[1] = i_net_ports[0];
840 net_ports[1] = new wxSpinCtrl( net_subpanels[1], NetPort2_Event,
841 wxString::Format(wxT("%d"), i_net_ports[1]),
842 wxDefaultPosition, wxDefaultSize,
844 0, 65535, i_net_ports[1] );
846 subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
847 subpanel_sizer->Add( net_ports[1], 1,
848 wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
849 net_subpanels[1]->SetSizerAndFit( subpanel_sizer );
851 /* HTTP and RTSP rows */
854 subpanel_sizer = new wxFlexGridSizer( 2, 1, 20 );
855 label = new wxStaticText( net_subpanels[i], -1, wxU(_("URL")) );
856 net_addrs[i] = new wxTextCtrl( net_subpanels[i], NetAddr1_Event + i,
857 (i == 2) ? wxT("") : wxT("rtsp://"),
858 wxDefaultPosition, wxSize( 200, -1 ),
860 subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
861 subpanel_sizer->Add( net_addrs[i], 1,
862 wxEXPAND | wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
863 net_subpanels[i]->SetSizerAndFit( subpanel_sizer );
866 /* Stuff everything into the main panel */
869 sizer->Add( net_radios[i], 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL |
871 sizer->Add( net_subpanels[i], 1, wxEXPAND | wxALIGN_LEFT |
872 wxALIGN_CENTER_VERTICAL | wxALL, 5 );
874 sizer->Add( net_timeshift, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL |
877 sizer_row->Add( sizer, 0, wxEXPAND | wxALL, 5 );
879 panel->SetSizerAndFit( sizer_row );
883 void OpenDialog::UpdateMRL()
885 UpdateMRL( i_current_access_method );
888 void OpenDialog::UpdateMRL( int i_access_method )
890 wxString mrltemp, caching_name;
892 i_current_access_method = i_access_method;
894 switch( i_access_method )
897 mrltemp = file_combo->GetValue();
898 caching_name = wxT("file-caching");
902 i_disc_type_selection = disc_type->GetSelection();
904 switch ( i_disc_type_selection )
906 case 0: /* DVD with menus */
907 case 1: /* DVD without menus */
908 disc_device->SetToolTip( wxU(_("Name of DVD device "
910 if( i_disc_type_selection == 0 )
912 mrltemp = wxT("dvd://") + disc_device->GetValue();
913 caching_name = wxT("dvdnav-caching");
917 mrltemp = wxT("dvdsimple://") + disc_device->GetValue();
918 caching_name = wxT("dvdread-caching");
921 if( i_disc_title > 0 )
923 mrltemp += wxString::Format( wxT("@%d"), i_disc_title );
925 if( i_disc_chapter > 0 )
926 mrltemp += wxString::Format( wxT(":%d"), i_disc_chapter );
929 if( i_disc_sub >= 0 )
930 mrltemp += wxString::Format( wxT(" :sub-track=%d"),
932 if( i_disc_audio >= 0 )
933 mrltemp += wxString::Format( wxT(" :audio-track=%d"),
937 case 2: /* VCD of some sort */
939 disc_device->SetToolTip( wxU(_("Name of CD-ROM device "
940 "to read Video CD from. If this field is left empty, we will scan "
941 "for a CD-ROM with a VCD in it.")) );
942 mrltemp = wxT("vcdx://") + disc_device->GetValue();
943 if( i_disc_title > 0 )
944 mrltemp += wxString::Format( wxT("@%c%d"),
945 config_GetInt( p_intf, "vcdx-PBC" )
946 ? 'P' : 'E', i_disc_title );
948 disc_device->SetToolTip( wxU(_("Name of CD-ROM device "
949 "to read Video CD from.")) );
950 mrltemp = wxT("vcd://") + disc_device->GetValue();
951 if( i_disc_title > 0 )
952 mrltemp += wxString::Format( wxT("@%d"), i_disc_title );
955 if( i_disc_sub >= 0 )
956 mrltemp += wxString::Format( wxT(" :sub-track=%d"),
959 if( i_disc_audio >= 0 )
960 mrltemp += wxString::Format( wxT(" :audio-track=%d"),
962 caching_name = wxT("vcd-caching");
967 disc_device->SetToolTip( wxU(_("Name of CD-ROM device "
968 "to read audio CD from. If this field is left empty, we will scan "
969 "for a CD-ROM with an audio CD in it." )) );
970 mrltemp = wxT("cddax://")
972 disc_device->SetToolTip( wxU(_("Name of CD-ROM device "
973 "to read audio CD from." )) );
974 mrltemp = wxT("cdda://")
976 + disc_device->GetValue();
977 if( i_disc_title > 0 )
978 mrltemp += wxString::Format( wxT("@%d"), i_disc_title );
980 caching_name = wxT("cdda-caching");
984 msg_Err( p_intf, "invalid selection (%d)",
985 disc_type->GetSelection() );
994 mrltemp = wxT("udp://@");
995 if ( net_ipv6->GetValue() )
997 mrltemp += wxT("[::]");
999 if( i_net_ports[0] !=
1000 config_GetInt( p_intf, "server-port" ) )
1002 mrltemp += wxString::Format( wxT(":%d"), i_net_ports[0] );
1005 caching_name = wxT("udp-caching");
1009 mrltemp = wxT("udp://@");
1010 if ((net_addrs[1]->GetLineText(0).Find (':') != -1)
1011 && (net_addrs[1]->GetLineText(0)[0u] != '['))
1013 /* automatically adds '[' and ']' to IPv6 addresses */
1014 mrltemp += wxT("[") + net_addrs[1]->GetLineText(0)
1019 mrltemp += net_addrs[1]->GetLineText(0);
1021 if( i_net_ports[1] != config_GetInt( p_intf, "server-port" ) )
1023 mrltemp += wxString::Format( wxT(":%d"), i_net_ports[1] );
1026 caching_name = wxT("udp-caching");
1031 if( net_addrs[2]->GetLineText(0).Find(wxT("://")) == -1 )
1032 mrltemp = wxT("http://");
1034 mrltemp += net_addrs[2]->GetLineText(0);
1036 caching_name = wxT("http-caching");
1041 if( net_addrs[3]->GetLineText(0).Find(wxT("rtsp://")) != 0 )
1043 mrltemp = wxT("rtsp://");
1045 mrltemp += net_addrs[3]->GetLineText(0);
1047 caching_name = wxT("rtsp-caching");
1050 if( net_timeshift->IsEnabled() && net_timeshift->IsChecked() )
1051 mrltemp += wxT(" :access-filter=timeshift");
1056 int i_item = i_access_method - MAX_ACCESS;
1058 if( i_item < 0 || i_item >= (int)input_tab_array.GetCount() )
1061 AutoBuiltPanel *input_panel = input_tab_array.Item( i_item );
1063 mrltemp = input_panel->name + wxT("://");
1065 for( int i=0; i < (int)input_panel->config_array.GetCount(); i++ )
1067 ConfigControl *control = input_panel->config_array.Item(i);
1069 mrltemp += wxT(" :");
1071 if( control->GetType() == CONFIG_ITEM_BOOL &&
1072 !control->GetIntValue() ) mrltemp += wxT("no-");
1074 mrltemp += control->GetName();
1076 switch( control->GetType() )
1078 case CONFIG_ITEM_STRING:
1079 case CONFIG_ITEM_FILE:
1080 case CONFIG_ITEM_DIRECTORY:
1081 case CONFIG_ITEM_MODULE:
1082 mrltemp += wxT("=\"") + control->GetPszValue() + wxT("\"");
1084 case CONFIG_ITEM_INTEGER:
1086 wxString::Format( wxT("=%i"), control->GetIntValue() );
1088 case CONFIG_ITEM_FLOAT:
1090 wxString::Format(wxT("=%f"), control->GetFloatValue());
1095 if( input_panel->p_advanced_mrl_combo &&
1096 input_panel->p_advanced_mrl_combo->GetValue() )
1098 mrltemp += wxT(" ") +
1099 input_panel->p_advanced_mrl_combo->GetValue();
1105 if( caching_name.size() )
1107 if( caching_value->IsEnabled() )
1109 mrltemp += wxT(" :") + caching_name +
1110 wxString::Format( wxT("=%d"), i_caching );
1114 int i_value = config_GetInt( p_intf, caching_name.mb_str() );
1115 caching_value->SetValue( i_value );
1119 mrl_combo->SetValue( mrltemp );
1122 /*****************************************************************************
1124 *****************************************************************************/
1125 void OpenDialog::OnOk( wxCommandEvent& WXUNUSED(event) )
1127 mrl = SeparateEntries( mrl_combo->GetValue() );
1128 mrl_combo->Append( mrl_combo->GetValue() );
1129 if( mrl_combo->GetCount() > 10 ) mrl_combo->Delete( 0 );
1130 mrl_combo->SetSelection( mrl_combo->GetCount() - 1 );
1132 if( i_method == OPEN_STREAM )
1134 if( IsModal() ) EndModal( wxID_OK );
1139 /* Update the playlist */
1140 playlist_t *p_playlist =
1141 (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
1143 if( p_playlist == NULL ) return;
1145 for( int i = 0; i < (int)mrl.GetCount(); i++ )
1147 vlc_bool_t b_start = !i && i_open_arg;
1148 playlist_item_t *p_item;
1151 psz_utf8 = wxFromLocale( mrl[i] );
1152 p_item = playlist_ItemNew( p_intf, psz_utf8, psz_utf8 );
1153 wxLocaleFree( psz_utf8 );
1155 /* Insert options */
1156 while( i + 1 < (int)mrl.GetCount() &&
1157 ((const char *)mrl[i + 1].mb_str())[0] == ':' )
1159 psz_utf8 = wxFromLocale( mrl[i + 1] );
1160 playlist_ItemAddOption( p_item, psz_utf8 );
1161 wxLocaleFree( psz_utf8 );
1165 /* Get the options from the subtitles dialog */
1166 if( subsfile_checkbox->IsChecked() && subsfile_mrl.GetCount() )
1168 for( int j = 0; j < (int)subsfile_mrl.GetCount(); j++ )
1170 psz_utf8 = wxFromLocale( subsfile_mrl[j] );
1171 playlist_ItemAddOption( p_item, psz_utf8 );
1172 wxLocaleFree( psz_utf8 );
1176 /* Get the options from the stream output dialog */
1177 if( sout_checkbox->IsChecked() && sout_mrl.GetCount() )
1179 for( int j = 0; j < (int)sout_mrl.GetCount(); j++ )
1181 psz_utf8 = wxFromLocale( sout_mrl[j] );
1182 playlist_ItemAddOption( p_item, psz_utf8 );
1183 wxLocaleFree( psz_utf8 );
1187 playlist_AddItem( p_playlist, p_item, PLAYLIST_APPEND, PLAYLIST_END );
1191 playlist_Control( p_playlist, PLAYLIST_ITEMPLAY, p_item );
1195 vlc_object_release( p_playlist );
1199 if( IsModal() ) EndModal( wxID_OK );
1202 void OpenDialog::OnCancel( wxCommandEvent& WXUNUSED(event) )
1204 wxCloseEvent cevent;
1208 void OpenDialog::OnClose( wxCloseEvent& WXUNUSED(event) )
1212 if( IsModal() ) EndModal( wxID_CANCEL );
1215 void OpenDialog::OnPageChange( wxNotebookEvent& event )
1217 UpdateMRL( event.GetSelection() );
1220 void OpenDialog::OnMRLChange( wxCommandEvent& event )
1222 //mrl = SeparateEntries( event.GetString() );
1225 /*****************************************************************************
1226 * File panel event methods.
1227 *****************************************************************************/
1228 void OpenDialog::OnFilePanelChange( wxCommandEvent& WXUNUSED(event) )
1230 UpdateMRL( FILE_ACCESS );
1233 void OpenDialog::OnFileBrowse( wxCommandEvent& WXUNUSED(event) )
1235 if( file_dialog == NULL )
1236 file_dialog = new wxFileDialog( this, wxU(_("Open File")),
1237 wxT(""), wxT(""), wxT("*"), wxOPEN | wxMULTIPLE );
1239 if( file_dialog && file_dialog->ShowModal() == wxID_OK )
1241 wxArrayString paths;
1244 file_dialog->GetPaths( paths );
1246 for( size_t i = 0; i < paths.GetCount(); i++ )
1248 if( paths[i].Find( wxT(' ') ) >= 0 )
1249 path += wxT("\"") + paths[i] + wxT("\" ");
1251 path += paths[i] + wxT(" ");
1254 file_combo->SetValue( path );
1255 file_combo->Append( path );
1256 if( file_combo->GetCount() > 10 ) file_combo->Delete( 0 );
1257 UpdateMRL( FILE_ACCESS );
1261 /*****************************************************************************
1262 * Disc panel event methods.
1263 *****************************************************************************/
1264 void OpenDialog::OnDiscPanelChangeSpin( wxSpinEvent& event )
1266 wxCommandEvent cevent;
1267 cevent.SetId(event.GetId());
1268 cevent.SetInt(event.GetPosition());
1269 OnDiscPanelChange(cevent);
1272 void OpenDialog::OnDiscPanelChange( wxCommandEvent& event )
1274 if( event.GetId() == DiscTitle_Event ) i_disc_title = event.GetInt();
1275 if( event.GetId() == DiscChapter_Event ) i_disc_chapter = event.GetInt();
1276 if( event.GetId() == DiscSub_Event ) i_disc_sub = event.GetInt();
1277 if( event.GetId() == DiscAudio_Event ) i_disc_audio = event.GetInt();
1279 UpdateMRL( DISC_ACCESS );
1282 void OpenDialog::OnDiscDeviceChange( wxCommandEvent& event )
1286 switch( disc_type->GetSelection() )
1289 psz_device = config_GetPsz( p_intf, "cd-audio" );
1293 psz_device = config_GetPsz( p_intf, "vcd" );
1297 psz_device = config_GetPsz( p_intf, "dvd" );
1301 if ( !psz_device ) psz_device = "";
1303 if( disc_device->GetValue().Cmp( wxL2U( psz_device ) ) )
1305 b_disc_device_changed = true;
1308 UpdateMRL( DISC_ACCESS );
1313 /* Return true if *psz_drive is a drive with a DVD in it. A more complete
1314 check would see if the media looks like a *playable* DVD. This should
1317 static bool IsDVD(const char *psz_drive)
1319 CdIo_t *p_cdio = cdio_open (psz_drive, DRIVER_UNKNOWN);
1322 discmode_t discmode = cdio_get_discmode(p_cdio);
1323 cdio_destroy(p_cdio);
1324 return cdio_is_discmode_dvd(discmode);
1330 /* Return a device that has a DVD in it. The caller needs to free
1331 the returned string.
1333 static char * ProbeDVD(const wxChar *device)
1335 char **ppsz_cd_drives;
1336 const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(device);
1337 char *psz_device = const_cast<char *>(tmp_buf.data());
1339 if( IsDVD(psz_device) )
1341 return strdup(psz_device);
1344 ppsz_cd_drives = cdio_get_devices(DRIVER_DEVICE);
1345 if( ppsz_cd_drives )
1348 for( c = ppsz_cd_drives; *c != NULL; c++ )
1352 char *psz_drive = strdup(*c);
1353 cdio_free_device_list(ppsz_cd_drives);
1354 return strdup(psz_drive);
1357 cdio_free_device_list(ppsz_cd_drives);
1363 static char * ProbeDevice(char **ppsz_search_devices, cdio_fs_anal_t mask,
1366 char **ppsz_devices;
1368 if( ppsz_search_devices && !ppsz_search_devices[0] )
1369 ppsz_search_devices = NULL;
1371 /* Start out trying the device that has been entered so far. */
1372 ppsz_devices = cdio_get_devices_with_cap(ppsz_search_devices, mask,
1375 if (ppsz_devices && *ppsz_devices)
1377 char *psz_device = strdup(*ppsz_devices);
1378 cdio_free_device_list(ppsz_devices);
1382 /* If there was no device specified on the first try, then give up
1383 now. Otherwise accept any CD-ROM in the class (e.g. VCD or DVD).
1385 if( !ppsz_search_devices ) return NULL;
1387 ppsz_devices = cdio_get_devices_with_cap(NULL, mask, true);
1389 if (ppsz_devices && *ppsz_devices)
1391 char *psz_device = strdup(*ppsz_devices);
1392 cdio_free_device_list(ppsz_devices);
1400 /* Return a device that has a CD-DA in it. The caller needs to free
1401 the returned string.
1403 static char * ProbeCDDA(const wxChar *device)
1405 char *ppsz_device[2];
1406 const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(device);
1407 char *psz_device = const_cast<char *>(tmp_buf.data());
1408 ppsz_device[0] = (device && *device) ? psz_device : NULL;
1409 ppsz_device[1] = NULL;
1410 return ProbeDevice(ppsz_device, CDIO_FS_AUDIO, false);
1413 /* Return a device that has a VCD in it. The caller needs to free
1414 the returned string.
1416 static char * ProbeVCD(const wxChar *device)
1418 char *ppsz_device[2];
1419 const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(device);
1420 char *psz_device = const_cast<char *>(tmp_buf.data());
1421 ppsz_device[0] = (device && *device) ? psz_device : NULL;
1422 ppsz_device[1] = NULL;
1423 return ProbeDevice(ppsz_device,
1424 (CDIO_FS_ANAL_SVCD|CDIO_FS_ANAL_CVD|CDIO_FS_ANAL_VIDEOCD
1425 |CDIO_FS_UNKNOWN), true);
1430 Probe (find anywhere) a CD-DA, VCD, or a DVD.
1431 First try the device name that may have been entered for the "disc type"
1432 selected. If that doesn't work we try any device for the disc type.
1433 If that doesn't work, try looking for CD-ROMs or DVD drives. the
1434 disc type, device name and paramter ranges are set to whatever we find.
1436 void OpenDialog::OnDiscProbe( wxCommandEvent& WXUNUSED(event) )
1438 wxCommandEvent dummy_event;
1439 char *psz_device = NULL;
1440 bool b_probed_DVD = false;
1441 bool b_probed_VCD = false;
1442 const int i_selection = disc_type->GetSelection();
1444 /* Reduce verbosity of cdio errors. */
1445 cdio_loglevel_default = CDIO_LOG_ERROR;
1448 switch( disc_type->GetSelection() )
1451 case SELECTION_DISC_TYPE_DVD_MENUS:
1452 case SELECTION_DISC_TYPE_DVD:
1453 /* If not a DVD then try for a VCD. If VCD fails it will
1455 if (!psz_device) psz_device = ProbeDVD(disc_device->GetValue());
1458 b_probed_DVD = true;
1459 disc_type->SetSelection(SELECTION_DISC_TYPE_VCD);
1460 OnDiscTypeChange( dummy_event );
1463 disc_device->SetValue( wxL2U(psz_device) );
1466 case SELECTION_DISC_TYPE_VCD: /* VCD probe of some sort */
1467 if(!psz_device) psz_device = ProbeVCD(disc_device->GetValue());
1471 #if LIBVCD_VERSION_NUM > 23
1472 vcdinfo_obj_t *p_vcdinfo;
1474 /* Set LID or entry range accurately if possible. */
1475 if( vcdinfo_open(&p_vcdinfo, &psz_device, DRIVER_DEVICE,
1476 NULL) == VCDINFO_OPEN_VCD)
1478 if (config_GetInt( p_intf, "vcdx-PBC" ))
1480 /* Set largest LID. */;
1481 disc_title->SetRange( 0, vcdinfo_get_num_LIDs(p_vcdinfo) );
1486 /* Set largest Entry */
1487 disc_title->SetRange( 0,
1488 vcdinfo_get_num_entries(p_vcdinfo)-1 );
1490 vcdinfo_close(p_vcdinfo);
1492 #endif /* LIBVCD_VERSION_NUM > 23 */
1493 disc_device->SetValue( wxL2U(psz_device) );
1495 CdIo_t *p_cdio = cdio_open (psz_device, DRIVER_UNKNOWN);
1496 disc_device->SetValue( wxL2U(psz_device) );
1498 /* Set track range accurately if possible. */
1501 track_t i_last_track = cdio_get_last_track_num(p_cdio);
1502 disc_title->SetRange( 0, i_last_track-1 );
1504 cdio_destroy(p_cdio);
1509 b_probed_VCD = true;
1511 /* Not a VCD. Try for a DVD unless we've been there before. */
1512 if( !b_probed_DVD && (psz_device = ProbeDVD(disc_device->GetValue())) )
1514 disc_type->SetSelection(SELECTION_DISC_TYPE_DVD_MENUS);
1515 OnDiscTypeChange( dummy_event );
1518 b_probed_DVD = true;
1520 /* Couldn't find a VCD or DVD. See if we can find a CD-DA. */
1521 psz_device = ProbeCDDA(disc_device->GetValue());
1524 disc_type->SetSelection(SELECTION_DISC_TYPE_CDDA);
1525 OnDiscTypeChange( dummy_event );
1529 /* Couldn't find a VCD, DVD or CD-DA. Null out the Device name and
1530 set to original selection.
1532 disc_device->SetValue( wxL2U("") );
1533 disc_type->SetSelection(i_selection);
1534 OnDiscTypeChange( dummy_event );
1537 case SELECTION_DISC_TYPE_CDDA:
1538 if(!psz_device) psz_device = ProbeCDDA(disc_device->GetValue());
1541 CdIo_t *p_cdio = cdio_open (psz_device, DRIVER_UNKNOWN);
1542 disc_device->SetValue( wxL2U(psz_device) );
1545 track_t i_last_track = cdio_get_last_track_num(p_cdio);
1546 disc_title->SetRange( 0, i_last_track );
1548 MediaInsertCDDA( p_intf, p_cdio, i_last_track );
1551 cdio_destroy(p_cdio);
1555 /* Not a CD-DA. Try for a DVD unless we've been there before. */
1556 if( !b_probed_DVD && (psz_device = ProbeDVD(disc_device->GetValue())) )
1558 disc_type->SetSelection(SELECTION_DISC_TYPE_DVD_MENUS);
1559 OnDiscTypeChange( dummy_event );
1563 /* Couldn't find a CD-DA or DVD. See if we can find a VCD, unless
1564 we've tried that before. */
1565 if (!b_probed_VCD) psz_device = ProbeVCD(disc_device->GetValue());
1568 disc_type->SetSelection(SELECTION_DISC_TYPE_VCD);
1569 OnDiscTypeChange( dummy_event );
1572 disc_device->SetValue( wxL2U("") );
1576 msg_Err( p_intf, "invalid Disc type selection (%d)",
1577 disc_type->GetSelection() );
1582 disc_probe->SetValue(FALSE);
1584 UpdateMRL( DISC_ACCESS );
1586 #endif /* HAVE_LIBCDIO */
1588 void OpenDialog::OnDiscTypeChange( wxCommandEvent& WXUNUSED(event) )
1590 char *psz_device = NULL;
1592 switch( disc_type->GetSelection() )
1595 case SELECTION_DISC_TYPE_DVD_MENUS:
1596 case SELECTION_DISC_TYPE_DVD:
1597 disc_sub->Enable(); disc_sub_label->Enable();
1598 disc_audio->Enable(); disc_audio_label->Enable();
1599 disc_chapter->Enable(); disc_chapter_label->Enable();
1600 disc_title_label->SetLabel ( wxU(_("Title")) );
1601 psz_device = config_GetPsz( p_intf, "dvd" );
1602 if( !b_disc_device_changed )
1604 if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
1605 else disc_device->SetValue( wxT("") );
1607 disc_title->SetRange( 0, 255 );
1608 disc_sub->SetRange( -1, 31 ); // up to 32 subtitles -1: no subtitle
1609 disc_audio->SetRange( 0, 7 ); // up to 8 audio channels
1610 disc_chapter->SetRange( 0, 255 );
1611 disc_title->SetToolTip( wxU(_("Title number.")) );
1612 disc_sub->SetToolTip( wxU(_(
1613 "DVD's can have up to 32 subtitles numbered 0..31. "
1614 "Note this is not the same thing as a subtitle name e.g. 'en'. "
1615 "If a value -1 is used, no subtitle will be shown." )) );
1616 disc_audio->SetToolTip( wxU(_("Audio track number. "
1617 "DVD's can have up to 8 audio tracks numbered 0..7."
1621 case SELECTION_DISC_TYPE_VCD:
1622 disc_sub->Enable(); disc_sub_label->Enable();
1623 disc_audio->Enable(); disc_audio_label->Enable();
1624 disc_chapter->Disable(); disc_chapter_label->Disable();
1625 psz_device = config_GetPsz( p_intf, "vcd" );
1626 if( !b_disc_device_changed )
1628 if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
1629 else disc_device->SetValue( wxT("") );
1633 if (config_GetInt( p_intf, "vcdx-PBC" ))
1635 disc_title_label->SetLabel ( wxT("Playback LID") );
1636 disc_title->SetToolTip( wxU(_(
1637 "Playback control (PBC) usually starts with number 1." )) );
1641 disc_title_label->SetLabel ( wxT("Entry") );
1642 disc_title->SetToolTip( wxU(_(
1643 "The first entry (the beginning of the first MPEG track) is 0." )) );
1647 disc_title_label->SetLabel ( wxU(_("Track")) );
1648 disc_title->SetToolTip( wxU(_("Track number.")) );
1650 disc_title->SetRange( 0, 99 ); // only 100 tracks allowed on VCDs
1651 disc_sub->SetRange( -1, 3 ); // up to 4 subtitles -1 = no subtitle
1652 disc_audio->SetRange( 0, 1 ); // up to 2 audio tracks
1653 disc_sub->SetToolTip( wxU(_(
1654 "SVCD's can have up to 4 subtitles numbered 0..3. "
1655 "If a value -1 is used, no subtitle will be shown." )) );
1656 disc_audio->SetToolTip( wxU(_("Audio track number. "
1657 "VCD's can have up to 2 audio tracks numbered 0 or 1. "
1661 case SELECTION_DISC_TYPE_CDDA:
1662 disc_sub->Disable(); disc_sub_label->Disable();
1663 disc_chapter->Disable(); disc_chapter_label->Disable();
1664 disc_audio->Disable(); disc_audio_label->Disable();
1665 disc_title_label->SetLabel ( wxU(_("Track")) );
1667 disc_title->SetToolTip( wxU(_(
1668 "Audio CDs can have up to 100 tracks, the first track is usually 1. "
1669 "If 0 is given, then all tracks are played.")) );
1671 disc_title->SetToolTip( wxU(_(
1672 "Audio CDs can have up to 100 tracks, the first track is usually 1."
1675 psz_device = config_GetPsz( p_intf, "cd-audio" );
1676 if( !b_disc_device_changed )
1678 if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
1679 else disc_device->SetValue( wxT("") );
1682 /* There are at most 100 tracks in a CD-DA */
1683 disc_title->SetRange( 0, 100 );
1687 msg_Err( p_intf, "invalid Disc type selection (%d)",
1688 disc_type->GetSelection() );
1692 disc_title->SetValue( 0 ); i_disc_title = 0;
1693 disc_chapter->SetValue( 0 ); i_disc_chapter = 0;
1695 if( psz_device ) free( psz_device );
1697 UpdateMRL( DISC_ACCESS );
1700 /*****************************************************************************
1701 * Net panel event methods.
1702 *****************************************************************************/
1703 void OpenDialog::OnNetPanelChangeSpin( wxSpinEvent& event )
1705 wxCommandEvent cevent;
1706 cevent.SetId(event.GetId());
1707 cevent.SetInt(event.GetPosition());
1708 OnNetPanelChange(cevent);
1711 void OpenDialog::OnNetPanelChange( wxCommandEvent& event )
1713 if( event.GetId() >= NetPort1_Event && event.GetId() <= NetPort3_Event )
1715 i_net_ports[event.GetId() - NetPort1_Event] = event.GetInt();
1718 UpdateMRL( NET_ACCESS );
1721 void OpenDialog::OnNetTypeChange( wxCommandEvent& event )
1725 i_net_type = event.GetId() - NetRadio1_Event;
1729 net_radios[i]->SetValue( event.GetId() == (NetRadio1_Event+i) );
1730 net_subpanels[i]->Enable( event.GetId() == (NetRadio1_Event+i) );
1732 /* UDP Unicast or multicast -> timeshift */
1733 if( i_net_type == 0 || i_net_type == 1 )
1734 net_timeshift->Enable();
1736 net_timeshift->Disable();
1738 UpdateMRL( NET_ACCESS );
1741 /*****************************************************************************
1742 * Subtitles file event methods.
1743 *****************************************************************************/
1744 void OpenDialog::OnSubsFileEnable( wxCommandEvent& event )
1746 subsfile_button->Enable( event.GetInt() != 0 );
1749 void OpenDialog::OnSubsFileSettings( wxCommandEvent& WXUNUSED(event) )
1751 /* Show/hide the open dialog */
1752 if( subsfile_dialog == NULL )
1753 subsfile_dialog = new SubsFileDialog( p_intf, this );
1755 if( subsfile_dialog && subsfile_dialog->ShowModal() == wxID_OK )
1757 subsfile_mrl.Empty();
1758 subsfile_mrl.Add( wxString(wxT("sub-file=")) +
1759 subsfile_dialog->file_combo->GetValue() );
1760 if( subsfile_dialog->encoding_combo )
1762 subsfile_mrl.Add( wxString(wxT("subsdec-encoding=")) +
1763 subsfile_dialog->encoding_combo->GetValue() );
1765 if( subsfile_dialog->align_combo )
1767 subsfile_mrl.Add( wxString::Format(wxT("subsdec-align=%i"),
1768 (int)subsfile_dialog->align_combo->GetClientData(
1769 subsfile_dialog->align_combo->GetSelection()) ) );
1771 if( subsfile_dialog->size_combo )
1773 subsfile_mrl.Add( wxString::Format( wxT("freetype-rel-fontsize=%i"),
1774 (int)subsfile_dialog->size_combo->GetClientData(
1775 subsfile_dialog->size_combo->GetSelection()) ) );
1777 subsfile_mrl.Add( wxString::Format( wxT("sub-fps=%i"),
1778 subsfile_dialog->fps_spinctrl->GetValue() ) );
1779 subsfile_mrl.Add( wxString::Format( wxT("sub-delay=%i"),
1780 subsfile_dialog->delay_spinctrl->GetValue() ) );
1784 /*****************************************************************************
1785 * Stream output event methods.
1786 *****************************************************************************/
1787 void OpenDialog::OnSoutEnable( wxCommandEvent& event )
1789 sout_button->Enable( event.GetInt() != 0 );
1792 void OpenDialog::OnSoutSettings( wxCommandEvent& WXUNUSED(event) )
1794 /* Show/hide the open dialog */
1795 if( sout_dialog == NULL )
1796 sout_dialog = new SoutDialog( p_intf, this );
1798 if( sout_dialog && sout_dialog->ShowModal() == wxID_OK )
1800 sout_mrl = sout_dialog->GetOptions();
1804 /*****************************************************************************
1805 * Caching event methods.
1806 *****************************************************************************/
1807 void OpenDialog::OnCachingEnable( wxCommandEvent& event )
1809 caching_value->Enable( event.GetInt() != 0 );
1810 i_caching = caching_value->GetValue();
1814 void OpenDialog::OnCachingChangeSpin( wxSpinEvent& event )
1816 wxCommandEvent cevent;
1817 OnCachingChange(cevent);
1820 void OpenDialog::OnCachingChange( wxCommandEvent& event )
1822 i_caching = event.GetInt();
1826 /*****************************************************************************
1827 * Utility functions.
1828 *****************************************************************************/
1829 wxArrayString SeparateEntries( wxString entries )
1831 vlc_bool_t b_quotes_mode = VLC_FALSE;
1833 wxArrayString entries_array;
1836 wxStringTokenizer token( entries, wxT(" \t\r\n\""), wxTOKEN_RET_DELIMS );
1838 while( token.HasMoreTokens() )
1840 entry += token.GetNextToken();
1842 if( entry.IsEmpty() ) continue;
1844 if( !b_quotes_mode && entry.Last() == wxT('\"') )
1846 /* Enters quotes mode */
1848 b_quotes_mode = VLC_TRUE;
1850 else if( b_quotes_mode && entry.Last() == wxT('\"') )
1852 /* Finished the quotes mode */
1854 b_quotes_mode = VLC_FALSE;
1856 else if( !b_quotes_mode && entry.Last() != wxT('\"') )
1858 /* we found a non-quoted standalone string */
1859 if( token.HasMoreTokens() ||
1860 entry.Last() == wxT(' ') || entry.Last() == wxT('\t') ||
1861 entry.Last() == wxT('\r') || entry.Last() == wxT('\n') )
1863 if( !entry.IsEmpty() ) entries_array.Add( entry );
1870 if( !entry.IsEmpty() ) entries_array.Add( entry );
1872 return entries_array;