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