changeset 1170:6877f4200912 3.0-integration

Merge from default branch
author Chris Cannam
date Wed, 02 Mar 2016 16:16:36 +0000
parents ea636412f9fe (current diff) 134ce7667256 (diff)
children abb78e824820
files data/fileio/AudioFileReaderFactory.cpp data/fileio/CodedAudioFileReader.cpp data/fileio/WavFileReader.cpp plugin/FeatureExtractionPluginFactory.cpp transform/TransformFactory.cpp
diffstat 12 files changed, 181 insertions(+), 47 deletions(-) [+]
line wrap: on
line diff
--- a/acinclude.m4	Thu Feb 04 11:16:05 2016 +0000
+++ b/acinclude.m4	Wed Mar 02 16:16:36 2016 +0000
@@ -69,6 +69,9 @@
    	AC_CHECK_PROG(QMAKE, qmake-qt5, $QTDIR/bin/qmake-qt5,,$QTDIR/bin/)
 fi
 if test x$QMAKE = x ; then
+   	AC_CHECK_PROG(QMAKE, qt5-qmake, $QTDIR/bin/qt5-qmake,,$QTDIR/bin/)
+fi
+if test x$QMAKE = x ; then
    	AC_CHECK_PROG(QMAKE, qmake, $QTDIR/bin/qmake,,$QTDIR/bin/)
 fi
 if test x$QMAKE = x ; then
@@ -78,6 +81,9 @@
    	AC_CHECK_PROG(QMAKE, qmake-qt5, qmake-qt5,,$PATH)
 fi
 if test x$QMAKE = x ; then
+   	AC_CHECK_PROG(QMAKE, qt5-qmake, qt5-qmake,,$PATH)
+fi
+if test x$QMAKE = x ; then
    	AC_CHECK_PROG(QMAKE, qmake, qmake,,$PATH)
 fi
 if test x$QMAKE = x ; then
--- a/configure	Thu Feb 04 11:16:05 2016 +0000
+++ b/configure	Wed Mar 02 16:16:36 2016 +0000
@@ -4129,6 +4129,45 @@
 
 fi
 if test x$QMAKE = x ; then
+   	# Extract the first word of "qt5-qmake", so it can be a program name with args.
+set dummy qt5-qmake; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_QMAKE+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$QMAKE"; then
+  ac_cv_prog_QMAKE="$QMAKE" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $QTDIR/bin/
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_QMAKE="$QTDIR/bin/qt5-qmake"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+QMAKE=$ac_cv_prog_QMAKE
+if test -n "$QMAKE"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $QMAKE" >&5
+$as_echo "$QMAKE" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test x$QMAKE = x ; then
    	# Extract the first word of "qmake", so it can be a program name with args.
 set dummy qmake; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
@@ -4246,6 +4285,45 @@
 
 fi
 if test x$QMAKE = x ; then
+   	# Extract the first word of "qt5-qmake", so it can be a program name with args.
+set dummy qt5-qmake; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_QMAKE+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$QMAKE"; then
+  ac_cv_prog_QMAKE="$QMAKE" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_QMAKE="qt5-qmake"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+QMAKE=$ac_cv_prog_QMAKE
+if test -n "$QMAKE"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $QMAKE" >&5
+$as_echo "$QMAKE" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test x$QMAKE = x ; then
    	# Extract the first word of "qmake", so it can be a program name with args.
 set dummy qmake; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
--- a/data/fileio/AudioFileReaderFactory.cpp	Thu Feb 04 11:16:05 2016 +0000
+++ b/data/fileio/AudioFileReaderFactory.cpp	Wed Mar 02 16:16:36 2016 +0000
@@ -29,6 +29,8 @@
 #include <QFileInfo>
 #include <iostream>
 
