]> git.sesse.net Git - vlc/commitdiff
Qt: rework of the Sout Dialog
authorJean-Baptiste Kempf <jb@videolan.org>
Fri, 6 Mar 2009 23:56:23 +0000 (00:56 +0100)
committerJean-Baptiste Kempf <jb@videolan.org>
Sun, 8 Mar 2009 17:13:28 +0000 (18:13 +0100)
You can now add any number of duplicate parts you want. You can add them to create a new Tab. You can have two HTTP output or two File output, for example.
Most of the widgets creation and MRL generation part has been splitted from the main class so that people why little knowledge of Qt can understand what is going on.

Expert in streaming can personnalize more easily 'their' part of the UI with derivation of VirtualDestBox and implementing constructor+getMRL()

The huge structure has been removed.
This is a huge change in this dialog, but I think the old one was beyond possible repair.

modules/gui/qt4/components/sout/profile_selector.cpp
modules/gui/qt4/components/sout/sout_widgets.cpp
modules/gui/qt4/components/sout/sout_widgets.hpp
modules/gui/qt4/dialogs/sout.cpp
modules/gui/qt4/dialogs/sout.hpp
modules/gui/qt4/ui/sout.ui

index f84f809682e139ec390396e349b52287d368d88e..96b647f51fe413b15adf2fef90db229a617f0283 100644 (file)
@@ -198,6 +198,7 @@ void VLCProfileSelector::updateOptions( int i )
     }
     else
         transcode = "";
+    emit optionsChanged();
 }
 
 
index b63e60a5895d3b600a127dbcc57f40f91c17a843..457228a8622cf4697d9a08b1e7c12cd98b3a9e5d 100644 (file)
  *****************************************************************************/
 
 #include "components/sout/sout_widgets.hpp"
+#include "dialogs/sout.hpp"
+#include "util/qt_dirs.hpp"
 
 #include <QGroupBox>
 #include <QGridLayout>
 #include <QLabel>
 #include <QLineEdit>
+#include <QFileDialog>
 
 SoutInputBox::SoutInputBox( QWidget *_parent, QString mrl ) : QGroupBox( _parent )
 {
@@ -63,10 +66,328 @@ void SoutInputBox::setMRL( QString mrl )
     int i = mrl.indexOf( "://" );
     if( i != -1 )
     {
-        printf( "%i\n", i );
         type = mrl.left( i );
     }
     else
         type = qtr( "File/Directory" );
     sourceValueLabel->setText( type );
 }
