From fa9b881e10e7cab8495909818cc61519d24d6117 Mon Sep 17 00:00:00 2001
From: dknn <yoann.blein@free.fr>
Date: Sat, 2 Jun 2012 17:31:42 +0200
Subject: Payload, serializer and parser for the "payload-type" XML node


diff --git a/Swiften/Elements/RTPPayloadType.h b/Swiften/Elements/RTPPayloadType.h
new file mode 100644
index 0000000..e61f921
--- /dev/null
+++ b/Swiften/Elements/RTPPayloadType.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2011 Yoann Blein
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Elements/Payload.h>
+#include <boost/shared_ptr.hpp>
+#include <boost/cstdint.hpp>
+
+#include <string>
+#include <map>
+
+namespace Swift {
+
+class RTPPayloadType : public Payload {
+public:
+	typedef boost::shared_ptr<RTPPayloadType> ref;
+	typedef std::map<std::string, std::string> ParameterMap;
+	
+public:
+	RTPPayloadType(boost::uint8_t id = 0, const std::string& name = "", boost::uint32_t clockrate = 0,
+				boost::uint8_t channels = 1, boost::uint32_t ptime = 0, boost::uint32_t maxptime = 0) :
+		m_id(id), m_name(name), m_clockrate(clockrate), m_channels(channels), m_ptime(ptime), m_maxptime(maxptime) {}
+	
+	void setChannels(boost::uint32_t channels) { m_channels = channels; }
+	boost::uint32_t getChannels() const { return m_channels; }
+	
+	void setClockrate(boost::uint32_t clockrate) { m_clockrate = clockrate; }
+	boost::uint32_t getClockrate() const { return m_clockrate; }
+	
+	void setID(boost::uint8_t id) { m_id = id; }
+	boost::uint8_t getID() const { return m_id; }
+	
+	void setMaxptime(boost::uint32_t maxptime) { m_maxptime = maxptime; }
+	boost::uint32_t getMaxptime() const { return m_maxptime; }
+
+	void setName(const std::string& name) { m_name = name; }
+	const std::string& getName() const { return m_name; }
+	
+	void setPTime(boost::uint32_t ptime) { m_ptime = ptime; }
+	boost::uint32_t getPTime() const { return m_ptime; }
+
+	bool addParameter(const std::string& name, const std::string& value) {
+		return parameters.insert(std::make_pair(name, value)).second;
+	}
+
+	const ParameterMap& getParameters() const { return parameters; }
+	
+private:
+	boost::uint8_t m_id;
+	std::string m_name;
+	boost::uint32_t m_clockrate;
+	boost::uint8_t m_channels;
+	boost::uint32_t m_ptime;
+	boost::uint32_t m_maxptime;
+	ParameterMap parameters;
+};
+
+}
diff --git a/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.cpp b/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.cpp
new file mode 100644
index 0000000..bddf96a
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2011 Yoann Blein
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "RTPPayloadTypeParser.h"
+
+#include <boost/optional.hpp>
+#include <boost/lexical_cast.hpp>
+
+//#include <Swiften/Base/DateTime.h>
+//#include <Swiften/Base/Log.h>
+
+namespace Swift {
+
+RTPPayloadTypeParser::RTPPayloadTypeParser() : level(0) {
+
+}
+
+void RTPPayloadTypeParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) {
+	if (level == 0) {
+		// channel
+		try {
+			getPayloadInternal()->setChannels(boost::lexical_cast<boost::uint32_t>(attributes.getAttributeValue("channels").get_value_or("1")));
+		} catch (boost::bad_lexical_cast &) {
+			getPayloadInternal()->setChannels(1);
+		}
+		// clockrate
+		try {
+			getPayloadInternal()->setClockrate(boost::lexical_cast<boost::uint32_t>(attributes.getAttributeValue("clockrate").get_value_or("0")));
+		} catch (boost::bad_lexical_cast &) {
+			getPayloadInternal()->setClockrate(0);
+		}
+		// ID
+		try {
+			getPayloadInternal()->setID(boost::lexical_cast<boost::uint8_t>(attributes.getAttributeValue("id").get_value_or("0")));
+		} catch (boost::bad_lexical_cast &) {
+			getPayloadInternal()->setID(0);
+		}
+		// maxptime
+		try {
+			getPayloadInternal()->setMaxptime(boost::lexical_cast<boost::uint32_t>(attributes.getAttributeValue("maxptime").get_value_or("0")));
+		} catch (boost::bad_lexical_cast &) {
+			getPayloadInternal()->setMaxptime(0);
+		}
+		// name
+		getPayloadInternal()->setName(attributes.getAttributeValue("name").get_value_or(""));
+		// ptime
+		try {
+			getPayloadInternal()->setPTime(boost::lexical_cast<boost::uint32_t>(attributes.getAttributeValue("ptime").get_value_or("0")));
+		} catch (boost::bad_lexical_cast &) {
+			getPayloadInternal()->setPTime(0);
+		}
+	} else if (level == 1) {
+		getPayloadInternal()->addParameter(attributes.getAttributeValue("name").get_value_or(""),
+				attributes.getAttributeValue("value").get_value_or(""));
+	}
+	++level;
+}
+
+void RTPPayloadTypeParser::handleEndElement(const std::string& element, const std::string&) {
+	--level;
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.h b/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.h
new file mode 100644
index 0000000..360053f
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/RTPPayloadTypeParser.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2011 Yoann Blein
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Elements/RTPPayloadType.h>
+#include <Swiften/Parser/GenericPayloadParser.h>
+
+namespace Swift {
+
+class RTPPayloadTypeParser : public GenericPayloadParser<RTPPayloadType> {
+	public:
+		RTPPayloadTypeParser();
+
+		virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes);
+		virtual void handleEndElement(const std::string& element, const std::string&);
+		virtual void handleCharacterData(const std::string&) {};
+		
+	private:
+		int level;
+};
+
+}
diff --git a/Swiften/SConscript b/Swiften/SConscript
index db18cc3..53ce39f 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -204,6 +204,7 @@ if env["SCONS_STAGE"] == "build" :
 			"Serializer/PayloadSerializers/DeliveryReceiptSerializer.cpp",
 			"Serializer/PayloadSerializers/DeliveryReceiptRequestSerializer.cpp",
 			"Serializer/PayloadSerializers/WhiteboardSerializer.cpp",
