diff --git a/Source/Processors/Channel/InfoObjects.h b/Source/Processors/Channel/InfoObjects.h
index 2cf7eb8f34bd3aabe7788a00691a22c7f10b24ee..cc2ea71544f290f0065dd265f14bc0772bede7b0 100644
--- a/Source/Processors/Channel/InfoObjects.h
+++ b/Source/Processors/Channel/InfoObjects.h
@@ -239,7 +239,7 @@ public:
 	{
 		//Numeration kept to maintain compatibility with old code
 		TTL = 3,
-		MESSAGE = 5,
+		TEXT = 5,
 		//generic binary types. These will be treated by the majority of record engines as simple binary blobs,
 		//while having strict typing helps creating stabler plugins
 		INT8_ARRAY = 10,
@@ -255,7 +255,7 @@ public:
 	};
 
 	/** Default constructor
-	@param type The type of event this channel represents (TTL, MESSAGE, BYINARY_MSG)
+	@param type The type of event this channel represents (TTL, TEXT, BYINARY_MSG)
 	@param idx The index of this event channel in the source processor
 	@param typeidx The index of this particular type of event channel in the source processor
 	@param source A pointer to the source processor
diff --git a/Source/Processors/Channel/MetaData.cpp b/Source/Processors/Channel/MetaData.cpp
index e29e5dd68191a2e6ed521769d46b4c26407aa479..c5b8726963af74c41be5866670a3bc3efd20e6fa 100644
--- a/Source/Processors/Channel/MetaData.cpp
+++ b/Source/Processors/Channel/MetaData.cpp
@@ -119,7 +119,7 @@ MetaDataValue::MetaDataValue(const MetaDataDescriptor& m)
 
 bool MetaDataValue::isOfType(const MetaDataDescriptor& m) const
 {
-	return ((m.getType() == m_type) && (m.getLength == m_length));
+	return ((m.getType() == m_type) && (m.getLength() == m_length));
 }
 
 bool MetaDataValue::isOfType(const MetaDataDescriptor* m) const
@@ -171,6 +171,7 @@ MetaDataValue& MetaDataValue::operator=(MetaDataValue&& v)
 	m_length = v.m_length;
 	m_type = v.m_type;
 	m_data.swapWith(v.m_data);
+	return *this;
 }
 #endif
 
@@ -193,16 +194,16 @@ void MetaDataValue::getValue(String& data) const
 template <typename T>
 void MetaDataValue::setValue(T data)
 {
-	jassert(m_numel == 1);
+	jassert(m_length == 1);
 	jassert(checkMetaDataType<T>(m_type));
-	*(static_cast<T*>(m_data.getData())) = data;
+	*(reinterpret_cast<T*>(m_data.getData())) = data;
 }
 
 template <typename T>
 void MetaDataValue::getValue(T& data) const
 {
 	jassert(checkMetaDataType<T>(m_type));
-	data = *(static_cast<T*>(m_data.getData()));
+	data = *(reinterpret_cast<T*>(m_data.getData()));
 }
 
 template <typename T>
@@ -230,7 +231,7 @@ template <typename T>
 void MetaDataValue::getValue(Array<T>& data) const
 {
 	jassert(checkMetaDataType<T>(m_type));
-	data.addArray(m_data.getData(), m_numel);
+	data.addArray(m_data.getData(), m_length);
 }
 
 //Actual template instantiations at the end of the file
@@ -288,7 +289,7 @@ const int MetaDataEventObject::getEventMetaDataCount() const
 }
 
 //MetaDataEvent
-void MetaDataEvent::SerializeMetaData(void* dstBuffer) const
+void MetaDataEvent::serializeMetaData(void* dstBuffer) const
 {
 	int metaDataSize = m_metaDataValues.size();
 	char* buffer = static_cast<char*>(dstBuffer);
@@ -296,12 +297,30 @@ void MetaDataEvent::SerializeMetaData(void* dstBuffer) const
 
 	for (int i = 0; i < metaDataSize; i++)
 	{
-		MetaDataValue* val = m_metaDataValues[i];
+		MetaDataValuePtr val = m_metaDataValues[i];
 		memcpy(buffer + ptrIndex, val->m_data.getData(), val->m_size);
 		ptrIndex += val->m_size;
 	}
 }
 
+bool MetaDataEvent::deserializeMetaData(const MetaDataEventObject* info, const void* srcBuffer, int size)
+{
+	MetaDataValueArray metaData;
+	int nMetaData = info->getEventMetaDataCount();
+	size_t memIndex = 0;
+	for (int i = 0; i < nMetaData; i++)
+	{
+		const MetaDataDescriptor* desc = info->getEventMetaDataDescriptor(i);
+		size_t dataSize = desc->getDataSize();
+		if ((memIndex + dataSize) < size) return false; //check for buffer boundaries
+		
+		metaData.add(new MetaDataValue(*desc, (static_cast<const char*>(srcBuffer) + memIndex)));
+		memIndex += dataSize;
+	}
+	m_metaDataValues.swapWith(metaData);
+	return true;
+}
+
 //Specific instantiations for templated metadata members.
 //This is done this way for two reasons
 //1-To have the actual binary code in the same translation unit, instead of replicated between GUI and plugins, as would happen if
@@ -370,7 +389,7 @@ template void MetaDataValue::setValue<float>(const Array<float>&);
 template void MetaDataValue::setValue<double>(const Array<double>&);
 
 template void MetaDataValue::getValue<char>(Array<char>&) const;
-template void MetaDataValue::getValue<int8>(Array<int8>&) const;
+/*template void MetaDataValue::getValue<int8>(Array<int8>&) const;
 template void MetaDataValue::getValue<uint8>(Array<uint8>&) const;
 template void MetaDataValue::getValue<int16>(Array<int16>&) const;
 template void MetaDataValue::getValue<uint16>(Array<uint16>&) const;
@@ -379,4 +398,5 @@ template void MetaDataValue::getValue<uint32>(Array<uint32>&) const;
 template void MetaDataValue::getValue<int64>(Array<int64>&) const;
 template void MetaDataValue::getValue<uint64>(Array<uint64>&) const;
 template void MetaDataValue::getValue<float>(Array<float>&) const;
-template void MetaDataValue::getValue<double>(Array<double>&) const;
\ No newline at end of file
+template void MetaDataValue::getValue<double>(Array<double>&) const;
+*/
\ No newline at end of file
diff --git a/Source/Processors/Channel/MetaData.h b/Source/Processors/Channel/MetaData.h
index da490689df5fa796fe147b7b35ae32e151f661ed..379c51a0e43c80a71421aa1d2c8f11c520f6502a 100644
--- a/Source/Processors/Channel/MetaData.h
+++ b/Source/Processors/Channel/MetaData.h
@@ -24,7 +24,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #ifndef METADATA_H_INCLUDED
 #define METADATA_H_INCLUDED
 