+
+ #define CT( x ) connect( x, SIGNAL( textChanged( const QString ) ), this, SIGNAL( mrlUpdated() ) );
+ #define CS( x ) connect( x, SIGNAL( valueChanged( int ) ), this, SIGNAL( mrlUpdated() ) );
+
+/* FileDest Box */
+FileDestBox::FileDestBox( QWidget *_parent ) : VirtualDestBox( _parent )
+{
+    QPushButton *fileSelectButton;
+    QGridLayout *layout = new QGridLayout( this );
+
+    QLabel *fileOutput = new QLabel(
+         qtr( "This modules outputs to a file on your disk."), this );
+    layout->addWidget(fileOutput, 0, 0, 1, -1);
+
+    QLabel *fileLabel = new QLabel( qtr( "Filename"), this );
+    layout->addWidget(fileLabel, 1, 0, 1, 1);
+
+    fileEdit = new QLineEdit(this);
+    layout->addWidget(fileEdit, 1, 4, 1, 1);
+
+    fileSelectButton = new QPushButton( qtr( "Browse..." ), this );
+    QSizePolicy sizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
+    fileSelectButton->setSizePolicy(sizePolicy);
+
+    layout->addWidget(fileSelectButton, 1, 5, 1, 1);
+    CT( fileEdit );
+    BUTTONACT( fileSelectButton, fileBrowse() );
+}
+
+QString FileDestBox::getMRL( QString mux )
+{
+    if( fileEdit->text().isEmpty() ) return "";
+
+    SoutMrl m;
+    m.begin( "std" );
+    m.option( "access", "file" );
+    if( !mux.isEmpty() )
+        m.option( "mux", mux ); //FIXME: alert if ext doesn't match
+    m.option( "dst", fileEdit->text() );
+    m.end();
+
+    return m.getMrl();
+}
+
+void FileDestBox::fileBrowse()
+{
+    QString fileName = QFileDialog::getSaveFileName( this, qtr( "Save file..." ),
+            "", qtr( "Containers (*.ps *.ts *.mpg *.ogg *.asf *.mp4 *.mov *.wav *.raw *.flv)" ) );
+    fileEdit->setText( toNativeSeparators( fileName ) );
+    emit mrlUpdated();
+}
+
+
+
+HTTPDestBox::HTTPDestBox( QWidget *_parent ) : VirtualDestBox( _parent )
+{
+    QGridLayout *layout = new QGridLayout( this );
+
+    QLabel *httpOutput = new QLabel(
+         qtr( "This modules streams on the networks with the HTTP protocol."), this );
+    layout->addWidget(httpOutput, 0, 0, 1, -1);
+
+    QLabel *HTTPLabel = new QLabel( qtr("Address"), this );
+    QLabel *HTTPPortLabel = new QLabel( qtr("Port"), this );
+    layout->addWidget(HTTPLabel, 1, 0, 1, 1);
+    layout->addWidget(HTTPPortLabel, 2, 0, 1, 1);
+
+    HTTPEdit = new QLineEdit(this);
+
+    HTTPPort = new QSpinBox(this);
+    HTTPPort->setMaximumSize(QSize(90, 16777215));
+    HTTPPort->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+    HTTPPort->setMinimum(1);
+    HTTPPort->setMaximum(65535);
+    HTTPPort->setValue(8080);
+
+    layout->addWidget(HTTPEdit, 1, 1, 1, 1);
+    layout->addWidget(HTTPPort, 2, 1, 1, 1);
+    CS( HTTPPort );
+    CT( HTTPEdit );
+}
+
+QString HTTPDestBox::getMRL( QString mux )
+{
+    if( HTTPEdit->text().isEmpty() ) return "";
+
+    SoutMrl m;
+    m.begin( "std" );
+    m.option(  "access", "http" );
+    if( !mux.isEmpty() )
+        m.option( "mux", mux );
+    m.option( "dst", HTTPEdit->text(), HTTPPort->value() );
+    m.end();
+
+    return m.getMrl();
+}
+
+MMSHDestBox::MMSHDestBox( QWidget *_parent ) : VirtualDestBox( _parent )
+{
+    QGridLayout *layout = new QGridLayout( this );
+
+    QLabel *mmshOutput = new QLabel(
+         qtr( "This modules streams on the networks with the mms: protocol."), this );
+    layout->addWidget(mmshOutput, 0, 0, 1, -1);
+
+    QLabel *MMSHLabel = new QLabel( qtr("Address"), this );
+    QLabel *MMSHPortLabel = new QLabel( qtr("Port"), this );
+    layout->addWidget(MMSHLabel, 1, 0, 1, 1);
+    layout->addWidget(MMSHPortLabel, 2, 0, 1, 1);
+
+    MMSHEdit = new QLineEdit(this);
+
+    MMSHPort = new QSpinBox(this);
+    MMSHPort->setMaximumSize(QSize(90, 16777215));
+    MMSHPort->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+    MMSHPort->setMinimum(1);
+    MMSHPort->setMaximum(65535);
+    MMSHPort->setValue(1234);
+
+    layout->addWidget(MMSHEdit, 1, 1, 1, 1);
+    layout->addWidget(MMSHPort, 2, 1, 1, 1);
+    CS( MMSHPort );
+    CT( MMSHEdit );
+}
+
+QString MMSHDestBox::getMRL( QString mux )
+{
+    if( MMSHEdit->text().isEmpty() ) return "";
+
+    SoutMrl m;
+    m.begin( "std" );
+    m.option(  "access", "mmsh" );
+    m.option( "mux", "asfh" );
+    m.option( "dst", MMSHEdit->text(), MMSHPort->value() );
+    m.end();
+
+    return m.getMrl();
+}
+
+
+UDPDestBox::UDPDestBox( QWidget *_parent ) : VirtualDestBox( _parent )
+{
+    QGridLayout *layout = new QGridLayout( this );
+
+    QLabel *udpOutput = new QLabel(
+         qtr( "This modules streams on the networks with the UDP protocol."), this );
+    layout->addWidget(udpOutput, 0, 0, 1, -1);
+
+    QLabel *UDPLabel = new QLabel( qtr("Address"), this );
+    QLabel *UDPPortLabel = new QLabel( qtr("Port"), this );
+    layout->addWidget(UDPLabel, 1, 0, 1, 1);
+    layout->addWidget(UDPPortLabel, 2, 0, 1, 1);
+
+    UDPEdit = new QLineEdit(this);
+
+    UDPPort = new QSpinBox(this);
+    UDPPort->setMaximumSize(QSize(90, 16777215));
+    UDPPort->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+    UDPPort->setMinimum(1);
+    UDPPort->setMaximum(65535);
+    UDPPort->setValue(1234);
+
+    layout->addWidget(UDPEdit, 1, 1, 1, 1);
+    layout->addWidget(UDPPort, 2, 1, 1, 1);
+    CS( UDPPort );
+    CT( UDPEdit );
+}
+
+QString UDPDestBox::getMRL( QString mux )
+{
+    if( UDPEdit->text().isEmpty() ) return "";
+
+    SoutMrl m;
+    m.begin( "std" );
+    m.option(  "access", "udp" );
+    if( !mux.isEmpty() )
+        m.option( "mux", mux );
+    m.option( "dst", UDPEdit->text(), UDPPort->value() );
+    m.end();
+
+    return m.getMrl();
+}
+
+
+
+RTPDestBox::RTPDestBox( QWidget *_parent ) : VirtualDestBox( _parent )
+{
+    QGridLayout *layout = new QGridLayout( this );
+
+    QLabel *rtpOutput = new QLabel(
+         qtr( "This modules streams on the networks with the RTP protocol."), this );
+    layout->addWidget(rtpOutput, 0, 0, 1, -1);
+
+    QLabel *RTPLabel = new QLabel( qtr("Address"), this );
+    QLabel *RTPPortLabel = new QLabel( qtr("Port"), this );
+    layout->addWidget(RTPLabel, 1, 0, 1, 1);
+    layout->addWidget(RTPPortLabel, 2, 0, 1, 1);
+
+    RTPEdit = new QLineEdit(this);
+
+    RTPPort = new QSpinBox(this);
+    RTPPort->setMaximumSize(QSize(90, 16777215));
+    RTPPort->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+    RTPPort->setMinimum(1);
+    RTPPort->setMaximum(65535);
+    RTPPort->setValue(1234);
+
+    RTPPortAudio = new QSpinBox(this);
+    RTPPortAudio->setMaximumSize(QSize(90, 16777215));
+    RTPPortAudio->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+    RTPPortAudio->setMinimum(-1);
+    RTPPortAudio->setMaximum(65535);
+    RTPPortAudio->setValue(-1);
+
+    RTPPortVideo = new QSpinBox(this);
+    RTPPortVideo->setMaximumSize(QSize(90, 16777215));
+    RTPPortVideo->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+    RTPPortVideo->setMinimum(-1);
+    RTPPortVideo->setMaximum(65535);
+    RTPPortVideo->setValue(-1);
+
+    layout->addWidget(RTPEdit, 1, 1, 1, 1);
+    layout->addWidget(RTPPort, 2, 1, 1, 1);
+
+    QLabel *RTPPortAudioLabel = new QLabel( qtr("Audio Port"), this );
+    QLabel *RTPPortVideoLabel = new QLabel( qtr("Video Port"), this );
+    layout->addWidget(RTPPortAudioLabel, 3, 0, 1, 1);
+    layout->addWidget(RTPPortAudio, 3, 1, 1, 1);
+    layout->addWidget(RTPPortVideoLabel, 3, 2, 1, 1);
+    layout->addWidget(RTPPortVideo, 3, 3, 1, 1);
+
+
+    CS( RTPPort );
+    CS( RTPPortAudio );
+    CS( RTPPortVideo );
+    CT( RTPEdit );
+}
+
+QString RTPDestBox::getMRL( QString mux )
+{
+    if( RTPEdit->text().isEmpty() ) return "";
+
+    SoutMrl m;
+    m.begin( "rtp" );
+    m.option( "dst", RTPEdit->text() );
+    m.option( "port", RTPPort->value() );
+    if( !mux.isEmpty() )
+        m.option( "mux", mux );
+    if( mux.isEmpty() || mux.compare( "ts", Qt::CaseInsensitive ) )
+    {
+
+        m.option( "port-audio", RTPPortAudio->value() );
+        m.option( "port-video", RTPPortVideo->value() );
+    }
+    m.end();
+
+    return m.getMrl();
+}
+
+
+ICEDestBox::ICEDestBox( QWidget *_parent ) : VirtualDestBox( _parent )
+{
+    QGridLayout *layout = new QGridLayout( this );
+
+    QLabel *iceOutput = new QLabel(
+         qtr( "This modules streams using IceCast."), this );
+    layout->addWidget(iceOutput, 0, 0, 1, -1);
+
+    QLabel *ICELabel = new QLabel( qtr("Address"), this );
+    QLabel *ICEPortLabel = new QLabel( qtr("Port"), this );
+    layout->addWidget(ICELabel, 1, 0, 1, 1);
+    layout->addWidget(ICEPortLabel, 2, 0, 1, 1);
+
+    ICEEdit = new QLineEdit(this);
+
+    ICEPort = new QSpinBox(this);
+    ICEPort->setMaximumSize(QSize(90, 16777215));
+    ICEPort->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
+    ICEPort->setMinimum(1);
+    ICEPort->setMaximum(65535);
+    ICEPort->setValue(1234);
+
+    layout->addWidget(ICEEdit, 1, 1, 1, 1);
+    layout->addWidget(ICEPort, 2, 1, 1, 1);
+
+    QLabel *IcecastMountpointLabel = new QLabel( qtr( "Mount Point" ), this );
+    QLabel *IcecastNameLabel = new QLabel( qtr( "Login:pass" ), this );
+    ICEMountEdit = new QLineEdit( this );
+    ICEPassEdit = new QLineEdit( this );
+    layout->addWidget(IcecastMountpointLabel, 3, 0, 1, 1 );
+    layout->addWidget(ICEMountEdit, 3, 1, 1, -1 );
+    layout->addWidget(IcecastNameLabel, 4, 0, 1, 1 );
+    layout->addWidget(ICEPassEdit, 4, 1, 1, -1 );
+
+    CS( ICEPort );
+    CT( ICEEdit );
+    CT( ICEMountEdit );
+    CT( ICEPassEdit );
+}
+
+QString ICEDestBox::getMRL( QString mux )
+{
+    if( ICEEdit->text().isEmpty() ) return "";
+
+    SoutMrl m;
+    m.begin( "std" );
+    m.option( "access", "shout" );
+    m.option( "mux", "ogg" );
+
+    QString url = ICEPassEdit->text() + "@"
+        + ICEEdit->text()
+        + ":" + QString::number( ICEPort->value(), 10 )
+        + "/" + ICEMountEdit->text();
+
+    m.option( "dst", url );
+    m.end();
+    return m.getMrl();
+}
+
index f10cf2fd17ec78ff8f7777c1e9e960b9e5658b73..83d8e28100a845ea4c523e53e5bc293f793c5654 100644 (file)
@@ -30,6 +30,7 @@
 
 class QLineEdit;
 class QLabel;
