]> git.sesse.net Git - vlc/blob - modules/gui/wxwindows/streamout.cpp
Use the new SAP/SLP syntax (sap,slp,name=)
[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 #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             if( ! announce_addr->GetLineText(0).IsEmpty() )
362             {
363                 dup_opts += wxT(",name=\"");
364                 dup_opts += announce_addr->GetLineText(0);
365                 dup_opts += wxT("\"");
366             }
367         }
368
369         /* SLP only if UDP */
370         if( slp_checkbox->IsChecked() )
371         {
372             dup_opts += wxT(",slp");
373             if( ! sap_checkbox->IsChecked() &&
374                 ! announce_addr->GetLineText(0).IsEmpty() )
375             {
376                 dup_opts += wxT(",name=\"");
377                 dup_opts += announce_addr->GetLineText(0);
378                 dup_opts += wxT("\"");
379             }
380         }
381
382         dup_opts += wxT("}");
383     }
384     if( access_checkboxes[RTP_ACCESS_OUT]->IsChecked() )
385     {
386         if( !dup_opts.IsEmpty() ) dup_opts += wxT(",");
387         dup_opts += wxT("dst=std{access=rtp,mux=");
388         dup_opts += encapsulation + wxT(",url=");
389         dup_opts += net_addrs[RTP_ACCESS_OUT]->GetLineText(0);
390         dup_opts += wxString::Format( wxT(":%d"),
391                                       net_ports[RTP_ACCESS_OUT]->GetValue() );
392         dup_opts += wxT("}");
393     }
394
395     wxString duplicate;
396     if( !dup_opts.IsEmpty() )
397     {
398         if( !transcode.IsEmpty() ) duplicate = wxT(":");
399         duplicate += wxT("duplicate{") + dup_opts + wxT("}");
400     }
401
402     if( !transcode.IsEmpty() || !duplicate.IsEmpty() )
403         mrl_combo->SetValue( wxT(":sout=#") + transcode + duplicate );
404     else
405         mrl_combo->SetValue( wxT("") );
406 }
407
408 wxPanel *SoutDialog::AccessPanel( wxWindow* parent )
409 {
410     int i;
411     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
412                                   wxSize(200, 200) );
413
414     wxStaticBox *panel_box = new wxStaticBox( panel, -1,
415                                               wxU(_("Output methods")) );
416     wxStaticBoxSizer *panel_sizer = new wxStaticBoxSizer( panel_box,
417                                                           wxVERTICAL );
418
419     wxFlexGridSizer *sizer = new wxFlexGridSizer( 2, 4, 20 );
420     static const wxString access_output_array[] =
421     {
422         wxU(_("Play locally")),
423         wxU(_("File")),
424         wxU(_("HTTP")),
425         wxU(_("MMSH")),
426         wxU(_("UDP")),
427         wxU(_("RTP"))
428     };
429
430     for( i=0; i < ACCESS_OUT_NUM; i++ )
431     {
432         access_checkboxes[i] = new wxCheckBox( panel, AccessType1_Event + i,
433                                                access_output_array[i] );
434         access_subpanels[i] = new wxPanel( panel, -1 );
435     }
436
437     /* Play locally row */
438     wxFlexGridSizer *subpanel_sizer;
439     wxStaticText *label;
440     label = new wxStaticText( access_subpanels[0], -1, wxT("") );
441     subpanel_sizer = new wxFlexGridSizer( 1, 1, 20 );
442     subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
443     access_subpanels[0]->SetSizerAndFit( subpanel_sizer );
444     access_subpanels[0]->Hide();
445
446     /* File row */
447     subpanel_sizer = new wxFlexGridSizer( 3, 2, 20 );
448     label = new wxStaticText( access_subpanels[1], -1, wxU(_("Filename")) );
449     file_combo = new wxComboBox( access_subpanels[1], FileName_Event, wxT(""),
450                                  wxPoint(20,25), wxSize(200, -1), 0, NULL );
451     wxButton *browse_button = new wxButton( access_subpanels[1],
452                                   FileBrowse_Event, wxU(_("Browse...")) );
453     subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
454     subpanel_sizer->Add( file_combo, 1,
455                          wxEXPAND | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
456     subpanel_sizer->Add( browse_button, 0,
457                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
458     subpanel_sizer->Add( new wxPanel(access_subpanels[1], -1), 0,
459                          wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
460     dump_checkbox = new wxCheckBox( access_subpanels[1], FileDump_Event,
461                                     wxU(_("Dump raw input")) );
462     subpanel_sizer->Add( dump_checkbox, 0,
463                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxTOP, 5 );
464
465     access_subpanels[1]->SetSizerAndFit( subpanel_sizer );
466
467     /* Net rows */
468     for( i = HTTP_ACCESS_OUT; i < ACCESS_OUT_NUM; i++ )
469     {
470         subpanel_sizer = new wxFlexGridSizer( 4, 1, 20 );
471         label = new wxStaticText( access_subpanels[i], -1, wxU(_("Address")) );
472         net_addrs[i] = new wxTextCtrl( access_subpanels[i],
473                                    NetAddr1_Event + i - HTTP_ACCESS_OUT,
474                                    wxT(""), wxDefaultPosition,
475                                    wxSize( 200, -1 ), wxTE_PROCESS_ENTER);
476         subpanel_sizer->Add( label, 0,
477                              wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
478         subpanel_sizer->Add( net_addrs[i], 1, wxEXPAND |
479                              wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
480
481         int val = config_GetInt( p_intf, "server-port" );
482         label = new wxStaticText( access_subpanels[i], -1, wxU(_("Port")) );
483         net_ports[i] = new wxSpinCtrl( access_subpanels[i],
484                                    NetPort1_Event + i - HTTP_ACCESS_OUT,
485                                    wxString::Format(wxT("%d"), val),
486                                    wxDefaultPosition, wxDefaultSize,
487                                    wxSP_ARROW_KEYS,
488                                    0, 16000, val );
489
490         subpanel_sizer->Add( label, 0,
491                              wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
492         subpanel_sizer->Add( net_ports[i], 0,
493                              wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
494
495         access_subpanels[i]->SetSizerAndFit( subpanel_sizer );
496     }
497
498
499     /* Stuff everything into the main panel */
500     for( i=1; i < ACCESS_OUT_NUM; i++ )
501     {
502         sizer->Add( access_checkboxes[i], 0,
503                     wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL  | wxALL, 5 );
504         sizer->Add( access_subpanels[i], 1, wxEXPAND | wxALIGN_CENTER_VERTICAL
505                     | wxALIGN_LEFT  | wxALL, 5 );
506     }
507
508     panel_sizer->Add( access_checkboxes[0], 0,
509                       wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL  | wxALL, 5 );
510     panel_sizer->Add( sizer, 1, wxEXPAND | wxTOP, 3 );
511
512     panel->SetSizerAndFit( panel_sizer );
513
514     /* Update access type panel */
515     for( i=1; i < ACCESS_OUT_NUM; i++ )
516     {
517         access_subpanels[i]->Disable();
518     }
519
520     return panel;
521 }
522
523 wxPanel *SoutDialog::MiscPanel( wxWindow* parent )
524 {
525     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
526                                   wxSize(200, 200) );
527
528     wxStaticBox *panel_box = new wxStaticBox( panel, -1,
529                                    wxU(_("Miscellaneous options")) );
530     wxStaticBoxSizer *panel_sizer = new wxStaticBoxSizer( panel_box,
531                                                           wxVERTICAL );
532
533     /* Announce Row */
534     misc_subpanels[ANN_MISC_SOUT] = new wxPanel( panel, -1 );
535     wxFlexGridSizer *subpanel_sizer = new wxFlexGridSizer( 4, 4, 20 );
536
537     sap_checkbox = new wxCheckBox( misc_subpanels[ANN_MISC_SOUT],SAPMisc_Event,
538                                    wxU(_("SAP announce")) );
539     slp_checkbox = new wxCheckBox( misc_subpanels[ANN_MISC_SOUT],SLPMisc_Event,
540                                    wxU(_("SLP announce")) );
541
542     wxStaticText *label = new wxStaticText( misc_subpanels[ANN_MISC_SOUT], -1,
543                                             wxU(_("Channel name")) );
544     announce_addr = new wxTextCtrl( misc_subpanels[ANN_MISC_SOUT],
545                                     AnnounceAddr_Event,
546                                     wxT(""), wxDefaultPosition,
547                                     wxSize( 200, -1 ), wxTE_PROCESS_ENTER);
548
549     subpanel_sizer->Add( sap_checkbox, 0,
550                          wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
551     subpanel_sizer->Add( slp_checkbox, 0,
552                          wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
553     subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
554     subpanel_sizer->Add( announce_addr, 1, wxEXPAND |
555                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
556
557     misc_subpanels[ANN_MISC_SOUT]->SetSizerAndFit( subpanel_sizer );
558
559     /* Stuff everything into the main panel */
560     panel_sizer->Add( misc_subpanels[ANN_MISC_SOUT], 1,
561                       wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 5 );
562
563     panel->SetSizerAndFit( panel_sizer );
564
565     /* Update misc panel */
566     misc_subpanels[ANN_MISC_SOUT]->Disable();
567     announce_addr->Disable();
568
569     return panel;
570 }
571
572 wxPanel *SoutDialog::EncapsulationPanel( wxWindow* parent )
573 {
574     int i;
575     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
576                                   wxSize(200, 200) );
577
578     wxStaticBox *panel_box = new wxStaticBox( panel, -1,
579                                               wxU(_("Encapsulation Method")) );
580     wxStaticBoxSizer *panel_sizer = new wxStaticBoxSizer( panel_box,
581                                                           wxHORIZONTAL );
582
583     static const wxString encapsulation_array[] =
584     {
585         wxT("MPEG TS"),
586         wxT("MPEG PS"),
587         wxT("MPEG 1"),
588         wxT("Ogg"),
589         wxT("Raw"),
590         wxT("ASF"),
591         wxT("AVI"),
592         wxT("MP4"),
593         wxT("MOV")
594     };
595
596     /* Stuff everything into the main panel */
597     for( i=0; i < ENCAPS_NUM; i++ )
598     {
599         encapsulation_radios[i] =
600             new wxRadioButton( panel, EncapsulationRadio1_Event + i,
601                                encapsulation_array[i] );
602         panel_sizer->Add( encapsulation_radios[i], 0,
603                           wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL |
604                           wxALL, 4 );
605     }
606
607     panel->SetSizerAndFit( panel_sizer );
608
609     /* Update encapsulation panel */
610     encapsulation_radios[TS_ENCAPSULATION]->SetValue(true);
611     i_encapsulation_type = TS_ENCAPSULATION;
612
613     return panel;
614 }
615
616 wxPanel *SoutDialog::TranscodingPanel( wxWindow* parent )
617 {
618     wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
619                                   wxSize(200, 200) );
620
621     wxStaticBox *panel_box = new wxStaticBox( panel, -1,
622                                               wxU(_("Transcoding options")) );
623     wxStaticBoxSizer *panel_sizer = new wxStaticBoxSizer( panel_box,
624                                                           wxVERTICAL );
625
626     /* Create video transcoding checkox */
627     static const wxString vcodecs_array[] =
628     {
629         wxT("mp1v"),
630         wxT("mp2v"),
631         wxT("mp4v"),
632         wxT("DIV1"),
633         wxT("DIV2"),
634         wxT("DIV3"),
635         wxT("H263"),
636         wxT("I263"),
637         wxT("WMV1"),
638         wxT("WMV2"),
639         wxT("MJPG"),
640         wxT("theo")
641     };
642     static const wxString vbitrates_array[] =
643     {
644         wxT("3072"),
645         wxT("2048"),
646         wxT("1024"),
647         wxT("768"),
648         wxT("512"),
649         wxT("384"),
650         wxT("256"),
651         wxT("192"),
652         wxT("128"),
653         wxT("96"),
654         wxT("64"),
655         wxT("32"),
656         wxT("16")
657     };
658     static const wxString vscales_array[] =
659     {
660         wxT("0.25"),
661         wxT("0.5"),
662         wxT("0.75"),
663         wxT("1"),
664         wxT("1.25"),
665         wxT("1.5"),
666         wxT("1.75"),
667         wxT("2")
668     };
669
670     wxFlexGridSizer *video_sizer = new wxFlexGridSizer( 6, 1, 20 );
671     video_transc_checkbox =
672         new wxCheckBox( panel, VideoTranscEnable_Event, wxU(_("Video codec")));
673     video_codec_combo =
674         new wxComboBox( panel, VideoTranscCodec_Event, wxT(""),
675                         wxPoint(20,25), wxDefaultSize, WXSIZEOF(vcodecs_array),
676                         vcodecs_array, wxCB_READONLY );
677     video_codec_combo->SetSelection(2);
678     wxStaticText *bitrate_label =
679         new wxStaticText( panel, -1, wxU(_("Bitrate (kb/s)")));
680     video_bitrate_combo =
681         new wxComboBox( panel, VideoTranscBitrate_Event, wxT("1024"),
682                         wxPoint(20,25), wxDefaultSize,
683                         WXSIZEOF(vbitrates_array), vbitrates_array );
684     wxStaticText *scale_label =
685         new wxStaticText( panel, -1, wxU(_("Scale")));
686     video_scale_combo =
687         new wxComboBox( panel, VideoTranscScale_Event, wxT("1"),
688                         wxPoint(20,25), wxDefaultSize,
689                         WXSIZEOF(vscales_array), vscales_array );
690     video_sizer->Add( video_transc_checkbox, 0,
691                       wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
692     video_sizer->Add( video_codec_combo, 1,
693                       wxEXPAND | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
694     video_sizer->Add( bitrate_label, 0,
695                       wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
696     video_sizer->Add( video_bitrate_combo, 1,
697                       wxEXPAND | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
698     video_sizer->Add( scale_label, 0,
699                       wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
700     video_sizer->Add( video_scale_combo, 1,
701                       wxEXPAND | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
702
703     /* Create audio transcoding checkox */
704     static const wxString acodecs_array[] =
705     {
706         wxT("mpga"),
707         wxT("mp3"),
708         wxT("mp4a"),
709         wxT("a52"),
710         wxT("vorb"),
711         wxT("flac"),
712         wxT("spx")
713     };
714     static const wxString abitrates_array[] =
715     {
716         wxT("512"),
717         wxT("256"),
718         wxT("192"),
719         wxT("128"),
720         wxT("96"),
721         wxT("64"),
722         wxT("32"),
723         wxT("16")
724     };
725     static const wxString achannels_array[] =
726     {
727         wxT("1"),
728         wxT("2"),
729         wxT("4"),
730         wxT("6")
731     };
732
733     wxFlexGridSizer *audio_sizer = new wxFlexGridSizer( 3, 1, 20 );
734     audio_transc_checkbox =
735         new wxCheckBox( panel, AudioTranscEnable_Event, wxU(_("Audio codec")));
736     audio_codec_combo =
737         new wxComboBox( panel, AudioTranscCodec_Event, wxT(""),
738                         wxPoint(10,25), wxDefaultSize, WXSIZEOF(acodecs_array),
739                         acodecs_array, wxCB_READONLY );
740     audio_codec_combo->SetSelection(0);
741 #if defined( __WXMSW__ )
742     wxFlexGridSizer *audio_sub_sizer = new wxFlexGridSizer( 4, 5, 20 );
743 #else
744     wxFlexGridSizer *audio_sub_sizer = new wxFlexGridSizer( 2, 5, 20 );
745 #endif
746     bitrate_label =
747         new wxStaticText( panel, -1, wxU(_("Bitrate (kb/s)")));
748     audio_bitrate_combo =
749         new wxComboBox( panel, AudioTranscBitrate_Event, wxT("192"),
750                         wxPoint(10,25), wxDefaultSize,
751                         WXSIZEOF(abitrates_array), abitrates_array );
752     wxStaticText *channels_label =
753         new wxStaticText( panel, -1, wxU(_("Channels")));
754     audio_channels_combo =
755         new wxComboBox( panel, AudioTranscChans_Event, wxT(""),
756                         wxPoint(10,25), wxDefaultSize,
757                         WXSIZEOF(achannels_array), achannels_array );
758     audio_channels_combo->SetSelection(1);
759     audio_sub_sizer->Add( bitrate_label, 0,
760                       wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
761     audio_sub_sizer->Add( audio_bitrate_combo, 1,
762                       wxEXPAND | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
763     audio_sub_sizer->Add( channels_label, 0,
764                       wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
765     audio_sub_sizer->Add( audio_channels_combo, 1,
766                       wxEXPAND | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
767
768     audio_sizer->Add( audio_transc_checkbox, 0,
769                       wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
770     audio_sizer->Add( audio_codec_combo, 1,
771                       wxEXPAND | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
772     audio_sizer->Add( audio_sub_sizer, 1,
773                       wxEXPAND | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
774
775     /* Stuff everything into the main panel */
776     panel_sizer->Add( video_sizer, 0,
777                       wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 5 );
778     panel_sizer->Add( audio_sizer, 0,
779                       wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 5 );
780
781     panel->SetSizerAndFit( panel_sizer );
782
783     /* Update transcoding panel */
784     wxCommandEvent event( 0, VideoTranscEnable_Event );
785     event.SetInt( 0 );
786     OnTranscodingEnable( event );
787     event.SetId( AudioTranscEnable_Event );
788     OnTranscodingEnable( event );
789
790     return panel;
791 }
792
793 /*****************************************************************************
794  * Events methods.
795  *****************************************************************************/
796 void SoutDialog::OnOk( wxCommandEvent& WXUNUSED(event) )
797 {
798     mrl_combo->Append( mrl_combo->GetValue() );
799     EndModal( wxID_OK );
800 }
801
802 void SoutDialog::OnCancel( wxCommandEvent& WXUNUSED(event) )
803 {
804     EndModal( wxID_CANCEL );
805 }
806
807 void SoutDialog::OnMRLChange( wxCommandEvent& event )
808 {
809     //mrl = event.GetString();
810 }
811
812 /*****************************************************************************
813  * Access output panel event methods.
814  *****************************************************************************/
815 void SoutDialog::OnAccessTypeChange( wxCommandEvent& event )
816 {
817     int i;
818     i_access_type = event.GetId() - AccessType1_Event;
819
820     access_subpanels[i_access_type]->Enable( event.GetInt() );
821
822     switch( i_access_type )
823     {
824     case UDP_ACCESS_OUT:
825         misc_subpanels[ANN_MISC_SOUT]->Enable( event.GetInt() );
826
827     case RTP_ACCESS_OUT:
828         for( i = 1; i < ENCAPS_NUM; i++ )
829         {
830             encapsulation_radios[i]->Enable( !event.GetInt() );
831         }
832         if( event.GetInt() )
833         {
834             encapsulation_radios[TS_ENCAPSULATION]->SetValue(true);
835             i_encapsulation_type = TS_ENCAPSULATION;
836         }
837         break;
838     }
839     UpdateMRL();
840 }
841
842 /*****************************************************************************
843  * AnnounceMisc panel event methods.
844  *****************************************************************************/
845 void SoutDialog::OnSAPMiscChange( wxCommandEvent& event )
846 {
847     if( !slp_checkbox->IsChecked() )
848     {
849         announce_addr->Enable( event.GetInt() );
850     }
851     UpdateMRL();
852 }
853
854 void SoutDialog::OnSLPMiscChange( wxCommandEvent& event )
855 {
856     if( !sap_checkbox->IsChecked() )
857     {
858         announce_addr->Enable( event.GetInt() );
859     }
860     UpdateMRL();
861 }
862
863 /*****************************************************************************
864  * SAPAddr panel event methods.
865  *****************************************************************************/
866 void SoutDialog::OnAnnounceAddrChange( wxCommandEvent& WXUNUSED(event) )
867 {
868     UpdateMRL();
869 }
870
871 /*****************************************************************************
872  * File access output event methods.
873  *****************************************************************************/
874 void SoutDialog::OnFileChange( wxCommandEvent& WXUNUSED(event) )
875 {
876     UpdateMRL();
877 }
878
879 void SoutDialog::OnFileBrowse( wxCommandEvent& WXUNUSED(event) )
880 {
881     wxFileDialog dialog( this, wxU(_("Save file")), wxT(""), wxT(""), wxT("*"),
882                          wxSAVE | wxOVERWRITE_PROMPT );
883
884     if( dialog.ShowModal() == wxID_OK )
885     {
886         file_combo->SetValue( dialog.GetPath() );
887         UpdateMRL();
888     }
889 }
890
891 void SoutDialog::OnFileDump( wxCommandEvent& event )
892 {
893     misc_panel->Enable( !event.GetInt() );
894     encapsulation_panel->Enable( !event.GetInt() );
895     transcoding_panel->Enable( !event.GetInt() );
896
897     for( int i = 0; i < ACCESS_OUT_NUM; i++ )
898     {
899         if( i != FILE_ACCESS_OUT )
900         {
901             access_checkboxes[i]->Enable( !event.GetInt() );
902             access_subpanels[i]->Enable( !event.GetInt() &&
903                                          access_checkboxes[i]->IsChecked() );
904         }
905     }
906
907     UpdateMRL();
908 }
909
910 /*****************************************************************************
911  * Net access output event methods.
912  *****************************************************************************/
913 void SoutDialog::OnNetChange( wxCommandEvent& WXUNUSED(event) )
914 {
915     UpdateMRL();
916 }
917
918 /*****************************************************************************
919  * Encapsulation panel event methods.
920  *****************************************************************************/
921 void SoutDialog::OnEncapsulationChange( wxCommandEvent& event )
922 {
923     i_encapsulation_type = event.GetId() - EncapsulationRadio1_Event;
924     UpdateMRL();
925 }
926
927 /*****************************************************************************
928  * Transcoding panel event methods.
929  *****************************************************************************/
930 void SoutDialog::OnTranscodingEnable( wxCommandEvent& event )
931 {
932     switch( event.GetId() )
933     {
934     case VideoTranscEnable_Event:
935         video_codec_combo->Enable( event.GetInt() );
936         video_bitrate_combo->Enable( event.GetInt() );
937         video_scale_combo->Enable( event.GetInt() );
938         break;
939     case AudioTranscEnable_Event:
940         audio_codec_combo->Enable( event.GetInt() );
941         audio_bitrate_combo->Enable( event.GetInt() );
942         audio_channels_combo->Enable( event.GetInt() );
943         break;
944     }
945
946     UpdateMRL();
947 }
948
949 void SoutDialog::OnTranscodingChange( wxCommandEvent& event )
950 {
951     UpdateMRL();
952 }