changeset 325:d5caf5e91a86 default-writer-writes-to-files

If the default writer were to be able to write to files (but this is backward-incompatible so probably unwise)
author Chris Cannam
date Fri, 18 May 2018 12:36:48 +0100
parents ef03350baec7
children
files runner/DefaultFeatureWriter.cpp runner/DefaultFeatureWriter.h tests/test-as-advertised/test-as-advertised.sh
diffstat 3 files changed, 97 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/runner/DefaultFeatureWriter.cpp	Fri May 18 11:27:02 2018 +0100
+++ b/runner/DefaultFeatureWriter.cpp	Fri May 18 12:36:48 2018 +0100
@@ -20,63 +20,110 @@
 
 #include "DefaultFeatureWriter.h"
 
+#include <QTextStream>
+#include <QTextCodec>
+
+DefaultFeatureWriter::DefaultFeatureWriter() :
+    FileFeatureWriter(SupportStdOut,
+                      "xml")
+{
+}
+
+DefaultFeatureWriter::~DefaultFeatureWriter()
+{
+}
+
 string
 DefaultFeatureWriter::getDescription() const
 {
     return "Write features in a generic XML format, with <feature> or <summary> elements containing output name and some or all of timestamp, duration, values, and label.";
 }
 
-void DefaultFeatureWriter::write(QString,
-                                 const Transform &,
+static QString
+toQStringAsStream(const RealTime &rt)
+{
+    // just for historical compatibility, get the same formatting as
+    // when streaming to an iostream
+    std::stringstream out;
+    out << rt;
+    std::string s = out.str();
+    return QString::fromStdString(s);
+}
+
+void DefaultFeatureWriter::write(QString trackId,
+                                 const Transform &transform,
                                  const Vamp::Plugin::OutputDescriptor& output,
-                                 const Vamp::Plugin::FeatureList& featureList,
+                                 const Vamp::Plugin::FeatureList& features,
                                  std::string summaryType)
 {
-    // generic XML output
+    // Select appropriate output file for our track/transform
+    // combination
+
+    TransformId transformId = transform.getIdentifier();
+
+    QTextStream *sptr = getOutputStream
+        (trackId, transformId, QTextCodec::codecForName("UTF-8"));
+    if (!sptr) {
+        throw FailedToOpenOutputStream(trackId, transformId);
+    }
+
+    QTextStream &stream = *sptr;
+
+    int n = int(features.size());
+
+    if (n == 0) return;
     
-    /*
+    /* we write a generic XML output of the form
      
-     <feature>
-        <name>output.name</name>
-        <timestamp>feature.timestamp</timestamp>    
-        <values>output.binName[0]:feature.value[0]...</values>
-        <label>feature.label</label>
-     </feature>
-     
+       <feature>
+          <name>output.name</name>
+          <timestamp>feature.timestamp</timestamp>    
+          <values>output.binName[0]:feature.value[0]...</values>
+          <label>feature.label</label>
+       </feature>
      */
     
-    for (int i = 0; i < (int)featureList.size(); ++i) {
-
+    for (int i = 0; i < n; ++i) {
         if (summaryType == "") {
-            cout << "<feature>" << endl;
+            stream << "<feature>" << endl;
         } else {
-            cout << "<summary type=\"" << summaryType << "\">" << endl;
+            stream << "<summary type=\"" << QString::fromStdString(summaryType)
+                   << "\">" << endl;
         }
-        cout << "\t<name>" << output.name << "</name>" << endl;
-        if (featureList[i].hasTimestamp) {
-            cout << "\t<timestamp>" << featureList[i].timestamp << "</timestamp>" << endl;    
+        stream << "\t<name>" << QString::fromStdString(output.name)
+               << "</name>" << endl;
+        if (features[i].hasTimestamp) {
+            stream << "\t<timestamp>"
+                   << toQStringAsStream(features[i].timestamp)
+                   << "</timestamp>" << endl;    
         }
-        if (featureList[i].hasDuration) {
-            cout << "\t<duration>" << featureList[i].duration << "</duration>" << endl;    
+        if (features[i].hasDuration) {
+            stream << "\t<duration>"
+                   << toQStringAsStream(features[i].duration)
+                   << "</duration>" << endl;    
         }
-        if (featureList[i].values.size() > 0)
+        if (features[i].values.size() > 0)
         {
-            cout << "\t<values>";
-            for (int j = 0; j < (int)featureList[i].values.size(); ++j) {
-                if (j > 0)
-                    cout << " ";
-                if (output.binNames.size() > 0)
-                    cout << output.binNames[j] << ":";
-                cout << featureList[i].values[j];
+            stream << "\t<values>";
+            for (int j = 0; j < (int)features[i].values.size(); ++j) {
+                if (j > 0) {
+                    stream << " ";
+                }
+                if (output.binNames.size() > 0) {
+                    stream << QString::fromStdString(output.binNames[j]) << ":";
+                }
+                stream << features[i].values[j];
             }
-            cout << "</values>" << endl;
+            stream << "</values>" << endl;
         }
-        if (featureList[i].label.length() > 0)
-            cout << "\t<label>" << featureList[i].label << "</label>" << endl;            
+        if (features[i].label.length() > 0)
+            stream << "\t<label>"
+                   << QString::fromStdString(features[i].label)
+                   << "</label>" << endl;
         if (summaryType == "") {
-            cout << "</feature>" << endl;
+            stream << "</feature>" << endl;
         } else {
-            cout << "</summary>" << endl;
+            stream << "</summary>" << endl;
         }
     }
 }
--- a/runner/DefaultFeatureWriter.h	Fri May 18 11:27:02 2018 +0100
+++ b/runner/DefaultFeatureWriter.h	Fri May 18 12:36:48 2018 +0100
@@ -13,23 +13,27 @@
     COPYING included with this distribution for more information.
 */
 
-#ifndef _DEFAULT_FEATURE_WRITER_H_
-#define _DEFAULT_FEATURE_WRITER_H_
+#ifndef DEFAULT_FEATURE_WRITER_H
+#define DEFAULT_FEATURE_WRITER_H
 
+#include "transform/FileFeatureWriter.h"
 
-#include "transform/FeatureWriter.h"
-
-class DefaultFeatureWriter : public FeatureWriter
+class DefaultFeatureWriter : public FileFeatureWriter
 {
 public:
-    virtual ~DefaultFeatureWriter() { }
+    DefaultFeatureWriter();
+    virtual ~DefaultFeatureWriter();
+    
     virtual string getDescription() const;
+
     virtual void write(QString trackid,
                        const Transform &transform,
                        const Vamp::Plugin::OutputDescriptor &output,
                        const Vamp::Plugin::FeatureList &features,
                        std::string summaryType = "");
+    
     virtual void finish() { }
+    
     virtual QString getWriterTag() const { return "default"; }
 };
 
--- a/tests/test-as-advertised/test-as-advertised.sh	Fri May 18 11:27:02 2018 +0100
+++ b/tests/test-as-advertised/test-as-advertised.sh	Fri May 18 12:36:48 2018 +0100
@@ -22,10 +22,7 @@
     mkdir -p $tmpdir
     cp $infile $tmpwav
 
-    # Some of these are special cases:
-    #
-    # * The "default" writer type always prints to stdout instead of
-    # to a file.
+    # Special cases:
     #
     # * The "audiodb" writer will not print any output for features
     # that have no values (but are only point events).  I don't know
@@ -36,32 +33,28 @@
 	audiodb) 
 	    mkdir -p $adbdir
 	    $r -t $df -w $type $tmpwav --audiodb-basedir $tmpdir --audiodb-catid `basename $adbdir` 2>/dev/null || \
-		fail "Fails to run with reader type \"$type\" and default options"
-	    ;;
-	default) 
-	    $r -t $onsets -w $type $tmpwav > $tmpdir/test.out 2>/dev/null || \
-		fail "Fails to run with reader type \"$type\" and default options"
+		fail "Fails to run with writer type \"$type\" and default options"
 	    ;;
 	*)
 	    $r -t $onsets -w $type $tmpwav 2>/dev/null || \
-		fail "Fails to run with reader type \"$type\" and default options"
+		fail "Fails to run with writer type \"$type\" and default options"
 	    ;;
     esac
     newfiles=`ls $tmpdir | fgrep -v .wav`
     if [ "$type" = audiodb ]; then newfiles=`ls $adbdir`; fi
 
     [ -n "$newfiles" ] || \
-	fail "Fails to create output file for reader \"$type\" with default options"
+	fail "Fails to create output file for writer \"$type\" with default options"
 
     case `echo $newfiles | wc -w` in
 	[2-9])
 	if [ "$type" != audiodb ]; then
-	    fail "Produces more than one output file for reader \"$type\" with default options"
+	    fail "Produces more than one output file for writer \"$type\" with default options"
 	fi
 	;;
 	1)
 	if [ "$type" = audiodb ]; then
-	    fail "Produces only one output file for reader \"$type\" with default options (expected two)"
+	    fail "Produces only one output file for writer \"$type\" with default options (expected two)"
 	fi
 	;;
     esac