+class QSpinBox;
 
 class SoutInputBox : public QGroupBox
 {
@@ -43,4 +44,89 @@ class SoutInputBox : public QGroupBox
 
 };
 
+class VirtualDestBox : public QWidget
+{
+    Q_OBJECT;
+    public:
+        VirtualDestBox( QWidget *_parent = NULL ) : QWidget( _parent ){}
+        virtual QString getMRL( QString ) = 0;
+    protected:
+        QString mrl;
+    signals:
+        void mrlUpdated();
+};
+
+class FileDestBox: public VirtualDestBox
+{
+    Q_OBJECT;
+    public:
+        FileDestBox( QWidget *_parent = NULL );
+        virtual QString getMRL( QString );
+    private:
+        QLineEdit *fileEdit;
+    private slots:
+        void fileBrowse();
+};
+
+class HTTPDestBox: public VirtualDestBox
+{
+    Q_OBJECT;
+    public:
+        HTTPDestBox( QWidget *_parent = NULL );
+        virtual QString getMRL( QString );
+    private:
+        QLineEdit *HTTPEdit;
+        QSpinBox *HTTPPort;
+};
+
+class MMSHDestBox: public VirtualDestBox
+{
+    Q_OBJECT;
+    public:
+        MMSHDestBox( QWidget *_parent = NULL );
+        virtual QString getMRL( QString );
+    private:
+        QLineEdit *MMSHEdit;
+        QSpinBox *MMSHPort;
+};
+
+class UDPDestBox: public VirtualDestBox
+{
+    Q_OBJECT;
+    public:
+        UDPDestBox( QWidget *_parent = NULL );
+        virtual QString getMRL( QString );
+    private:
+        QLineEdit *UDPEdit;
+        QSpinBox *UDPPort;
+};
+
+class RTPDestBox: public VirtualDestBox
+{
+    Q_OBJECT;
+    public:
+        RTPDestBox( QWidget *_parent = NULL );
+        virtual QString getMRL( QString );
+    private:
+        QLineEdit *RTPEdit;
+        QSpinBox *RTPPort;
+        QSpinBox *RTPPortVideo;
+        QSpinBox *RTPPortAudio;
+};
+
+class ICEDestBox: public VirtualDestBox
+{
+    Q_OBJECT;
+    public:
+        ICEDestBox( QWidget *_parent = NULL );
+        virtual QString getMRL( QString );
+    private:
+        QLineEdit *ICEEdit;
+        QLineEdit *ICEMountEdit;
+        QLineEdit *ICEPassEdit;
+        QSpinBox *ICEPort;
+};
+
+
+
 #endif
index 59c8ab55c01680204b6005e975596df7cd6f7c6a..250dc3cf5e82e2c4d5d916aff9fa86ea65c83b27 100644 (file)
 
 #include <QString>
 #include <QFileDialog>
-
-struct streaming_account_t
-{
-    char *psz_username; /*< username of account */
-    char *psz_password; /*< password of account */
-};
-
-struct sout_gui_descr_t
-{
-    /* Access types */
-    bool b_local;   /*< local access module */
-    bool b_file;    /*< file access module */
-    bool b_http;    /*< http access module */
-    bool b_mms;     /*< mms access module */
-    bool b_rtp;     /*< rtp access module */
-    bool b_udp;     /*< udp access module */
-    bool b_dump;    /*< dump access module */
-    bool b_icecast; /*< icecast access module */
-
-    char *psz_file;     /*< filename */
-    char *psz_http;     /*< HTTP servername or ipaddress */
-    char *psz_mms;      /*< MMS servername or ipaddress */
-    char *psz_rtp;      /*< RTP servername or ipaddress */
-    char *psz_udp;      /*< UDP servername or ipaddress */
-    char *psz_icecast;  /*< Icecast servername or ipaddress*/
-
-    int32_t i_http;     /*< http port number */
-    int32_t i_mms;      /*< mms port number */
-    int32_t i_rtp;      /*< rtp port number */
-    int32_t i_rtp_audio;      /*< rtp port number */
-    int32_t i_rtp_video;      /*< rtp port number */
-    int32_t i_udp;      /*< udp port number */
-    int32_t i_icecast;  /*< icecast port number */
-
-    /* Mux */
-    char *psz_mux;      /*< name of muxer to use in streaming */
-
-    /* Misc */
-    bool b_sap;   /*< send SAP announcement */
-    bool b_all_es;/*< send all elementary streams from source stream */
-    bool b_sout_keep;
-    char *psz_group;    /*< SAP Group name */
-    char *psz_name;     /*< SAP name */
-    int32_t i_ttl;      /*< Time To Live (TTL) for network traversal */
-
-    /* Icecast */
-    char *psz_icecast_mountpoint;/*< path to Icecast mountpoint */
-    struct streaming_account_t sa_icecast;  /*< Icecast account information */
-};
+#include <QToolButton>
 
 SoutDialog* SoutDialog::instance = NULL;
 
@@ -103,46 +55,44 @@ SoutDialog::SoutDialog( QWidget *parent, intf_thread_t *_p_intf, QString inputMR
             "You should start by checking that your input matches what you "
             "want and go on with the \"Next\" button.\n" );
 
-    changeUDPandRTPmess( false );
-
-/* ADD HERE for new profiles */
-#define ADD_PROFILE( name, shortname ) ui.profileBox->addItem( qtr( name ), QVariant( QString( shortname ) ) );
-/*    ADD_PROFILE( "Custom" , "Custom" )
-    ADD_PROFILE( "Ogg / Theora", "theora" )
-    ADD_PROFILE( "Ogg / Vorbis", "vorbis" )
-    ADD_PROFILE( "MPEG-2", "mpeg2" )
-    ADD_PROFILE( "MP3", "mp3" )
-    ADD_PROFILE( "MPEG-4 audio AAC", "aac" )
-    ADD_PROFILE( "MPEG-4 / DivX", "mp4" )
-    ADD_PROFILE( "H264", "h264" )
-    ADD_PROFILE( "IPod (mp4/aac)", "IPod" )
-    ADD_PROFILE( "XBox", "XBox" )
-    ADD_PROFILE( "Windows (wmv/asf)", "Windows" )
-    ADD_PROFILE( "PSP", "PSP")
-
-*/
     ui.mrlEdit->setToolTip ( qtr( "Stream output string.\n"
                 "This is automatically generated "
                  "when you change the above settings,\n"
                  "but you can change it manually." ) ) ;
 
+#if 0
+    /* This needs Qt4.5 to be cool */
+    ui.destTab->setTabsClosable( true );
+#else
+    closeTabButton = new QToolButton( this );
+    ui.destTab->setCornerWidget( closeTabButton );
+    closeTabButton->hide();
+    closeTabButton->setAutoRaise( true );
+    closeTabButton->setIcon( QIcon( ":/clear" ) );
+    BUTTONACT( closeTabButton, closeTab() );
+#endif
+    CONNECT( ui.destTab, currentChanged( int ), this, tabChanged( int ) );
+    ui.destTab->setTabIcon( 0, QIcon( ":/playlist_add" ) );
+
+    ui.destBox->addItem( qtr( "File" ) );
+    ui.destBox->addItem( "HTTP" );
+    ui.destBox->addItem( "MMS" );
+    ui.destBox->addItem( "UDP" );
+    ui.destBox->addItem( "RTP" );
+    ui.destBox->addItem( "IceCast" );
+
+    BUTTONACT( ui.addButton, addDest() );
+
 //     /* Connect everything to the updateMRL function */
  #define CB( x ) CONNECT( ui.x, toggled( bool ), this, updateMRL() );
  #define CT( x ) CONNECT( ui.x, textChanged( const QString ), this, updateMRL() );
  #define CS( x ) CONNECT( ui.x, valueChanged( int ), this, updateMRL() );
  #define CC( x ) CONNECT( ui.x, currentIndexChanged( int ), this, updateMRL() );
-    /* Output */
-    CB( fileOutput ); CB( HTTPOutput ); CB( localOutput );
-    CB( RTPOutput ); CB( MMSHOutput ); CB( rawInput ); CB( UDPOutput );
-    CT( fileEdit ); CT( HTTPEdit ); CT( RTPEdit ); CT( MMSHEdit ); CT( UDPEdit );
-    CT( IcecastEdit ); CT( IcecastMountpointEdit ); CT( IcecastNamePassEdit );
-    CS( HTTPPort ); CS( RTPPort ); CS( RTPPort2 ); CS( MMSHPort ); CS( UDPPort );
+
     /* Misc */
     CB( soutAll ); CB( soutKeep );  CS( ttl ); CT( sapName ); CT( sapGroup );
-
-//    CONNECT( ui.profileSelect, optionsChanged(), this, updateMRL() );
-    CONNECT( ui.fileSelectButton, clicked() , this, fileBrowse()  );
-    CONNECT( ui.rawInput, toggled( bool ), this, setRawOptions( bool ) );
+    CB( localOutput );
+    CONNECT( ui.profileSelect, optionsChanged(), this, updateMRL() );
 
     okButton = new QPushButton( qtr( "&Stream" ) );
     QPushButton *cancelButton = new QPushButton( qtr( "&Cancel" ) );
@@ -154,9 +104,6 @@ SoutDialog::SoutDialog( QWidget *parent, intf_thread_t *_p_intf, QString inputMR
     BUTTONACT( okButton, ok() );
     BUTTONACT( cancelButton, cancel() );
 
-    CONNECT( ui.UDPOutput, toggled( bool ), this, changeUDPandRTPmess( bool ) );
-    CONNECT( ui.RTPOutput, clicked(bool), this, RTPtoggled( bool ) );
-
     BUTTONACT( ui.nextButton, next() );
     BUTTONACT( ui.nextButton2, next() );
     BUTTONACT( ui.prevButton, prev() );
@@ -173,113 +120,72 @@ void SoutDialog::prev()
     ui.toolBox->setCurrentIndex( ui.toolBox->currentIndex() - 1 );
 }
 
-
-void SoutDialog::fileBrowse()
-{
-    QString fileName = QFileDialog::getSaveFileName( this, qtr( "Save file..." ),
-            "", qtr( "Containers (*.ps *.ts *.mpg *.ogg *.asf *.mp4 *.mov *.wav *.raw *.flv)" ) );
-    ui.fileEdit->setText( toNativeSeparators( fileName ) );
-    updateMRL();
-}
-
-void SoutDialog::setRawOptions( bool b_raw )
+void SoutDialog::tabChanged( int i )
 {
-    ui.localOutput->setEnabled( !b_raw );
-    ui.HTTPOutput->setEnabled( !b_raw );
-    ui.MMSHOutput->setEnabled( !b_raw );
-    ui.UDPOutput->setEnabled( !b_raw );
-    ui.RTPOutput->setEnabled( !b_raw );
-    ui.IcecastOutput->setEnabled( !b_raw );
-    ui.UDPRTPLabel->setEnabled( !b_raw );
-
-    if( b_raw ) 
-        ;
-//        ui.tabWidget->setDisabled( true );
-    else
-        setOptions();
+    closeTabButton->setVisible( (i != 0) );
 }
 
-void SoutDialog::setOptions()
+void SoutDialog::closeTab()
 {
-/*    QString profileString =
-        ui.profileBox->itemData( ui.profileBox->currentIndex() ).toString();
-    msg_Dbg( p_intf, "Profile Used: %s",  qtu( profileString )); */
-    int index;
-
-#define setProfile( muxName, hasVideo, vCodecName, hasAudio, aCodecName ) \
-    { \
-        ui.muxName ##Mux->setChecked( true ); \
-        \
-        ui.transcodeAudio->setChecked( hasAudio ); \
-        index = ui.aCodecBox->findData( aCodecName );  \
-        if( index >= 0 ) ui.aCodecBox->setCurrentIndex( index ); \
-        \
-        ui.transcodeVideo->setChecked( hasVideo ); \
-        index = ui.vCodecBox->findData( vCodecName );  \
-        if( index >=0 ) ui.vCodecBox->setCurrentIndex( index ); \
-    }
+    int i = ui.destTab->currentIndex();
+    if( i == 0 ) return;
 
-    /* ADD HERE the profiles you want and need */
-/*    if( profileString == "IPod" ) setProfile( MP4, true, "mp4v", true, "mp4a" )
-    else if( profileString == "theora" ) setProfile( Ogg, true, "theo", true, "vorb" )
-    else if( profileString == "vorbis" ) setProfile( Ogg, false, "", true, "vorb" )
-    else if( profileString == "mpeg2" ) setProfile( TS, true, "mp2v", true, "mpga" )
-    else if( profileString == "mp3" ) setProfile( RAW, false, "", true, "mp3" )
-    else if( profileString == "aac" ) setProfile( MP4, false, "", true, "mp4a" )
-    else if( profileString == "mp4" ) setProfile( MP4, true, "mp4v", true, "mp4a" )
-    else if( profileString == "h264" ) setProfile( TS, true, "h264", true, "mp4a" )
-    else if( profileString == "XBox" ) setProfile( ASF, true, "WMV2", true, "wma" )
-    else if( profileString == "Windows" ) setProfile( ASF, true, "WMV2", true, "wma" )
-    else if( profileString == "PSP" ) setProfile( MP4, true, "mp4v", true, "mp4a" )*/
-
-        /* If the profile is not a custom one, then disable the tabWidget */
-      /*  if ( profileString == "Custom" )
-            ui.tabWidget->setEnabled( true );
-        else
-            ui.tabWidget->setDisabled( true );
-
-    /* Update the MRL !! */
+    QWidget *temp = ui.destTab->currentWidget();
+    ui.destTab->removeTab( i );
+    delete temp;
     updateMRL();
 }
 
