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