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