-void SoutDialog::changeUDPandRTPmess( bool b_udp )
+void SoutDialog::addDest( )
 {
-    ui.RTPEdit->setVisible( !b_udp );
-    ui.RTPLabel->setVisible( !b_udp );
-    ui.RTPPort->setVisible( !b_udp );
-    ui.RTPPortLabel->setVisible( !b_udp );
-    ui.UDPEdit->setVisible( b_udp );
-    ui.UDPLabel->setVisible( b_udp );
-    ui.UDPPortLabel->setText( b_udp ? qtr( "Port:") : qtr( "Audio Port:" ) );
-    ui.RTPPort2->setVisible( !b_udp );
-    ui.RTPPortLabel2->setVisible( !b_udp );
-}
-
-void SoutDialog::RTPtoggled( bool b_en )
-{
-    if( !b_en )
+    int index;
+    switch( ui.destBox->currentIndex() )
     {
-        if( ui.RTPPort->value() == ui.UDPPort->value() )
-        {
-            ui.UDPPort->setValue( ui.UDPPort->value() + 1 );
-        }
-
-        while( ui.RTPPort2->value() == ui.UDPPort->value() ||
-                ui.RTPPort2->value() == ui.RTPPort->value() )
-        {
-            ui.RTPPort2->setValue( ui.RTPPort2->value() + 1 );
-        }
+        case 0:
+            {
+                FileDestBox *fdb = new FileDestBox( this );
+                index = ui.destTab->addTab( fdb, "File" );
+                CONNECT( fdb, mrlUpdated(), this, updateMRL() );
+            }
+            break;
+        case 1:
+            {
+                HTTPDestBox *hdb = new HTTPDestBox( this );
+                index = ui.destTab->addTab( hdb, "HTTP" );
+                CONNECT( hdb, mrlUpdated(), this, updateMRL() );
+            }
+            break;
+        case 2:
+            {
+                MMSHDestBox *mdb = new MMSHDestBox( this );
+                index = ui.destTab->addTab( mdb, "MMSH" );
+                CONNECT( mdb, mrlUpdated(), this, updateMRL() );
+            }
+            break;
+        case 3:
+            {
+                UDPDestBox *udb = new UDPDestBox( this );
+                index = ui.destTab->addTab( udb, "UDP" );
+                CONNECT( udb, mrlUpdated(), this, updateMRL() );
+            }
+            break;
+        case 4:
+            {
+                RTPDestBox *rdb = new RTPDestBox( this );
+                index = ui.destTab->addTab( rdb, "RTP" );
+                CONNECT( rdb, mrlUpdated(), this, updateMRL() );
+            }
+            break;
+        case 5:
+            {
+                ICEDestBox *idb = new ICEDestBox( this );
+                index = ui.destTab->addTab( idb, "Icecast" );
+                CONNECT( idb, mrlUpdated(), this, updateMRL() );
+            }
     }
-    ui.sap->setEnabled( b_en );
-    ui.RTPLabel->setEnabled( b_en );
-    ui.RTPEdit->setEnabled( b_en );
-    ui.UDPOutput->setEnabled( b_en );
-    ui.UDPRTPLabel->setEnabled( b_en );
-    ui.UDPEdit->setEnabled( b_en );
-    ui.UDPPort->setEnabled( b_en );
-    ui.UDPPortLabel->setEnabled( b_en );
-    ui.RTPPort2->setEnabled( b_en );
-    ui.RTPPortLabel2->setEnabled( b_en );
+
+    ui.destTab->setCurrentIndex( index );
+    updateMRL();
 }
 
 void SoutDialog::ok()
