Index: CLAM/src/Processing/Controls/ControlTrace.cxx
===================================================================
--- CLAM/src/Processing/Controls/ControlTrace.cxx	(revision 0)
+++ CLAM/src/Processing/Controls/ControlTrace.cxx	(revision 0)
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
+ *                         UNIVERSITAT POMPEU FABRA
+ * Copyright (c) 2007 Superlucidity Services, LLC and Zachary T Welch
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "ControlTrace.hxx"
+#include "Factory.hxx"
+#include "XMLAdapter.hxx"
+#include "XMLStorage.hxx"
+#include "XMLIterableAdapter.hxx"
+#include "XMLAdapter.hxx"
+#include "XmlStorageErr.hxx"
+#include <sstream>
+
+namespace CLAM
+{
+
+ControlTraceEvent::ControlTraceEvent()
+	: mSteps(1)
+{
+}
+ControlTraceEvent::ControlTraceEvent(const ControlTraceEvent &obj)
+	: mSteps(obj.mSteps)
+	, mValues(obj.mValues)
+{
+}
+ControlTraceEvent::ControlTraceEvent(const InControlArray &inputs)
+	: mSteps(1)
+{
+	mValues.resize(inputs.Size());
+	for (int i = 0; i < inputs.Size(); i++)
+		mValues[i] = inputs[i].GetLastValue();
+}
+
+void ControlTraceEvent::UpdateControls(OutControlArray &outputs) const
+{
+	for (int i = 0; i < outputs.Size(); i++)
+		outputs[i].SendControl(mValues[i]);
+}
+
+void ControlTraceEvent::LoadFrom( Storage& storage )
+{
+	XMLIterableAdapter<ValueArray> vAdapter(mValues, "x", "controls", true);
+	storage.Load(vAdapter);
+
+	XMLAdapter<unsigned int> sAdapter(mSteps, "repeats", true);
+	storage.Load(sAdapter);
+}
+
+void ControlTraceEvent::StoreOn( Storage& storage ) const
+{
+	XMLIterableAdapter<ValueArray> vAdapter(mValues, "x", "controls", true);
+	storage.Store(vAdapter);
+
+	if (mSteps > 1)
+	{
+		XMLAdapter<unsigned int> sAdapter(mSteps, "repeats", true);
+		storage.Store(sAdapter);
+	}
+}
+
+const ControlTraceEvent& ControlTraceEvent::operator=(const ControlTraceEvent& rhs)
+{
+	mValues = rhs.mValues;
+	return *this;
+}
+
+bool ControlTraceEvent::ValuesEqual(const ControlTraceEvent &rhs) const
+{
+	if (mValues.size() != rhs.mValues.size())
+		return false;
+
+	for (size_t i = 0; i < mValues.size(); i++)
+	{
+		if (mValues[i] != rhs.mValues[i])
+			return false;
+	}
+
+	return true;
+}
+
+/* ================================================================== */
+
+const unsigned int ControlTraceData::DumpVersion = 1;
+
+ControlTraceData::ControlTraceData()
+	: mVersion(DumpVersion)
+{
+}
+ControlTraceData::ControlTraceData(const ControlTraceData &obj)
+	: mVersion(DumpVersion), mEvents(obj.mEvents)
+{
+}
+
+void ControlTraceData::LoadFrom( Storage& storage )
+{
+	mVersion = 0;
+	XMLAdapter<unsigned int> versionAdapter(mVersion, "version");
+	storage.Load(versionAdapter);
+	if (!mVersion || mVersion > DumpVersion)
+	{
+		std::stringstream err;
+		err << "Unknown CLAM Control Trace file version: " << mVersion;
+		throw XmlStorageErr(err.str());
+	}
+
+	XMLIterableAdapter<EventList> adapter(mEvents, "event", "events", true);
+	storage.Load(adapter);
+}
+void ControlTraceData::StoreOn( Storage& storage ) const
+{
+	XMLAdapter<unsigned int> versionAdapter(mVersion, "version");
+	storage.Store(versionAdapter);
+
+	XMLIterableAdapter<EventList> adapter(mEvents, "event", "events", true);
+	storage.Store(adapter);
+}
+
+void ControlTraceData::Append(const ControlTraceEvent &data)
+{
+	ControlTraceEvent &prev = mEvents.back();
+	if (prev.ValuesEqual(data))
+		prev.AddStep();
+	else
+		mEvents.push_back(data);
+}
+
+/* ================================================================== */
+
+static const char clamControlTraceFileTypeFamily[] = "CLAM Control Trace";
+static const Filename::Filter clamControlTraceFileFilters[] = {
+		{ "CLAM Control Traces (v1)", "*.clamtrace" },
+	};
+
+const char* ControlTraceInFilename::TypeFamily() const
+{
+	return clamControlTraceFileTypeFamily;
+}
+const Filename::Filter * ControlTraceInFilename::Filters() const
+{
+	return clamControlTraceFileFilters;
+}
+
+const char* ControlTraceOutFilename::TypeFamily() const
+{
+	return clamControlTraceFileTypeFamily;
+}
+const Filename::Filter * ControlTraceOutFilename::Filters() const
+{
+	return clamControlTraceFileFilters;
+}
+
+/* ================================================================= */
+
+void ControlTraceWriterConfig::DefaultInit()
+{
+	AddAll();
+	UpdateData();
+	SetNumberOfInputs(1.);
+}
+
+ControlTraceWriter::ControlTraceWriter()
+{
+	Configure(mConfig);
+}
+
+ControlTraceWriter::ControlTraceWriter( const ProcessingConfig& cfg )
+{
+	Configure( cfg );
+}
+
+ControlTraceWriter::~ControlTraceWriter()
+{
+	RemoveOldControls();
+}
+
+bool ControlTraceWriter::ConcreteConfigure( const ProcessingConfig& cfgObj )
+{
+	RemoveOldControls();
+	CopyAsConcreteConfig( mConfig, cfgObj );
+	if ( !mConfig.HasTraceFile() )
+	{
+		AddConfigErrorMessage("No 'trace file' was specified in the configuration!");
+		return false;
+	}
+
+	ControlTraceOutFilename &file = mConfig.GetTraceFile();
+	if ( file == "" )
+	{
+		AddConfigErrorMessage("No trace file selected");
+		return false;
+	}
+
+	if (!mConfig.HasNumberOfInputs() || mConfig.GetNumberOfInputs() < 1.)
+	{
+		AddConfigErrorMessage("The number of inputs has not been configured.");
+		return false;
+	}
+
+	mInputs.Resize(int(mConfig.GetNumberOfInputs()), "Input", this);
+	return true;
+}
+
+bool ControlTraceWriter::ConcreteStop()
+{
+	XMLStorage::Dump(mTrace, "trace", mConfig.GetTraceFile().c_str());
+	mTrace.Clear();
+	return true;
+}
+
+bool ControlTraceWriter::Do()
+{
+	mTrace.Append(ControlTraceEvent(mInputs));
+	return true;
+}
+
+
+void ControlTraceWriter::RemoveOldControls()
+{
+	mInputs.Clear();
+	GetInControls().Clear();
+}
+
+/* ================================================================= */
+
+void ControlTraceReaderConfig::DefaultInit()
+{
+	AddAll();
+	UpdateData();
+}
+
+ControlTraceReader::ControlTraceReader()
+{
+	Configure(mConfig);
+}
+
+ControlTraceReader::ControlTraceReader( const ProcessingConfig& cfg )
+{
+	Configure( cfg );
+}
+
+ControlTraceReader::~ControlTraceReader()
+{
+	RemoveOldControls();
+}
+
+bool ControlTraceReader::ConcreteConfigure( const ProcessingConfig& cfgObj )
+{
+	RemoveOldControls();
+	CopyAsConcreteConfig( mConfig, cfgObj );
+	if ( !mConfig.HasTraceFile() )
+	{
+		AddConfigErrorMessage("No 'trace file' was specified in the configuration!");
+		return false;
+	}
+
+	ControlTraceInFilename &file = mConfig.GetTraceFile();
+	if ( file == "" )
+	{
+		AddConfigErrorMessage("No trace file selected");
+		return false;
+	}
+
+	try {
+		XMLStorage::Restore(mTrace, mConfig.GetTraceFile().c_str());
+	}
+	catch (XmlStorageErr &e)
+	{
+		AddConfigErrorMessage(e.what());
+		return false;
+	}
+
+	if (mTrace.GetNumberOfControls() < 1)
+	{
+		AddConfigErrorMessage("The specified file does not contain any control events.");
+		return false;
+	}
+
+	mOutputs.Resize(mTrace.GetNumberOfControls(), "Output", this);
+	return true;
+}
+
+bool ControlTraceReader::ConcreteStart()
+{
+	mIterator = mTrace.Begin();
+	mStepCounter = 0;
+	return true;
+}
+
+bool ControlTraceReader::Do()
+{
+	if (mIterator == mTrace.End())
+		return false;
+
+	const ControlTraceEvent &event = *mIterator;
+
+	// if this is the zeroth (first) step, update the controls
+	if (!mStepCounter)
+		event.UpdateControls(mOutputs);
+
+	// if this step completes the current event, advance and reset counter
+	if (++mStepCounter == event.Steps()) {
+		mIterator++;
+		mStepCounter = 0;
+	}
+	return true;
+}
+
+void ControlTraceReader::RemoveOldControls()
+{
+	mOutputs.Clear();
+	GetOutControls().Clear();
+}
+
+/* ================================================================== */
+
+namespace detail
+{
+typedef CLAM::Factory<CLAM::Processing> ProcessingFactory;
+static ProcessingFactory::Registrator<CLAM::ControlTraceReader>
+		regtControlTraceReader("ControlTraceReader");
+static ProcessingFactory::Registrator<CLAM::ControlTraceWriter>
+		regtControlTraceWriter("ControlTraceWriter");
+}
+
+
+} // CLAM namespace
+
Index: CLAM/src/Processing/Controls/ControlTrace.hxx
===================================================================
--- CLAM/src/Processing/Controls/ControlTrace.hxx	(revision 0)
+++ CLAM/src/Processing/Controls/ControlTrace.hxx	(revision 0)
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
+ *                         UNIVERSITAT POMPEU FABRA
+ * Copyright (c) 2007 Superlucidity Services, LLC and Zachary T Welch
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef CONTROL_TRACE_HXX
+#define CONTROL_TRACE_HXX
+
+#include <CLAM/Processing.hxx>
+#include <CLAM/ProcessingConfig.hxx>
+#include <CLAM/InControlArray.hxx>
+#include <CLAM/OutControlArray.hxx>
+#include <CLAM/Filename.hxx>
+#include <vector>
+
+class Network;
+
+struct fann;
+
+namespace CLAM
+{
+
+class ControlTraceEvent : public Component {
+public:
+	typedef std::vector<TControlData> ValueArray;
+
+	ControlTraceEvent();
+	ControlTraceEvent(const InControlArray &inputs);
+	ControlTraceEvent(const ControlTraceEvent &event);
+	const ControlTraceEvent& operator=( const ControlTraceEvent& );
+	virtual ~ControlTraceEvent() { }
+
+	const char *GetClassName() const { return "ControlTraceEvent"; }
+
+	void LoadFrom( Storage& storage);
+	void StoreOn( Storage& storage ) const;
+
+	void AddStep() { mSteps++; }
+	unsigned int Steps() const { return mSteps; }
+	size_t Size() const { return mValues.size(); }
+
+	void UpdateControls(OutControlArray &array) const;
+
+	bool ValuesEqual(const ControlTraceEvent &rhs) const;
+
+private:
+	unsigned int mSteps;
+	ValueArray mValues;
+};
+
+class ControlTraceData : public Component {
+	static const unsigned int DumpVersion;
+public:
+	typedef std::list<ControlTraceEvent> EventList;
+	virtual ~ControlTraceData() { }
+
+	ControlTraceData();
+	ControlTraceData(const ControlTraceData &obj);
+
+	const char *GetClassName() const { return "ControlTraceData"; }
+
+	unsigned int GetVersion() const { return mVersion; }
+
+	void LoadFrom( Storage& storage);
+	void StoreOn( Storage& storage ) const;
+
+	size_t GetNumberOfControls() const { return mEvents.front().Size(); }
+
+	void Append(const ControlTraceEvent &data);
+
+	EventList::iterator Begin() { return mEvents.begin(); }
+	EventList::iterator End() { return mEvents.end(); }
+
+	void Clear() { mEvents.clear(); }
+
+private:
+	unsigned int mVersion;
+	EventList mEvents;
+};
+
+
+class ControlTraceInFilename : public InFilename
+{
+public:
+	ControlTraceInFilename(const std::string & s="") : InFilename(s) {}
+	ControlTraceInFilename(const char * s) : InFilename(s) {}
+	const char* TypeFamily() const;
+	const Filter * Filters() const;
+};
+CLAM_TYPEINFOGROUP(BasicCTypeInfo, ControlTraceInFilename);
+
+class ControlTraceReaderConfig  : public ProcessingConfig {
+	DYNAMIC_TYPE_USING_INTERFACE
+	( ControlTraceReaderConfig, 1, ProcessingConfig );
+
+	DYN_ATTRIBUTE( 0, public, ControlTraceInFilename, TraceFile );
+
+protected:
+	void DefaultInit();
+};
+
+class ControlTraceReader : public Processing
+{
+public:
+	ControlTraceReader();
+	ControlTraceReader( const ProcessingConfig& cfg );
+	virtual ~ControlTraceReader();
+
+	const char* GetClassName() const { return "ControlTraceReader"; }
+	const ProcessingConfig& GetConfig() const { return mConfig; }
+
+	bool Do();
+
+protected: // methods
+	bool ConcreteConfigure( const ProcessingConfig& cfgObject );
+	bool ConcreteStart();
+	void RemoveOldControls();
+	
+protected: // attributes
+	ControlTraceReaderConfig mConfig;
+	ControlTraceData mTrace;
+	ControlTraceData::EventList::iterator mIterator;
+	unsigned int mStepCounter;
+	OutControlArray mOutputs;
+};
+
+
+class ControlTraceOutFilename : public OutFilename
+{
+public:
+	ControlTraceOutFilename(const std::string & s="") : OutFilename(s) {}
+	ControlTraceOutFilename(const char * s) : OutFilename(s) {}
+	const char* TypeFamily() const;
+	const Filter * Filters() const;
+};
+CLAM_TYPEINFOGROUP(BasicCTypeInfo, ControlTraceOutFilename);
+
+class ControlTraceWriterConfig  : public ProcessingConfig {
+	DYNAMIC_TYPE_USING_INTERFACE
+	( ControlTraceWriterConfig, 2, ProcessingConfig );
+
+	DYN_ATTRIBUTE( 0, public, ControlTraceOutFilename, TraceFile );
+	DYN_ATTRIBUTE( 1, public, TData, NumberOfInputs );
+
+protected:
+	void DefaultInit();
+};
+
+class ControlTraceWriter : public Processing
+{
+public:
+	ControlTraceWriter();
+	ControlTraceWriter( const ProcessingConfig& cfg );
+	virtual ~ControlTraceWriter();
+
+	const char* GetClassName() const { return "ControlTraceWriter"; }
+	const ProcessingConfig& GetConfig() const { return mConfig; }
+
+	bool Do();
+
+protected: // methods
+	bool ConcreteConfigure( const ProcessingConfig& cfgObject );
+	bool ConcreteStop();
+	void RemoveOldControls();
+	
+protected: // attributes
+	ControlTraceWriterConfig mConfig;
+	ControlTraceData mTrace;
+	InControlArray mInputs;
+};
+
+} // CLAM namespace
+
+#endif
Index: NetworkEditor/src/ProcessingTree.cxx
===================================================================
--- NetworkEditor/src/ProcessingTree.cxx	(revision 10016)
+++ NetworkEditor/src/ProcessingTree.cxx	(working copy)
@@ -67,6 +67,8 @@
 	"ControlSource",
 	"ControlSink",
 	"ControlPrinter",