+			"Serializer/PayloadSerializers/RTPPayloadTypeSerializer.cpp",			
 			"Serializer/PresenceSerializer.cpp",
 			"Serializer/StanzaSerializer.cpp",
 			"Serializer/StreamErrorSerializer.cpp",
diff --git a/Swiften/Serializer/PayloadSerializers/RTPPayloadTypeSerializer.cpp b/Swiften/Serializer/PayloadSerializers/RTPPayloadTypeSerializer.cpp
new file mode 100644
index 0000000..db21146
--- /dev/null
+++ b/Swiften/Serializer/PayloadSerializers/RTPPayloadTypeSerializer.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2011 Yoann Blein
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <Swiften/Serializer/PayloadSerializers/RTPPayloadTypeSerializer.h>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include <Swiften/Serializer/XML/XMLElement.h>
+
+
+
+namespace Swift {
+
+RTPPayloadTypeSerializer::RTPPayloadTypeSerializer() {
+}
+								    
+std::string RTPPayloadTypeSerializer::serializePayload(boost::shared_ptr<RTPPayloadType> payloadType) const {
+	XMLElement payloadTypeElement("payload-type");
+	
+	if (payloadType->getChannels() != 1) {
+		payloadTypeElement.setAttribute("channels", boost::lexical_cast<std::string>(payloadType->getChannels()));
+	}
+	if (payloadType->getClockrate() != 0) {
+		payloadTypeElement.setAttribute("clockrate", boost::lexical_cast<std::string>(payloadType->getClockrate()));
+	}
+	payloadTypeElement.setAttribute("id", boost::lexical_cast<std::string>(static_cast<int>(payloadType->getID())));
+	if (payloadType->getMaxptime() != 0) {
+		payloadTypeElement.setAttribute("maxptime", boost::lexical_cast<std::string>(payloadType->getMaxptime()));
+	}
+	if (!payloadType->getName().empty()) {
+		payloadTypeElement.setAttribute("name", payloadType->getName());
+	}
+	if (payloadType->getPTime() != 0) {
+		payloadTypeElement.setAttribute("ptime", boost::lexical_cast<std::string>( payloadType->getPTime()));
+	}
+
+	const RTPPayloadType::ParameterMap &parameters = payloadType->getParameters();
+	RTPPayloadType::ParameterMap::const_iterator it;
+	for (it = parameters.begin(); it != parameters.end(); ++it) {
+		boost::shared_ptr<XMLElement> parameterElement = boost::make_shared<XMLElement>("parameter");
+		parameterElement->setAttribute("name", it->first);
+		parameterElement->setAttribute("value", it->second);
+		payloadTypeElement.addNode(parameterElement);
+	}
+	
+	return payloadTypeElement.serialize();
+}
+
+}
diff --git a/Swiften/Serializer/PayloadSerializers/RTPPayloadTypeSerializer.h b/Swiften/Serializer/PayloadSerializers/RTPPayloadTypeSerializer.h
new file mode 100644
index 0000000..dda40ea
--- /dev/null
+++ b/Swiften/Serializer/PayloadSerializers/RTPPayloadTypeSerializer.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2011 Yoann Blein
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Serializer/GenericPayloadSerializer.h>
+#include <Swiften/Elements/RTPPayloadType.h>
+
+#include <Swiften/Serializer/XML/XMLElement.h>
+
+namespace Swift {
+	class PayloadSerializerCollection; // NEEDED ?
+
+	class RTPPayloadTypeSerializer : public GenericPayloadSerializer<RTPPayloadType> {
+		public:
+			RTPPayloadTypeSerializer();
+
+			virtual std::string serializePayload(boost::shared_ptr<RTPPayloadType>)  const;
+	};
+}
diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp
index e3ec8fc..a1526fc 100644
--- a/Swiften/Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp
+++ b/Swiften/Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp
@@ -14,6 +14,7 @@
 #include <Swiften/Serializer/PayloadSerializers/StreamInitiationFileInfoSerializer.h>
 #include <Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.h>
 #include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h>
