Chris@49: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@0: Chris@0: /* Chris@0: A waveform viewer and audio annotation editor. Chris@2: Chris Cannam, Queen Mary University of London, 2005-2006 Chris@0: Chris@0: This is experimental software. Not for distribution. Chris@0: */ Chris@0: Chris@0: #include "TransformFactory.h" Chris@0: Chris@0: #include "BeatDetectTransform.h" Chris@0: #include "BeatDetectionFunctionTransform.h" Chris@0: #include "FeatureExtractionPluginTransform.h" Chris@0: Chris@0: #include "plugin/FeatureExtractionPluginFactory.h" Chris@0: Chris@0: #include Chris@0: Chris@0: TransformFactory * Chris@0: TransformFactory::m_instance = new TransformFactory; Chris@0: Chris@0: TransformFactory * Chris@0: TransformFactory::instance() Chris@0: { Chris@0: return m_instance; Chris@0: } Chris@0: Chris@0: TransformFactory::~TransformFactory() Chris@0: { Chris@0: } Chris@0: Chris@0: TransformFactory::TransformList Chris@0: TransformFactory::getAllTransforms() Chris@0: { Chris@16: if (m_transforms.empty()) populateTransforms(); Chris@16: Chris@0: TransformList list; Chris@16: for (TransformMap::const_iterator i = m_transforms.begin(); Chris@16: i != m_transforms.end(); ++i) { Chris@16: list.push_back(TransformDesc(i->first, i->second)); Chris@16: } Chris@0: Chris@16: return list; Chris@16: } Chris@16: Chris@16: void Chris@16: TransformFactory::populateTransforms() Chris@16: { Chris@0: std::vector fexplugs = Chris@0: FeatureExtractionPluginFactory::getAllPluginIdentifiers(); Chris@0: Chris@47: std::map makers; Chris@47: Chris@0: for (size_t i = 0; i < fexplugs.size(); ++i) { Chris@0: Chris@0: QString pluginId = fexplugs[i]; Chris@0: Chris@0: FeatureExtractionPluginFactory *factory = Chris@0: FeatureExtractionPluginFactory::instanceFor(pluginId); Chris@0: Chris@20: if (!factory) { Chris@20: std::cerr << "WARNING: TransformFactory::populateTransforms: No feature extraction plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl; Chris@20: continue; Chris@20: } Chris@0: Chris@20: FeatureExtractionPlugin *plugin = Chris@20: factory->instantiatePlugin(pluginId, 48000); Chris@0: Chris@20: if (!plugin) { Chris@20: std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to instantiate plugin " << pluginId.toLocal8Bit().data() << std::endl; Chris@20: continue; Chris@20: } Chris@20: Chris@20: QString pluginDescription = plugin->getDescription().c_str(); Chris@20: FeatureExtractionPlugin::OutputList outputs = Chris@20: plugin->getOutputDescriptors(); Chris@0: Chris@20: for (size_t j = 0; j < outputs.size(); ++j) { Chris@0: Chris@20: QString transformName = QString("%1:%2") Chris@20: .arg(pluginId).arg(outputs[j].name.c_str()); Chris@20: Chris@20: QString userDescription; Chris@20: Chris@20: if (outputs.size() == 1) { Chris@20: userDescription = pluginDescription; Chris@20: } else { Chris@20: userDescription = QString("%1: %2") Chris@20: .arg(pluginDescription) Chris@20: .arg(outputs[j].description.c_str()); Chris@0: } Chris@20: Chris@20: m_transforms[transformName] = userDescription; Chris@47: Chris@47: makers[transformName] = plugin->getMaker().c_str(); Chris@0: } Chris@0: } Chris@47: Chris@47: // disambiguate plugins with similar descriptions Chris@47: Chris@47: std::map descriptions; Chris@47: Chris@47: for (TransformMap::iterator i = m_transforms.begin(); i != m_transforms.end(); Chris@47: ++i) { Chris@47: Chris@47: QString name = i->first, description = i->second; Chris@47: Chris@47: ++descriptions[description]; Chris@47: ++descriptions[QString("%1 [%2]").arg(description).arg(makers[name])]; Chris@47: } Chris@47: Chris@47: std::map counts; Chris@47: TransformMap newMap; Chris@47: Chris@47: for (TransformMap::iterator i = m_transforms.begin(); i != m_transforms.end(); Chris@47: ++i) { Chris@47: Chris@47: QString name = i->first, description = i->second; Chris@47: Chris@47: if (descriptions[description] > 1) { Chris@47: description = QString("%1 [%2]").arg(description).arg(makers[name]); Chris@47: if (descriptions[description] > 1) { Chris@47: description = QString("%1 <%2>") Chris@47: .arg(description).arg(++counts[description]); Chris@47: } Chris@47: } Chris@47: Chris@47: newMap[name] = description; Chris@47: } Chris@47: Chris@47: m_transforms = newMap; Chris@16: } Chris@16: Chris@16: QString Chris@16: TransformFactory::getTransformDescription(TransformName name) Chris@16: { Chris@16: if (m_transforms.find(name) != m_transforms.end()) { Chris@16: return m_transforms[name]; Chris@16: } else return ""; Chris@0: } Chris@0: Chris@18: QString Chris@18: TransformFactory::getTransformFriendlyName(TransformName name) Chris@18: { Chris@18: QString description = getTransformDescription(name); Chris@18: Chris@18: int i = description.indexOf(':'); Chris@18: if (i >= 0) { Chris@18: return description.remove(0, i + 2); Chris@18: } else { Chris@18: return description; Chris@18: } Chris@18: } Chris@18: Chris@0: Transform * Chris@0: TransformFactory::createTransform(TransformName name, Model *inputModel) Chris@0: { Chris@0: return createTransform(name, inputModel, true); Chris@0: } Chris@0: Chris@0: Transform * Chris@0: TransformFactory::createTransform(TransformName name, Model *inputModel, Chris@0: bool start) Chris@0: { Chris@0: Transform *transform = 0; Chris@0: Chris@0: if (name == BeatDetectTransform::getName()) { Chris@0: transform = new BeatDetectTransform(inputModel); Chris@0: } else if (name == BeatDetectionFunctionTransform::getName()) { Chris@0: transform = new BeatDetectionFunctionTransform(inputModel); Chris@0: } else { Chris@0: QString id = name.section(':', 0, 2); Chris@0: QString output = name.section(':', 3); Chris@0: if (FeatureExtractionPluginFactory::instanceFor(id)) { Chris@0: transform = new FeatureExtractionPluginTransform(inputModel, Chris@0: id, output); Chris@0: } else { Chris@0: std::cerr << "TransformFactory::createTransform: Unknown transform " Chris@0: << name.toStdString() << std::endl; Chris@0: } Chris@0: } Chris@0: Chris@0: if (start && transform) transform->start(); Chris@16: transform->setObjectName(name); Chris@0: return transform; Chris@0: } Chris@0: Chris@0: Model * Chris@0: TransformFactory::transform(TransformName name, Model *inputModel) Chris@0: { Chris@0: Transform *t = createTransform(name, inputModel, false); Chris@0: Chris@0: if (!t) return 0; Chris@0: Chris@0: connect(t, SIGNAL(finished()), this, SLOT(transformFinished())); Chris@0: Chris@0: t->start(); Chris@0: return t->detachOutputModel(); Chris@0: } Chris@0: Chris@0: void Chris@0: TransformFactory::transformFinished() Chris@0: { Chris@0: QObject *s = sender(); Chris@0: Transform *transform = dynamic_cast(s); Chris@0: Chris@0: if (!transform) { Chris@0: std::cerr << "WARNING: TransformFactory::transformFinished: sender is not a transform" << std::endl; Chris@0: return; Chris@0: } Chris@0: Chris@0: transform->wait(); // unnecessary but reassuring Chris@0: delete transform; Chris@0: } Chris@0: