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