+	"ControlTraceReader",
+	"ControlTraceWriter",
 	"ControlScaler", 
 	"AutoPanner",
 	"FlagControl",
Index: NetworkEditor/src/ProcessingBox.cxx
===================================================================
--- NetworkEditor/src/ProcessingBox.cxx	(revision 10016)
+++ NetworkEditor/src/ProcessingBox.cxx	(working copy)
@@ -85,7 +85,7 @@
 	if (className=="ControlSurface")
 		return new ControlSurfaceWidget(processing);
 
-	if (className=="ControlPrinter")
+	if (className=="ControlPrinter" || className=="ControlTraceWriter")
 		return new ControlPrinterWidget(processing);
 
 	if (className=="Vumeter")
Index: NetworkEditor/src/RegisterConfiguratorLaunchers.cxx
===================================================================
--- NetworkEditor/src/RegisterConfiguratorLaunchers.cxx	(revision 10016)
+++ NetworkEditor/src/RegisterConfiguratorLaunchers.cxx	(working copy)
@@ -66,6 +66,7 @@
 #include <CLAM/ControlScaler.hxx>
 #include "ControlSurface.hxx"
 #include <CLAM/ControlSource.hxx>
+#include <CLAM/ControlTrace.hxx>
 #include <CLAM/OutControlSender.hxx>
 
 //MIDI