@@ -296,222 +202,62 @@ void SoutDialog::cancel()
 
 void SoutDialog::updateMRL()
 {
-    sout_gui_descr_t sout;
-    memset( &sout, 0, sizeof( sout_gui_descr_t ) );
-    unsigned int counter = 0;
-
-    sout.b_local = ui.localOutput->isChecked();
-    sout.b_file = ui.fileOutput->isChecked();
-    sout.b_http = ui.HTTPOutput->isChecked();
-    sout.b_mms = ui.MMSHOutput->isChecked();
-    sout.b_icecast = ui.IcecastOutput->isChecked();
-    sout.b_rtp = ui.RTPOutput->isChecked();
-    sout.b_udp = ui.UDPOutput->isChecked();
-    sout.b_dump = ui.rawInput->isChecked();
-    sout.b_sap = ui.sap->isChecked();
-    sout.b_all_es = ui.soutAll->isChecked();
-    sout.b_sout_keep = ui.soutKeep->isChecked();
-/*    sout.psz_vcodec = strdup( qtu( ui.vCodecBox->itemData( ui.vCodecBox->currentIndex() ).toString() ) );
-    sout.psz_acodec = strdup( qtu( ui.aCodecBox->itemData( ui.aCodecBox->currentIndex() ).toString() ) );
-    sout.psz_scodec = strdup( qtu( ui.subsCodecBox->itemData( ui.subsCodecBox->currentIndex() ).toString() ) );*/
-    sout.psz_file = strdup( qtu( ui.fileEdit->text() ) );
-    sout.psz_http = strdup( qtu( ui.HTTPEdit->text() ) );
-    sout.psz_mms = strdup( qtu( ui.MMSHEdit->text() ) );
-    sout.psz_rtp = strdup( qtu( ui.RTPEdit->text() ) );
-    sout.psz_udp = strdup( qtu( ui.UDPEdit->text() ) );
-    sout.psz_icecast = strdup( qtu( ui.IcecastEdit->text() ) );
-    sout.sa_icecast.psz_username = strdup( qtu( ui.IcecastNamePassEdit->text() ) );
-    sout.sa_icecast.psz_password = strdup( qtu( ui.IcecastNamePassEdit->text() ) );
-    sout.psz_icecast_mountpoint = strdup( qtu( ui.IcecastMountpointEdit->text() ) );
-    sout.i_http = ui.HTTPPort->value();
-    sout.i_mms = ui.MMSHPort->value();
-    sout.i_rtp = ui.RTPPort->value();
-    sout.i_rtp_audio = sout.i_udp = ui.UDPPort->value();
-    sout.i_rtp_video = ui.RTPPort2->value();
-    sout.i_icecast = ui.IcecastPort->value();
-/*    sout.i_ab = ui.aBitrateSpin->value();
-    sout.i_vb = ui.vBitrateSpin->value();
-    sout.i_channels = ui.aChannelsSpin->value();
-    sout.f_scale = atof( qtu( ui.vScaleBox->currentText() ) ); */
-    sout.psz_group = strdup( qtu( ui.sapGroup->text() ) );
-    sout.psz_name = strdup( qtu( ui.sapName->text() ) );
-
-    if ( sout.b_local ) counter++ ;
-    if ( sout.b_file ) counter++ ;
-    if ( sout.b_http ) counter++ ;
-    if ( sout.b_mms ) counter++ ;
-    if ( sout.b_rtp ) counter++ ;
-    if ( sout.b_udp ) counter ++;
-    if ( sout.b_icecast ) counter ++;
-
-    sout.psz_mux = strdup( qtu( ui.profileSelect->getMux() ) );
-
-    bool trans = false;
-    bool more = false;
+    QString qs_mux = ui.profileSelect->getMux();
 
     SoutMrl smrl( ":sout=#" );
-
-    /* Special case for demuxdump */
-    if ( sout.b_file && sout.b_dump )
-    {
-        mrl = ":demux=dump :demuxdump-file=";
-        mrl.append( qfu( sout.psz_file ) );
-    }
-    else {
     if( !ui.profileSelect->getTranscode().isEmpty() )
     {
         smrl.begin( ui.profileSelect->getTranscode() );
         smrl.end();
     }
 
-    /* Protocol output */
-    if ( sout.b_local || sout.b_file || sout.b_http ||
-         sout.b_mms || sout.b_rtp || sout.b_udp || sout.b_icecast )
-    {
-        if( counter > 1 )
-            smrl.begin( "duplicate" );
-
-#define ADD(m) do { if( counter > 1 ) { \
-                smrl.option( "dst", m.getMrl() ); \
-            } else { \
-                smrl.begin( m.getMrl() ); \
-                smrl.end(); \
-            } } while(0)
-
-        if ( sout.b_local )
-        {
-            SoutMrl m;
-            m.begin( "display" );
-            m.end();
-
-            ADD( m );
-            more = true;
-        }
-
-        if ( sout.b_file )
-        {
-            SoutMrl m;
-
-            m.begin( "std" );
-            m.option( "access", "file" );
-            if( sout.psz_mux )
-                m.option( "mux", qfu( sout.psz_mux ) );
-            m.option( "dst", qfu( sout.psz_file ) );
-            m.end();
-
-            ADD( m );
-            more = true;
-        }
+    bool multi = false;
 
-        if ( sout.b_http )
-        {
-            SoutMrl m;
+    if( ui.destTab->count() >= 3 ||
+        ( ui.destTab->count() == 2 && ui.localOutput->isChecked() ) )
+        multi = true;
 
-            m.begin( "std" );
-            m.option(  "access", "http" );
-            if( sout.psz_mux )
-                m.option( "mux", qfu( sout.psz_mux ) );
-            m.option( "dst", qfu( sout.psz_http ), sout.i_http );
-            m.end();
+    if( multi )
+        smrl.begin( "duplicate" );
 
-            ADD( m );
-            more = true;
-        }
+    for( int i = 1; i < ui.destTab->count(); i++ )
+    {
+        VirtualDestBox *vdb = qobject_cast<VirtualDestBox *>(ui.destTab->widget( i ));
+        QString tempMRL = vdb->getMRL( qs_mux );
 
-        if ( sout.b_mms )
+        if( tempMRL.isEmpty() ) continue;
+        if( multi )
+            smrl.option( "dst", tempMRL );
+        else
         {
-            SoutMrl m;
-
-            m.begin( "std" );
-            m.option(  "access", "mmsh" );
-            m.option( "mux", "asfh" );
-            m.option( "dst", qfu( sout.psz_mms ), sout.i_mms );
-            m.end();
-
-            ADD( m );
-            more = true;
+            smrl.begin( tempMRL);
+            smrl.end();
         }
-
-        if ( sout.b_rtp )
+    }
+    if( ui.localOutput->isChecked() )
+    {
+        if( multi )
+            smrl.option( "dst", "display" );
+        else
         {
-            SoutMrl m;
-            if ( sout.b_udp )
-            {
-                m.begin( "std" );
-                m.option(  "access", "udp" );
-                if( sout.psz_mux )
-                    m.option( "mux", qfu( sout.psz_mux ) );
-                m.option( "dst", qfu( sout.psz_udp ), sout.i_udp );
-            }
-            else
-            {
-                m.begin( "rtp" );
-
-                if( sout.psz_rtp && *sout.psz_rtp )
-                    m.option( "dst", qfu( sout.psz_rtp ) );
-                if( sout.psz_mux )
-                    m.option( "mux", qfu( sout.psz_mux ) );
-
-                m.option( "port", sout.i_rtp );
-                if( !sout.psz_mux || strncmp( sout.psz_mux, "ts", 2 ) )
-                {
-                    m.option( "port-audio", sout.i_rtp_audio );
-                    m.option( "port-video", sout.i_rtp_video );
-                }
-            }
-
-            /* SAP */
-            if ( sout.b_sap )
-            {
-                m.option( "sap" );
-                m.option( "group", qfu( sout.psz_group ) );
-                m.option( "name", qfu( sout.psz_name ) );
-            }
-
-            m.end();
-            ADD( m );
-            more = true;
+            smrl.begin( "display" );
+            smrl.end();
         }
+    }
 
-        if( sout.b_icecast )
-        {
-            SoutMrl m;
-            QString url;
-
-            url = qfu(sout.sa_icecast.psz_username) + "@"
-                + qfu( sout.psz_icecast )
-                + ":" + QString::number( sout.i_icecast, 10 )
-                + "/" + qfu( sout.psz_icecast_mountpoint );
-
-            m.begin( "std" );
-            m.option( "access", "shout" );
-            m.option( "mux", "ogg" );
-            m.option( "dst", url );
-            m.end();
-
-            ADD( m );
-            more = true;
-        }
+    if ( multi ) smrl.end();
 
-        if ( counter )
-            smrl.end();
+    mrl = smrl.getMrl();
 
-        mrl = smrl.getMrl();
-    }
-    }
+    /* FIXME, deal with SAP 
+    sout.b_sap = ui.sap->isChecked();
+    sout.psz_group = strdup( qtu( ui.sapGroup->text() ) );
+    sout.psz_name = strdup( qtu( ui.sapName->text() ) ); */
 
-    if ( sout.b_all_es )
-        mrl.append( " :sout-all" );
+    if( ui.soutAll->isChecked() )  mrl.append( " :sout-all" );
 
-    if ( sout.b_sout_keep )
-        mrl.append( " :sout-keep" );
+    if( ui.soutKeep->isChecked() ) mrl.append( " :sout-keep" );
 
     ui.mrlEdit->setPlainText( mrl );
-    free( sout.psz_file );free( sout.psz_http ); free( sout.psz_mms );
-    free( sout.psz_rtp ); free( sout.psz_udp ); free( sout.psz_mux );
-    free( sout.psz_name ); free( sout.psz_group );
-    free( sout.psz_icecast ); free( sout.psz_icecast_mountpoint );
-    free( sout.sa_icecast.psz_password ); free( sout.sa_icecast.psz_username );
 }
 
-
index d5b391b1e8c05c5a3e2c7d5e6d8d95de5efe1095..67ee3aba99c527a4ef30a4fc1c9e3990cc87d11a 100644 (file)
@@ -34,6 +34,7 @@
 #include "util/qvlcframe.hpp"
 
 class QPushButton;
+class QToolButton;
 class QCheckBox;
 class QGridLayout;
 class QTextEdit;
@@ -133,8 +134,10 @@ private:
     Ui::Sout ui;
     static SoutDialog *instance;
     SoutDialog( QWidget* parent, intf_thread_t *, QString mrl );
-    QPushButton *okButton;
+
     QString mrl;
+    QPushButton *okButton;
+    QToolButton *closeTabButton;
 
 public slots:
     void updateMRL();
@@ -142,13 +145,11 @@ public slots:
 private slots:
     void ok();
     void cancel();
-    void setOptions();
-    void fileBrowse();
-    void setRawOptions( bool );
-    void changeUDPandRTPmess( bool );
-    void RTPtoggled( bool );
     void next();
     void prev();
+    void closeTab();
+    void tabChanged( int );
+    void addDest();
 };
 
 #endif
