traverso-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Traverso-commit] traverso/src commands/AudioClipExternalProcessi...


From: Remon Sijrier
Subject: [Traverso-commit] traverso/src commands/AudioClipExternalProcessi...
Date: Wed, 20 Jun 2007 15:27:16 +0000

CVSROOT:        /sources/traverso
Module name:    traverso
Changes by:     Remon Sijrier <r_sijrier>       07/06/20 15:27:16

Modified files:
        src/commands   : AudioClipExternalProcessing.cpp 
                         AudioClipExternalProcessing.h 
        src/core       : AudioSource.h 
Added files:
        src/commands/ui: ExternalProcessing.ui 

Log message:
        improved external clip processing dialog

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/traverso/src/commands/AudioClipExternalProcessing.cpp?cvsroot=traverso&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/traverso/src/commands/AudioClipExternalProcessing.h?cvsroot=traverso&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/traverso/src/commands/ui/ExternalProcessing.ui?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/AudioSource.h?cvsroot=traverso&r1=1.19&r2=1.20

Patches:
Index: commands/AudioClipExternalProcessing.cpp
===================================================================
RCS file: 
/sources/traverso/traverso/src/commands/AudioClipExternalProcessing.cpp,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- commands/AudioClipExternalProcessing.cpp    30 May 2007 13:14:45 -0000      
1.6
+++ commands/AudioClipExternalProcessing.cpp    20 Jun 2007 15:27:15 -0000      
1.7
@@ -30,18 +30,89 @@
 #include <Project.h>
 #include <ResourcesManager.h>
 #include <Utils.h>
+#include "Interface.h"
+#include "Export.h"
+#include "WriteSource.h"
 
-#include <QInputDialog>
+#include <QThread>
+#include <QFile>
 
 
 // Always put me below _all_ includes, this is needed
 // in case we run with memory leak detection enabled!
 #include "Debugger.h"
 
+class MergeThread : public QThread
+{
+public:
+       MergeThread(ReadSource* source, QString outFileName) {
+               m_outFileName = outFileName;
+               m_readsource = source;
+       }
+
+       void run() {
+               uint buffersize = 4096;
+               audio_sample_t readbuffer[buffersize];
+               audio_sample_t mixdown[2 * buffersize];
+       
+               ExportSpecification* spec = new ExportSpecification();
+               spec->start_frame = 0;
+               spec->end_frame = m_readsource->get_nframes();
+               spec->total_frames = spec->end_frame;
+               spec->pos = 0;
+               spec->isRecording = false;
+               spec->extension = "wav";
+       
+               spec->exportdir = pm().get_project()->get_root_dir() + 
"/audiosources/";
+               spec->format = SF_FORMAT_WAV;
+               spec->data_width = 16;
+               spec->format |= SF_FORMAT_PCM_16;
+               spec->channels = 2;
+               spec->sample_rate = m_readsource->get_rate();
+               spec->blocksize = buffersize;
+               spec->name = m_outFileName;
+               spec->dataF = new audio_sample_t[buffersize * 2];
+       
+               WriteSource* writesource = new WriteSource(spec);
+       
+               do {
+                       nframes_t this_nframes = 
std::min((nframes_t)(spec->end_frame - spec->pos), buffersize);
+                       nframes_t nframes = this_nframes;
+               
+                       memset (spec->dataF, 0, sizeof (spec->dataF[0]) * 
nframes * spec->channels);
+               
+                       for (int chan=0; chan < 2; ++chan) {
+                       
+                               m_readsource->file_read(chan, mixdown, 
spec->pos, nframes, readbuffer);
+                       
+                               for (uint x = 0; x < nframes; ++x) {
+                                       spec->dataF[chan+(x*spec->channels)] = 
mixdown[x];
+                               }
+                       }
+               
+                       writesource->process(buffersize);
+               
+                       spec->pos += nframes;
+                       
+               } while (spec->pos != spec->total_frames);
+               
+               writesource->finish_export();
+               delete writesource;
+               delete [] spec->dataF;
+               delete spec;
+       }
+
+private:
+       QString m_outFileName;
+       ReadSource* m_readsource;
+};
+
+
 AudioClipExternalProcessing::AudioClipExternalProcessing(AudioClip* clip)
        : Command(clip, tr("Clip: External Processing"))
 {
        m_clip = clip;
+       m_resultingclip = 0;
        m_track = m_clip->get_track();
 }
 
