# HG changeset patch
# User Chris Cannam
# Date 1413286519 -3600
# Node ID db83ea0e102d3e2565d329bdca8d93924efe617f
# Parent  a1300db6c63edd6365cd9bace3c9ea55eed11460
Make the JSON well-formed (though still empty), except in the case where we are asked to write more than one file's features to the same output file or stdout

diff -r a1300db6c63e -r db83ea0e102d runner/JAMSFeatureWriter.cpp
--- a/runner/JAMSFeatureWriter.cpp	Tue Oct 14 11:27:43 2014 +0100
+++ b/runner/JAMSFeatureWriter.cpp	Tue Oct 14 12:35:19 2014 +0100
@@ -25,6 +25,7 @@
 JAMSFeatureWriter::JAMSFeatureWriter() :
     FileFeatureWriter(SupportOneFilePerTrackTransform |
                       SupportOneFilePerTrack |
+                      SupportOneFileTotal |
 		      SupportStdOut,
                       "json"),
     m_network(false),
@@ -73,10 +74,11 @@
 JAMSFeatureWriter::setTrackMetadata(QString trackId, TrackMetadata metadata)
 {
     QString json
-	("'file_metadata':"
-	 "  { 'artist': \"%1\","
-	 "    'title': \"%2\" }");
+	(" \"file_metadata\":\n"
+	 "  { \"artist\": \"%1\",\n"
+	 "    \"title\": \"%2\" },\n");
     m_metadata[trackId] = json.arg(metadata.maker).arg(metadata.title);
+    cerr << "setTrackMetadata: metadata is: " << m_metadata[trackId] << endl;
 }
 
 void
@@ -95,30 +97,66 @@
 
     QTextStream &stream = *sptr;
 
-    if (m_startedTransforms.find(transformId) == m_startedTransforms.end()) {
+    TrackTransformPair tt(trackId, transformId);
+    TrackTransformPair targetKey = getFilenameKey(trackId, transformId);
+
+    if (m_startedTargets.find(targetKey) == m_startedTargets.end()) {
+        // Need to write track-level preamble
+        stream << "{" << m_metadata[trackId] << endl;
+        m_startedTargets.insert(targetKey);
+    }
+
+    if (m_data.find(tt) == m_data.end()) {
 
 	identifyTask(transform);
 
-	if (m_manyFiles ||
-	    (m_startedTracks.find(trackId) == m_startedTracks.end())) {
-
-	    // track-level preamble
-	    stream << "{" << m_metadata[trackId] << endl;
-	}
-
-	stream << "'" << getTaskKey(m_tasks[transformId]) << "':" << endl;
-	stream << "  [ ";
+        QString json("\"%1\": [ ");
+        m_data[tt] = json.arg(getTaskKey(m_tasks[transformId]));
     }
 
-    m_startedTracks.insert(trackId);
-    m_startedTransforms.insert(transformId);
-
     for (int i = 0; i < int(features.size()); ++i) {
 	
     }	
 }
 
 void
+JAMSFeatureWriter::finish()
+{
+    cerr << "Finish called on " << this << endl;
+
+    set<QTextStream *> startedStreams;
+
+    for (DataMap::const_iterator i = m_data.begin();
+         i != m_data.end(); ++i) {
+
+        TrackTransformPair tt = i->first;
+        QString data = i->second;
+
+        QTextStream *sptr = getOutputStream(tt.first, tt.second);
+        if (!sptr) {
+            throw FailedToOpenOutputStream(tt.first, tt.second);
+        }
+
+        if (startedStreams.find(sptr) != startedStreams.end()) {
+            *sptr << "," << endl;
+        }
+        startedStreams.insert(sptr);
+        
+        *sptr << data << "]";
+    }
+        
+    for (FileStreamMap::const_iterator i = m_streams.begin();
+	 i != m_streams.end(); ++i) {
+	*(i->second) << endl << "}" << endl;
+    }
+
+    m_data.clear();
+    m_startedTargets.clear();
+
+    FileFeatureWriter::finish();
+}
+
+void
 JAMSFeatureWriter::loadRDFDescription(const Transform &transform)
 {
     QString pluginId = transform.getPluginIdentifier();
@@ -223,15 +261,3 @@
     }
     return "unknown";
 }
-
-void
-JAMSFeatureWriter::finish()
-{
-    for (FileStreamMap::const_iterator i = m_streams.begin();
-	 i != m_streams.end(); ++i) {
-	*(i->second) << "}" << endl;
-    }
-
-    FileFeatureWriter::finish();
-}
-
diff -r a1300db6c63e -r db83ea0e102d runner/JAMSFeatureWriter.h
--- a/runner/JAMSFeatureWriter.h	Tue Oct 14 11:27:43 2014 +0100
+++ b/runner/JAMSFeatureWriter.h	Tue Oct 14 12:35:19 2014 +0100
@@ -65,13 +65,14 @@
     typedef map<QString, QString> TrackMetadataMap; // track id -> json object
     TrackMetadataMap m_metadata;
 
+    typedef map<TrackTransformPair, QString> DataMap;
+    DataMap m_data;
+
     typedef map<QString, Task> TaskMap; // by transform id
     TaskMap m_tasks;
 
-    //!!! no -- need to map track-transform (could have same transform for many tracks)
-    typedef set<QString> StartedSet; // transform or track id
-    StartedSet m_startedTracks;
-    StartedSet m_startedTransforms;
+    typedef set<TrackTransformPair> StartedSet;
+    StartedSet m_startedTargets;
 
     void loadRDFDescription(const Transform &);
     void identifyTask(const Transform &);
diff -r a1300db6c63e -r db83ea0e102d runner/MIDIFeatureWriter.cpp
--- a/runner/MIDIFeatureWriter.cpp	Tue Oct 14 11:27:43 2014 +0100
+++ b/runner/MIDIFeatureWriter.cpp	Tue Oct 14 12:35:19 2014 +0100
@@ -166,6 +166,8 @@
 	}
     }
 
+    m_notes.clear();
+
     FileFeatureWriter::finish();
 }
 
diff -r a1300db6c63e -r db83ea0e102d tests/test-json-destinations/test-json-destinations.sh
--- a/tests/test-json-destinations/test-json-destinations.sh	Tue Oct 14 11:27:43 2014 +0100
+++ b/tests/test-json-destinations/test-json-destinations.sh	Tue Oct 14 12:35:19 2014 +0100
@@ -80,10 +80,10 @@
 
 ctx="onsets transform, two audio files, one-file JSON writer"
 
-# Does not support one file across all tracks
+$r -t $transformdir/onsets.n3 -w json --json-one-file $tmpjson $infile1 $infile2 2>/dev/null || \
+    fail "Fails to run with $ctx"
 
-$r -t $transformdir/onsets.n3 -w json --json-one-file $tmpjson $infile1 $infile2 2>/dev/null && \
-    fail "Fails by completing successfully with $ctx"
+check_json $tmpjson "$ctx"
 
 
 ctx="onsets transform, two audio files, stdout JSON writer"