[vlc-devel] [PATCH] Adds batch convert support to the VLC GUI.

Lochlin Duperron lochlinduperron at gmail.com
Tue Nov 11 09:46:26 CET 2014


This commit modifies the convert wizard to accept multiple files from the file dialog box
The GUI should operate the same when a single file is selected (providing an option of where and what to name the file), but when multiple files are selected the files are
placed into the same folder with the same name and a new extention (there is an option to append -converted if you are converting to the same extention).
There are some tooltips to explain this operation.

Most of the changes are pretty straight-forward, converting QStrings to QStringLists and passing the full list of MRLs around.  The playlist already supports the batch processing
in a pretty straightforward way, so there's no issues there.

StandardPanel.cpp was modified to create a temp QStringList for passing to the streamingDialog, as it now takes the full list of input files rather than just one

Convert.cpp/hpp modified to take the QStringList and to behave (semi)-intelligently when reciving multiple files
open.cpp modified to pass the MRLs rather than MRL[0]
and the Dialogs_provider.cpp/hpp to pass the MRLs along, pretty much.  It also clears the playlist when recieving a list and starts the playlist from the beginning when it's added all the files to be converted.
---
 .../gui/qt4/components/playlist/standardpanel.cpp  |  12 ++-
 modules/gui/qt4/dialogs/convert.cpp                | 120 ++++++++++++++++-----
 modules/gui/qt4/dialogs/convert.hpp                |  12 ++-
 modules/gui/qt4/dialogs/open.cpp                   |  19 +++-
 modules/gui/qt4/dialogs_provider.cpp               |  45 ++++++--
 modules/gui/qt4/dialogs_provider.hpp               |   2 +-
 6 files changed, 164 insertions(+), 46 deletions(-)

diff --git a/modules/gui/qt4/components/playlist/standardpanel.cpp b/modules/gui/qt4/components/playlist/standardpanel.cpp
index 38de867..eb99f1b 100644
--- a/modules/gui/qt4/components/playlist/standardpanel.cpp
+++ b/modules/gui/qt4/components/playlist/standardpanel.cpp
@@ -319,14 +319,22 @@ void StandardPLPanel::popupAction( QAction *action )
         /* locally handled only */
         temp = model->getURI( index );
         if ( ! temp.isEmpty() )
-            THEDP->streamingDialog( NULL, temp, false );
+        {
+            QStringList tempList;
+            tempList.append(temp);
+            THEDP->streamingDialog( NULL, tempList, false );
+        }
         break;
 
     case VLCModelSubInterface::ACTION_SAVE:
         /* locally handled only */
         temp = model->getURI( index );
         if ( ! temp.isEmpty() )
-            THEDP->streamingDialog( NULL, temp );
+        {
+            QStringList tempList;
+            tempList.append(temp);
+            THEDP->streamingDialog( NULL, tempList );
+        }
         break;
 
     case VLCModelSubInterface::ACTION_CREATENODE:
diff --git a/modules/gui/qt4/dialogs/convert.cpp b/modules/gui/qt4/dialogs/convert.cpp
index 2674928..5a7bcee 100644
--- a/modules/gui/qt4/dialogs/convert.cpp
+++ b/modules/gui/qt4/dialogs/convert.cpp
@@ -38,7 +38,7 @@
 #include <QCheckBox>
 
 ConvertDialog::ConvertDialog( QWidget *parent, intf_thread_t *_p_intf,
-                              const QString& inputMRL )
+                              const QStringList& inputMRLs )
               : QVLCDialog( parent, _p_intf )
 {
     setWindowTitle( qtr( "Convert" ) );
@@ -46,7 +46,18 @@ ConvertDialog::ConvertDialog( QWidget *parent, intf_thread_t *_p_intf,
 
     QGridLayout *mainLayout = new QGridLayout( this );
     SoutInputBox *inputBox = new SoutInputBox( this );
-    inputBox->setMRL( inputMRL );
+    incomingMRLs = &inputMRLs;
+
+    singleFileSelected = (inputMRLs.length() == 1);
+
+    if(singleFileSelected)
+    {
+        inputBox->setMRL( inputMRLs[0] );
+    }
+    else
+    {
+        inputBox->setMRL("Multiple files selected.");
+    }
     mainLayout->addWidget( inputBox, 0, 0, 1, -1  );
 
     /**
@@ -62,12 +73,26 @@ ConvertDialog::ConvertDialog( QWidget *parent, intf_thread_t *_p_intf,
     fileLine->setMinimumWidth( 300 );
     fileLine->setFocus( Qt::ActiveWindowFocusReason );
     destLabel->setBuddy( fileLine );
+    // You can set a specific name for only one file.
+    if(singleFileSelected)
+    {
+        QPushButton *fileSelectButton = new QPushButton( qtr( "Browse" ) );
+        destLayout->addWidget( fileSelectButton, 0, 2);
+        BUTTONACT( fileSelectButton, fileBrowse() );
+    }
 
-    QPushButton *fileSelectButton = new QPushButton( qtr( "Browse" ) );
-    destLayout->addWidget( fileLine, 0, 1 );
-    destLayout->addWidget( fileSelectButton, 0, 2);
-    BUTTONACT( fileSelectButton, fileBrowse() );
+    // but multiple files follow a naming convention
+    else
+    {
+        fileLine->setText("Multiple Files Selected.");
+        fileLine->setReadOnly(true);
+        fileLine->setToolTip("Files will be placed in the same directory "
+                "with the same name.");
 
+        appendBox = new QCheckBox( qtr( "Append '-converted' to filename" ) );
+        destLayout->addWidget( appendBox, 1, 0 );
+    }
+    destLayout->addWidget( fileLine, 0, 1 );
     mainLayout->addWidget( destBox, 3, 0, 1, -1  );
 
 
@@ -147,29 +172,74 @@ void ConvertDialog::close()
 {
     hide();
 
-    if( dumpRadio->isChecked() )
-    {
-        mrl = "demux=dump :demuxdump-file=" + fileLine->text();
-    }
-    else
+    for(int i = 0; i < incomingMRLs->length(); i++)
     {
-        mrl = "sout=#" + profile->getTranscode();
-        if( deinterBox->isChecked() )
+        QString mrl;
+
+        if( dumpRadio->isChecked() )
         {
-            mrl.remove( '}' );
-            mrl += ",deinterlace}";
+            mrl = "demux=dump :demuxdump-file=" + fileLine->text();
         }
-        mrl += ":";
-        if( displayBox->isChecked() )
-            mrl += "duplicate{dst=display,dst=";
-        mrl += "std{access=file{no-overwrite},mux=" + profile->getMux()
-             + ",dst='" + fileLine->text().replace( QChar('\''), "\\\'" )
-             + "'}";
-        if( displayBox->isChecked() )
-            mrl += "}";
+        else
+        {
+            mrl = "sout=#" + profile->getTranscode();
+            if( deinterBox->isChecked() )
+            {
+                mrl.remove( '}' );
+                mrl += ",deinterlace}";
+            }
+            mrl += ":";
+            if( displayBox->isChecked() )
+            {
+                mrl += "duplicate{dst=display,dst=";
+            }
+
+            QString newFileName;
+
+            // Only one file, use the destination provided
+            if(singleFileSelected)
+            {
+                newFileName = fileLine->text();
+            }
+
+            // Multiple, use the convention.
+            else
+            {
+                QString fileExtension = ( ! profile->isEnabled() ) ? ".*" : "." + profile->getMux();
+
+                newFileName = incomingMRLs->at(i);
+
+                // Remove the file:// from the front of our MRL
+                newFileName = newFileName.remove(0,7);
+
+                // Remote the existing extention (if any)
+                int extentionPos = newFileName.lastIndexOf('.');
+                if(extentionPos >= 0)
+                {
+                    newFileName = newFileName.remove(extentionPos, newFileName.length() - extentionPos);
+                }
+
+                // If we have multiple files (i.e. we have an appenBox) and it's checked
+                if(!singleFileSelected && appendBox->isChecked())
+                {
+                    newFileName = newFileName.append("-converted");
+                }
+
+                // Stick our new extention on
+                newFileName = newFileName.append(fileExtension);
+            }
+
+            newFileName.replace( QChar('\''), "\\\'" );
+
+            mrl += "std{access=file{no-overwrite},mux=" + profile->getMux()
+                 + ",dst='" + newFileName
+                 + "'}";
+            if( displayBox->isChecked() )
+                mrl += "}";
+        }
+        msg_Dbg( p_intf, "Transcode MRL: %s", qtu( mrl ) );
+        mrls.append(mrl);
     }
-
-    msg_Dbg( p_intf, "Transcode MRL: %s", qtu( mrl ) );
     accept();
 }
 
diff --git a/modules/gui/qt4/dialogs/convert.hpp b/modules/gui/qt4/dialogs/convert.hpp
index 9a9727e..8b69c0b 100644
--- a/modules/gui/qt4/dialogs/convert.hpp
+++ b/modules/gui/qt4/dialogs/convert.hpp
@@ -36,19 +36,23 @@ class ConvertDialog : public QVLCDialog
 {
     Q_OBJECT
 public:
-    ConvertDialog( QWidget *, intf_thread_t *, const QString& );
+    ConvertDialog( QWidget *, intf_thread_t *, const QStringList& );
     virtual ~ConvertDialog(){}
 
-    QString getMrl() {return mrl;}
+    QStringList getMrls() {return mrls;}
 
 private:
     QLineEdit *fileLine;
 
-    QCheckBox *displayBox, *deinterBox;
+    QCheckBox *displayBox, *deinterBox, *appendBox;
     QRadioButton *dumpRadio;
     QPushButton *okButton;
     VLCProfileSelector *profile;
-    QString mrl;
+
+    const QStringList *incomingMRLs;
+    bool singleFileSelected;
+    QStringList mrls;
+
 private slots:
     void close() Q_DECL_OVERRIDE;
     void cancel() Q_DECL_OVERRIDE;
diff --git a/modules/gui/qt4/dialogs/open.cpp b/modules/gui/qt4/dialogs/open.cpp
index 56ea980..90c7949 100644
--- a/modules/gui/qt4/dialogs/open.cpp
+++ b/modules/gui/qt4/dialogs/open.cpp
@@ -392,13 +392,24 @@ void OpenDialog::transcode()
 
 void OpenDialog::stream( bool b_transcode_only )
 {
-    QString soutMRL = getMRL( false );
-    if( soutMRL.isEmpty() ) return;
+//    QString soutMRL = getMRL( false );
+//    if( soutMRL.isEmpty() ) return;
+
+    QStringList soutMRLS = getMRLs(false);
+    if(soutMRLS.empty())
+    {
+        return;
+    }
+
     toggleVisible();
 
     /* Dbg and send :D */
-    msg_Dbg( p_intf, "MRL passed to the Sout: %s", qtu( soutMRL ) );
-    THEDP->streamingDialog( this, soutMRL, b_transcode_only,
+    msg_Dbg( p_intf, "MRL(s) passed to the Sout: %i", soutMRLS.length() );
+    for(int i = 0; i < soutMRLS.length(); i++)
+    {
+        msg_Dbg( p_intf, "MRL(s) passed to the Sout: %s", qtu( soutMRLS[i] ) );
+    }
+    THEDP->streamingDialog( this, soutMRLS, b_transcode_only,
                             getOptions().split( " :" ) );
 }
 
diff --git a/modules/gui/qt4/dialogs_provider.cpp b/modules/gui/qt4/dialogs_provider.cpp
index 7c3cf16..33cc010 100644
--- a/modules/gui/qt4/dialogs_provider.cpp
+++ b/modules/gui/qt4/dialogs_provider.cpp
@@ -62,6 +62,7 @@
 #include <QApplication>
 #include <QSignalMapper>
 #include <QFileDialog>
+#include <matroska/c/libmatroska_t.h>
 
 #define I_OP_DIR_WINTITLE I_DIR_OR_FOLDER( N_("Open Directory"), \
                                            N_("Open Folder") )
@@ -689,20 +690,22 @@ void DialogsProvider::saveRecentsToPlaylist()
  ****************************************************************************/
 
 void DialogsProvider::streamingDialog( QWidget *parent,
-                                       const QString& mrl,
+                                       const QStringList& mrls,
                                        bool b_transcode_only,
                                        QStringList options )
 {
-    QString soutoption;
+    QStringList outputMRLs;
 
     /* Stream */
+    // Does streaming multiple files make sense?  I suppose so, just stream one
+    // after the other, but not at the moment.
     if( !b_transcode_only )
     {
-        SoutDialog *s = new SoutDialog( parent, p_intf, mrl );
+        SoutDialog *s = new SoutDialog( parent, p_intf, mrls[0] );
         s->setAttribute( Qt::WA_QuitOnClose, false ); // See #4883
         if( s->exec() == QDialog::Accepted )
         {
-            soutoption = s->getMrl();
+            outputMRLs.append(s->getMrl());
             delete s;
         }
         else
@@ -711,11 +714,15 @@ void DialogsProvider::streamingDialog( QWidget *parent,
         }
     } else {
     /* Convert */
-        ConvertDialog *s = new ConvertDialog( parent, p_intf, mrl );
+        ConvertDialog *s = new ConvertDialog( parent, p_intf, mrls );
         s->setAttribute( Qt::WA_QuitOnClose, false ); // See #4883
         if( s->exec() == QDialog::Accepted )
         {
-            soutoption = s->getMrl();
+            /* Clear the playlist.  This is because we're going to be populating
+               it */
+            playlist_Clear( THEPL, pl_Unlocked );
+
+            outputMRLs = s->getMrls();
             delete s;
         }
         else
@@ -724,12 +731,30 @@ void DialogsProvider::streamingDialog( QWidget *parent,
         }
     }
 
-    /* Get SoutMRL */
-    if( !soutoption.isEmpty() )
+    /* Get SoutMRL(s) */
+    if( !outputMRLs.isEmpty() )
     {
-        options += soutoption.split( " :");
+        /* For all of our MRLs */
+        for(int i = 0; i < outputMRLs.length(); i++)
+        {
+
+            /* Duplicate the options list.  This is because we need to have a
+             copy for every file we add to the playlist.*/
+            QStringList optionsCopy;
+            for(int j = 0; j < options.length(); j++)
+            {
+                optionsCopy.append(options[j]);
+            }
+
+            optionsCopy+= outputMRLs[i].split( " :");
+            QString title = "Converting " + mrls[i];
+
+            /* Add each file to convert to our playlist, making sure to not attempt to start playing it.*/
+            Open::openMRLwithOptions( p_intf, mrls[i], &optionsCopy, false, true, _(title.toStdString().c_str()) );
+        }
 
-        Open::openMRLwithOptions( p_intf, mrl, &options, true, true, _("Streaming") );
+        /* Start the playlist from the beginning */
+        playlist_Control(THEPL,PLAYLIST_PLAY,pl_Unlocked);
     }
 }
 
diff --git a/modules/gui/qt4/dialogs_provider.hpp b/modules/gui/qt4/dialogs_provider.hpp
index 4327fcd..3b577d0 100644
--- a/modules/gui/qt4/dialogs_provider.hpp
+++ b/modules/gui/qt4/dialogs_provider.hpp
@@ -160,7 +160,7 @@ public slots:
     void PLOpenDir();
     void PLAppendDir();
 
-    void streamingDialog( QWidget *parent, const QString& mrl, bool b_stream = true,
+    void streamingDialog( QWidget *parent, const QStringList& mrls, bool b_stream = true,
                           QStringList options = QStringList("") );
     void openAndStreamingDialogs();
     void openAndTranscodingDialogs();
-- 
2.1.0




More information about the vlc-devel mailing list