-#include "../../../JuceLibraryCode/JuceHeader.h"
+#include <JuceHeader.h>
 #include "../PluginManager/OpenEphysPlugin.h"
 
 class GenericProcessor;
@@ -141,6 +141,8 @@ private:
 
 typedef ReferenceCountedArray<MetaDataDescriptor> MetaDataDescriptorArray;
 typedef ReferenceCountedArray<MetaDataValue> MetaDataValueArray;
+typedef ReferenceCountedObjectPtr<MetaDataDescriptor> MetaDataDescriptorPtr;
+typedef ReferenceCountedObjectPtr<MetaDataValue> MetaDataValuePtr;
 
 //Inherited for all info objects that have metadata
 class PLUGIN_API MetaDataInfoObject
@@ -188,10 +190,10 @@ protected:
 class PLUGIN_API MetaDataEvent
 {
 protected:
-	void SerializeMetaData(void* dstBuffer) const;
+	void serializeMetaData(void* dstBuffer) const;
+	bool deserializeMetaData(const MetaDataEventObject* info, const void* srcBuffer, int size);
 	MetaDataEvent();
 	MetaDataValueArray m_metaDataValues;
-
 };
 
 
diff --git a/Source/Processors/Events/Events.cpp b/Source/Processors/Events/Events.cpp
index 9cfdf89322515462c896ad721eb28919ab5c43f5..9736213db3736a35fc6b61a6e1a2c84d968f8446 100644
--- a/Source/Processors/Events/Events.cpp
+++ b/Source/Processors/Events/Events.cpp
@@ -23,7 +23,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include "Events.h"
 #include "../GenericProcessor/GenericProcessor.h"
-#define EVENT_EXTRA_SIZE 16
+#define EVENT_BASE_SIZE 18
 
 //EventBase
 
@@ -99,40 +99,41 @@ EventChannel::EventChannelTypes Event::getEventType(const MidiMessage& msg)
 	return static_cast<EventChannel::EventChannelTypes>(*(data + 1));
 }
 
