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