index 504936d3d38f1e00d97c780badb79b5810c23fdf..72c5403321a55ff6a5fd1ae38dce702e3aeb7cc9 100644 (file)
@@ -7,8 +7,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>651</width>
-    <height>532</height>
+    <width>708</width>
+    <height>587</height>
    </rect>
   </property>
   <property name="windowTitle">
    <item>
     <widget class="QToolBox" name="toolBox">
      <property name="currentIndex">
-      <number>0</number>
+      <number>1</number>
      </property>
-     <widget class="QWidget" name="page">
+     <widget class="QWidget" name="sourcePage">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>0</y>
-        <width>633</width>
-        <height>414</height>
+        <width>690</width>
+        <height>469</height>
        </rect>
       </property>
       <attribute name="label">
        </item>
       </layout>
      </widget>
-     <widget class="QWidget" name="page_3">
+     <widget class="QWidget" name="destPage">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>0</y>
-        <width>649</width>
-        <height>399</height>
+        <width>690</width>
+        <height>469</height>
        </rect>
       </property>
       <attribute name="label">
        <string>_(&quot;Destination&quot;)</string>
       </attribute>
-      <layout class="QGridLayout" name="gridLayout">
+      <layout class="QGridLayout" name="gridLayout_6">
        <item row="0" column="0" colspan="3">
-        <layout class="QGridLayout" name="_3">
-         <item row="0" column="1" colspan="2">
-          <widget class="QCheckBox" name="localOutput">
-           <property name="text">
-            <string>_(&quot;Play locally&quot;)</string>
-           </property>
-          </widget>
-         </item>
-         <item row="1" column="1" colspan="2">
-          <widget class="QCheckBox" name="fileOutput">
-           <property name="contextMenuPolicy">
-            <enum>Qt::NoContextMenu</enum>
-           </property>
-           <property name="text">
-            <string>_(&quot;File&quot;)</string>
-           </property>
-          </widget>
-         </item>
-         <item row="1" column="3">
-          <widget class="QLabel" name="fileLabel">
-           <property name="text">
-            <string>_(&quot;Filename&quot;)</string>
-           </property>
-          </widget>
-         </item>
-         <item row="1" column="4">
-          <widget class="QLineEdit" name="fileEdit"/>
-         </item>
-         <item row="1" column="5">
-          <widget class="QPushButton" name="fileSelectButton">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="text">
-            <string>_(&quot;Browse...&quot;)</string>
-           </property>
-          </widget>
-         </item>
-         <item row="1" column="6">
-          <widget class="QCheckBox" name="rawInput">
-           <property name="text">
-            <string>_(&quot;Dump raw input&quot;)</string>
-           </property>
-          </widget>
-         </item>
-         <item row="2" column="1" colspan="2">
-          <widget class="QCheckBox" name="HTTPOutput">
-           <property name="text">
-            <string>HTTP</string>
-           </property>
-          </widget>
-         </item>
-         <item row="2" column="3">
-          <widget class="QLabel" name="HTTPLabel">
-           <property name="text">
-            <string>_(&quot;Address&quot;)</string>
-           </property>
-          </widget>
-         </item>
-         <item row="2" column="4">
-          <widget class="QLineEdit" name="HTTPEdit"/>
-         </item>
-         <item row="2" column="5">
-          <widget class="QLabel" name="HTTPPortLabel">
-           <property name="text">
-            <string>_(&quot;Port:&quot;)</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="2" column="6">
-          <widget class="QSpinBox" name="HTTPPort">
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-           </property>
-           <property name="minimum">
-            <number>1</number>
-           </property>
-           <property name="maximum">
-            <number>65535</number>
-           </property>
-           <property name="singleStep">
-            <number>1</number>
-           </property>
-           <property name="value">
-            <number>8080</number>
-           </property>
-          </widget>
-         </item>
-         <item row="3" column="1" colspan="2">
-          <widget class="QCheckBox" name="MMSHOutput">
-           <property name="text">
-            <string>MMSH</string>
-           </property>
-          </widget>
-         </item>
-         <item row="3" column="3">
-          <widget class="QLabel" name="MMSHLabel">
-           <property name="text">
-            <string>_(&quot;Address&quot;)</string>
-           </property>
-          </widget>
-         </item>
-         <item row="3" column="4">
-          <widget class="QLineEdit" name="MMSHEdit"/>
-         </item>
-         <item row="3" column="5">
-          <widget class="QLabel" name="MMSHPortLabel">
-           <property name="text">
-            <string>_(&quot;Port:&quot;)</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="3" column="6">
-          <widget class="QSpinBox" name="MMSHPort">
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-           </property>
-           <property name="minimum">
-            <number>1</number>
-           </property>
-           <property name="maximum">
-            <number>65535</number>
-           </property>
-           <property name="value">
-            <number>1234</number>
-           </property>
-          </widget>
-         </item>
-         <item row="4" column="1" colspan="2">
-          <widget class="QCheckBox" name="RTPOutput">
-           <property name="text">
-            <string>RTP</string>
-           </property>
-          </widget>
-         </item>
-         <item row="4" column="3">
-          <widget class="QLabel" name="RTPLabel">
-           <property name="text">
-            <string>_(&quot;Address&quot;)</string>
-           </property>
-          </widget>
-         </item>
-         <item row="4" column="4">
-          <widget class="QLineEdit" name="RTPEdit"/>
-         </item>
-         <item row="4" column="5">
-          <widget class="QLabel" name="RTPPortLabel">
-           <property name="text">
-            <string>_(&quot;Port:&quot;)</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="4" column="6">
-          <widget class="QSpinBox" name="RTPPort">
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-           </property>
-           <property name="minimum">
-            <number>1</number>
-           </property>
-           <property name="maximum">
-            <number>65535</number>
-           </property>
-           <property name="value">
-            <number>1234</number>
-           </property>
-          </widget>
-         </item>
-         <item row="5" column="3">
-          <widget class="QLabel" name="UDPLabel">
-           <property name="enabled">
-            <bool>true</bool>
-           </property>
-           <property name="text">
-            <string>_(&quot;Address&quot;)</string>
-           </property>
-          </widget>
-         </item>
-         <item row="5" column="4">
-          <widget class="QLineEdit" name="UDPEdit"/>
-         </item>
-         <item row="5" column="5">
-          <widget class="QLabel" name="UDPPortLabel">
-           <property name="text">
-            <string>_(&quot;Port&quot;)</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="5" column="6">
-          <widget class="QSpinBox" name="UDPPort">
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-           </property>
-           <property name="accelerated">
-            <bool>true</bool>
-           </property>
-           <property name="minimum">
-            <number>1</number>
-           </property>
-           <property name="maximum">
-            <number>65535</number>
-           </property>
-           <property name="value">
-            <number>1234</number>
-           </property>
-          </widget>
-         </item>
-         <item row="6" column="5">
-          <widget class="QLabel" name="RTPPortLabel2">
-           <property name="text">
-            <string>_(&quot;Video Port&quot;)</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="6" column="6">
-          <widget class="QSpinBox" name="RTPPort2">
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-           </property>
-           <property name="accelerated">
-            <bool>true</bool>
-           </property>
-           <property name="maximum">
-            <number>65355</number>
-           </property>
-           <property name="value">
-            <number>1234</number>
-           </property>
-          </widget>
-         </item>
-         <item row="7" column="1" colspan="2">
-          <widget class="QCheckBox" name="IcecastOutput">
-           <property name="text">
-            <string>IceCast</string>
-           </property>
-          </widget>
-         </item>
-         <item row="7" column="3">
-          <widget class="QLabel" name="IcecastLabel">
-           <property name="text">
-            <string>_(&quot;Address&quot;)</string>
-           </property>
-          </widget>
-         </item>
-         <item row="7" column="4">
-          <widget class="QLineEdit" name="IcecastEdit"/>
-         </item>
-         <item row="7" column="5">
-          <widget class="QLabel" name="IcecastPortLabel">
-           <property name="text">
-            <string>_(&quot;Port:&quot;)</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="7" column="6">
-          <widget class="QSpinBox" name="IcecastPort">
-           <property name="maximumSize">
-            <size>
-             <width>90</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-           </property>
-           <property name="maximum">
-            <number>65535</number>
-           </property>
-           <property name="value">
-            <number>1024</number>
-           </property>
-          </widget>
-         </item>
-         <item row="8" column="3">
-          <widget class="QLabel" name="IcecastMountpointLabel">
-           <property name="text">
-            <string>_(&quot;Mount Point&quot;)</string>
-           </property>
-          </widget>
-         </item>
-         <item row="8" column="4">
-          <widget class="QLineEdit" name="IcecastMountpointEdit"/>
-         </item>
-         <item row="8" column="5">
-          <widget class="QLabel" name="IcecastNameLabel">
-           <property name="text">
-            <string>_(&quot;Login:pass:&quot;)</string>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-           </property>
-          </widget>
-         </item>
-         <item row="8" column="6">
-          <widget class="QLineEdit" name="IcecastNamePassEdit"/>
-         </item>
-         <item row="5" column="2" rowspan="2">
-          <widget class="QLabel" name="UDPRTPLabel">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="maximumSize">
-            <size>
-             <width>100</width>
-             <height>16777215</height>
-            </size>
-           </property>
-           <property name="text">
-            <string>_(&quot;Prefer UDP over RTP&quot;)</string>
-           </property>
-           <property name="textFormat">
-            <enum>Qt::PlainText</enum>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
-           </property>
-           <property name="wordWrap">
-            <bool>true</bool>
-           </property>
-           <property name="buddy">
-            <cstring>UDPOutput</cstring>
-           </property>
-          </widget>
-         </item>
-         <item row="5" column="1">
-          <widget class="QCheckBox" name="UDPOutput">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="toolTip">
-            <string>_(&quot;Using this option is not recommended in most of the cases.&quot;)</string>
-           </property>
-           <property name="text">
-            <string/>
-           </property>
-          </widget>
-         </item>
-        </layout>
+        <widget class="QGroupBox" name="groupBox">
+         <property name="title">
+          <string>_(&quot;Destinations&quot;)</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_7">
+          <item row="0" column="0">
+           <widget class="QTabWidget" name="destTab">
+            <property name="currentIndex">
+             <number>0</number>
+            </property>
+            <widget class="QWidget" name="tab">
+             <attribute name="title">
+              <string/>
+             </attribute>
+             <layout class="QGridLayout" name="gridLayout_10">
+              <item row="1" column="0">
+               <widget class="QLabel" name="label">
+                <property name="text">
+                 <string>_(&quot;New destination&quot;)</string>
+                </property>
+               </widget>
+              </item>
+              <item row="1" column="1">
+               <widget class="QComboBox" name="destBox"/>
+              </item>
+              <item row="1" column="2">
+               <widget class="QPushButton" name="addButton">
+                <property name="sizePolicy">
+                 <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+                  <horstretch>0</horstretch>
+                  <verstretch>0</verstretch>
+                 </sizepolicy>
+                </property>
+                <property name="text">
+                 <string>_(&quot;Add&quot;)</string>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="0" colspan="3">
+               <widget class="QLabel" name="label_2">
+                <property name="text">
+                 <string>_(&quot;Add destinations following the streaming methods you need.
+Be sure to check with transcoding that the format is compatible with the method used.&quot;)</string>
+                </property>
+                <property name="textFormat">
+                 <enum>Qt::PlainText</enum>
+                </property>
+                <property name="wordWrap">
+                 <bool>true</bool>
+                </property>
+               </widget>
+              </item>
+              <item row="2" column="0">
+               <widget class="QCheckBox" name="localOutput">
+                <property name="text">
+                 <string>_(&quot;Display locally&quot;)</string>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </widget>
+           </widget>
+          </item>
+         </layout>
+        </widget>
        </item>
