# HG changeset patch # User Chris Cannam # Date 1194630418 0 # Node ID 1afaf98dbf1122aab250c88f28585ce0829ad482 # Parent 13e5870040e61885bf22ba3164e7ae1329f97c1d * Factor out uses of "Sonic Visualiser" in "common" code to applicationName() * Add ability to show work title + artist in top-left of pane (thinking of Vect but may be useful in SV in future) * A few other generalisations useful for Vect diff -r 13e5870040e6 -r 1afaf98dbf11 data/fileio/AudioFileReader.h --- a/data/fileio/AudioFileReader.h Wed Nov 07 14:53:12 2007 +0000 +++ b/data/fileio/AudioFileReader.h Fri Nov 09 17:46:58 2007 +0000 @@ -47,6 +47,13 @@ */ virtual QString getTitle() const { return ""; } + /** + * Return the "maker" of the work in the audio file, if known. + * This could represent almost anything (band, composer, + * conductor, artist etc). + */ + virtual QString getMaker() const { return ""; } + /** * Return interleaved samples for count frames from index start. * The resulting sample block will contain count * diff -r 13e5870040e6 -r 1afaf98dbf11 data/fileio/MP3FileReader.cpp --- a/data/fileio/MP3FileReader.cpp Wed Nov 07 14:53:12 2007 +0000 +++ b/data/fileio/MP3FileReader.cpp Fri Nov 09 17:46:58 2007 +0000 @@ -168,48 +168,12 @@ return; } - id3_frame *frame = id3_tag_findframe(tag, "TIT2", 0); // work title - if (!frame) { -#ifdef DEBUG_ID3TAG - std::cerr << "MP3FileReader::loadTags: No work title in ID3 tag" << std::endl; -#endif - id3_file_close(file); - return; - } - - if (frame->nfields < 2) { - std::cerr << "MP3FileReader::loadTags: WARNING: Not enough fields (" << frame->nfields << ") for work title in ID3 tag" << std::endl; - id3_file_close(file); - return; - } + m_title = loadTag(tag, "TIT2"); // work title + if (m_title == "") m_title = loadTag(tag, "TIT1"); - unsigned int nstrings = id3_field_getnstrings(&frame->fields[1]); - if (nstrings == 0) { -#ifdef DEBUG_ID3TAG - std::cerr << "MP3FileReader::loadTags: No data for work title in ID3 tag" << std::endl; -#endif - id3_file_close(file); - return; - } + m_maker = loadTag(tag, "TPE1"); // "lead artist" + if (m_maker == "") m_maker = loadTag(tag, "TPE2"); - id3_ucs4_t const *ustr = id3_field_getstrings(&frame->fields[1], 0); - if (!ustr) { -#ifdef DEBUG_ID3TAG - std::cerr << "MP3FileReader::loadTags: Invalid or absent data for work title in ID3 tag" << std::endl; -#endif - id3_file_close(file); - return; - } - - id3_utf8_t *u8str = id3_ucs4_utf8duplicate(ustr); - if (!u8str) { - std::cerr << "MP3FileReader::loadTags: ERROR: Internal error: Failed to convert UCS4 to UTF8 in ID3 title" << std::endl; - id3_file_close(file); - return; - } - - m_title = QString::fromUtf8((const char *)u8str); - free(u8str); id3_file_close(file); #else @@ -218,7 +182,56 @@ << std::endl; #endif #endif +} +QString +MP3FileReader::loadTag(void *vtag, const char *name) +{ +#ifdef HAVE_ID3TAG + id3_tag *tag = (id3_tag *)vtag; + + id3_frame *frame = id3_tag_findframe(tag, name, 0); + if (!frame) { +#ifdef DEBUG_ID3TAG + std::cerr << "MP3FileReader::loadTags: No \"" << name << "\" in ID3 tag" << std::endl; +#endif + return ""; + } + + if (frame->nfields < 2) { + std::cerr << "MP3FileReader::loadTags: WARNING: Not enough fields (" << frame->nfields << ") for \"" << name << "\" in ID3 tag" << std::endl; + return ""; + } + + unsigned int nstrings = id3_field_getnstrings(&frame->fields[1]); + if (nstrings == 0) { +#ifdef DEBUG_ID3TAG + std::cerr << "MP3FileReader::loadTags: No data for \"" << name << "\" in ID3 tag" << std::endl; +#endif + return ""; + } + + id3_ucs4_t const *ustr = id3_field_getstrings(&frame->fields[1], 0); + if (!ustr) { +#ifdef DEBUG_ID3TAG + std::cerr << "MP3FileReader::loadTags: Invalid or absent data for \"" << name << "\" in ID3 tag" << std::endl; +#endif + return ""; + } + + id3_utf8_t *u8str = id3_ucs4_utf8duplicate(ustr); + if (!u8str) { + std::cerr << "MP3FileReader::loadTags: ERROR: Internal error: Failed to convert UCS4 to UTF8 in ID3 title" << std::endl; + return ""; + } + + QString rv = QString::fromUtf8((const char *)u8str); + free(u8str); + return rv; + +#else + return ""; +#endif } void diff -r 13e5870040e6 -r 1afaf98dbf11 data/fileio/MP3FileReader.h --- a/data/fileio/MP3FileReader.h Wed Nov 07 14:53:12 2007 +0000 +++ b/data/fileio/MP3FileReader.h Fri Nov 09 17:46:58 2007 +0000 @@ -61,6 +61,7 @@ QString m_path; QString m_error; QString m_title; + QString m_maker; size_t m_fileSize; double m_bitrateNum; size_t m_bitrateDenom; @@ -101,6 +102,7 @@ DecodeThread *m_decodeThread; void loadTags(); + QString loadTag(void *vtag, const char *name); }; #endif diff -r 13e5870040e6 -r 1afaf98dbf11 data/fileio/OggVorbisFileReader.cpp --- a/data/fileio/OggVorbisFileReader.cpp Wed Nov 07 14:53:12 2007 +0000 +++ b/data/fileio/OggVorbisFileReader.cpp Fri Nov 09 17:46:58 2007 +0000 @@ -173,10 +173,19 @@ OggVorbisFileReader *reader = (OggVorbisFileReader *)data; if (!reader->m_commentsRead) { - const FishSoundComment *comment = fish_sound_comment_first_byname - (fs, "TITLE"); - if (comment && comment->value) { - reader->m_title = QString::fromUtf8(comment->value); + { + const FishSoundComment *comment = fish_sound_comment_first_byname + (fs, "TITLE"); + if (comment && comment->value) { + reader->m_title = QString::fromUtf8(comment->value); + } + } + { + const FishSoundComment *comment = fish_sound_comment_first_byname + (fs, "ARTIST"); + if (comment && comment->value) { + reader->m_maker = QString::fromUtf8(comment->value); + } } reader->m_commentsRead = true; } diff -r 13e5870040e6 -r 1afaf98dbf11 data/fileio/OggVorbisFileReader.h --- a/data/fileio/OggVorbisFileReader.h Wed Nov 07 14:53:12 2007 +0000 +++ b/data/fileio/OggVorbisFileReader.h Fri Nov 09 17:46:58 2007 +0000 @@ -46,6 +46,7 @@ virtual QString getError() const { return m_error; } virtual QString getTitle() const { return m_title; } + virtual QString getMaker() const { return m_maker; } static void getSupportedExtensions(std::set &extensions); static bool supportsExtension(QString ext); @@ -63,6 +64,7 @@ QString m_path; QString m_error; QString m_title; + QString m_maker; OGGZ *m_oggz; FishSound *m_fishSound; diff -r 13e5870040e6 -r 1afaf98dbf11 data/fileio/QuickTimeFileReader.cpp --- a/data/fileio/QuickTimeFileReader.cpp Wed Nov 07 14:53:12 2007 +0000 +++ b/data/fileio/QuickTimeFileReader.cpp Fri Nov 09 17:46:58 2007 +0000 @@ -26,7 +26,7 @@ #include #include -#ifdef WIN32 +#ifdef _WIN32 #include #include #else diff -r 13e5870040e6 -r 1afaf98dbf11 data/model/AlignmentModel.cpp --- a/data/model/AlignmentModel.cpp Wed Nov 07 14:53:12 2007 +0000 +++ b/data/model/AlignmentModel.cpp Fri Nov 09 17:46:58 2007 +0000 @@ -150,8 +150,8 @@ if (!m_pathComplete) { int completion = 0; m_path->isReady(&completion); - std::cerr << "AlignmentModel::pathCompletionChanged: completion = " - << completion << std::endl; +// std::cerr << "AlignmentModel::pathCompletionChanged: completion = " +// << completion << std::endl; m_pathComplete = (completion == 100); if (m_pathComplete) { constructReversePath(); diff -r 13e5870040e6 -r 1afaf98dbf11 data/model/EditableDenseThreeDimensionalModel.cpp --- a/data/model/EditableDenseThreeDimensionalModel.cpp Wed Nov 07 14:53:12 2007 +0000 +++ b/data/model/EditableDenseThreeDimensionalModel.cpp Fri Nov 09 17:46:58 2007 +0000 @@ -244,7 +244,7 @@ } void -EditableDenseThreeDimensionalModel::setCompletion(int completion) +EditableDenseThreeDimensionalModel::setCompletion(int completion, bool update) { if (m_completion != completion) { m_completion = completion; @@ -256,7 +256,8 @@ } else if (!m_notifyOnAdd) { - if (m_sinceLastNotifyMin >= 0 && + if (update && + m_sinceLastNotifyMin >= 0 && m_sinceLastNotifyMax >= 0) { emit modelChanged(m_sinceLastNotifyMin, m_sinceLastNotifyMax + m_resolution); diff -r 13e5870040e6 -r 1afaf98dbf11 data/model/EditableDenseThreeDimensionalModel.h --- a/data/model/EditableDenseThreeDimensionalModel.h Wed Nov 07 14:53:12 2007 +0000 +++ b/data/model/EditableDenseThreeDimensionalModel.h Fri Nov 09 17:46:58 2007 +0000 @@ -106,7 +106,7 @@ virtual void setBinName(size_t n, QString); virtual void setBinNames(std::vector names); - virtual void setCompletion(int completion); + virtual void setCompletion(int completion, bool update = true); virtual int getCompletion() const { return m_completion; } virtual QString toDelimitedDataString(QString delimiter) const; diff -r 13e5870040e6 -r 1afaf98dbf11 data/model/Model.cpp --- a/data/model/Model.cpp Wed Nov 07 14:53:12 2007 +0000 +++ b/data/model/Model.cpp Fri Nov 09 17:46:58 2007 +0000 @@ -56,6 +56,8 @@ m_sourceModel = model; if (m_sourceModel) { + connect(m_sourceModel, SIGNAL(alignmentCompletionChanged()), + this, SIGNAL(alignmentCompletionChanged())); connect(m_sourceModel, SIGNAL(aboutToBeDeleted()), this, SLOT(sourceModelAboutToBeDeleted())); } @@ -96,35 +98,64 @@ const Model * Model::getAlignmentReference() const { - if (!m_alignment) return this; + if (!m_alignment) { + if (m_sourceModel) return m_sourceModel->getAlignmentReference(); + return this; + } return m_alignment->getReferenceModel(); } size_t Model::alignToReference(size_t frame) const { - if (!m_alignment) return frame; - return m_alignment->toReference(frame); + if (!m_alignment) { + if (m_sourceModel) return m_sourceModel->alignToReference(frame); + else return frame; + } + size_t refFrame = m_alignment->toReference(frame); + //!!! this should be totally wrong, but because alignToReference and + // alignFromReference are the wrong way around, it's right... *sigh* + if (refFrame > getEndFrame()) refFrame = getEndFrame(); + return refFrame; } size_t Model::alignFromReference(size_t refFrame) const { - if (!m_alignment) return refFrame; - return m_alignment->fromReference(refFrame); + if (!m_alignment) { + if (m_sourceModel) return m_sourceModel->alignFromReference(refFrame); + else return refFrame; + } + size_t frame = m_alignment->fromReference(refFrame); + return frame; } int Model::getAlignmentCompletion() const { // std::cerr << "Model::getAlignmentCompletion" << std::endl; - if (!m_alignment) return 100; + if (!m_alignment) { + if (m_sourceModel) return m_sourceModel->getAlignmentCompletion(); + else return 100; + } int completion = 0; (void)m_alignment->isReady(&completion); // std::cerr << " -> " << completion << std::endl; return completion; } +QString +Model::getTitle() const +{ + if (m_sourceModel) return m_sourceModel->getTitle(); +} + +QString +Model::getMaker() const +{ + if (m_sourceModel) return m_sourceModel->getMaker(); +} + void Model::toXml(QTextStream &stream, QString indent, QString extraAttributes) const diff -r 13e5870040e6 -r 1afaf98dbf11 data/model/Model.h --- a/data/model/Model.h Wed Nov 07 14:53:12 2007 +0000 +++ b/data/model/Model.h Fri Nov 09 17:46:58 2007 +0000 @@ -67,6 +67,16 @@ virtual size_t getNativeRate() const { return getSampleRate(); } /** + * Return the "work title" of the model, if known. + */ + virtual QString getTitle() const; + + /** + * Return the "artist" or "maker" of the model, if known. + */ + virtual QString getMaker() const; + + /** * Return a copy of this model. * * If the model is not editable, this may be effectively a shallow diff -r 13e5870040e6 -r 1afaf98dbf11 data/model/SparseModel.h --- a/data/model/SparseModel.h Wed Nov 07 14:53:12 2007 +0000 +++ b/data/model/SparseModel.h Fri Nov 09 17:46:58 2007 +0000 @@ -127,7 +127,7 @@ return ready; } - virtual void setCompletion(int completion); + virtual void setCompletion(int completion, bool update = true); virtual int getCompletion() const { return m_completion; } virtual bool hasTextLabels() const { return m_hasTextLabels; } @@ -511,7 +511,7 @@ template void -SparseModel::setCompletion(int completion) +SparseModel::setCompletion(int completion, bool update) { // std::cerr << "SparseModel::setCompletion(" << completion << ")" << std::endl; @@ -529,7 +529,8 @@ } else if (!m_notifyOnAdd) { - if (m_sinceLastNotifyMin >= 0 && + if (update && + m_sinceLastNotifyMin >= 0 && m_sinceLastNotifyMax >= 0) { emit modelChanged(m_sinceLastNotifyMin, m_sinceLastNotifyMax); m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1; diff -r 13e5870040e6 -r 1afaf98dbf11 data/model/WaveFileModel.cpp --- a/data/model/WaveFileModel.cpp Wed Nov 07 14:53:12 2007 +0000 +++ b/data/model/WaveFileModel.cpp Fri Nov 09 17:46:58 2007 +0000 @@ -158,6 +158,22 @@ return rate; } +QString +WaveFileModel::getTitle() const +{ + QString title; + if (m_reader) title = m_reader->getTitle(); + if (title == "") title = objectName(); + return title; +} + +QString +WaveFileModel::getMaker() const +{ + if (m_reader) return m_reader->getMaker(); + return ""; +} + size_t WaveFileModel::getData(int channel, size_t start, size_t count, float *buffer) const diff -r 13e5870040e6 -r 1afaf98dbf11 data/model/WaveFileModel.h --- a/data/model/WaveFileModel.h Wed Nov 07 14:53:12 2007 +0000 +++ b/data/model/WaveFileModel.h Fri Nov 09 17:46:58 2007 +0000 @@ -48,6 +48,9 @@ size_t getSampleRate() const; size_t getNativeRate() const; + QString getTitle() const; + QString getMaker() const; + virtual Model *clone() const; float getValueMinimum() const { return -1.0f; } diff -r 13e5870040e6 -r 1afaf98dbf11 plugin/transform/FeatureExtractionModelTransformer.cpp --- a/plugin/transform/FeatureExtractionModelTransformer.cpp Wed Nov 07 14:53:12 2007 +0000 +++ b/plugin/transform/FeatureExtractionModelTransformer.cpp Fri Nov 09 17:46:58 2007 +0000 @@ -216,6 +216,8 @@ m_output = model; } + + if (m_output) m_output->setSourceModel(m_input); } FeatureExtractionModelTransformer::~FeatureExtractionModelTransformer() @@ -527,27 +529,27 @@ SparseOneDimensionalModel *model = getOutput(); if (!model) return; - model->setCompletion(completion); + model->setCompletion(completion, m_context.updates); } else if (binCount == 1) { SparseTimeValueModel *model = getOutput(); if (!model) return; - model->setCompletion(completion); + model->setCompletion(completion, m_context.updates); } else if (m_descriptor->sampleType == Vamp::Plugin::OutputDescriptor::VariableSampleRate) { NoteModel *model = getOutput(); if (!model) return; - model->setCompletion(completion); + model->setCompletion(completion, m_context.updates); } else { EditableDenseThreeDimensionalModel *model = getOutput(); if (!model) return; - model->setCompletion(completion); + model->setCompletion(completion, m_context.updates); } } diff -r 13e5870040e6 -r 1afaf98dbf11 plugin/transform/PluginTransformer.cpp --- a/plugin/transform/PluginTransformer.cpp Wed Nov 07 14:53:12 2007 +0000 +++ b/plugin/transform/PluginTransformer.cpp Fri Nov 09 17:46:58 2007 +0000 @@ -33,7 +33,8 @@ windowType(HanningWindow), startFrame(0), duration(0), - sampleRate(0) + sampleRate(0), + updates(true) { } @@ -46,7 +47,8 @@ windowType(_wt), startFrame(0), duration(0), - sampleRate(0) + sampleRate(0), + updates(true) { } diff -r 13e5870040e6 -r 1afaf98dbf11 plugin/transform/PluginTransformer.h --- a/plugin/transform/PluginTransformer.h Wed Nov 07 14:53:12 2007 +0000 +++ b/plugin/transform/PluginTransformer.h Fri Nov 09 17:46:58 2007 +0000 @@ -51,6 +51,7 @@ size_t startFrame; size_t duration; // 0 -> whole thing float sampleRate; // 0 -> model's rate + bool updates; }; protected: diff -r 13e5870040e6 -r 1afaf98dbf11 plugin/transform/TransformFactory.cpp --- a/plugin/transform/TransformFactory.cpp Wed Nov 07 14:53:12 2007 +0000 +++ b/plugin/transform/TransformFactory.cpp Fri Nov 09 17:46:58 2007 +0000 @@ -426,6 +426,7 @@ bool TransformFactory::haveTransform(TransformId identifier) { + if (m_transforms.empty()) populateTransforms(); return (m_transforms.find(identifier) != m_transforms.end()); }