diff options
| author | Remko Tronçon <git@el-tramo.be> | 2014-01-19 11:46:51 (GMT) | 
|---|---|---|
| committer | Remko Tronçon <git@el-tramo.be> | 2014-01-19 16:49:19 (GMT) | 
| commit | cbd01a5368f0b761d2032d75c9f7dfde2bf61578 (patch) | |
| tree | 5016505b1e977e84655cc3bba4435ef7cb80e811 | |
| parent | 4083d6da47ac0e3b77da9c7c222a9439b3e1c04c (diff) | |
| download | swift-cbd01a5368f0b761d2032d75c9f7dfde2bf61578.zip swift-cbd01a5368f0b761d2032d75c9f7dfde2bf61578.tar.bz2 | |
Sluift: Add iTunes & PEP User Tune support
Change-Id: I25b3840bb40ce38531922cc737bc82828e026d3f
25 files changed, 676 insertions, 6 deletions
| diff --git a/BuildTools/scons2ninja.py b/BuildTools/scons2ninja.py index 2666ae6..0ca3e42 100755 --- a/BuildTools/scons2ninja.py +++ b/BuildTools/scons2ninja.py @@ -343,6 +343,9 @@ ninja.rule('generator',    generator = '1',    description = 'Regenerating build.ninja') +ninja.rule('sdef', +  command = 'sdef $in | sdp -fh --basename $basename -o $outdir', +  description = 'SDEF $out')  ################################################################################  # Build Statements @@ -580,6 +583,15 @@ for line in build_lines :      files, flags = extract_non_flags(flags)      ninja.build(out, 'dsymutil', files, dsymutilflags = flags) +  elif tool == 'sdef' : +    source = flags[0]; +    outdir, flags = extract_binary_flag("-o", flags) +    basename, flags = extract_binary_flag("--basename", flags) +    ninja.build(os.path.join(outdir, basename + ".h"), 'sdef', [source],  +        basename = basename, +        outdir = outdir) + +    elif not ninja_custom_command(ninja, line)  :      raise Exception("Unknown tool: '" + line + "'") diff --git a/Sluift/.gitignore b/Sluift/.gitignore index e2d8bbf..4e4c2a4 100644 --- a/Sluift/.gitignore +++ b/Sluift/.gitignore @@ -4,5 +4,6 @@ sluift_dll.cpp  sluift  dll.c  core.c +iTunes.h  dll/  exe/ diff --git a/Sluift/ElementConvertors/ElementConvertors.ipp b/Sluift/ElementConvertors/ElementConvertors.ipp index b7b9166..da25eb6 100644 --- a/Sluift/ElementConvertors/ElementConvertors.ipp +++ b/Sluift/ElementConvertors/ElementConvertors.ipp @@ -1,5 +1,5 @@  /* - * Copyright (c) 2013 Remko Tronçon + * Copyright (c) 2013-2014 Remko Tronçon   * Licensed under the GNU General Public License.   * See the COPYING file for more information.   */ @@ -10,6 +10,7 @@  #include <Sluift/ElementConvertors/PubSubItemsConvertor.h>  #include <Sluift/ElementConvertors/PubSubOwnerRedirectConvertor.h>  #include <Sluift/ElementConvertors/PubSubEventRedirectConvertor.h> +#include <Sluift/ElementConvertors/UserTuneConvertor.h>  #include <Sluift/ElementConvertors/PubSubConfigureConvertor.h>  #include <Sluift/ElementConvertors/PubSubEventDisassociateConvertor.h>  #include <Sluift/ElementConvertors/PubSubOwnerAffiliationsConvertor.h> @@ -48,6 +49,7 @@ void LuaElementConvertors::registerConvertors() {  	convertors.push_back(boost::make_shared<PubSubItemsConvertor>(this));  	convertors.push_back(boost::make_shared<PubSubOwnerRedirectConvertor>(this));  	convertors.push_back(boost::make_shared<PubSubEventRedirectConvertor>(this)); +	convertors.push_back(boost::make_shared<UserTuneConvertor>(this));  	convertors.push_back(boost::make_shared<PubSubConfigureConvertor>(this));  	convertors.push_back(boost::make_shared<PubSubEventDisassociateConvertor>(this));  	convertors.push_back(boost::make_shared<PubSubOwnerAffiliationsConvertor>(this)); diff --git a/Sluift/ElementConvertors/SConscript b/Sluift/ElementConvertors/SConscript index e98f7c4..921e325 100644 --- a/Sluift/ElementConvertors/SConscript +++ b/Sluift/ElementConvertors/SConscript @@ -8,6 +8,7 @@ convertors = [  	env.File("PubSubItemsConvertor.cpp"),  	env.File("PubSubOwnerRedirectConvertor.cpp"),  	env.File("PubSubEventRedirectConvertor.cpp"), +	env.File("UserTuneConvertor.cpp"),  	env.File("PubSubConfigureConvertor.cpp"),  	env.File("PubSubEventDisassociateConvertor.cpp"),  	env.File("PubSubOwnerAffiliationsConvertor.cpp"), diff --git a/Sluift/ElementConvertors/UserTuneConvertor.cpp b/Sluift/ElementConvertors/UserTuneConvertor.cpp new file mode 100644 index 0000000..22ca94e --- /dev/null +++ b/Sluift/ElementConvertors/UserTuneConvertor.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2014 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Sluift/ElementConvertors/UserTuneConvertor.h> + +#include <lua.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <boost/numeric/conversion/cast.hpp> + + + +#pragma clang diagnostic ignored "-Wunused-private-field" + +using namespace Swift; + +UserTuneConvertor::UserTuneConvertor(LuaElementConvertors* convertors) :  +		GenericLuaElementConvertor<UserTune>("user_tune"), +		convertors(convertors) { +} + +UserTuneConvertor::~UserTuneConvertor() { +} + +boost::shared_ptr<UserTune> UserTuneConvertor::doConvertFromLua(lua_State* L) { +	boost::shared_ptr<UserTune> result = boost::make_shared<UserTune>(); +	lua_getfield(L, -1, "rating"); +	if (lua_isnumber(L, -1)) { +		result->setRating(boost::numeric_cast<unsigned int>(lua_tonumber(L, -1))); +	} +	lua_pop(L, 1); +	lua_getfield(L, -1, "title"); +	if (lua_isstring(L, -1)) { +		result->setTitle(std::string(lua_tostring(L, -1))); +	} +	lua_pop(L, 1); +	lua_getfield(L, -1, "track"); +	if (lua_isstring(L, -1)) { +		result->setTrack(std::string(lua_tostring(L, -1))); +	} +	lua_pop(L, 1); +	lua_getfield(L, -1, "artist"); +	if (lua_isstring(L, -1)) { +		result->setArtist(std::string(lua_tostring(L, -1))); +	} +	lua_pop(L, 1); +	lua_getfield(L, -1, "uri"); +	if (lua_isstring(L, -1)) { +		result->setURI(std::string(lua_tostring(L, -1))); +	} +	lua_pop(L, 1); +	lua_getfield(L, -1, "source"); +	if (lua_isstring(L, -1)) { +		result->setSource(std::string(lua_tostring(L, -1))); +	} +	lua_pop(L, 1); +	lua_getfield(L, -1, "length"); +	if (lua_isnumber(L, -1)) { +		result->setLength(boost::numeric_cast<unsigned int>(lua_tonumber(L, -1))); +	} +	lua_pop(L, 1); +	return result; +} + +void UserTuneConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<UserTune> payload) { +	lua_createtable(L, 0, 0); +	if (payload->getRating()) { +		lua_pushnumber(L, (*payload->getRating())); +		lua_setfield(L, -2, "rating"); +	} +	if (payload->getTitle()) { +		lua_pushstring(L, (*payload->getTitle()).c_str()); +		lua_setfield(L, -2, "title"); +	} +	if (payload->getTrack()) { +		lua_pushstring(L, (*payload->getTrack()).c_str()); +		lua_setfield(L, -2, "track"); +	} +	if (payload->getArtist()) { +		lua_pushstring(L, (*payload->getArtist()).c_str()); +		lua_setfield(L, -2, "artist"); +	} +	if (payload->getURI()) { +		lua_pushstring(L, (*payload->getURI()).c_str()); +		lua_setfield(L, -2, "uri"); +	} +	if (payload->getSource()) { +		lua_pushstring(L, (*payload->getSource()).c_str()); +		lua_setfield(L, -2, "source"); +	} +	if (payload->getLength()) { +		lua_pushnumber(L, (*payload->getLength())); +		lua_setfield(L, -2, "length"); +	} +} + +boost::optional<LuaElementConvertor::Documentation> UserTuneConvertor::getDocumentation() const { +	return Documentation( +		"UserTune", +		"This table has the following fields:\n\n" +		"- `rating`: number (Optional)\n" +		"- `title`: string (Optional)\n" +		"- `track`: string (Optional)\n" +		"- `artist`: string (Optional)\n" +		"- `uri`: string (Optional)\n" +		"- `source`: string (Optional)\n" +		"- `length`: number (Optional)\n" +	); +} diff --git a/Sluift/ElementConvertors/UserTuneConvertor.h b/Sluift/ElementConvertors/UserTuneConvertor.h new file mode 100644 index 0000000..6f95164 --- /dev/null +++ b/Sluift/ElementConvertors/UserTuneConvertor.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/Override.h> + +#include <Sluift/GenericLuaElementConvertor.h> +#include <Swiften/Elements/UserTune.h> + +namespace Swift { +	class LuaElementConvertors; + +	class UserTuneConvertor : public GenericLuaElementConvertor<UserTune> { +		public: +			UserTuneConvertor(LuaElementConvertors* convertors); +			virtual ~UserTuneConvertor(); + +			virtual boost::shared_ptr<UserTune> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; +			virtual void doConvertToLua(lua_State*, boost::shared_ptr<UserTune>) SWIFTEN_OVERRIDE; +			virtual boost::optional<Documentation> getDocumentation() const SWIFTEN_OVERRIDE; + +		private: +			LuaElementConvertors* convertors; +	}; +} diff --git a/Sluift/Examples/Tunes.lua b/Sluift/Examples/Tunes.lua new file mode 100644 index 0000000..37ad996 --- /dev/null +++ b/Sluift/Examples/Tunes.lua @@ -0,0 +1,68 @@ +--[[ +	Copyright (c) 2014 Remko Tronçon +	Licensed under the GNU General Public License v3. +	See Documentation/Licenses/GPLv3.txt for more information. +--]] + +--[[ + +	Tune Publisher/Listener + +	Publishes the currently playing tune in iTunes, and prints  +	the playing tunes of contacts + +	The following environment variables are used: +	- SLUIFT_JID, SWIFT_PASS: JID and password to log in with +	- SLUIFT_DEBUG: Sets whether debugging should be turned on + +--]] + +require 'sluift' + +sluift.debug = os.getenv('SLUIFT_DEBUG') or false + +client = sluift.new_client(os.getenv('SLUIFT_JID'), os.getenv('SLUIFT_PASS')) +client:connect(function (c)  +	-- Send initial presence (with service discovery information) +	c:set_caps_node('http://swift.im/Tunes') +	c:set_disco_info{ +		identities = {{name = 'Tunes'}},  +		features = { +			sluift.disco.features.DISCO_INFO, +			sluift.disco.features.USER_TUNE .. '+notify' +	}} +	c:send_presence{priority = -1} + +	local pubsub = c:pubsub(sluift.jid.to_bare(c:jid())) +	local tunes_node = pubsub:node(sluift.disco.features.USER_TUNE) +	local current_track = nil +	while true do +		-- Publish currently playing tune +		if sluift.itunes then +			local track = sluift.itunes.get_current_track() +			if track ~= current_track then +				tunes_node:publish{item = { +					_type = 'user_tune', +					title = track.name, +					artist = track.artist, +					track = track.track_number, +					source = track.album, +					length = track.length, +					rating = track.rating and track.rating / 10 or nil +				}} +				current_track = track +			end +		end + +		-- Print incoming events for a while +		for event in c:pubsub_events{timeout = 1000} do +			if event._type == 'pubsub_event_items'  +					and event.node == sluift.disco.features.USER_TUNE +					and event.item.title then +				print(event.from .. ' is playing "'  +					.. (event.item.artist or '<Unknown Artist>') .. ' - '  +					.. event.item.title .. '"') +			end +		end +	end +end) diff --git a/Sluift/ITunesInterface.h b/Sluift/ITunesInterface.h new file mode 100644 index 0000000..c3cccd2 --- /dev/null +++ b/Sluift/ITunesInterface.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> + +#include <boost/shared_ptr.hpp> +#include <boost/optional/optional_fwd.hpp> + +namespace Swift { +	class SWIFTEN_API ITunesInterface { +		public: +			struct Track { +				std::string name; +				std::string artist; +				std::string album; +				long trackNumber; +				double duration; +				long rating; +			}; + +			ITunesInterface(); +			virtual ~ITunesInterface(); + +			boost::optional<Track> getCurrentTrack() const; + +		private: +			bool haveApplication() const; + +		private: +			struct Private; +			boost::shared_ptr<Private> p; +	}; +} diff --git a/Sluift/ITunesInterface.mm b/Sluift/ITunesInterface.mm new file mode 100644 index 0000000..19c6253 --- /dev/null +++ b/Sluift/ITunesInterface.mm @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Sluift/ITunesInterface.h> + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wfour-char-constants" +#import <Sluift/iTunes.h> +#pragma clang diagnostic pop +#include <ScriptingBridge/ScriptingBridge.h> + +#include <boost/smart_ptr/make_shared.hpp> +#include <boost/optional.hpp> +#include <SwifTools/Cocoa/CocoaUtil.h> + +using namespace Swift; + +struct ITunesInterface::Private { +	Private() : iTunes(nil) { +	} + +	iTunesApplication* iTunes; +}; + +ITunesInterface::ITunesInterface() : p(boost::make_shared<Private>()) { +} + +ITunesInterface::~ITunesInterface() { +} + +boost::optional<ITunesInterface::Track> ITunesInterface::getCurrentTrack() const { +	if (!haveApplication()) { +		return boost::optional<ITunesInterface::Track>(); +	} +	iTunesTrack* currentTrack = p->iTunes.currentTrack; +	if (!currentTrack) { +		return boost::optional<ITunesInterface::Track>(); +	} +	ITunesInterface::Track result; +	result.name = NS2STDSTRING(currentTrack.name); +	result.artist = NS2STDSTRING(currentTrack.artist); +	result.album = NS2STDSTRING(currentTrack.album); +	result.trackNumber = currentTrack.trackNumber; +	result.duration = currentTrack.duration; +	result.rating = currentTrack.rating; +	return result; +} + + +bool ITunesInterface::haveApplication() const { +	if (!p->iTunes) { +		p->iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"]; +	} +	return p->iTunes != nil && [p->iTunes isRunning]; +} diff --git a/Sluift/Lua/LuaUtils.cpp b/Sluift/Lua/LuaUtils.cpp index 2192689..915f3cc 100644 --- a/Sluift/Lua/LuaUtils.cpp +++ b/Sluift/Lua/LuaUtils.cpp @@ -32,6 +32,17 @@ void Swift::Lua::registerTableToString(lua_State* L, int index) {  	lua_pop(L, 1);  } +void Swift::Lua::registerTableEquals(lua_State* L, int index) { +	index = Lua::absoluteOffset(L, index); +	lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); +	lua_getfield(L, -1, "register_table_equals"); +	lua_pushvalue(L, index); +	if (lua_pcall(L, 1, 0, 0) != 0) { +		throw Lua::Exception(lua_tostring(L, -1)); +	} +	lua_pop(L, 1); +} +  void Swift::Lua::registerGetByTypeIndex(lua_State* L, int index) {  	index = Lua::absoluteOffset(L, index);  	lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); diff --git a/Sluift/Lua/LuaUtils.h b/Sluift/Lua/LuaUtils.h index 19ab74e..105f249 100644 --- a/Sluift/Lua/LuaUtils.h +++ b/Sluift/Lua/LuaUtils.h @@ -23,6 +23,7 @@ namespace Swift {  		int convertTableToString(lua_State* L);  		void registerTableToString(lua_State* L, int index); +		void registerTableEquals(lua_State* L, int index);  		void registerGetByTypeIndex(lua_State* L, int index);  		void registerHelp(lua_State* L, int index,   				const std::string& description, const std::string& parameters, const std::string& options); diff --git a/Sluift/SConscript b/Sluift/SConscript index c2bbff5..3cc1f29 100644 --- a/Sluift/SConscript +++ b/Sluift/SConscript @@ -1,6 +1,6 @@  import Version, os.path -Import(["env", "conf_env"]) +Import(["env"])  if env["SCONS_STAGE"] == "build" and not GetOption("help") and not env.get("HAVE_LUA", 0) :  	print "Warning: Lua was not found. Sluift will not be built." @@ -42,6 +42,8 @@ elif env["SCONS_STAGE"] == "build" :  	]  	sluift_sources += env.SConscript("ElementConvertors/SConscript") + +  	sluift_env = env.Clone()  	sluift_env.UseFlags(env.get("LUA_FLAGS", {}))  	sluift_env.UseFlags(env["SWIFTEN_FLAGS"]) @@ -51,6 +53,13 @@ elif env["SCONS_STAGE"] == "build" :  	if sluift_env["PLATFORM"] == "win32" :  		sluift_env.Append(CPPDEFINES = ["SLUIFT_BUILD_DLL"]) +	if sluift_env["PLATFORM"] == "darwin" and os.path.isdir("/Applications/iTunes.app") : +		sluift_env.Append(FRAMEWORKS = ["ScriptingBridge"]) +		sluift_env.Command("iTunes.h", "/Applications/iTunes.app",  +				"sdef ${SOURCE} | sdp -fh --basename iTunes -o ${TARGET.dir}") +		sluift_env.Append(CPPDEFINES = ["HAVE_ITUNES"]) +		sluift_sources += ["ITunesInterface.mm"] +  	# Generate Version.h  	version_header = "#pragma once\n\n"  	version_header += "#define SLUIFT_VERSION_STRING \"" + Version.getBuildVersion(env.Dir("#").abspath, "sluift") + "\"\n" diff --git a/Sluift/SluiftGlobals.h b/Sluift/SluiftGlobals.h index 5de7cfe..e89f495 100644 --- a/Sluift/SluiftGlobals.h +++ b/Sluift/SluiftGlobals.h @@ -9,6 +9,9 @@  #include <Sluift/LuaElementConvertors.h>  #include <Swiften/EventLoop/SimpleEventLoop.h>  #include <Swiften/Network/BoostNetworkFactories.h> +#ifdef HAVE_ITUNES +#include <Sluift/ITunesInterface.h> +#endif  #include <signal.h>  namespace Swift { @@ -25,5 +28,8 @@ namespace Swift {  		int coreLibIndex;  		int moduleLibIndex;  		sig_atomic_t interruptRequested; +#ifdef HAVE_ITUNES +		ITunesInterface iTunes; +#endif  	};  } diff --git a/Sluift/core.lua b/Sluift/core.lua index f387354..1969690 100644 --- a/Sluift/core.lua +++ b/Sluift/core.lua @@ -72,7 +72,22 @@ local function register_table_tostring(table, print_functions)  			metatable.__tostring = table_tostring  		end  	end -	return table +end + +-- FIXME: Not really a good or efficiant equals, but does the trick for now +local function table_equals(t1, t2)  +	return tostring(t1) == tostring(t2)  +end + +local function register_table_equals(table) +	if type(table) == 'table' then +		local metatable = getmetatable(table) +		if not metatable then +			metatable = {} +			setmetatable(table, metatable) +		end +		metatable.__eq = table_equals +	end  end  local function merge_tables(...) @@ -983,6 +998,7 @@ return {  	register_help = register_help,  	register_class_help = register_class_help,  	register_table_tostring = register_table_tostring, +	register_table_equals = register_table_equals,  	register_get_by_type_index = register_get_by_type_index,  	process_pubsub_event = process_pubsub_event,  	tprint = tprint, diff --git a/Sluift/sluift.cpp b/Sluift/sluift.cpp index 08ffd92..17990e8 100644 --- a/Sluift/sluift.cpp +++ b/Sluift/sluift.cpp @@ -33,6 +33,7 @@  #include <Swiften/IDN/IDNConverter.h>  #include <Swiften/Crypto/CryptoProvider.h>  #include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Sluift/ITunesInterface.h>  using namespace Swift; @@ -176,7 +177,6 @@ SLUIFT_LUA_FUNCTION_WITH_HELP(  	return 1;  } -  /*******************************************************************************   * JID Functions   ******************************************************************************/ @@ -271,6 +271,34 @@ SLUIFT_LUA_FUNCTION(IDN, stringprep) {  	return 1;  } +/******************************************************************************* + * iTunes Functions + ******************************************************************************/ + +#ifdef HAVE_ITUNES +SLUIFT_LUA_FUNCTION(iTunes, get_current_track) { +	boost::optional<ITunesInterface::Track> track = Sluift::globals.iTunes.getCurrentTrack(); +	if (!track) { +		return 0; +	} +	lua_createtable(L, 0, 0); +	lua_pushstring(L, track->artist.c_str()); +	lua_setfield(L, -2, "artist"); +	lua_pushstring(L, track->name.c_str()); +	lua_setfield(L, -2, "name"); +	lua_pushstring(L, track->album.c_str()); +	lua_setfield(L, -2, "album"); +	lua_pushinteger(L, track->trackNumber); +	lua_setfield(L, -2, "track_number"); +	lua_pushnumber(L, track->duration); +	lua_setfield(L, -2, "duration"); +	lua_pushinteger(L, track->rating); +	lua_setfield(L, -2, "rating"); +	Lua::registerTableToString(L, -1); +	Lua::registerTableEquals(L, -1); +	return 1; +} +#endif  /*******************************************************************************   * Module registration @@ -296,6 +324,11 @@ SLUIFT_API int luaopen_sluift(lua_State* L) {  	lua_call(L, 0, 1);  	Sluift::globals.coreLibIndex = luaL_ref(L, LUA_REGISTRYINDEX); +	lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); +	lua_getfield(L, -1, "Client"); +	lua_setmetatable(L, -3); +	lua_pop(L, 1); +  	// Register functions  	Lua::FunctionRegistry::getInstance().addFunctionsToTable(L, "Sluift");  	Lua::FunctionRegistry::getInstance().createFunctionTable(L, "JID"); @@ -304,6 +337,10 @@ SLUIFT_API int luaopen_sluift(lua_State* L) {  	lua_setfield(L, -2, "base64");  	Lua::FunctionRegistry::getInstance().createFunctionTable(L, "IDN");  	lua_setfield(L, -2, "idn"); +#ifdef HAVE_ITUNES +	Lua::FunctionRegistry::getInstance().createFunctionTable(L, "iTunes"); +	lua_setfield(L, -2, "itunes"); +#endif  	// Register convenience functions  	lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); diff --git a/Swiften/Elements/UserTune.cpp b/Swiften/Elements/UserTune.cpp new file mode 100644 index 0000000..e4c0241 --- /dev/null +++ b/Swiften/Elements/UserTune.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2014 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Elements/UserTune.h> + +using namespace Swift; + +UserTune::UserTune() { +} + +UserTune::~UserTune() { +} diff --git a/Swiften/Elements/UserTune.h b/Swiften/Elements/UserTune.h new file mode 100644 index 0000000..5e0999a --- /dev/null +++ b/Swiften/Elements/UserTune.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Elements/Payload.h> +#include <boost/optional.hpp> +#include <string> + + + +namespace Swift { +	class SWIFTEN_API UserTune : public Payload { +		public: +			 +			UserTune(); +			 +			virtual ~UserTune(); + +			const boost::optional< unsigned int >& getRating() const { +				return rating; +			} + +			void setRating(const boost::optional< unsigned int >& value) { +				this->rating = value ; +			} + +			const boost::optional< std::string >& getTitle() const { +				return title; +			} + +			void setTitle(const boost::optional< std::string >& value) { +				this->title = value ; +			} + +			const boost::optional< std::string >& getTrack() const { +				return track; +			} + +			void setTrack(const boost::optional< std::string >& value) { +				this->track = value ; +			} + +			const boost::optional< std::string >& getArtist() const { +				return artist; +			} + +			void setArtist(const boost::optional< std::string >& value) { +				this->artist = value ; +			} + +			const boost::optional< std::string >& getURI() const { +				return uri; +			} + +			void setURI(const boost::optional< std::string >& value) { +				this->uri = value ; +			} + +			const boost::optional< std::string >& getSource() const { +				return source; +			} + +			void setSource(const boost::optional< std::string >& value) { +				this->source = value ; +			} + +			const boost::optional< unsigned int >& getLength() const { +				return length; +			} + +			void setLength(const boost::optional< unsigned int >& value) { +				this->length = value ; +			} + + +		private: +			boost::optional< unsigned int > rating; +			boost::optional< std::string > title; +			boost::optional< std::string > track; +			boost::optional< std::string > artist; +			boost::optional< std::string > uri; +			boost::optional< std::string > source; +			boost::optional< unsigned int > length; +	}; +} diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp index 3ec5a7a..22019b4 100644 --- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp +++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp @@ -1,5 +1,5 @@  /* - * Copyright (c) 2010-2013 Remko Tronçon + * Copyright (c) 2010-2014 Remko Tronçon   * Licensed under the GNU General Public License v3.   * See Documentation/Licenses/GPLv3.txt for more information.   */ @@ -75,6 +75,7 @@  #include <Swiften/Parser/PayloadParsers/PubSubEventParser.h>  #include <Swiften/Parser/PayloadParsers/PubSubErrorParserFactory.h>  #include <Swiften/Parser/PayloadParsers/UserLocationParser.h> +#include <Swiften/Parser/PayloadParsers/UserTuneParser.h>  using namespace boost; @@ -135,6 +136,7 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() {  	factories_.push_back(boost::make_shared<GenericPayloadParserFactory<S5BProxyRequestParser> >("query", "http://jabber.org/protocol/bytestreams"));  	factories_.push_back(boost::make_shared<GenericPayloadParserFactory<WhiteboardParser> >("wb", "http://swift.im/whiteboard"));  	factories_.push_back(boost::make_shared<GenericPayloadParserFactory<UserLocationParser> >("geoloc", "http://jabber.org/protocol/geoloc")); +	factories_.push_back(boost::make_shared<GenericPayloadParserFactory<UserTuneParser> >("tune", "http://jabber.org/protocol/tune"));  	factories_.push_back(boost::make_shared<DeliveryReceiptParserFactory>());  	factories_.push_back(boost::make_shared<DeliveryReceiptRequestParserFactory>());  	factories_.push_back(boost::make_shared<GenericPayloadParserFactory<IdleParser> >("idle", "urn:xmpp:idle:1")); diff --git a/Swiften/Parser/PayloadParsers/UserTuneParser.cpp b/Swiften/Parser/PayloadParsers/UserTuneParser.cpp new file mode 100644 index 0000000..bb299e4 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UserTuneParser.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/UserTuneParser.h> + +#include <boost/lexical_cast.hpp> + +using namespace Swift; + +UserTuneParser::UserTuneParser() : level(0) { +} + +UserTuneParser::~UserTuneParser() { +} + +void UserTuneParser::handleStartElement(const std::string&, const std::string&, const AttributeMap&) { +	if (level == 1) { +		currentText = ""; +	} +	++level; +} + +void UserTuneParser::handleEndElement(const std::string& element, const std::string&) { +	--level; +	if (level == 1) { +		try { +			if (element == "artist") { +				getPayloadInternal()->setArtist(currentText); +			} +			else if (element == "length") { +				getPayloadInternal()->setLength(boost::lexical_cast<unsigned int>(currentText)); +			} +			else if (element == "rating") { +				getPayloadInternal()->setRating(boost::lexical_cast<unsigned int>(currentText)); +			} +			else if (element == "source") { +				getPayloadInternal()->setSource(currentText); +			} +			else if (element == "title") { +				getPayloadInternal()->setTitle(currentText); +			} +			else if (element == "track") { +				getPayloadInternal()->setTrack(currentText); +			} +			else if (element == "URI") { +				getPayloadInternal()->setURI(currentText); +			} +		} +		catch (const boost::bad_lexical_cast&) { +		} +	} +} + +void UserTuneParser::handleCharacterData(const std::string& data) { +	currentText += data; +} diff --git a/Swiften/Parser/PayloadParsers/UserTuneParser.h b/Swiften/Parser/PayloadParsers/UserTuneParser.h new file mode 100644 index 0000000..1cfadea --- /dev/null +++ b/Swiften/Parser/PayloadParsers/UserTuneParser.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2014 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> +#include <string> + +#include <Swiften/Base/Override.h> +#include <Swiften/Base/API.h> +#include <Swiften/Parser/GenericPayloadParser.h> +#include <Swiften/Elements/UserTune.h> + +namespace Swift { +	class SWIFTEN_API UserTuneParser : public GenericPayloadParser<UserTune> { +		public: +			UserTuneParser(); +			virtual ~UserTuneParser(); + +			virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) SWIFTEN_OVERRIDE; +			virtual void handleEndElement(const std::string& element, const std::string&) SWIFTEN_OVERRIDE; +			virtual void handleCharacterData(const std::string& data) SWIFTEN_OVERRIDE; + +		private: +			int level; +			std::string currentText; +	}; +} diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript index 0a6972e..4d6db11 100644 --- a/Swiften/Parser/SConscript +++ b/Swiften/Parser/SConscript @@ -74,6 +74,7 @@ sources = [  		"PayloadParsers/DeliveryReceiptParser.cpp",  		"PayloadParsers/DeliveryReceiptRequestParser.cpp",  		"PayloadParsers/UserLocationParser.cpp", +		"PayloadParsers/UserTuneParser.cpp",  		"PayloadParsers/WhiteboardParser.cpp",  		"PayloadParsers/PubSubErrorParserFactory.cpp",  		"PlatformXMLParserFactory.cpp", diff --git a/Swiften/SConscript b/Swiften/SConscript index 75944f0..b5e13a9 100644 --- a/Swiften/SConscript +++ b/Swiften/SConscript @@ -137,6 +137,7 @@ if env["SCONS_STAGE"] == "build" :  			"Elements/StreamResume.cpp",  			"Elements/StreamResumed.cpp",  			"Elements/UserLocation.cpp", +			"Elements/UserTune.cpp",  			"Elements/VCard.cpp",  			"Elements/MUCOccupant.cpp",  			"Entity/Entity.cpp", @@ -215,6 +216,7 @@ if env["SCONS_STAGE"] == "build" :  			"Serializer/PayloadSerializers/DeliveryReceiptSerializer.cpp",  			"Serializer/PayloadSerializers/DeliveryReceiptRequestSerializer.cpp",  			"Serializer/PayloadSerializers/UserLocationSerializer.cpp", +			"Serializer/PayloadSerializers/UserTuneSerializer.cpp",  			"Serializer/PayloadSerializers/WhiteboardSerializer.cpp",  			"Serializer/PresenceSerializer.cpp",  			"Serializer/StanzaSerializer.cpp", diff --git a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp index a57a74e..16c79d5 100644 --- a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp +++ b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp @@ -1,5 +1,5 @@  /* - * Copyright (c) 2010-2013 Remko Tronçon + * Copyright (c) 2010-2014 Remko Tronçon   * Licensed under the GNU General Public License v3.   * See Documentation/Licenses/GPLv3.txt for more information.   */ @@ -52,6 +52,7 @@  #include <Swiften/Serializer/PayloadSerializers/LastSerializer.h>  #include <Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.h>  #include <Swiften/Serializer/PayloadSerializers/UserLocationSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/UserTuneSerializer.h>  #include <Swiften/Serializer/PayloadSerializers/IdleSerializer.h>  #include <Swiften/Serializer/PayloadSerializers/PubSubSerializer.h>  #include <Swiften/Serializer/PayloadSerializers/PubSubOwnerPubSubSerializer.h> @@ -117,6 +118,7 @@ FullPayloadSerializerCollection::FullPayloadSerializerCollection() {  	serializers_.push_back(new LastSerializer());  	serializers_.push_back(new WhiteboardSerializer());  	serializers_.push_back(new UserLocationSerializer()); +	serializers_.push_back(new UserTuneSerializer());  	serializers_.push_back(new IdleSerializer());  	serializers_.push_back(new StreamInitiationFileInfoSerializer()); diff --git a/Swiften/Serializer/PayloadSerializers/UserTuneSerializer.cpp b/Swiften/Serializer/PayloadSerializers/UserTuneSerializer.cpp new file mode 100644 index 0000000..6c7799e --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UserTuneSerializer.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/UserTuneSerializer.h> + +#include <boost/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <boost/lexical_cast.hpp> + +#include <Swiften/Base/foreach.h> +#include <Swiften/Serializer/XML/XMLElement.h> + +namespace Swift { + +UserTuneSerializer::UserTuneSerializer() { +} + +std::string UserTuneSerializer::serializePayload( +		boost::shared_ptr<UserTune> payload) const { +	XMLElement result("tune", "http://jabber.org/protocol/tune"); +	if (boost::optional<std::string> value = payload->getArtist()) { +		result.addNode(boost::make_shared<XMLElement>("artist", "", *value)); +	} +	if (boost::optional<unsigned int> value = payload->getLength()) { +		result.addNode(boost::make_shared<XMLElement>("length", "", boost::lexical_cast<std::string>(*value))); +	} +	if (boost::optional<unsigned int> value = payload->getRating()) { +		result.addNode(boost::make_shared<XMLElement>("rating", "", boost::lexical_cast<std::string>(*value))); +	} +	if (boost::optional<std::string> value = payload->getSource()) { +		result.addNode(boost::make_shared<XMLElement>("source", "", *value)); +	} +	if (boost::optional<std::string> value = payload->getTitle()) { +		result.addNode(boost::make_shared<XMLElement>("title", "", *value)); +	} +	if (boost::optional<std::string> value = payload->getTrack()) { +		result.addNode(boost::make_shared<XMLElement>("track", "", *value)); +	} +	if (boost::optional<std::string> value = payload->getURI()) { +		result.addNode(boost::make_shared<XMLElement>("uri", "", *value)); +	} +	return result.serialize(); +} + +} diff --git a/Swiften/Serializer/PayloadSerializers/UserTuneSerializer.h b/Swiften/Serializer/PayloadSerializers/UserTuneSerializer.h new file mode 100644 index 0000000..8c20cbd --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/UserTuneSerializer.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2014 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/UserTune.h> + +namespace Swift { +	class UserTuneSerializer : public GenericPayloadSerializer<UserTune> { +		public: +			UserTuneSerializer(); + +			virtual std::string serializePayload(boost::shared_ptr<UserTune>)  const; +	}; +} | 
 Swift
 Swift