-       <item row="1" column="0">
+       <item row="1" column="0" colspan="3">
+        <widget class="QGroupBox" name="groupBox_2">
+         <property name="title">
+          <string>_(&quot;Transcoding options&quot;)</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_5">
+          <item row="0" column="0">
+           <widget class="VLCProfileSelector" name="profileSelect" native="true"/>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="3" column="0">
         <widget class="QPushButton" name="prevButton">
          <property name="text">
           <string>_(&quot;Previous&quot;)</string>
          </property>
         </widget>
        </item>
-       <item row="1" column="1">
-        <spacer name="horizontalSpacer_2">
+       <item row="3" column="1">
+        <spacer name="horizontalSpacer_4">
          <property name="orientation">
           <enum>Qt::Horizontal</enum>
          </property>
          <property name="sizeHint" stdset="0">
           <size>
-           <width>581</width>
-           <height>20</height>
+           <width>382</width>
+           <height>26</height>
           </size>
          </property>
         </spacer>
        </item>
-       <item row="1" column="2">
+       <item row="3" column="2">
         <widget class="QPushButton" name="nextButton2">
          <property name="text">
           <string>_(&quot;Next&quot;)</string>
          </property>
         </widget>
        </item>
+       <item row="2" column="1">
+        <spacer name="verticalSpacer_2">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
       </layout>
      </widget>
-     <widget class="QWidget" name="page_4">
+     <widget class="QWidget" name="miscPage">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>0</y>
-        <width>633</width>
-        <height>414</height>
+        <width>690</width>
+        <height>469</height>
        </rect>
       </property>
       <attribute name="label">
       </attribute>
       <layout class="QGridLayout" name="gridLayout_2">
        <item row="0" column="0" colspan="2">
-        <widget class="Line" name="line">
-         <property name="orientation">
-          <enum>Qt::Horizontal</enum>
-         </property>
-        </widget>
-       </item>
-       <item row="1" column="0" colspan="2">
-        <widget class="VLCProfileSelector" name="profileSelect" native="true"/>
-       </item>
-       <item row="2" column="0" colspan="2">
-        <widget class="Line" name="line_2">
-         <property name="orientation">
-          <enum>Qt::Horizontal</enum>
-         </property>
-        </widget>
-       </item>
-       <item row="3" column="0" colspan="2">
         <widget class="QGroupBox" name="groupBox_3">
          <property name="title">
           <string>_(&quot;Miscellaneous&quot;)</string>
          </layout>
         </widget>
        </item>
-       <item row="4" column="0" colspan="2">
+       <item row="1" column="0" colspan="2">
         <widget class="QGroupBox" name="groupBox_4">
          <property name="title">
           <string>_(&quot;Generated stream output string&quot;)</string>
          </layout>
         </widget>
        </item>
-       <item row="5" column="0">
+       <item row="2" column="0">
         <widget class="QPushButton" name="prevButton2">
          <property name="text">
           <string>_(&quot;Previous&quot;)</string>
          </property>
         </widget>
        </item>
-       <item row="5" column="1">
+       <item row="2" column="1">
         <spacer name="horizontalSpacer_3">
          <property name="orientation">
           <enum>Qt::Horizontal</enum>