-Event::Event(const EventChannel* channelInfo, uint64 timestamp)
+Event::Event(const EventChannel* channelInfo, uint64 timestamp, uint16 channel)
 	: EventBase(PROCESSOR_EVENT, timestamp),
+	m_channel(channel),
 	m_channelInfo(channelInfo),
 	m_eventType(channelInfo->getChannelType())
 {}
 
 Event* Event::deserializeFromMessage(const MidiMessage& msg, const EventChannel* channelInfo)
 {
-	EventChannel::EventChannelTypes type = channelInfo->getChannelType());
+	EventChannel::EventChannelTypes type = channelInfo->getChannelType();
 	
 	if (type == EventChannel::TTL)
 		return TTLEvent::deserializeFromMessage(msg, channelInfo);
-	else if (type == EventChannel::MESSAGE)
-		return MessageEvent::deserializeFromMessage(msg, channelInfo);
+	else if (type == EventChannel::TEXT)
+		return TextEvent::deserializeFromMessage(msg, channelInfo);
 	else if (type >= EventChannel::INT8_ARRAY && type <= EventChannel::DOUBLE_ARRAY)
 		return BinaryEvent::deserializeFromMessage(msg, channelInfo);
 	else return nullptr;
 }
 
+uint16 Event::getChannel() const
+{
+	return m_channel;
+}
+
 //TTLEvent
 
-TTLEvent::TTLEvent(const EventChannel* channelInfo, uint64 timestamp, unsigned int channel, const void* eventData)
-	: Event(channelInfo, timestamp), m_channel(channel)
+TTLEvent::TTLEvent(const EventChannel* channelInfo, uint64 timestamp, uint16 channel, const void* eventData)
+	: Event(channelInfo, timestamp, channel)
 {
 	size_t size = m_channelInfo->getDataSize();
 	m_data.malloc(size);
 	memcpy(m_data.getData(), eventData, size);
 }
 
-unsigned int TTLEvent::getChannel() const
-{
-	return m_channel;
-}
-
 bool TTLEvent::getState() const
 {
 	int byteIndex = m_channel / 8;
@@ -147,10 +148,10 @@ const void* TTLEvent::getTTLWordPointer() const
 	return m_data.getData();
 }
 
