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