+#include <Swiften/Serializer/PayloadSerializers/RTPPayloadTypeSerializer.h>
 #include <Swiften/Elements/JingleFileTransferDescription.h>
 #include <Swiften/Elements/StreamInitiationFileInfo.h>
 #include <Swiften/Elements/JingleIBBTransportPayload.h>
@@ -21,12 +22,14 @@
 #include <Swiften/Elements/JingleFileTransferHash.h>
 #include <Swiften/Elements/JinglePayload.h>
 #include <Swiften/Elements/JingleFileTransferReceived.h>
+#include <Swiften/Elements/RTPPayloadType.h>
 #include <Swiften/Base/DateTime.h>
 
 using namespace Swift;
 
 class JingleSerializersTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST_SUITE(JingleSerializersTest);
+
 		CPPUNIT_TEST(testSerialize_StreamInitiationFileInfo);
 		CPPUNIT_TEST(testSerialize_StreamInitiationFileInfoRange);
 		
@@ -43,6 +46,9 @@ class JingleSerializersTest : public CppUnit::TestFixture {
 
 		CPPUNIT_TEST(testSerialize_Xep0260_Example1);
 
+		CPPUNIT_TEST(testSerialize_RTPPayloadType_Simple);
+		CPPUNIT_TEST(testSerialize_RTPPayloadType_WithSub);
+
 		CPPUNIT_TEST_SUITE_END();
 		
 		 boost::shared_ptr<JinglePayloadSerializer> createTestling() {
@@ -504,6 +510,39 @@ class JingleSerializersTest : public CppUnit::TestFixture {
 			CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload));
 		}
 
+		void testSerialize_RTPPayloadType_Simple() {
+			std::string expected =	"<payload-type clockrate=\"16000\" id=\"96\" name=\"speex\"/>";
+			
+			RTPPayloadType::ref payloadType = boost::make_shared<RTPPayloadType>(96);
+			payloadType->setName("speex");
+			payloadType->setClockrate(16000);
+			
+			boost::shared_ptr<RTPPayloadTypeSerializer> serializer = boost::make_shared<RTPPayloadTypeSerializer>();
+			CPPUNIT_ASSERT_EQUAL(expected, serializer->serializePayload(payloadType));
+		}
+			
+		void testSerialize_RTPPayloadType_WithSub() {
+			std::string expected =	"<payload-type clockrate=\"90000\" id=\"98\" name=\"theora\">"
+										"<parameter name=\"configuration\" value=\"somebase16string\"/>"
+										"<parameter name=\"delivery-method\" value=\"inline\"/>"
+										"<parameter name=\"height\" value=\"600\"/>"
+										"<parameter name=\"sampling\" value=\"YCbCr-4:2:2\"/>"
+										"<parameter name=\"width\" value=\"800\"/>"
+									"</payload-type>";
+			
+			RTPPayloadType::ref payloadType = boost::make_shared<RTPPayloadType>(98);
+			payloadType->setName("theora");
+			payloadType->setClockrate(90000);
+			payloadType->addParameter("height", "600");
+			payloadType->addParameter("width", "800");
+			payloadType->addParameter("delivery-method", "inline");
+			payloadType->addParameter("configuration", "somebase16string");
+			payloadType->addParameter("sampling", "YCbCr-4:2:2");
+			
+			boost::shared_ptr<RTPPayloadTypeSerializer> serializer = boost::make_shared<RTPPayloadTypeSerializer>();
+			CPPUNIT_ASSERT_EQUAL(expected, serializer->serializePayload(payloadType));
+		}
+
 	private:
 		FullPayloadSerializerCollection collection;
 };
-- 
cgit v0.10.2-6-g49f6