]> git.sesse.net Git - vlc/blob - modules/gui/wxwindows/streamout.cpp
Automatically adds [ and ] around IPv6 addresses in Media Resource Locator.
[vlc] / modules / gui / wxwindows / streamout.cpp
1 /*****************************************************************************
2  * streamout.cpp : wxWindows plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2001 VideoLAN
5  * $Id: streamout.cpp,v 1.38 2003/12/10 11:04:25 courmisch 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 #include <vlc/intf.h>
34
35 #include "wxwindows.h"
36 #include <wx/notebook.h>
37 #include <wx/textctrl.h>
38 #include <wx/combobox.h>
39 #include <wx/spinctrl.h>
40 #include <wx/statline.h>
41
42 #ifndef wxRB_SINGLE
43 #   define wxRB_SINGLE 0
44 #endif
45
46 /*****************************************************************************
47  * Event Table.
48  *****************************************************************************/
49
50 /* IDs for the controls and the menu commands */
51 enum
52 {
53     Notebook_Event = wxID_HIGHEST,
54     MRL_Event,
55
56     FileBrowse_Event,
57     FileName_Event,
58     FileDump_Event,
59
60     AccessType1_Event, AccessType2_Event, AccessType3_Event,
61     AccessType4_Event, AccessType5_Event, AccessType6_Event,
62     NetPort1_Event, NetPort2_Event, NetPort3_Event, NetPort4_Event,
63     NetAddr1_Event, NetAddr2_Event, NetAddr3_Event, NetAddr4_Event,
64
65     EncapsulationRadio1_Event, EncapsulationRadio2_Event,
66     EncapsulationRadio3_Event, EncapsulationRadio4_Event,
67     EncapsulationRadio5_Event, EncapsulationRadio6_Event,
68     EncapsulationRadio7_Event, EncapsulationRadio8_Event,
69
70     VideoTranscEnable_Event, VideoTranscCodec_Event, VideoTranscBitrate_Event,
71     AudioTranscEnable_Event, AudioTranscCodec_Event, AudioTranscBitrate_Event,
72     AudioTranscChans_Event,
73
74     SAPMisc_Event, SLPMisc_Event, AnnounceAddr_Event
75 };
76
77 BEGIN_EVENT_TABLE(SoutDialog, wxDialog)
78     /* Button events */
79     EVT_BUTTON(wxID_OK, SoutDialog::OnOk)
80     EVT_BUTTON(wxID_CANCEL, SoutDialog::OnCancel)
81
82     /* Events generated by the access output panel */
83     EVT_CHECKBOX(AccessType1_Event, SoutDialog::OnAccessTypeChange)
84     EVT_CHECKBOX(AccessType2_Event, SoutDialog::OnAccessTypeChange)
85     EVT_CHECKBOX(AccessType3_Event, SoutDialog::OnAccessTypeChange)
86     EVT_CHECKBOX(AccessType4_Event, SoutDialog::OnAccessTypeChange)
87     EVT_CHECKBOX(AccessType5_Event, SoutDialog::OnAccessTypeChange)
88     EVT_CHECKBOX(AccessType6_Event, SoutDialog::OnAccessTypeChange)
89     EVT_TEXT(FileName_Event, SoutDialog::OnFileChange)
90     EVT_BUTTON(FileBrowse_Event, SoutDialog::OnFileBrowse)
91     EVT_CHECKBOX(FileDump_Event, SoutDialog::OnFileDump)
92
93     EVT_TEXT(NetPort1_Event, SoutDialog::OnNetChange)
94     EVT_TEXT(NetAddr1_Event, SoutDialog::OnNetChange)
95     EVT_TEXT(NetPort2_Event, SoutDialog::OnNetChange)
96     EVT_TEXT(NetAddr2_Event, SoutDialog::OnNetChange)
97     EVT_TEXT(NetPort3_Event, SoutDialog::OnNetChange)
98     EVT_TEXT(NetAddr3_Event, SoutDialog::OnNetChange)
99     EVT_TEXT(NetPort4_Event, SoutDialog::OnNetChange)
100     EVT_TEXT(NetAddr4_Event, SoutDialog::OnNetChange)
101
102     /* Events generated by the encapsulation panel */
103     EVT_RADIOBUTTON(EncapsulationRadio1_Event,
104                     SoutDialog::OnEncapsulationChange)
105     EVT_RADIOBUTTON(EncapsulationRadio2_Event,
106                     SoutDialog::OnEncapsulationChange)
107     EVT_RADIOBUTTON(EncapsulationRadio3_Event,
108                     SoutDialog::OnEncapsulationChange)
109     EVT_RADIOBUTTON(EncapsulationRadio4_Event,
110                     SoutDialog::OnEncapsulationChange)
111     EVT_RADIOBUTTON(EncapsulationRadio5_Event,
112                     SoutDialog::OnEncapsulationChange)
113     EVT_RADIOBUTTON(EncapsulationRadio6_Event,
114                     SoutDialog::OnEncapsulationChange)
115     EVT_RADIOBUTTON(EncapsulationRadio7_Event,
116                     SoutDialog::OnEncapsulationChange)
117     EVT_RADIOBUTTON(EncapsulationRadio8_Event,
118                     SoutDialog::OnEncapsulationChange)
119
120     /* Events generated by the transcoding panel */
121     EVT_CHECKBOX(VideoTranscEnable_Event, SoutDialog::OnTranscodingEnable)
122     EVT_CHECKBOX(AudioTranscEnable_Event, SoutDialog::OnTranscodingEnable)
123     EVT_COMBOBOX(VideoTranscCodec_Event, SoutDialog::OnTranscodingChange)
124     EVT_TEXT(VideoTranscCodec_Event, SoutDialog::OnTranscodingChange)
125     EVT_COMBOBOX(AudioTranscCodec_Event, SoutDialog::OnTranscodingChange)
126     EVT_TEXT(AudioTranscCodec_Event, SoutDialog::OnTranscodingChange)
127     EVT_COMBOBOX(VideoTranscBitrate_Event, SoutDialog::OnTranscodingChange)
128     EVT_TEXT(VideoTranscBitrate_Event, SoutDialog::OnTranscodingChange)
129     EVT_COMBOBOX(AudioTranscBitrate_Event, SoutDialog::OnTranscodingChange)
130     EVT_TEXT(AudioTranscBitrate_Event, SoutDialog::OnTranscodingChange)
131     EVT_COMBOBOX(AudioTranscChans_Event, SoutDialog::OnTranscodingChange)
132     EVT_TEXT(AudioTranscChans_Event, SoutDialog::OnTranscodingChange)
133
134     /* Events generated by the misc panel */
135     EVT_CHECKBOX(SAPMisc_Event, SoutDialog::OnSAPMiscChange)
136     EVT_CHECKBOX(SLPMisc_Event, SoutDialog::OnSLPMiscChange)
137     EVT_TEXT(AnnounceAddr_Event, SoutDialog::OnAnnounceAddrChange)
138
139 END_EVENT_TABLE()
140
141 /*****************************************************************************
142  * Constructor.
143  *****************************************************************************/
144 SoutDialog::SoutDialog( intf_thread_t *_p_intf, wxWindow* _p_parent ):
145     wxDialog( _p_parent, -1, wxU(_("Stream output")),
146              wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE )
147 {
148     /* Initializations */
149     p_intf = _p_intf;
150     p_parent = _p_parent;
151     SetIcon( *p_intf->p_sys->p_icon );
152
153     /* Create a panel to put everything in */
154     wxPanel *panel = new wxPanel( this, -1 );
155     panel->SetAutoLayout( TRUE );
156
157     /* Create MRL combobox */
158     wxBoxSizer *mrl_sizer_sizer = new wxBoxSizer( wxHORIZONTAL );
159     wxStaticBox *mrl_box = new wxStaticBox( panel, -1,
160                                wxU(_("Stream output MRL")) );
161     wxStaticBoxSizer *mrl_sizer = new wxStaticBoxSizer( mrl_box,
162                                                         wxHORIZONTAL );
163     wxStaticText *mrl_label = new wxStaticText( panel, -1,
164                                                 wxU(_("Destination Target:")));
165     mrl_combo = new wxComboBox( panel, MRL_Event, wxT(""),
166                                 wxPoint(20,25), wxSize(120, -1), 0, NULL );
167     mrl_combo->SetToolTip( wxU(_("You can use this field directly by typing "
168         "the full MRL you want to open.\n""Alternatively, the field will be "
169         "filled automatically when you use the controls below")) );
170
171     mrl_sizer->Add( mrl_label, 0, wxALL | wxALIGN_CENTER, 5 );
172     mrl_sizer->Add( mrl_combo, 1, wxALL | wxALIGN_CENTER, 5 );
173     mrl_sizer_sizer->Add( mrl_sizer, 1, wxEXPAND | wxALL, 5 );
174
175     /* Create the output encapsulation panel */
176     encapsulation_panel = EncapsulationPanel( panel );
177
178     /* Create the access output panel */
179     access_panel = AccessPanel( panel );
180
181     /* Create the transcoding panel */
182     transcoding_panel = TranscodingPanel( panel );
183
184     /* Create the Misc panel */
185     misc_panel = MiscPanel( panel );
186
187     /* Separation */
188     wxStaticLine *static_line = new wxStaticLine( panel, wxID_OK );
189
190     /* Create the buttons */
191     wxButton *ok_button = new wxButton( panel, wxID_OK, wxU(_("OK")) );
192     ok_button->SetDefault();
193     wxButton *cancel_button = new wxButton( panel, wxID_CANCEL,
194                                             wxU(_("Cancel")) );
195
196     /* Place everything in sizers */
197     wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
198     button_sizer->Add( ok_button, 0, wxALL, 5 );
199     button_sizer->Add( cancel_button, 0, wxALL, 5 );
200     button_sizer->Layout();
201     wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
202     wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
203     panel_sizer->Add( mrl_sizer_sizer, 0, wxEXPAND, 5 );
204     panel_sizer->Add( access_panel, 1, wxEXPAND | wxALL, 5 );
205     panel_sizer->Add( encapsulation_panel, 0, wxEXPAND | wxALL, 5 );
206     panel_sizer->Add( transcoding_panel, 0, wxEXPAND | wxALL, 5 );
207     panel_sizer->Add( misc_panel, 0, wxEXPAND | wxALL, 5 );
208     panel_sizer->Add( static_line, 0, wxEXPAND | wxALL, 5 );
209     panel_sizer->Add( button_sizer, 0, wxALIGN_LEFT | wxALIGN_BOTTOM |
210                       wxALL, 5 );
211     panel_sizer->Layout();
212     panel->SetSizerAndFit( panel_sizer );
213     main_sizer->Add( panel, 1, wxGROW, 0 );
214     main_sizer->Layout();
215     SetSizerAndFit( main_sizer );
216 }
217
218 SoutDialog::~SoutDialog()
219 {
220 }
221
222 wxArrayString SoutDialog::GetOptions()
223 {
224    return SeparateEntries( mrl_combo->GetValue() );
225 }
226
227 /*****************************************************************************
228  * Private methods.
229  *****************************************************************************/
230 void SoutDialog::UpdateMRL()
231 {
232     /* Check the demux dump option */
233     if( dump_checkbox->IsChecked() )
234     {
235         wxString dumpfile;
236
237         if( file_combo->GetValue().size() )
238             dumpfile = wxT(" :demuxdump-file=\"") +
239                        file_combo->GetValue() + wxT("\"");
240         mrl_combo->SetValue( wxT(":demux=demuxdump") + dumpfile );
241
242         return;
243     }
244
245     /* Let's start with the transcode options */
246     wxString transcode;
247     if( video_transc_checkbox->IsChecked() ||
248         audio_transc_checkbox->IsChecked() )
249     {
250         transcode = wxT("transcode{");
251         if( video_transc_checkbox->IsChecked() )
252         {
253             transcode += wxT("vcodec=") + video_codec_combo->GetValue();
254             transcode += wxT(",vb=") + video_bitrate_combo->GetValue();
255             if( audio_transc_checkbox->IsChecked() ) transcode += wxT(",");
256         }
257         if( audio_transc_checkbox->IsChecked() )
258         {
259             transcode += wxT("acodec=") + audio_codec_combo->GetValue();
260             transcode += wxT(",ab=") + audio_bitrate_combo->GetValue();
261             transcode += wxT(",channels=") + audio_channels_combo->GetValue();
262         }
263         transcode += wxT("}");
264     }
265
266     /* Encapsulation */
267     wxString encapsulation;
268     switch( i_encapsulation_type )
269     {
270     case PS_ENCAPSULATION:
271         encapsulation = wxT("ps");
272         break;
273     case MPEG1_ENCAPSULATION:
274         encapsulation = wxT("mpeg1");
275         break;
276     case AVI_ENCAPSULATION:
277         encapsulation = wxT("avi");
278         break;
279     case OGG_ENCAPSULATION:
280         encapsulation = wxT("ogg");
281         break;
282     case MP4_ENCAPSULATION:
283         encapsulation = wxT("mp4");
284         break;
285     case MOV_ENCAPSULATION:
286         encapsulation = wxT("mov");
287         break;
288     case ASF_ENCAPSULATION:
289         encapsulation = wxT("asf");
290         break;
291     case TS_ENCAPSULATION:
292     default:
293         encapsulation = wxT("ts");
294         break;
295     }
296
297     /* Now continue with the duplicate option */
298     wxString dup_opts;
299     if( access_checkboxes[PLAY_ACCESS_OUT]->IsChecked() )
300     {
301         dup_opts += wxT("dst=display");
302     }
303     if( access_checkboxes[FILE_ACCESS_OUT]->IsChecked() )
304     {
305         if( !dup_opts.IsEmpty() ) dup_opts += wxT(",");
306         dup_opts += wxT("dst=std{access=file,mux=");
307         dup_opts += encapsulation + wxT(",url=\"");
308         dup_opts += file_combo->GetValue() + wxT("\"}");
309     }
310     if( access_checkboxes[HTTP_ACCESS_OUT]->IsChecked() )
311     {
312         if( !dup_opts.IsEmpty() ) dup_opts += wxT(",");
313         dup_opts += wxT("dst=std{access=http,mux=");
314         dup_opts += encapsulation + wxT(",url=");
315         dup_opts += net_addrs[HTTP_ACCESS_OUT]->GetLineText(0);
316         dup_opts += wxString::Format( wxT(":%d"),
317                                       net_ports[HTTP_ACCESS_OUT]->GetValue() );
318         dup_opts += wxT("}");
319     }
320     if( access_checkboxes[MMSH_ACCESS_OUT]->IsChecked() )
321     {
322         if( !dup_opts.IsEmpty() ) dup_opts += wxT(",");
323         dup_opts += wxT("dst=std{access=mmsh,mux=");
324         dup_opts += encapsulation;
325         if( i_encapsulation_type == ASF_ENCAPSULATION ) dup_opts += wxT("h");
326         dup_opts += wxT(",url=");
327         dup_opts += net_addrs[HTTP_ACCESS_OUT]->GetLineText(0);
328         dup_opts += wxString::Format( wxT(":%d"),
329                                       net_ports[MMSH_ACCESS_OUT]->GetValue() );
330         dup_opts += wxT("}");
331     }
332     if( access_checkboxes[UDP_ACCESS_OUT]->IsChecked() )
333     {
334         if( !dup_opts.IsEmpty() ) dup_opts += wxT(",");
335         dup_opts += wxT("dst=std{access=udp,mux=");
336         dup_opts += encapsulation + wxT(",url=");
337
338         wxString udp_addr = net_addrs[UDP_ACCESS_OUT]->GetLineText(0);
339         if ((udp_addr[0u] != '[') && (udp_addr.Find(':') != -1))
340         {
341             dup_opts += wxT ("[") + udp_addr + wxT ("]");
342         }
343         else
344         {
345             dup_opts += udp_addr;
346         }
347         dup_opts += wxString::Format( wxT(":%d"),
348                                       net_ports[UDP_ACCESS_OUT]->GetValue() );
349
350         /* SAP only if UDP */
351         if( sap_checkbox->IsChecked() )
352         {
353             dup_opts += wxT(",sap=\"");
354             dup_opts += announce_addr->GetLineText(0);
355             dup_opts += wxT("\"");
356         }
357
358         /* SLP only if UDP */
359         if( slp_checkbox->IsChecked() )
360         {
361             dup_opts += wxT(",slp=\"");
362             dup_opts += announce_addr->GetLineText(0);
363             dup_opts += wxT("\"");
364         }
365
366         dup_opts += wxT("}");
367     }
368     if( access_checkboxes[RTP_ACCESS_OUT]->IsChecked() )
369     {
370         if( !dup_opts.IsEmpty() ) dup_opts += wxT(",");
371         dup_opts += wxT("dst=std{access=rtp,mux=");
372         dup_opts += encapsulation + wxT(",url=");
373         dup_opts += net_addrs[RTP_ACCESS_OUT]->GetLineText(0);
374         dup_opts += wxString::Format( wxT(":%d"),
375                                       net_ports[RTP_ACCESS_OUT]->GetValue() );
376         dup_opts += wxT("}");
377     }
378
379     wxString duplicate;
380     if( !dup_opts.IsEmpty() )
381     {
382         if( !transcode.IsEmpty() ) duplicate = wxT(":");
383         duplicate += wxT("duplicate{") + dup_opts + wxT("}");
384     }
385
386     if( !transcode.IsEmpty() || !duplicate.IsEmpty() )
387         mrl_combo->SetValue( wxT(":sout=#") + transcode + duplicate );
388     else
389         mrl_combo->SetValue( wxT("") );
390 }
391
392 wxPanel *SoutDialog::AccessPanel( wxWindow* parent )
393 {
394     int i;
395     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
396                                   wxSize(200, 200) );
397
398     wxStaticBox *panel_box = new wxStaticBox( panel, -1,
399                                               wxU(_("Output Methods")) );
400     wxStaticBoxSizer *panel_sizer = new wxStaticBoxSizer( panel_box,
401                                                           wxVERTICAL );
402
403     wxFlexGridSizer *sizer = new wxFlexGridSizer( 2, 4, 20 );
404     static const wxString access_output_array[] =
405     {
406         wxU(_("Play locally")),
407         wxU(_("File")),
408         wxU(_("HTTP")),
409         wxU(_("MMSH")),
410         wxU(_("UDP")),
411         wxU(_("RTP"))
412     };
413
414     for( i=0; i < ACCESS_OUT_NUM; i++ )
415     {
416         access_checkboxes[i] = new wxCheckBox( panel, AccessType1_Event + i,
417                                                access_output_array[i] );
418         access_subpanels[i] = new wxPanel( panel, -1 );
419     }
420
421     /* Play locally row */
422     wxFlexGridSizer *subpanel_sizer;
423     wxStaticText *label;
424     label = new wxStaticText( access_subpanels[0], -1, wxT("") );
425     subpanel_sizer = new wxFlexGridSizer( 1, 1, 20 );
426     subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
427     access_subpanels[0]->SetSizerAndFit( subpanel_sizer );
428     access_subpanels[0]->Hide();
429
430     /* File row */
431     subpanel_sizer = new wxFlexGridSizer( 3, 2, 20 );
432     label = new wxStaticText( access_subpanels[1], -1, wxU(_("Filename")) );
433     file_combo = new wxComboBox( access_subpanels[1], FileName_Event, wxT(""),
434                                  wxPoint(20,25), wxSize(200, -1), 0, NULL );
435     wxButton *browse_button = new wxButton( access_subpanels[1],
436                                   FileBrowse_Event, wxU(_("Browse...")) );
437     subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
438     subpanel_sizer->Add( file_combo, 1,
439                          wxEXPAND | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
440     subpanel_sizer->Add( browse_button, 0,
441                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
442     subpanel_sizer->Add( new wxPanel(access_subpanels[1], -1), 0,
443                          wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
444     dump_checkbox = new wxCheckBox( access_subpanels[1], FileDump_Event,
445                                     wxU(_("Dump raw input")) );
446     subpanel_sizer->Add( dump_checkbox, 0,
447                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxTOP, 5 );
448
449     access_subpanels[1]->SetSizerAndFit( subpanel_sizer );
450
451     /* Net rows */
452     for( i = HTTP_ACCESS_OUT; i < ACCESS_OUT_NUM; i++ )
453     {
454         subpanel_sizer = new wxFlexGridSizer( 4, 1, 20 );
455         label = new wxStaticText( access_subpanels[i], -1, wxU(_("Address")) );
456         net_addrs[i] = new wxTextCtrl( access_subpanels[i],
457                                    NetAddr1_Event + i - HTTP_ACCESS_OUT,
458                                    wxT(""), wxDefaultPosition,
459                                    wxSize( 200, -1 ), wxTE_PROCESS_ENTER);
460         subpanel_sizer->Add( label, 0,
461                              wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
462         subpanel_sizer->Add( net_addrs[i], 1, wxEXPAND |
463                              wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
464
465         int val = config_GetInt( p_intf, "server-port" );
466         label = new wxStaticText( access_subpanels[i], -1, wxU(_("Port")) );
467         net_ports[i] = new wxSpinCtrl( access_subpanels[i],
468                                    NetPort1_Event + i - HTTP_ACCESS_OUT,
469                                    wxString::Format(wxT("%d"), val),
470                                    wxDefaultPosition, wxDefaultSize,
471                                    wxSP_ARROW_KEYS,
472                                    0, 16000, val );
473
474         subpanel_sizer->Add( label, 0,
475                              wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
476         subpanel_sizer->Add( net_ports[i], 0,
477                              wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
478
479         access_subpanels[i]->SetSizerAndFit( subpanel_sizer );
480     }
481
482
483     /* Stuff everything into the main panel */
484     for( i=1; i < ACCESS_OUT_NUM; i++ )
485     {
486         sizer->Add( access_checkboxes[i], 0,
487                     wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL  | wxALL, 5 );
488         sizer->Add( access_subpanels[i], 1, wxEXPAND | wxALIGN_CENTER_VERTICAL
489                     | wxALIGN_LEFT  | wxALL, 5 );
490     }
491
492     panel_sizer->Add( access_checkboxes[0], 0,
493                       wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL  | wxALL, 5 );
494     panel_sizer->Add( sizer, 1, wxEXPAND | wxTOP, 3 );
495
496     panel->SetSizerAndFit( panel_sizer );
497
498     /* Update access type panel */
499     for( i=1; i < ACCESS_OUT_NUM; i++ )
500     {
501         access_subpanels[i]->Disable();
502     }
503
504     return panel;
505 }
506
507 wxPanel *SoutDialog::MiscPanel( wxWindow* parent )
508 {
509     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
510                                   wxSize(200, 200) );
511
512     wxStaticBox *panel_box = new wxStaticBox( panel, -1,
513                                    wxU(_("Miscellaneous Options")) );
514     wxStaticBoxSizer *panel_sizer = new wxStaticBoxSizer( panel_box,
515                                                           wxVERTICAL );
516
517     /* Announce Row */
518     misc_subpanels[ANN_MISC_SOUT] = new wxPanel( panel, -1 );
519     wxFlexGridSizer *subpanel_sizer = new wxFlexGridSizer( 4, 4, 20 );
520
521     sap_checkbox = new wxCheckBox( misc_subpanels[ANN_MISC_SOUT],SAPMisc_Event,
522                                    wxU(_("SAP Announce")) );
523     slp_checkbox = new wxCheckBox( misc_subpanels[ANN_MISC_SOUT],SLPMisc_Event,
524                                    wxU(_("SLP Announce")) );
525
526     wxStaticText *label = new wxStaticText( misc_subpanels[ANN_MISC_SOUT], -1,
527                                             wxU(_("Channel Name")) );
528     announce_addr = new wxTextCtrl( misc_subpanels[ANN_MISC_SOUT],
529                                     AnnounceAddr_Event,
530                                     wxT(""), wxDefaultPosition,
531                                     wxSize( 200, -1 ), wxTE_PROCESS_ENTER);
532
533     subpanel_sizer->Add( sap_checkbox, 0,
534                          wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
535     subpanel_sizer->Add( slp_checkbox, 0,
536                          wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
537     subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
538     subpanel_sizer->Add( announce_addr, 1, wxEXPAND |
539                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
540
541     misc_subpanels[ANN_MISC_SOUT]->SetSizerAndFit( subpanel_sizer );
542
543     /* Stuff everything into the main panel */
544     panel_sizer->Add( misc_subpanels[ANN_MISC_SOUT], 1,
545                       wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 5 );
546
547     panel->SetSizerAndFit( panel_sizer );
548
549     /* Update misc panel */
550     misc_subpanels[ANN_MISC_SOUT]->Disable();
551     announce_addr->Disable();
552
553     return panel;
554 }
555
556 wxPanel *SoutDialog::EncapsulationPanel( wxWindow* parent )
557 {
558     int i;
559     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
560                                   wxSize(200, 200) );
561
562     wxStaticBox *panel_box = new wxStaticBox( panel, -1,
563                                               wxU(_("Encapsulation Method")) );
564     wxStaticBoxSizer *panel_sizer = new wxStaticBoxSizer( panel_box,
565                                                           wxHORIZONTAL );
566
567     static const wxString encapsulation_array[] =
568     {
569         wxT("MPEG TS"),
570         wxT("MPEG PS"),
571         wxT("MPEG 1"),
572         wxT("Ogg"),
573         wxT("ASF"),
574         wxT("AVI"),
575         wxT("MP4"),
576         wxT("MOV")
577     };
578
579     /* Stuff everything into the main panel */
580     for( i=0; i < ENCAPS_NUM; i++ )
581     {
582         encapsulation_radios[i] =
583             new wxRadioButton( panel, EncapsulationRadio1_Event + i,
584                                encapsulation_array[i] );
585         panel_sizer->Add( encapsulation_radios[i], 0,
586                           wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL |
587                           wxALL, 4 );
588     }
589
590     panel->SetSizerAndFit( panel_sizer );
591
592     /* Update encapsulation panel */
593     encapsulation_radios[TS_ENCAPSULATION]->SetValue(true);
594     i_encapsulation_type = TS_ENCAPSULATION;
595
596     return panel;
597 }
598
599 wxPanel *SoutDialog::TranscodingPanel( wxWindow* parent )
600 {
601     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
602                                   wxSize(200, 200) );
603
604     wxStaticBox *panel_box = new wxStaticBox( panel, -1,
605                                               wxU(_("Transcoding options")) );
606     wxStaticBoxSizer *panel_sizer = new wxStaticBoxSizer( panel_box,
607                                                           wxVERTICAL );
608
609     /* Create video transcoding checkox */
610     static const wxString vcodecs_array[] =
611     {
612         wxT("mp1v"),
613         wxT("mp2v"),
614         wxT("mp4v"),
615         wxT("DIV1"),
616         wxT("DIV2"),
617         wxT("DIV3"),
618         wxT("H263"),
619         wxT("I263"),
620         wxT("WMV1"),
621         wxT("WMV2"),
622         wxT("MJPG"),
623         wxT("theo")
624     };
625     static const wxString vbitrates_array[] =
626     {
627         wxT("3072"),
628         wxT("2048"),
629         wxT("1024"),
630         wxT("768"),
631         wxT("512"),
632         wxT("384"),
633         wxT("256"),
634         wxT("192"),
635         wxT("128"),
636         wxT("96"),
637         wxT("64"),
638         wxT("32"),
639         wxT("16")
640     };
641
642     wxFlexGridSizer *video_sizer = new wxFlexGridSizer( 4, 1, 20 );
643     video_transc_checkbox =
644         new wxCheckBox( panel, VideoTranscEnable_Event, wxU(_("Video codec")));
645     video_codec_combo =
646         new wxComboBox( panel, VideoTranscCodec_Event, wxT(""),
647                         wxPoint(20,25), wxDefaultSize, WXSIZEOF(vcodecs_array),
648                         vcodecs_array, wxCB_READONLY );
649     video_codec_combo->SetSelection(2);
650     wxStaticText *bitrate_label =
651         new wxStaticText( panel, -1, wxU(_("Bitrate (kb/s)")));
652     video_bitrate_combo =
653         new wxComboBox( panel, VideoTranscBitrate_Event, wxT("1024"),
654                         wxPoint(20,25), wxDefaultSize,
655                         WXSIZEOF(vbitrates_array), vbitrates_array );
656     video_sizer->Add( video_transc_checkbox, 0,
657                       wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
658     video_sizer->Add( video_codec_combo, 1,
659                       wxEXPAND | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
660     video_sizer->Add( bitrate_label, 0,
661                       wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
662     video_sizer->Add( video_bitrate_combo, 1,
663                       wxEXPAND | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
664
665     /* Create audio transcoding checkox */
666     static const wxString acodecs_array[] =
667     {
668         wxT("mpga"),
669         wxT("mp3"),
670         wxT("a52"),
671         wxT("vorb"),
672         wxT("flac"),
673         wxT("spx")
674     };
675     static const wxString abitrates_array[] =
676     {
677         wxT("512"),
678         wxT("256"),
679         wxT("192"),
680         wxT("128"),
681         wxT("96"),
682         wxT("64"),
683         wxT("32"),
684         wxT("16")
685     };
686     static const wxString achannels_array[] =
687     {
688         wxT("1"),
689         wxT("2"),
690         wxT("4"),
691         wxT("6")
692     };
693
694     wxFlexGridSizer *audio_sizer = new wxFlexGridSizer( 3, 1, 20 );
695     audio_transc_checkbox =
696         new wxCheckBox( panel, AudioTranscEnable_Event, wxU(_("Audio codec")));
697     audio_codec_combo =
698         new wxComboBox( panel, AudioTranscCodec_Event, wxT(""),
699                         wxPoint(10,25), wxDefaultSize, WXSIZEOF(acodecs_array),
700                         acodecs_array, wxCB_READONLY );
701     audio_codec_combo->SetSelection(0);
702 #if defined( __WXMSW__ )
703     wxFlexGridSizer *audio_sub_sizer = new wxFlexGridSizer( 4, 5, 20 );
704 #else
705     wxFlexGridSizer *audio_sub_sizer = new wxFlexGridSizer( 2, 5, 20 );
706 #endif
707     bitrate_label =
708         new wxStaticText( panel, -1, wxU(_("Bitrate (kb/s)")));
709     audio_bitrate_combo =
710         new wxComboBox( panel, AudioTranscBitrate_Event, wxT("192"),
711                         wxPoint(10,25), wxDefaultSize,
712                         WXSIZEOF(abitrates_array), abitrates_array );
713     wxStaticText *channels_label =
714         new wxStaticText( panel, -1, wxU(_("Channels")));
715     audio_channels_combo =
716         new wxComboBox( panel, AudioTranscChans_Event, wxT(""),
717                         wxPoint(10,25), wxDefaultSize,
718                         WXSIZEOF(achannels_array), achannels_array );
719     audio_channels_combo->SetSelection(1);
720     audio_sub_sizer->Add( bitrate_label, 0,
721                       wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
722     audio_sub_sizer->Add( audio_bitrate_combo, 1,
723                       wxEXPAND | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
724     audio_sub_sizer->Add( channels_label, 0,
725                       wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
726     audio_sub_sizer->Add( audio_channels_combo, 1,
727                       wxEXPAND | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
728
729     audio_sizer->Add( audio_transc_checkbox, 0,
730                       wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
731     audio_sizer->Add( audio_codec_combo, 1,
732                       wxEXPAND | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
733     audio_sizer->Add( audio_sub_sizer, 1,
734                       wxEXPAND | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
735
736     /* Stuff everything into the main panel */
737     panel_sizer->Add( video_sizer, 0,
738                       wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 5 );
739     panel_sizer->Add( audio_sizer, 0,
740                       wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 5 );
741
742     panel->SetSizerAndFit( panel_sizer );
743
744     /* Update transcoding panel */
745     wxCommandEvent event( 0, VideoTranscEnable_Event );
746     event.SetInt( 0 );
747     OnTranscodingEnable( event );
748     event.SetId( AudioTranscEnable_Event );
749     OnTranscodingEnable( event );
750
751     return panel;
752 }
753
754 /*****************************************************************************
755  * Events methods.
756  *****************************************************************************/
757 void SoutDialog::OnOk( wxCommandEvent& WXUNUSED(event) )
758 {
759     mrl_combo->Append( mrl_combo->GetValue() );
760     EndModal( wxID_OK );
761 }
762
763 void SoutDialog::OnCancel( wxCommandEvent& WXUNUSED(event) )
764 {
765     EndModal( wxID_CANCEL );
766 }
767
768 void SoutDialog::OnMRLChange( wxCommandEvent& event )
769 {
770     //mrl = event.GetString();
771 }
772
773 /*****************************************************************************
774  * Access output panel event methods.
775  *****************************************************************************/
776 void SoutDialog::OnAccessTypeChange( wxCommandEvent& event )
777 {
778     int i;
779     i_access_type = event.GetId() - AccessType1_Event;
780
781     access_subpanels[i_access_type]->Enable( event.GetInt() );
782
783     switch( i_access_type )
784     {
785     case UDP_ACCESS_OUT:
786         misc_subpanels[ANN_MISC_SOUT]->Enable( event.GetInt() );
787
788     case RTP_ACCESS_OUT:
789         for( i = 1; i < ENCAPS_NUM; i++ )
790         {
791             encapsulation_radios[i]->Enable( !event.GetInt() );
792         }
793         if( event.GetInt() )
794         {
795             encapsulation_radios[TS_ENCAPSULATION]->SetValue(true);
796             i_encapsulation_type = TS_ENCAPSULATION;
797         }
798         break;
799     }
800     UpdateMRL();
801 }
802
803 /*****************************************************************************
804  * AnnounceMisc panel event methods.
805  *****************************************************************************/
806 void SoutDialog::OnSAPMiscChange( wxCommandEvent& event )
807 {
808     if( !slp_checkbox->IsChecked() )
809     {
810         announce_addr->Enable( event.GetInt() );
811     }
812     UpdateMRL();
813 }
814
815 void SoutDialog::OnSLPMiscChange( wxCommandEvent& event )
816 {
817     if( !sap_checkbox->IsChecked() )
818     {
819         announce_addr->Enable( event.GetInt() );
820     }
821     UpdateMRL();
822 }
823
824 /*****************************************************************************
825  * SAPAddr panel event methods.
826  *****************************************************************************/
827 void SoutDialog::OnAnnounceAddrChange( wxCommandEvent& WXUNUSED(event) )
828 {
829     UpdateMRL();
830 }
831
832 /*****************************************************************************
833  * File access output event methods.
834  *****************************************************************************/
835 void SoutDialog::OnFileChange( wxCommandEvent& WXUNUSED(event) )
836 {
837     UpdateMRL();
838 }
839
840 void SoutDialog::OnFileBrowse( wxCommandEvent& WXUNUSED(event) )
841 {
842     wxFileDialog dialog( this, wxU(_("Save file")), wxT(""), wxT(""), wxT("*"),
843                          wxSAVE | wxOVERWRITE_PROMPT );
844
845     if( dialog.ShowModal() == wxID_OK )
846     {
847         file_combo->SetValue( dialog.GetPath() );
848         UpdateMRL();
849     }
850 }
851
852 void SoutDialog::OnFileDump( wxCommandEvent& event )
853 {
854     misc_panel->Enable( !event.GetInt() );
855     encapsulation_panel->Enable( !event.GetInt() );
856     transcoding_panel->Enable( !event.GetInt() );
857
858     for( int i = 0; i < ACCESS_OUT_NUM; i++ )
859     {
860         if( i != FILE_ACCESS_OUT )
861         {
862             access_checkboxes[i]->Enable( !event.GetInt() );
863             access_subpanels[i]->Enable( !event.GetInt() &&
864                                          access_checkboxes[i]->IsChecked() );
865         }
866     }
867
868     UpdateMRL();
869 }
870
871 /*****************************************************************************
872  * Net access output event methods.
873  *****************************************************************************/
874 void SoutDialog::OnNetChange( wxCommandEvent& WXUNUSED(event) )
875 {
876     UpdateMRL();
877 }
878
879 /*****************************************************************************
880  * Encapsulation panel event methods.
881  *****************************************************************************/
882 void SoutDialog::OnEncapsulationChange( wxCommandEvent& event )
883 {
884     i_encapsulation_type = event.GetId() - EncapsulationRadio1_Event;
885     UpdateMRL();
886 }
887
888 /*****************************************************************************
889  * Transcoding panel event methods.
890  *****************************************************************************/
891 void SoutDialog::OnTranscodingEnable( wxCommandEvent& event )
892 {
893     switch( event.GetId() )
894     {
895     case VideoTranscEnable_Event:
896         video_codec_combo->Enable( event.GetInt() );
897         video_bitrate_combo->Enable( event.GetInt() );
898         break;
899     case AudioTranscEnable_Event:
900         audio_codec_combo->Enable( event.GetInt() );
901         audio_bitrate_combo->Enable( event.GetInt() );
902         audio_channels_combo->Enable( event.GetInt() );
903         break;
904     }
905
906     UpdateMRL();
907 }
908
909 void SoutDialog::OnTranscodingChange( wxCommandEvent& event )
910 {
911     UpdateMRL();
912 }