# HG changeset patch # User cannam # Date 1164625432 0 # Node ID b30fcffc500072c543a9aa2b14062642b2980975 # Parent b046af03c719fb02ba61eb2807a81d37cdb5acdd * Better organisation of action classes; support for AND-type rules diff -r b046af03c719 -r b30fcffc5000 host/Action.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/host/Action.h Mon Nov 27 11:03:52 2006 +0000 @@ -0,0 +1,21 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +#ifndef _ACTION_H_ +#define _ACTION_H_ + +#include +#include + +class Action : public QObject +{ +public: + virtual ~Action() { } + + virtual QString getName() const = 0; + virtual void fire() = 0; + +protected: + Action() { } +}; + +#endif diff -r b046af03c719 -r b30fcffc5000 host/ImageAction.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/host/ImageAction.cpp Mon Nov 27 11:03:52 2006 +0000 @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +#include "ImageAction.h" +#include "ImageWindow.h" + +#include + +ImageAction::ImageAction(QString imageName) : + m_imageName(imageName) +{ + connect(this, SIGNAL(showImage(QString)), + ImageWindow::getInstance(), SLOT(showImage(QString))); +} + +ImageAction::~ImageAction() +{ +} + +QString +ImageAction::getName() const +{ + return QString("image: %1").arg(m_imageName); +} + +void +ImageAction::fire() +{ + std::cerr << "ImageAction(\"" << getName().toStdString() << "\"::fire" + << std::endl; + emit showImage(m_imageName); +} + diff -r b046af03c719 -r b30fcffc5000 host/ImageAction.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/host/ImageAction.h Mon Nov 27 11:03:52 2006 +0000 @@ -0,0 +1,26 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +#ifndef _IMAGE_ACTION_H_ +#define _IMAGE_ACTION_H_ + +#include "Action.h" + +class ImageAction : public Action +{ + Q_OBJECT + +public: + ImageAction(QString imageName); + virtual ~ImageAction(); + + virtual QString getName() const; + virtual void fire(); + +signals: + void showImage(QString image); + +protected: + QString m_imageName; +}; + +#endif diff -r b046af03c719 -r b30fcffc5000 host/ImageWindow.cpp --- a/host/ImageWindow.cpp Fri Nov 10 17:46:44 2006 +0000 +++ b/host/ImageWindow.cpp Mon Nov 27 11:03:52 2006 +0000 @@ -8,6 +8,8 @@ #include +ImageWindow *ImageWindow::m_instance = 0; + ImageWindow::ImageWindow(QWidget *parent) : QDialog(parent), m_pixmap(0) @@ -23,6 +25,15 @@ delete m_pixmap; } +ImageWindow * +ImageWindow::getInstance() +{ + if (m_instance) return m_instance; + m_instance = new ImageWindow(); + m_instance->show(); + return m_instance; +} + void ImageWindow::showImage(QString image) { diff -r b046af03c719 -r b30fcffc5000 host/ImageWindow.h --- a/host/ImageWindow.h Fri Nov 10 17:46:44 2006 +0000 +++ b/host/ImageWindow.h Mon Nov 27 11:03:52 2006 +0000 @@ -14,16 +14,21 @@ Q_OBJECT public: - ImageWindow(QWidget *parent = 0); virtual ~ImageWindow(); + static ImageWindow *getInstance(); + public slots: void showImage(QString image); protected: + ImageWindow(QWidget *parent = 0); + QString m_imageName; QLabel *m_label; QPixmap *m_pixmap; + + static ImageWindow *m_instance; }; #endif diff -r b046af03c719 -r b30fcffc5000 host/Processor.cpp --- a/host/Processor.cpp Fri Nov 10 17:46:44 2006 +0000 +++ b/host/Processor.cpp Mon Nov 27 11:03:52 2006 +0000 @@ -31,6 +31,9 @@ { m_exiting = true; wait(); + while (!m_rules.empty()) { + delete *m_rules.begin(); + } } void @@ -420,73 +423,84 @@ } void -Processor::addImageRule(Rule rule, QString image) +Processor::addRule(Rule *rule) { - m_imageRules.insert(RuleImageMap::value_type(rule, image)); + m_rules.insert(rule); } bool Processor::processRules() { - for (RuleImageMap::iterator i = m_imageRules.begin(); - i != m_imageRules.end(); ++i) { + for (RuleSet::iterator i = m_rules.begin(); i != m_rules.end(); ++i) { - Rule rule(i->first); - QString image(i->second); + Rule *rule(*i); - int pluginIndex = rule.getPluginIndex(); - int outputNumber = rule.getOutputNumber(); - Rule::Condition condition = rule.getCondition(); - float argument = rule.getArgument(); + bool passed = false; - OutputState state = m_pluginStates[pluginIndex][outputNumber]; + for (Rule::ConditionList::const_iterator j = rule->getConditions().begin(); + j != rule->getConditions().end(); ++j) { + + Condition condition(*j); + + int pluginIndex = condition.getPluginIndex(); + int outputNumber = condition.getOutputNumber(); + Condition::Type type = condition.getType(); + float argument = condition.getArgument(); + + OutputState state = m_pluginStates[pluginIndex][outputNumber]; #ifdef DEBUG_RUN_PROCESSOR - std::cerr << "Present = " << state.present << ", changed = " << state.changed << ", value = " << state.value << std::endl; + std::cerr << "Present = " << state.present << ", changed = " << state.changed << ", value = " << state.value << std::endl; #endif - if (!state.changed) continue; + passed = false; - bool fire = false; + if (!state.changed) break; //!!!??? - switch (condition) { + switch (type) { - case Rule::GreaterThan: - fire = (state.value > argument); - break; + case Condition::GreaterThan: + passed = (state.value > argument); + break; + + case Condition::LessThan: + passed = (state.value < argument); + break; + + case Condition::EqualTo: + passed = fabsf(state.value - argument) < 0.000001; + break; + + case Condition::NotEqualTo: + passed = fabsf(state.value - argument) > 0.000001; + break; + + case Condition::Present: + passed = state.present; + break; + + case Condition::Changed: + passed = true; + break; + + case Condition::GapGreaterThan: + passed = (state.gap > Vamp::RealTime::fromSeconds(argument)); + break; + + case Condition::GapLessThan: + passed = (state.gap < Vamp::RealTime::fromSeconds(argument)); + break; + } - case Rule::LessThan: - fire = (state.value < argument); - break; - - case Rule::EqualTo: - fire = fabsf(state.value - argument) < 0.000001; - break; - - case Rule::NotEqualTo: - fire = fabsf(state.value - argument) > 0.000001; - break; - - case Rule::Present: - fire = state.present; - break; - - case Rule::Changed: - fire = true; - break; - - case Rule::GapGreaterThan: - fire = (state.gap > Vamp::RealTime::fromSeconds(argument)); - break; - - case Rule::GapLessThan: - fire = (state.gap < Vamp::RealTime::fromSeconds(argument)); - break; + if (!passed) break; } - if (fire) { - std::cerr << "FIRING RULE: " << image.toStdString() << "!" << std::endl; - emit showImage(image); + if (passed) { + Action *action = rule->getAction(); + if (action) { + std::cerr << "FIRING RULE: " << action->getName().toStdString() << "!" << std::endl; + action->fire(); + } } } diff -r b046af03c719 -r b30fcffc5000 host/Processor.h --- a/host/Processor.h Fri Nov 10 17:46:44 2006 +0000 +++ b/host/Processor.h Mon Nov 27 11:03:52 2006 +0000 @@ -27,10 +27,7 @@ int addPlugin(QString pluginId); // returns reference number, 0 for failure void removePlugin(int number); - void addImageRule(Rule rule, QString image); - -signals: - void showImage(QString image); + void addRule(Rule *rule); // I take ownership of rule protected: virtual void run(); @@ -61,9 +58,8 @@ StepSizeReaderMap m_stepSizeReaderMap; ReaderSet m_unusedReaders; - // Map from rule to image name - typedef std::multimap RuleImageMap; - RuleImageMap m_imageRules; + typedef std::multiset RuleSet; + RuleSet m_rules; class OutputState { public: diff -r b046af03c719 -r b30fcffc5000 host/Rule.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/host/Rule.cpp Mon Nov 27 11:03:52 2006 +0000 @@ -0,0 +1,22 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +#include "Rule.h" + +Rule::~Rule() +{ + delete m_action; +} + +void +Rule::addCondition(Condition condition) +{ + m_conditions.push_back(condition); +} + +void +Rule::setAction(Action *action) +{ + delete m_action; + m_action = action; +} + diff -r b046af03c719 -r b30fcffc5000 host/Rule.h --- a/host/Rule.h Fri Nov 10 17:46:44 2006 +0000 +++ b/host/Rule.h Mon Nov 27 11:03:52 2006 +0000 @@ -3,10 +3,14 @@ #ifndef _RULE_H_ #define _RULE_H_ -class Rule +#include + +#include "Action.h" + +class Condition { public: - enum Condition { + enum Type { EqualTo, GreaterThan, LessThan, @@ -17,34 +21,55 @@ GapLessThan }; - Rule(int pluginIndex, int outputNumber, - Condition condition, float argument = 0.f) : + Condition(int pluginIndex, int outputNumber, + Type type, float argument = 0.f) : m_pluginIndex(pluginIndex), m_outputNumber(outputNumber), - m_condition(condition), + m_type(type), m_argument(argument) { } int getPluginIndex() const { return m_pluginIndex; } int getOutputNumber() const { return m_outputNumber; } - Condition getCondition() const { return m_condition; } + Type getType() const { return m_type; } float getArgument() const { return m_argument; } - bool operator<(const Rule &r) const { - if (m_pluginIndex < r.m_pluginIndex) return true; - else if (m_pluginIndex > r.m_pluginIndex) return false; - if (m_outputNumber < r.m_outputNumber) return true; - else if (m_outputNumber > r.m_outputNumber) return false; - if (int(m_condition) < int(r.m_condition)) return true; - else if (int(m_condition) > int(r.m_condition)) return true; - return m_argument < r.m_argument; +/* + bool operator<(const Condition &c) const { + if (m_pluginIndex < c.m_pluginIndex) return true; + else if (m_pluginIndex > c.m_pluginIndex) return false; + if (m_outputNumber < c.m_outputNumber) return true; + else if (m_outputNumber > c.m_outputNumber) return false; + if (int(m_type) < int(c.m_type)) return true; + else if (int(m_type) > int(c.m_type)) return true; + return m_argument < c.m_argument; } +*/ protected: int m_pluginIndex; int m_outputNumber; - Condition m_condition; + Type m_type; float m_argument; }; +class Rule +{ +public: + Rule() : m_action(0) { } + virtual ~Rule(); + + void addCondition(Condition condition); + void setAction(Action *action); // I take ownership of action + + typedef std::vector ConditionList; + const ConditionList &getConditions() const { return m_conditions; } + + Action *getAction() { return m_action; } + +protected: + std::vector m_conditions; + Action *m_action; +}; + #endif diff -r b046af03c719 -r b30fcffc5000 host/SimpleXMLRuleLoader.cpp --- a/host/SimpleXMLRuleLoader.cpp Fri Nov 10 17:46:44 2006 +0000 +++ b/host/SimpleXMLRuleLoader.cpp Mon Nov 27 11:03:52 2006 +0000 @@ -2,6 +2,7 @@ #include "SimpleXMLRuleLoader.h" #include "Rule.h" +#include "ImageAction.h" #include #include @@ -10,7 +11,9 @@ SimpleXMLRuleLoader::SimpleXMLRuleLoader() : m_processor(0), m_inPlugins(false), - m_inRules(false) + m_inRules(false), + m_inRule(false), + m_rule(0) { } @@ -98,7 +101,21 @@ std::cerr << "ERROR: SimpleXMLRuleLoader: Rule outside rules element" << std::endl; return false; } + if (m_inRule) { + std::cerr << "ERROR: SimpleXMLRuleLoader: Nested output rules" << std::endl; + return false; + } + m_inRule = true; + m_rule = new Rule(); + + } else if (name == "condition") { + + if (!m_inRule) { + std::cerr << "ERROR: SimpleXMLRuleLoader: Condition outside rule" << std::endl; + return false; + } + int extIndex = atts.value("pluginIndex").toInt(); if (m_externalInternalIndexMap.find(extIndex) == @@ -115,31 +132,41 @@ if (!ok) outputNumber = 0; QString condStr = atts.value("condition").toLower(); - Rule::Condition condition(Rule::Present); + Condition::Type type(Condition::Present); - if (condStr == "present") condition = Rule::Present; - else if (condStr == "equalto") condition = Rule::EqualTo; - else if (condStr == "greaterthan") condition = Rule::GreaterThan; - else if (condStr == "lessthan") condition = Rule::LessThan; - else if (condStr == "gapgreaterthan") condition = Rule::GapGreaterThan; - else if (condStr == "gaplessthan") condition = Rule::GapLessThan; - else if (condStr == "notequalto") condition = Rule::NotEqualTo; - else if (condStr == "changed") condition = Rule::Changed; + if (condStr == "present") type = Condition::Present; + else if (condStr == "equalto") type = Condition::EqualTo; + else if (condStr == "greaterthan") type = Condition::GreaterThan; + else if (condStr == "lessthan") type = Condition::LessThan; + else if (condStr == "gapgreaterthan") type = Condition::GapGreaterThan; + else if (condStr == "gaplessthan") type = Condition::GapLessThan; + else if (condStr == "notequalto") type = Condition::NotEqualTo; + else if (condStr == "changed") type = Condition::Changed; float arg = atts.value("argument").toFloat(&ok); if (!ok) arg = 0.f; - Rule rule(intIndex, outputNumber, condition, arg); + Condition condition(intIndex, outputNumber, type, arg); - QString action = atts.value("action").toLower(); + m_rule->addCondition(condition); - if (action == "image") { + } else if (name == "action") { + + if (!m_inRule) { + std::cerr << "ERROR: SimpleXMLRuleLoader: Action outside rule" << std::endl; + return false; + } + + QString type = atts.value("type").toLower(); + + if (type == "image") { QString image = atts.value("image").toLower(); - m_processor->addImageRule(rule, image); - std::cerr << "INFO: SimpleXMLRuleLoader: Added image rule" << std::endl; + Action *action = new ImageAction(image); + m_rule->setAction(action); + std::cerr << "INFO: SimpleXMLRuleLoader: Added image action" << std::endl; } else { - std::cerr << "WARNING: SimpleXMLRuleLoader: Unknown action \"" - << action.toStdString() << "\"" << std::endl; + std::cerr << "WARNING: SimpleXMLRuleLoader: Unknown action type \"" + << type.toStdString() << "\"" << std::endl; } } @@ -172,7 +199,18 @@ std::cerr << "WARNING: SimpleXMLRuleLoader: Parse problem: unexpected end of rules element (trying to continue)" << std::endl; } m_inRules = false; + + } else if (name == "outputrule") { + + if (!m_inRule) { + std::cerr << "WARNING: SimpleXMLRuleLoader: Parse problem: unexpected end of outputRule element" << std::endl; + return false; + } else { + m_processor->addRule(m_rule); + } + m_inRule = false; } + return true; } diff -r b046af03c719 -r b30fcffc5000 host/SimpleXMLRuleLoader.h --- a/host/SimpleXMLRuleLoader.h Fri Nov 10 17:46:44 2006 +0000 +++ b/host/SimpleXMLRuleLoader.h Mon Nov 27 11:03:52 2006 +0000 @@ -42,10 +42,11 @@ bool m_inPlugins; bool m_inRules; + bool m_inRule; + + Rule *m_rule; std::map m_externalInternalIndexMap; - -// Rule m_currentRule; }; #endif diff -r b046af03c719 -r b30fcffc5000 host/host.cpp --- a/host/host.cpp Fri Nov 10 17:46:44 2006 +0000 +++ b/host/host.cpp Mon Nov 27 11:03:52 2006 +0000 @@ -52,14 +52,14 @@ return 1; } - ImageWindow window; - window.show(); +// ImageWindow window; +// window.show(); Processor processor(target); - +/* QObject::connect(&processor, SIGNAL(showImage(QString)), &window, SLOT(showImage(QString))); - +*/ SimpleXMLRuleLoader loader; if (!loader.loadFile(processor, "test.xml")) { std::cerr << "ERROR: Failed to load test XML file" << std::endl; diff -r b046af03c719 -r b30fcffc5000 test.xml --- a/test.xml Fri Nov 10 17:46:44 2006 +0000 +++ b/test.xml Mon Nov 27 11:03:52 2006 +0000 @@ -4,8 +4,14 @@ - - + + + + + + + + diff -r b046af03c719 -r b30fcffc5000 vamp-live-host.pro --- a/vamp-live-host.pro Fri Nov 10 17:46:44 2006 +0000 +++ b/vamp-live-host.pro Mon Nov 27 11:03:52 2006 +0000 @@ -23,8 +23,11 @@ audioio/AudioPortAudioSource.h \ audioio/AudioRecordSourceFactory.h \ audioio/BufferingAudioCallbackRecordTarget.h \ + host/Action.h \ + host/ImageAction.h \ host/ImageWindow.h \ host/Processor.h \ + host/Rule.h \ host/SimpleXMLRuleLoader.h SOURCES += audioio/AudioCallbackRecordSource.cpp \ audioio/AudioJACKSource.cpp \ @@ -32,6 +35,8 @@ audioio/AudioRecordSourceFactory.cpp \ audioio/BufferingAudioCallbackRecordTarget.cpp \ host/host.cpp \ + host/ImageAction.cpp \ host/ImageWindow.cpp \ host/Processor.cpp \ + host/Rule.cpp \ host/SimpleXMLRuleLoader.cpp