+//#define DEBUG_AUDIO_FILE_READER_FACTORY 1
+
 QString
 AudioFileReaderFactory::getKnownExtensions()
 {
@@ -87,7 +89,9 @@
 {
     QString err;
 
-    SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\"): Requested rate: " << targetRate << endl;
+#ifdef DEBUG_AUDIO_FILE_READER_FACTORY
+    cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\"): Requested rate: " << targetRate << endl;
+#endif
 
     if (!source.isOK()) {
         cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Failed to retrieve source (transmission error?): " << source.getErrorString() << endl;
@@ -95,7 +99,7 @@
     }
 
     if (!source.isAvailable()) {
-        SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Source not found" << endl;
+        cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Source not found" << endl;
         return 0;
     }
 
@@ -139,8 +143,10 @@
              (cacheMode == CodedAudioFileReader::CacheInMemory) ||
              (targetRate != 0 && fileRate != targetRate))) {
 
-            SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", in memory " << (cacheMode == CodedAudioFileReader::CacheInMemory) << ", creating decoding reader" << endl;
-
+#ifdef DEBUG_AUDIO_FILE_READER_FACTORY
+            cerr << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", in memory " << (cacheMode == CodedAudioFileReader::CacheInMemory) << ", creating decoding reader" << endl;
+#endif
+            
             delete reader;
             reader = new DecodingWavFileReader
                 (source,
@@ -208,7 +214,9 @@
          (cacheMode == CodedAudioFileReader::CacheInMemory) ||
          (targetRate != 0 && fileRate != targetRate))) {
 
-        SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", in memory " << (cacheMode == CodedAudioFileReader::CacheInMemory) << ", creating decoding reader" << endl;
+#ifdef DEBUG_AUDIO_FILE_READER_FACTORY
+        cerr << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", in memory " << (cacheMode == CodedAudioFileReader::CacheInMemory) << ", creating decoding reader" << endl;
+#endif
 
         delete reader;
         reader = new DecodingWavFileReader
--- a/data/fileio/CodedAudioFileReader.cpp	Thu Feb 04 11:16:05 2016 +0000
+++ b/data/fileio/CodedAudioFileReader.cpp	Wed Mar 02 16:16:36 2016 +0000
@@ -146,11 +146,27 @@
             }
             fileInfo.samplerate = fileRate;
             fileInfo.channels = m_channelCount;
-            
-            // No point in writing 24-bit or float; generally this
-            // class is used for decoding files that have come from a
-            // 16 bit source or that decode to only 16 bits anyway.
-            fileInfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
+
+            // Previously we were writing SF_FORMAT_PCM_16 and in a
+            // comment I wrote: "No point in writing 24-bit or float;
+            // generally this class is used for decoding files that
+            // have come from a 16 bit source or that decode to only
+            // 16 bits anyway." That was naive -- we want to preserve
+            // the original values to the same float precision that we
+            // use internally. Saving PCM_16 obviously doesn't
+            // preserve values for sources at bit depths greater than
+            // 16, but it also doesn't always do so for sources at bit
+            // depths less than 16.
+            //
+            // (This came to light with a bug in libsndfile 1.0.26,
+            // which always reports every file as non-seekable, so
+            // that coded readers were being used even for WAV
+            // files. This changed the values that came from PCM_8 WAV
+            // sources, breaking Sonic Annotator's output comparison
+            // tests.)
+            //
+            // So: now we write floats.
+            fileInfo.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT;
     
             m_cacheFileWritePtr = sf_open(m_cacheFileName.toLocal8Bit(),
                                           SFM_WRITE, &fileInfo);
--- a/data/fileio/MP3FileReader.cpp	Thu Feb 04 11:16:05 2016 +0000
+++ b/data/fileio/MP3FileReader.cpp	Wed Mar 02 16:16:36 2016 +0000
@@ -32,6 +32,7 @@
 #ifdef HAVE_ID3TAG
 #include <id3tag.h>
 #endif
+
 //#define DEBUG_ID3TAG 1
 
 #include <QFileInfo>
@@ -178,7 +179,7 @@
     id3_tag *tag = id3_file_tag(file);
     if (!tag) {
 #ifdef DEBUG_ID3TAG
-        SVDEBUG << "MP3FileReader::loadTags: No ID3 tag found" << endl;
+        cerr << "MP3FileReader::loadTags: No ID3 tag found" << endl;
 #endif
         id3_file_close(file);
         return;
@@ -201,7 +202,7 @@
 
 #else
 #ifdef DEBUG_ID3TAG
-    SVDEBUG << "MP3FileReader::loadTags: ID3 tag support not compiled in"
+    cerr << "MP3FileReader::loadTags: ID3 tag support not compiled in"
               << endl;
 #endif
 #endif
@@ -216,20 +217,20 @@
     id3_frame *frame = id3_tag_findframe(tag, name, 0);
     if (!frame) {
 #ifdef DEBUG_ID3TAG
-        SVDEBUG << "MP3FileReader::loadTags: No \"" << name << "\" in ID3 tag" << endl;
+        cerr << "MP3FileReader::loadTags: No \"" << name << "\" in ID3 tag" << endl;
 #endif
         return "";
     }
         
     if (frame->nfields < 2) {
-        SVDEBUG << "MP3FileReader::loadTags: WARNING: Not enough fields (" << frame->nfields << ") for \"" << name << "\" in ID3 tag" << endl;
+        cerr << "MP3FileReader::loadTags: WARNING: Not enough fields (" << frame->nfields << ") for \"" << name << "\" in ID3 tag" << endl;
         return "";
     }
 
     unsigned int nstrings = id3_field_getnstrings(&frame->fields[1]);
     if (nstrings == 0) {
 #ifdef DEBUG_ID3TAG
-        SVDEBUG << "MP3FileReader::loadTags: No strings for \"" << name << "\" in ID3 tag" << endl;
+        cerr << "MP3FileReader::loadTags: No strings for \"" << name << "\" in ID3 tag" << endl;
 #endif
         return "";
     }
@@ -237,7 +238,7 @@
     id3_ucs4_t const *ustr = id3_field_getstrings(&frame->fields[1], 0);
     if (!ustr) {
 #ifdef DEBUG_ID3TAG
-        SVDEBUG << "MP3FileReader::loadTags: Invalid or absent data for \"" << name << "\" in ID3 tag" << endl;
+        cerr << "MP3FileReader::loadTags: Invalid or absent data for \"" << name << "\" in ID3 tag" << endl;
 #endif
         return "";
     }
@@ -252,7 +253,7 @@
     free(u8str);
 
 #ifdef DEBUG_ID3TAG
-	SVDEBUG << "MP3FileReader::loadTags: tag \"" << name << "\" -> \""
+	cerr << "MP3FileReader::loadTags: tag \"" << name << "\" -> \""
 	<< rv << "\"" << endl;
 #endif
 
--- a/data/fileio/WavFileReader.cpp	Thu Feb 04 11:16:05 2016 +0000
+++ b/data/fileio/WavFileReader.cpp	Wed Mar 02 16:16:36 2016 +0000
@@ -62,20 +62,26 @@
 
         m_seekable = (m_fileInfo.seekable != 0);
 
-        // Our m_seekable reports whether a file is rapidly seekable,
-        // so things like Ogg don't qualify. We cautiously report
-        // every file type of "at least" the historical period of Ogg
-        // or FLAC as non-seekable.
         int type = m_fileInfo.format & SF_FORMAT_TYPEMASK;
-//        cerr << "WavFileReader: format type is " << type << " (flac, ogg are " << SF_FORMAT_FLAC << ", " << SF_FORMAT_OGG << ")" << endl;
+        int subtype = m_fileInfo.format & SF_FORMAT_SUBMASK;
+
         if (type >= SF_FORMAT_FLAC || type >= SF_FORMAT_OGG) {
-//            cerr << "WavFileReader: Recording as non-seekable" << endl;
+            // Our m_seekable reports whether a file is rapidly
+            // seekable, so things like Ogg don't qualify. We
+            // cautiously report every file type of "at least" the
+            // historical period of Ogg or FLAC as non-seekable.
             m_seekable = false;
+        } else if (type == SF_FORMAT_WAV && subtype <= SF_FORMAT_DOUBLE) {
+            // libsndfile 1.0.26 has a bug (subsequently fixed in the
+            // repo) that causes all files to be reported as
+            // non-seekable. We know that certain common file types
+            // are definitely seekable so, again cautiously, identify
+            // and mark those (basically only non-adaptive WAVs).
+            m_seekable = true;
         }
     }
 
-//    cerr << "WavFileReader: Frame count " << m_frameCount << ", channel count " << m_channelCount << ", sample rate " << m_sampleRate << ", seekable " << m_seekable << endl;
-
+//    cerr << "WavFileReader: Filename " << m_path << ", frame count " << m_frameCount << ", channel count " << m_channelCount << ", sample rate " << m_sampleRate << ", format " << m_fileInfo.format << ", seekable " << m_fileInfo.seekable << " adjusted to " << m_seekable << endl;
 }
 
 WavFileReader::~WavFileReader()
--- a/plugin/FeatureExtractionPluginFactory.cpp	Thu Feb 04 11:16:05 2016 +0000
+++ b/plugin/FeatureExtractionPluginFactory.cpp	Wed Mar 02 16:16:36 2016 +0000
@@ -195,10 +195,6 @@
     
     for (QString soname : candidates) {
 
-#ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
-            cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: trying potential library " << soname << endl;
-#endif
-
         void *libraryHandle = DLOPEN(soname, RTLD_LAZY | RTLD_LOCAL);
             
         if (!libraryHandle) {
@@ -206,10 +202,6 @@
             continue;
         }
 
-#ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
-            cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: It's a library all right, checking for descriptor" << endl;
-#endif
-
         VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction)
             DLSYM(libraryHandle, "vampGetPluginDescriptor");
 
@@ -260,7 +252,7 @@
                     ("vamp", soname, descriptor->identifier);
                 rv.push_back(id);
 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
-                    cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: Found plugin id " << id << " at index " << index << endl;
+                cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: Found plugin id " << id << " at index " << index << endl;
 #endif
                 ++index;
             }
--- a/rdf/RDFTransformFactory.cpp	Thu Feb 04 11:16:05 2016 +0000
+++ b/rdf/RDFTransformFactory.cpp	Wed Mar 02 16:16:36 2016 +0000
@@ -129,7 +129,12 @@
         }
         m_store->import(qurl, BasicStore::ImportIgnoreDuplicates);
         m_isRDF = true;