@@ -132,6 +133,8 @@
 STANDARD_PROCESSING_CONFIG_REGISTER(ControlScalerConfig);
 STANDARD_PROCESSING_CONFIG_REGISTER(ControlSourceConfig);
 STANDARD_PROCESSING_CONFIG_REGISTER(ControlSurfaceConfig);
+STANDARD_PROCESSING_CONFIG_REGISTER(ControlTraceReaderConfig);
+STANDARD_PROCESSING_CONFIG_REGISTER(ControlTraceWriterConfig);
 STANDARD_PROCESSING_CONFIG_REGISTER(FlagControlConfig);
 STANDARD_PROCESSING_CONFIG_REGISTER(Fundamental2ControlConfig);
 STANDARD_PROCESSING_CONFIG_REGISTER(OneOverFConfig);
Index: CLAM/test/FunctionalTests/ProcessingTests/TestControlTraces.cxx
===================================================================
--- CLAM/test/FunctionalTests/ProcessingTests/TestControlTraces.cxx	(revision 0)
+++ CLAM/test/FunctionalTests/ProcessingTests/TestControlTraces.cxx	(revision 0)
@@ -0,0 +1,251 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include "cppUnitHelper.hxx"
+#include <CLAM/ControlTrace.hxx>
+#include "similarityHelper.hxx"
+#include <algorithm>
+#include <cstdio>
+
+namespace CLAMTest
+{
+
+class ControlTraceReaderFunctionalTest;
+CPPUNIT_TEST_SUITE_REGISTRATION( ControlTraceReaderFunctionalTest );
+
+class ControlTraceReaderFunctionalTest : public CppUnit::TestFixture
+{
+	CPPUNIT_TEST_SUITE( ControlTraceReaderFunctionalTest );
+
+	// Configuration values checking tests
+	CPPUNIT_TEST( testConfigure_ReturnsTrueWithJustFilename );
+	CPPUNIT_TEST( testConfigure_ReturnsFalseWithoutTraceFileInConfig );
+	CPPUNIT_TEST( testConfigure_ReturnsTrueWhenFileExists );
+	CPPUNIT_TEST( testConfigure_ReturnsFalseWhenFileDoesNotExist );
+	CPPUNIT_TEST( testConfigure_ReturnsTrueWhenTraceEventsExist );
+	CPPUNIT_TEST( testConfigure_ReturnsFalseWhenTraceFileIsEmpty );
+
+	CPPUNIT_TEST_SUITE_END();
+
+protected: // Attributes
+
+	std::string mPathToTestData;
+	std::string mInputFileName;
+	std::string mEmptyFileName;
+
+protected: // Auxiliary methods
+
+public: // TestFixture interface
+
+	void setUp()
+	{
+		mPathToTestData = GetTestDataDirectory() + "ControlTraceReader";
+		mInputFileName = mPathToTestData + "Input.clamtrace";
+		mEmptyFileName = mPathToTestData + "Empty.clamtrace";
+	}
+
+	void tearDown()
+	{
+	}
+
+private: // tests cases
+
+	void testConfigure_ReturnsTrueWithJustFilename()
+	{
+		CLAM::ControlTraceReaderConfig cfg;
+
+		CLAM::ControlTraceInFilename file(mInputFileName);
+		cfg.SetTraceFile( file );
+
+		CLAM::ControlTraceReader proc;
+
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( true, configResult );
+	}
+
+	void testConfigure_ReturnsFalseWithoutTraceFileInConfig()
+	{
+		CLAM::ControlTraceReaderConfig cfg;
+		cfg.RemoveTraceFile();
+		cfg.UpdateData();
+		
+		CLAM::ControlTraceReader proc;
+		
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( false, configResult );
+	}
+	
+	void testConfigure_ReturnsTrueWhenFileExists()
+	{
+		CLAM::ControlTraceReaderConfig cfg;
+
+		CLAM::ControlTraceInFilename file(mInputFileName);
+		cfg.SetTraceFile( file );
+
+		CLAM::ControlTraceReader proc;
+		
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( true, configResult );
+	}
+
+	void testConfigure_ReturnsFalseWhenFileDoesNotExist()
+	{
+		CLAM::ControlTraceReaderConfig cfg;
+
+		CLAM::ControlTraceInFilename file(mPathToTestData + 
+				std::string( "missing-file.clamtrace" ) );
+		cfg.SetTraceFile( file );
+
+		CLAM::ControlTraceReader proc;
+
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( false, configResult );
+	}
+	
+	void testConfigure_ReturnsTrueWhenTraceEventsExist()
+	{
+		CLAM::ControlTraceReaderConfig cfg;
+
+		CLAM::ControlTraceInFilename file(mInputFileName);
+		cfg.SetTraceFile( file );
+
+		CLAM::ControlTraceReader proc;
+
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( true, configResult );
+	}
+
+	void testConfigure_ReturnsFalseWhenTraceFileIsEmpty()
+	{
+		CLAM::ControlTraceReaderConfig cfg;
+
+		CLAM::ControlTraceInFilename file(mEmptyFileName);
+		cfg.SetTraceFile( file );
+
+		CLAM::ControlTraceReader proc;
+
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( false, configResult );
+		
+	}
+
+};
+
+class ControlTraceWriterFunctionalTest;
+CPPUNIT_TEST_SUITE_REGISTRATION( ControlTraceWriterFunctionalTest );
+
+class ControlTraceWriterFunctionalTest : public CppUnit::TestFixture
+{
+	CPPUNIT_TEST_SUITE( ControlTraceWriterFunctionalTest );
+
+	// Configuration values checking tests
+	CPPUNIT_TEST( testConfigure_ReturnsTrueWithJustFilename );
+	CPPUNIT_TEST( testConfigure_ReturnsFalseWithoutTraceFileInConfig );
+	CPPUNIT_TEST( testConfigure_ReturnsTrueWhenFileExists );
+	CPPUNIT_TEST( testConfigure_ReturnsFalseWithoutInputsInConfig );
+	CPPUNIT_TEST( testConfigure_ReturnsFalseWhenConfiguredWithNoInputs );
+
+	CPPUNIT_TEST_SUITE_END();
+
+protected: // Attributes
+
+	std::string mPathToTestData;
+	std::string mOutputFileName;
+
+protected: // Auxiliary methods
+
+public: // TestFixture interface
+
+	void setUp()
+	{
+		mPathToTestData = GetTestDataDirectory() + "ControlTraceWriter";
+		mOutputFileName = mPathToTestData + "Output.clamtrace";
+	}
+
+	void tearDown()
+	{
+	}
+
+private: // tests cases
+
+	void testConfigure_ReturnsTrueWithJustFilename()
+	{
+		CLAM::ControlTraceWriterConfig cfg;
+
+		CLAM::ControlTraceOutFilename file(mOutputFileName);
+		cfg.SetTraceFile( file );
+
+		CLAM::ControlTraceWriter proc;
+
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( true, configResult );
+	}
+
+	void testConfigure_ReturnsFalseWithoutTraceFileInConfig()
+	{
+		CLAM::ControlTraceWriterConfig cfg;
+		cfg.RemoveTraceFile();
+		cfg.UpdateData();
+		
+		CLAM::ControlTraceWriter proc;
+		
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( false, configResult );
+	}
+	
+	void testConfigure_ReturnsTrueWhenFileExists()
+	{
+		CLAM::ControlTraceWriterConfig cfg;
+
+		CLAM::ControlTraceOutFilename file(mOutputFileName);
+		cfg.SetTraceFile( file );
+
+		CLAM::ControlTraceWriter proc;
+		
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( true, configResult );
+	}
+
+	void testConfigure_ReturnsFalseWithoutInputsInConfig()
+	{
+		CLAM::ControlTraceWriterConfig cfg;
+		cfg.RemoveNumberOfInputs();
+		cfg.UpdateData();
+
+		CLAM::ControlTraceOutFilename file(mOutputFileName);
+		cfg.SetTraceFile( file );
+
+		CLAM::ControlTraceWriter proc;
+
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( false, configResult );
+		
+	}
+
+	void testConfigure_ReturnsFalseWhenConfiguredWithNoInputs()
+	{
+		CLAM::ControlTraceWriterConfig cfg;
+
+		CLAM::ControlTraceOutFilename file(mOutputFileName);
+		cfg.SetTraceFile( file );
+		cfg.SetNumberOfInputs( 0 );
+
+		CLAM::ControlTraceWriter proc;
+
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( false, configResult );
+		
+	}
+};
+
+}
+
