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