-    } catch (...) { }
+    } catch (const std::exception &e) {
+        // The file is not RDF -- we report this by returning false
+        // from isRDF (because we have not reached the m_isRDF = true
+        // line above), but we also set the error string
+        m_errorString = e.what();
+    }
 }
 
 RDFTransformFactoryImpl::~RDFTransformFactoryImpl()
@@ -146,7 +151,7 @@
 bool
 RDFTransformFactoryImpl::isOK()
 {
-    return (m_errorString == "");
+    return m_isRDF && (m_errorString == "");
 }
 
 QString
@@ -160,6 +165,8 @@
 {
     std::vector<Transform> transforms;
 
+    if (!m_isRDF) return transforms;
+    
     std::map<QString, Transform> uriTransformMap;
 
     Nodes tnodes = m_store->match
--- a/rdf/RDFTransformFactory.h	Thu Feb 04 11:16:05 2016 +0000
+++ b/rdf/RDFTransformFactory.h	Wed Mar 02 16:16:36 2016 +0000
@@ -36,8 +36,28 @@
     RDFTransformFactory(QString url);
     virtual ~RDFTransformFactory();
 
-    bool isRDF(); // true if the file was parseable and had transforms in it
-    bool isOK();  // true if the transforms could be completely constructed
+    /** isRDF() may be queried at any point after construction. It
+        returns true if the file was parseable as RDF.
+    */
+    bool isRDF();
+
+    /** isOK() may be queried at any point after getTransforms() has
+        been called. It is true if the file was parseable as RDF and
+        any transforms in it could be completely constructed.
+
+        Note that even if isOK() returns true, it is still possible
+        that the file did not define any transforms; in this case,
+        getTransforms() would have returned an empty list.
+
+        If isOK() is called before getTransforms() has been invoked to
+        query the file, it will return true iff isRDF() is true.
+    */
+    bool isOK();
+
+    /** Return any error string resulting from loading or querying the
+        file. This will be non-empty if isRDF() or isOK() returns
+        false.
+     */
     QString getErrorString() const;
 
     std::vector<Transform> getTransforms(ProgressReporter *reporter);
--- a/transform/CSVFeatureWriter.cpp	Thu Feb 04 11:16:05 2016 +0000
+++ b/transform/CSVFeatureWriter.cpp	Wed Mar 02 16:16:36 2016 +0000
@@ -99,10 +99,10 @@
     SVDEBUG << "CSVFeatureWriter::setParameters" << endl;
     for (map<string, string>::iterator i = params.begin();
          i != params.end(); ++i) {
-        cerr << i->first << " -> " << i->second << endl;
+        SVDEBUG << i->first << " -> " << i->second << endl;
         if (i->first == "separator") {
             m_separator = i->second.c_str();
-            cerr << "m_separator = " << m_separator << endl;
+            SVDEBUG << "m_separator = " << m_separator << endl;
             if (m_separator == "\\t") {
                 m_separator = QChar::Tabulation;
             }
--- a/transform/Transform.cpp	Thu Feb 04 11:16:05 2016 +0000
+++ b/transform/Transform.cpp	Wed Mar 02 16:16:36 2016 +0000
@@ -54,12 +54,8 @@
     int errorColumn;
 
     if (!doc.setContent(xml, false, &error, &errorLine, &errorColumn)) {
-        cerr << "Transform::Transform: Error in parsing XML: "
-                  << error << " at line " << errorLine
-                  << ", column " << errorColumn << endl;
-        cerr << "Input follows:" << endl;
-        cerr << xml << endl;
-        cerr << "Input ends." << endl;
+        m_errorString = QString("%1 at line %2, column %3")
+            .arg(error).arg(errorLine).arg(errorColumn);
         return;
     }
     
--- a/transform/Transform.h	Thu Feb 04 11:16:05 2016 +0000
+++ b/transform/Transform.h	Wed Mar 02 16:16:36 2016 +0000
@@ -46,7 +46,8 @@
 
     /**
      * Construct a Transform by parsing the given XML data string.
-     * This is the inverse of toXml.
+     * This is the inverse of toXml. If this fails, getErrorString()
+     * will return a non-empty string.
      */
     Transform(QString xml);
 
@@ -156,6 +157,8 @@
      */
     void setFromXmlAttributes(const QXmlAttributes &);
 
+    QString getErrorString() const { return m_errorString; }
+    
     static SummaryType stringToSummaryType(QString);
     static QString summaryTypeToString(SummaryType);
 
@@ -195,6 +198,7 @@
     RealTime m_startTime;
     RealTime m_duration;
     sv_samplerate_t m_sampleRate;
+    QString m_errorString;
 };
 
 typedef std::vector<Transform> Transforms;