-void TTLEvent::Serialize(void* dstBuffer, size_t dstSize) const
+void TTLEvent::serialize(void* dstBuffer, size_t dstSize) const
 {
 	size_t dataSize = m_channelInfo->getDataSize();
-	size_t eventSize = dataSize + EVENT_EXTRA_SIZE; 
+	size_t eventSize = dataSize + EVENT_BASE_SIZE; 
 	size_t totalSize = eventSize + m_channelInfo->getTotalEventMetaDataSize();
 	if (totalSize < dstSize)
 	{
@@ -166,11 +167,12 @@ void TTLEvent::Serialize(void* dstBuffer, size_t dstSize) const
 	*(reinterpret_cast<uint16*>(buffer + 4)) = m_channelInfo->getSubProcessorIdx();
 	*(reinterpret_cast<uint16*>(buffer + 6)) = m_channelInfo->getSourceIndex();
 	*(reinterpret_cast<uint64*>(buffer + 8)) = m_timestamp;
-	memcpy((buffer + 16), m_data.getData(), dataSize);
-	SerializeMetaData(buffer + eventSize);
+	*(reinterpret_cast<uint64*>(buffer + 16)) = m_channel;
+	memcpy((buffer + 18), m_data.getData(), dataSize);
+	serializeMetaData(buffer + eventSize);
 }
 
-TTLEvent* TTLEvent::createTTLEvent(const EventChannel* channelInfo, uint64 timestamp, unsigned int channel, const void* eventData)
+TTLEvent* TTLEvent::createTTLEvent(const EventChannel* channelInfo, uint64 timestamp, const void* eventData, uint16 channel)
 {
 
 	if (!channelInfo) return nullptr;
@@ -181,7 +183,7 @@ TTLEvent* TTLEvent::createTTLEvent(const EventChannel* channelInfo, uint64 times
 	return new TTLEvent(channelInfo, timestamp, channel, eventData);
 }
 
-TTLEvent* TTLEvent::createTTLEvent(const EventChannel* channelInfo, uint64 timestamp, unsigned int channel, const void* eventData, const MetaDataValueArray& metaData)
+TTLEvent* TTLEvent::createTTLEvent(const EventChannel* channelInfo, uint64 timestamp, const void* eventData, const MetaDataValueArray& metaData, uint16 channel)
 {
 
 	if (!channelInfo) return nullptr;
@@ -198,8 +200,10 @@ TTLEvent* TTLEvent::createTTLEvent(const EventChannel* channelInfo, uint64 times
 TTLEvent* TTLEvent::deserializeFromMessage(const MidiMessage& msg, const EventChannel* channelInfo)
 {
 	size_t totalSize = msg.getRawDataSize();
+	size_t dataSize = channelInfo->getDataSize();
+	size_t metaDataSize = channelInfo->getTotalEventMetaDataSize();
 
-	if (totalSize != (channelInfo->getDataSize() + EVENT_EXTRA_SIZE + channelInfo->getTotalEventMetaDataSize()))
+	if (totalSize != (dataSize + EVENT_BASE_SIZE + metaDataSize))
 	{
 		return nullptr;
 	}
@@ -207,7 +211,24 @@ TTLEvent* TTLEvent::deserializeFromMessage(const MidiMessage& msg, const EventCh
 	if ((buffer + 0) != PROCESSOR_EVENT) return nullptr;
 	if ((buffer + 1) != EventChannel::TTL) return nullptr;
 
-	
+	uint64 timestamp = *(reinterpret_cast<const uint64*>(buffer + 8));
+	uint16 channel = *(reinterpret_cast<const uint16*>(buffer + 16));
+
+	ScopedPointer<TTLEvent> ttl = new TTLEvent(channelInfo, timestamp, channel, (buffer + 16));
+	bool ret;
+	if (metaDataSize > 0)
+		 ret = ttl->deserializeMetaData(channelInfo, (buffer + EVENT_BASE_SIZE + dataSize), metaDataSize);
 
+	if (ret)
+		return ttl.release();
+	else
+		return nullptr;
+}
+
+//TextEvent
+
+TextEvent(const EventChannel* channelInfo, uint64 timestamp, uint16 channel, const String& msg)
+	: Event(channelInfo, timestamp, channel)
+{
 
 }
\ No newline at end of file
diff --git a/Source/Processors/Events/Events.h b/Source/Processors/Events/Events.h
index f4546da9c49adac36fecfa624a75445d60d8e931..ec289e1d6c394b03609a3b9d73c1363014fe2a30 100644
--- a/Source/Processors/Events/Events.h
+++ b/Source/Processors/Events/Events.h
@@ -36,7 +36,8 @@ EventType - 1byte
 SubType - 1byte
 Source processor ID - 2bytes
 Source Subprocessor index - 2 bytes
-Source Channel index (except system events)
+Source Event index - 2 bytes (except system events)
+Event Virtual Channel - 2 byte
 Timestamp - 8 bytes (except for system events that are not timestamp)
 data - variable
 */
@@ -59,7 +60,7 @@ class PLUGIN_API EventBase
 	: public MetaDataEvent
 {
 public: 
-	virtual void Serialize(void* dstBuffer, size_t dstSize) const = 0;
+	virtual void serialize(void* dstBuffer, size_t dstSize) const = 0;
 	EventType getBaseType() const;
 
 	static EventType getBaseType(const MidiMessage& msg);
@@ -78,17 +79,21 @@ class PLUGIN_API Event
 	: public EventBase
 {
 public:
-	virtual void Serialize(void* dstBuffer, size_t dstSize) const override = 0;
+	virtual void serialize(void* dstBuffer, size_t dstSize) const override = 0;
 	EventChannel::EventChannelTypes getEventType() const;
 	const EventChannel* getChannelInfo() const;
 
+	/** Gets the channel that triggered the event */
+	uint16 getChannel() const;
+
 	static EventChannel::EventChannelTypes getEventType(const MidiMessage& msg);
 	static Event* deserializeFromMessage(const MidiMessage& msg, const EventChannel* channelInfo);
 
 protected:
-	Event(const EventChannel* channelInfo, uint64 timestamp);
+	Event(const EventChannel* channelInfo, uint64 timestamp, uint16 channel);
 	Event() = delete;
 
+	const uint16 m_channel;
 	const EventChannel* m_channelInfo;
 	const EventChannel::EventChannelTypes m_eventType;
 
@@ -98,64 +103,61 @@ class PLUGIN_API TTLEvent
 	: public Event
 {
 public:
-	void Serialize(void* dstBuffer, size_t dstSize) const override;
+	void serialize(void* dstBuffer, size_t dstSize) const override;
 
-	/** Gets the channel that triggered the event */
-	unsigned int getChannel() const;
 	/** Gets the state true ='1' false = '0'*/
 	bool getState() const;
 	
 	const void* getTTLWordPointer() const;
 
-	static TTLEvent* createTTLEvent(const EventChannel* channelInfo, uint64 timestamp, unsigned int channel,const void* eventData);
-	static TTLEvent* createTTLEvent(const EventChannel* channelInfo, uint64 timestamp, unsigned int channel, const void* eventData, const MetaDataValueArray& metaData);
+	static TTLEvent* createTTLEvent(const EventChannel* channelInfo, uint64 timestamp, const void* eventData, uint16 channel);
+	static TTLEvent* createTTLEvent(const EventChannel* channelInfo, uint64 timestamp, const void* eventData, const MetaDataValueArray& metaData, uint16 channel);
 	static TTLEvent* deserializeFromMessage(const MidiMessage& msg, const EventChannel* channelInfo);
 private:
 	TTLEvent() = delete;
-	TTLEvent(const EventChannel* channelInfo, uint64 timestamp, unsigned int channel, const void* eventData);
+	TTLEvent(const EventChannel* channelInfo, uint64 timestamp, uint16 channel, const void* eventData);
 
-	const unsigned int m_channel;
 	HeapBlock<char> m_data;
 	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(TTLEvent);
 };
 
-class PLUGIN_API MessageEvent
+class PLUGIN_API TextEvent
 	: public Event
 {
 public:
-	void Serialize(void* dstBuffer, size_t dstSize) const override;
-	String getMessage() const;
+	void serialize(void* dstBuffer, size_t dstSize) const override;
+	String getText() const;
 
-	static MessageEvent* createMessageEvent(const EventChannel* channelInfo, uint64 timestamp, const String& msg);
-	static MessageEvent* createMessageEvent(const EventChannel* channelInfo, uint64 timestamp, const String& msg, const MetaDataValueArray& metaData);
-	static MessageEvent* deserializeFromMessage(const MidiMessage& msg, const EventChannel* channelInfo);
+	static TextEvent* createMessageEvent(const EventChannel* channelInfo, uint64 timestamp, const String& msg, uint16 channel = 1);
+	static TextEvent* createMessageEvent(const EventChannel* channelInfo, uint64 timestamp, const String& msg, const MetaDataValueArray& metaData, uint16 channel = 1);
+	static TextEvent* deserializeFromMessage(const MidiMessage& msg, const EventChannel* channelInfo);
 private:
-	MessageEvent() = delete;
-	MessageEvent(const EventChannel* channelInfo, uint64 timestamp, const String& msg);
+	TextEvent() = delete;
+	TextEvent(const EventChannel* channelInfo, uint64 timestamp, uint16 channel, const String& msg);
 
 	const String m_msg;
-	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MessageEvent);
+	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(TextEvent);
 };
 
 class PLUGIN_API BinaryEvent
 	: public Event
 {
 public:
-	void Serialize(void* dstBuffer, size_t dstSize) const override;
+	void serialize(void* dstBuffer, size_t dstSize) const override;
 
 	const void* getBinaryDataPointer() const;
 
 	template<typename T>
-	static BinaryEvent* createBinaryEvent(const EventChannel* channelInfo, uint64 timestamp, const T* data);
+	static BinaryEvent* createBinaryEvent(const EventChannel* channelInfo, uint64 timestamp, const T* data, uint16 channel = 1);
 
 	template<typename T>
-	static BinaryEvent* createBinaryEvent(const EventChannel* channelInfo, uint64 timestamp, const T* data, const MetaDataValueArray& metaData);
+	static BinaryEvent* createBinaryEvent(const EventChannel* channelInfo, uint64 timestamp, const T* data, const MetaDataValueArray& metaData, uint16 channel = 1);
 
 	static BinaryEvent* deserializeFromMessage(const MidiMessage& msg, const EventChannel* channelInfo);
 	
 private:
 	BinaryEvent() = delete;
-	BinaryEvent(const EventChannel* channelInfo, uint64 timestamp, const void* data);
+	BinaryEvent(const EventChannel* channelInfo, uint64 timestamp, uint16 channel, const void* data);
 
 	HeapBlock<char> m_data;
 	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(BinaryEvent);
@@ -179,7 +181,7 @@ public:
 		Array<unsigned int> positions; 
 
 	};
-	void Serialize(void* dstBuffer, size_t dstSize) const override;
+	void serialize(void* dstBuffer, size_t dstSize) const override;
 
 	const float* getDataPointer() const;