@@ -52,106 +123,237 @@
 
 int AudioClipExternalProcessing::prepare_actions()
 {
-       bool ok;
+       ExternalProcessingDialog epdialog(Interface::instance(), this);
+       
+       epdialog.exec();
        
-       QString command = QInputDialog::getText(
-                               0, 
-                               tr("Clip Processing"),
-                               tr("Enter sox command"),
-                               QLineEdit::Normal,
-                               "",
-                               &ok );
-       
-       if (! ok || command.isEmpty()) {
-               // Nothing typed in, or used hit cancel
-               printf("No input command, or cancel button clicked\n");
+       if (! m_resultingclip) {
                return -1;
        }
        
-       printf("returned command: %s\n", QS_C(command));
+       return 1;
+}
+
+
+int AudioClipExternalProcessing::do_action()
+{
+       PENTER;
+       Command::process_command(m_track->remove_clip(m_clip, false));
+       Command::process_command(m_track->add_clip(m_resultingclip, false));
+       
+       return 1;
+}
+
+int AudioClipExternalProcessing::undo_action()
+{
+       PENTER;
+       Command::process_command(m_track->remove_clip(m_resultingclip, false));
+       Command::process_command(m_track->add_clip(m_clip, false));
+       return 1;
+}
+
+
+
+/************************************************************************/
+/*                             DIALOG                                  */
+/************************************************************************/
        
        
+ExternalProcessingDialog::ExternalProcessingDialog(QWidget * parent, 
AudioClipExternalProcessing* acep)
+       : QDialog(parent)
+{
+       setupUi(this);
+       m_acep = acep;
+       m_queryOptions = false;
+       m_merger = 0;
+       
        m_processor = new QProcess(this);
        m_processor->setProcessChannelMode(QProcess::MergedChannels);
        
-       ReadSource* rs = 
resources_manager()->get_readsource(m_clip->get_readsource_id());
-/*     if (! rs) {
-               // This should NOT be possible, but just in case....
-               printf("resources manager didn't return a resource for the to 
be processed audioclip (%lld) !!!!\n",
-                               m_clip->get_id());
-               return -1;
-       }*/
+       command_lineedit_text_changed("sox");
        
-       QString name = rs->get_name();
+       connect(m_processor, SIGNAL(readyReadStandardOutput()), this, 
SLOT(read_standard_output()));
+       connect(m_processor, SIGNAL(started()), this, SLOT(process_started()));
+       connect(m_processor, SIGNAL(finished(int, QProcess::ExitStatus)), this, 
SLOT(process_finished(int, QProcess::ExitStatus)));
+       connect(m_processor, SIGNAL(error( QProcess::ProcessError)), this, 
SLOT(process_error(QProcess::ProcessError)));
+       connect(argsComboBox, SIGNAL(activated(const QString&)), this, 
SLOT(arg_combo_index_changed(const QString&)));
+       connect(programLineEdit, SIGNAL(textChanged(const QString&)), this, 
SLOT(command_lineedit_text_changed(const QString&)));
+       connect(startButton, SIGNAL(clicked()), this, 
SLOT(prepare_for_external_processing()));
+       connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
+}
        
-       QString infilename = rs->get_filename();
-       QString outfilename = pm().get_project()->get_audiosources_dir() + 
name.remove(".wav").remove(".")
-                                                       
.append("-").append(command.simplified()).append(".wav");
+ExternalProcessingDialog::~ ExternalProcessingDialog()
+{
+       delete m_processor;
+}
        
-       printf("infilename is %s\n", QS_C(infilename));
-       printf("outfilename is %s\n", QS_C(outfilename));
        
-       QStringList arguments;
-       arguments.append(infilename);
-       arguments.append(outfilename);
-       arguments += command.split(QRegExp("\\s+"));
+void ExternalProcessingDialog::prepare_for_external_processing()
+{
+       m_commandargs = argumentsLineEdit->text();
        
-       printf("Complete command is %s\n", QS_C( arguments.join(" ")));
+       ReadSource* rs = 
resources_manager()->get_readsource(m_acep->m_clip->get_readsource_id());
        
-       m_processor->start("sox", arguments);
+       //This should NOT be possible, but just in case....
+       if (! rs) {
+               printf("ExternalProcessing:: resources manager did NOT return a 
resource for the to be processed audioclip (%lld) !!!!\n", 
m_acep->m_clip->get_id());
+               return;
+       }
        
-       QString result;
+       m_filename = rs->get_name();
        
-       if (! m_processor->waitForFinished() ) {
-               if (!result.isEmpty())
-               result = m_processor->errorString();
-               if (!result.isEmpty())
-                       printf("output: \n %s", QS_C(result));
-               return -1;
+       m_infilename = rs->get_filename();
+       // remove the extension and any dots that might confuse the external 
program, append the 
+       // new name and again the extension.
+       m_outfilename = pm().get_project()->get_audiosources_dir() + 
+                       
m_filename.remove(".wav").remove(".").append("-").append(m_commandargs.simplified()).append(".wav");
+       
+       printf("infilename is %s\n", QS_C(m_infilename));
+       printf("outfilename is %s\n", QS_C(m_outfilename));
+       printf("Complete command is %s\n", QS_C(m_arguments.join(" ")));
+       
+       
+       if (rs->get_channel_count() == 2 && rs->get_file_count() == 2) {
+               m_merger = new MergeThread(rs, "merged.wav");
+               connect(m_merger, SIGNAL(finished()), this, 
SLOT(start_external_processing()));
+               m_merger->start();
+               statusText->setHtml(tr("Preparing audio data to a format that 
can be used by <b>%1</b>, this can take a while for large 
files!").arg(m_program));
+               progressBar->setMaximum(0);
        } else {
-               result = m_processor->readAllStandardOutput();
-               if (!result.isEmpty())
-                       printf("output: \n %s", QS_C(result));
+               start_external_processing();
+       }
+}
+
+void ExternalProcessingDialog::start_external_processing()
+{
+       m_arguments.append("-S");
+       if (m_merger) {
+               progressBar->setMaximum(100);
+               m_arguments.append(pm().get_project()->get_audiosources_dir() + 
"merged.wav");
+               delete m_merger;
+       } else {
+               m_arguments.append(m_infilename);
+       }
+       m_arguments.append(m_outfilename);
+       m_arguments += m_commandargs.split(QRegExp("\\s+"));
+       
+       m_processor->start(m_program, m_arguments);
+}
+
+void ExternalProcessingDialog::read_standard_output()
+{
+       if (m_queryOptions) {
+               QString result = m_processor->readAllStandardOutput();
+               if (m_program == "sox") {
+                       QStringList list = result.split("\n");
+                       foreach(QString string, list) {
+                               if (string.contains("Supported effects:")) {
+                                       result = string.remove("Supported 
effects:");
+                                       QStringList options = 
string.split(QRegExp("\\s+"));
+                                       foreach(QString string, options) {
+                                               if (!string.isEmpty())
+                                                       
argsComboBox->addItem(string);
+                                       }
+                               }
+                       }
+               }
+               return;
+       }
+       
+       QString result = m_processor->readAllStandardOutput();
+       
+       if (result.contains("%")) {
+               QStringList tokens = result.split(QRegExp("\\s+"));
+               foreach(QString token, tokens) {
+                       if (token.contains("%")) {
+                               token = token.remove("%)");
+                               int number = (int)token.toDouble();
+                               progressBar->setValue(number);
+                               return;
+                       }
+               }
+       }
+       
+       statusText->append(result);
+}
+
+void ExternalProcessingDialog::process_started()
+{
+       statusText->clear();
+}
+
+void ExternalProcessingDialog::process_finished(int exitcode, 
QProcess::ExitStatus exitstatus)
+{
+       Q_UNUSED(exitcode);
+       Q_UNUSED(exitstatus);
+       
+       if (m_queryOptions) {
+               m_queryOptions = false;
+               return;
+       }
                
                QString dir = pm().get_project()->get_audiosources_dir();
        
-               ReadSource* source = resources_manager()->import_source(dir, 
name);
+       // In case we used the merger, remove the file...
+       QFile::remove(dir + "/merged.wav");
+       
+       if (progressBar->value() != 100) {
+               // not sure if this is always valid, but it at least should be 
100 all 
+               // the time, that is, after succesfull operation....
+               // so if not 100 -> unsucesfull, and we bail out
+               return;
+       }
+       
+       QString result = m_processor->readAllStandardOutput();
+       // print anything on command line we didn't catch
+       printf("output: \n %s", QS_C(result));
+               
+       ReadSource* source = resources_manager()->import_source(dir, 
m_filename);
                if (!source) {
                        printf("ResourcesManager didn't return a ReadSource, 
most likely sox didn't understand your command\n");
-                       return -1;
+               return rejected();
                }
                
-               m_resultingclip = 
resources_manager()->new_audio_clip(name.remove(".wav"));
+       m_acep->m_resultingclip = 
resources_manager()->new_audio_clip(m_filename.remove(".wav"));
+       resources_manager()->set_source_for_clip(m_acep->m_resultingclip, 
source);
                // Clips live at project level, we have to set its Song, Track 
and ReadSource explicitely!!
-               m_resultingclip->set_song(m_clip->get_song());
-               m_resultingclip->set_track(m_clip->get_track());
-               resources_manager()->set_source_for_clip(m_resultingclip, 
source);
-               
m_resultingclip->set_track_start_frame(m_clip->get_track_start_frame());
-       }
+       m_acep->m_resultingclip->set_song(m_acep->m_clip->get_song());
+       m_acep->m_resultingclip->set_track(m_acep->m_clip->get_track());
+       
m_acep->m_resultingclip->set_track_start_frame(m_acep->m_clip->get_track_start_frame());
        
+       close();
+}
        
-       return 1;
+void ExternalProcessingDialog::query_options()
+{
+       m_queryOptions = true;
+       argsComboBox->clear();
+       m_processor->start(m_program, QStringList());
 }
 
+void ExternalProcessingDialog::arg_combo_index_changed(const QString & text)
+{
+       argumentsLineEdit->setText(text);       
+}
 
-int AudioClipExternalProcessing::do_action()
+void ExternalProcessingDialog::command_lineedit_text_changed(const QString & 
text)
 {
-       PENTER;
-       Command::process_command(m_track->remove_clip(m_clip, false));
-       Command::process_command(m_track->add_clip(m_resultingclip, false));
+       m_program = text;
+       if (m_program == "sox") {
+               query_options();
+               argsComboBox->show();
+               argsComboBox->setToolTip(tr("Available arguments for the sox 
program"));
+               return;
+       }
        
-       return 1;
+       argsComboBox->hide();
 }
 
-int AudioClipExternalProcessing::undo_action()
+void ExternalProcessingDialog::process_error(QProcess::ProcessError error)
 {
-       PENTER;
-       Command::process_command(m_track->remove_clip(m_resultingclip, false));
-       Command::process_command(m_track->add_clip(m_clip, false));
-       return 1;
+       if (error == QProcess::FailedToStart) {
+               statusText->setHtml(tr("Program <b>%1</b> not installed, or 
insufficient permissions to run!").arg(m_program));
+       }
 }
 
 
-
-// eof
-

Index: commands/AudioClipExternalProcessing.h
===================================================================
RCS file: 
/sources/traverso/traverso/src/commands/AudioClipExternalProcessing.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- commands/AudioClipExternalProcessing.h      16 Mar 2007 00:10:54 -0000      
1.1
+++ commands/AudioClipExternalProcessing.h      20 Jun 2007 15:27:15 -0000      
1.2
@@ -19,11 +19,54 @@
 
 */
 
+#ifndef AUDIOCLIP_EXTERNAL_PROCESSING_H
+#define AUDIOCLIP_EXTERNAL_PROCESSING_H
+
+#include <QDialog>
 #include <QProcess>
 #include <Command.h>
 
+#include "build/ui_ExternalProcessing.h"
+
 class AudioClip;
 class Track;
+class AudioClipExternalProcessing;
+class MergeThread;
+
+class ExternalProcessingDialog : public QDialog, protected 
Ui::ExternalProcessing
+{
+       Q_OBJECT
+       
+public:
+       ExternalProcessingDialog(QWidget* parent, AudioClipExternalProcessing* 
acep);
+       ~ExternalProcessingDialog();
+
+
+private:
+       AudioClipExternalProcessing* m_acep;
+       QProcess* m_processor;
+       MergeThread* m_merger;
+       QString m_filename;
+       QString m_program;
+       bool m_queryOptions;
+       QStringList m_arguments;
+       QString m_commandargs;
+       QString m_infilename;
+       QString m_outfilename;
+               
+       void query_options();
+       
+private slots:
+       void read_standard_output();
+       void prepare_for_external_processing();
+       void process_started();
+       void process_finished(int exitcode, QProcess::ExitStatus exitstatus);
+       void arg_combo_index_changed ( const QString & text );
+       void start_external_processing();
+       void command_lineedit_text_changed(const QString & text);
+       void process_error(QProcess::ProcessError error);
+};
+
 
 class AudioClipExternalProcessing : public Command
 {
@@ -40,6 +83,11 @@
        AudioClip* m_clip;
        AudioClip* m_resultingclip;
        QProcess* m_processor;
+       
+       friend class ExternalProcessingDialog;
+       
 };
 
+#endif
+
 //eof

Index: core/AudioSource.h
===================================================================
RCS file: /sources/traverso/traverso/src/core/AudioSource.h,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -b -r1.19 -r1.20
--- core/AudioSource.h  5 Jun 2007 12:47:09 -0000       1.19
+++ core/AudioSource.h  20 Jun 2007 15:27:16 -0000      1.20
@@ -56,6 +56,7 @@
        qint64 get_orig_song_id() const {return m_origSongId;}
        int get_rate() const;
        uint get_channel_count() const;
+       uint get_file_count() const {return m_fileCount;}
        int get_bit_depth() const;
        
 protected:

Index: commands/ui/ExternalProcessing.ui
===================================================================
RCS file: commands/ui/ExternalProcessing.ui
diff -N commands/ui/ExternalProcessing.ui
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ commands/ui/ExternalProcessing.ui   20 Jun 2007 15:27:15 -0000      1.1
@@ -0,0 +1,186 @@
+<ui version="4.0" >
+ <class>ExternalProcessing</class>
+ <widget class="QDialog" name="ExternalProcessing" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>430</width>
+    <height>269</height>
+   </rect>
+  </property>
+  <property name="minimumSize" >
+   <size>
+    <width>380</width>
+    <height>0</height>
+   </size>
+  </property>
+  <property name="maximumSize" >
+   <size>
+    <width>460</width>
+    <height>400</height>
+   </size>
+  </property>
+  <property name="windowTitle" >
+   <string>External Processing</string>
+  </property>
+  <layout class="QVBoxLayout" >
+   <property name="margin" >
+    <number>9</number>
+   </property>
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <item>
+    <layout class="QHBoxLayout" >
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <item>
+      <layout class="QVBoxLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <widget class="QLabel" name="label" >
+         <property name="text" >
+          <string>Program</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLabel" name="label_2" >
+         <property name="text" >
+          <string>Arguments</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLabel" name="label_4" >
+         <property name="text" >
+          <string>Progress</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <layout class="QVBoxLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <widget class="QLineEdit" name="programLineEdit" >
+         <property name="text" >
+          <string>sox</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QLineEdit" name="argumentsLineEdit" />
+         </item>
+         <item>
+          <widget class="QComboBox" name="argsComboBox" >
+           <property name="minimumSize" >
+            <size>
+             <width>100</width>
+             <height>0</height>
+            </size>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <widget class="QProgressBar" name="progressBar" >
+         <property name="value" >
+          <number>0</number>
+         </property>
+         <property name="textVisible" >
+          <bool>true</bool>
+         </property>
+         <property name="orientation" >
+          <enum>Qt::Horizontal</enum>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" >
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <item>
+      <spacer>
+       <property name="orientation" >
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" >
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="startButton" >
+       <property name="text" >
+        <string>Start</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="cancelButton" >
+       <property name="text" >
+        <string>Cancel</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QLabel" name="label_3" >
+     <property name="text" >
+      <string>Program output</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QTextEdit" name="statusText" >
+     <property name="acceptDrops" >
+      <bool>false</bool>
+     </property>
+     <property name="textInteractionFlags" >
+      <enum>Qt::TextSelectableByMouse</enum>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>




reply via email to

[Prev in Thread] Current Thread [Next in Thread]