summaryrefslogtreecommitdiffstats
path: root/bindings/_common
diff options
context:
space:
mode:
Diffstat (limited to 'bindings/_common')
-rw-r--r--bindings/_common/ActionConfig.cxx92
-rw-r--r--bindings/_common/ActionConfig.h52
-rw-r--r--bindings/_common/Common.h44
-rw-r--r--bindings/_common/DDebug.cxx142
-rw-r--r--bindings/_common/DDebug.h49
-rw-r--r--bindings/_common/MediaContent.cxx169
-rw-r--r--bindings/_common/MediaContent.h73
-rw-r--r--bindings/_common/MediaSessionMgr.cxx114
-rw-r--r--bindings/_common/MediaSessionMgr.h62
-rw-r--r--bindings/_common/Msrp.cxx273
-rw-r--r--bindings/_common/Msrp.h91
-rw-r--r--bindings/_common/Msrp.i34
-rw-r--r--bindings/_common/ProxyConsumer.cxx519
-rw-r--r--bindings/_common/ProxyConsumer.h161
-rw-r--r--bindings/_common/ProxyPluginMgr.cxx290
-rw-r--r--bindings/_common/ProxyPluginMgr.h124
-rw-r--r--bindings/_common/ProxyProducer.cxx438
-rw-r--r--bindings/_common/ProxyProducer.h137
-rw-r--r--bindings/_common/SMS.i7
-rw-r--r--bindings/_common/SMSEncoder.cxx376
-rw-r--r--bindings/_common/SMSEncoder.h115
-rw-r--r--bindings/_common/SafeObject.cxx42
-rw-r--r--bindings/_common/SafeObject.h41
-rw-r--r--bindings/_common/SipCallback.cxx31
-rw-r--r--bindings/_common/SipCallback.h54
-rw-r--r--bindings/_common/SipEvent.cxx306
-rw-r--r--bindings/_common/SipEvent.h193
-rw-r--r--bindings/_common/SipMessage.cxx258
-rw-r--r--bindings/_common/SipMessage.h66
-rw-r--r--bindings/_common/SipSession.cxx727
-rw-r--r--bindings/_common/SipSession.h216
-rw-r--r--bindings/_common/SipStack.cxx524
-rw-r--r--bindings/_common/SipStack.h109
-rw-r--r--bindings/_common/SipStack.i258
-rw-r--r--bindings/_common/SipUri.cxx93
-rw-r--r--bindings/_common/SipUri.h49
-rw-r--r--bindings/_common/Xcap.cxx564
-rw-r--r--bindings/_common/Xcap.h165
-rw-r--r--bindings/_common/Xcap.i22
-rw-r--r--bindings/_common/tinyWRAP.i67
-rw-r--r--bindings/_common/tinyWRAP_config.h68
41 files changed, 7215 insertions, 0 deletions
diff --git a/bindings/_common/ActionConfig.cxx b/bindings/_common/ActionConfig.cxx
new file mode 100644
index 0000000..2182433
--- /dev/null
+++ b/bindings/_common/ActionConfig.cxx
@@ -0,0 +1,92 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*/
+
+#include "ActionConfig.h"
+
+tmedia_type_t _get_media_type(twrap_media_type_t type){
+ int media_type = tmedia_none; // Use int because | operator not defined for enumerators
+ switch(type){
+ case twrap_media_msrp:
+ media_type |= tmedia_msrp;
+ break;
+ case twrap_media_audio:
+ media_type |= tmedia_audio;
+ break;
+ case twrap_media_video:
+ media_type |= tmedia_video;
+ break;
+ case twrap_media_audiovideo:
+ media_type |= tmedia_audiovideo;
+ break;
+ }
+ return (tmedia_type_t)media_type;
+}
+
+ActionConfig::ActionConfig()
+{
+ this->handle = tsip_action_create(tsip_atype_config,
+ TSIP_ACTION_SET_NULL());
+}
+
+ActionConfig::~ActionConfig()
+{
+ TSK_OBJECT_SAFE_FREE(this->handle);
+}
+
+bool ActionConfig::addHeader(const char* name, const char* value)
+{
+ return (tsip_action_set(this->handle,
+ TSIP_ACTION_SET_HEADER(name, value),
+ TSIP_ACTION_SET_NULL()) == 0);
+}
+
+ActionConfig* ActionConfig::setResponseLine(short code, const char* phrase)
+{
+ int32_t _code = code;
+ tsip_action_set(this->handle,
+ TSIP_ACTION_SET_RESP_LINE(_code, phrase),
+ TSIP_ACTION_SET_NULL());
+ return this;
+}
+
+ActionConfig* ActionConfig::setMediaString(twrap_media_type_t type, const char* key, const char* value)
+{
+ tmedia_type_t media_type = _get_media_type(type);
+ tsip_action_set(this->handle,
+ TSIP_ACTION_SET_MEDIA(
+ TMEDIA_SESSION_SET_STR(media_type, key, value),
+ TMEDIA_SESSION_SET_NULL()),
+ TSIP_ACTION_SET_NULL());
+
+ return this;
+}
+
+ActionConfig* ActionConfig::setMediaInt(twrap_media_type_t type, const char* key, int value)
+{
+ tmedia_type_t media_type = _get_media_type(type);
+ tsip_action_set(this->handle,
+ TSIP_ACTION_SET_MEDIA(
+ TMEDIA_SESSION_SET_INT32(media_type, key, value),
+ TMEDIA_SESSION_SET_NULL()),
+ TSIP_ACTION_SET_NULL());
+
+ return this;
+} \ No newline at end of file
diff --git a/bindings/_common/ActionConfig.h b/bindings/_common/ActionConfig.h
new file mode 100644
index 0000000..b2ae0dd
--- /dev/null
+++ b/bindings/_common/ActionConfig.h
@@ -0,0 +1,52 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#ifndef TINYWRAP_ACTIONCONFIG_H
+#define TINYWRAP_ACTIONCONFIG_H
+
+#include "tinysip.h"
+#include "Common.h"
+
+class ActionConfig
+{
+public:
+ ActionConfig();
+ virtual ~ActionConfig();
+
+ bool addHeader(const char* name, const char* value);
+
+ ActionConfig* setResponseLine(short code, const char* phrase);
+ ActionConfig* setMediaString(twrap_media_type_t type, const char* key, const char* value);
+ ActionConfig* setMediaInt(twrap_media_type_t type, const char* key, int value);
+
+private:
+ tsip_action_handle_t* handle;
+
+#if !defined(SWIG)
+public:
+ const tsip_action_handle_t* getHandle()const{
+ return this->handle;
+ }
+#endif
+};
+
+
+#endif /* TINYWRAP_ACTIONCONFIG_H */
diff --git a/bindings/_common/Common.h b/bindings/_common/Common.h
new file mode 100644
index 0000000..a9ce11a
--- /dev/null
+++ b/bindings/_common/Common.h
@@ -0,0 +1,44 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#ifndef TINYWRAP_COMMON_H
+#define TINYWRAP_COMMON_H
+
+#if ANDROID
+# define dyn_cast static_cast
+# define __JNIENV JNIEnv
+#else
+# define dyn_cast dynamic_cast
+# define __JNIENV void
+#endif
+
+typedef enum twrap_media_type_e
+{
+ twrap_media_none,
+ twrap_media_audio,
+ twrap_media_video,
+ twrap_media_audiovideo,
+ twrap_media_msrp
+}
+twrap_media_type_t;
+
+#endif /* TINYWRAP_COMMON_H */
+
diff --git a/bindings/_common/DDebug.cxx b/bindings/_common/DDebug.cxx
new file mode 100644
index 0000000..f9ec73a
--- /dev/null
+++ b/bindings/_common/DDebug.cxx
@@ -0,0 +1,142 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#include "DDebug.h"
+
+#include "SipStack.h"
+
+#include "Common.h"
+
+#if ANDROID /* callbacks will fail with jni */
+# include <android/log.h>
+# define ANDROID_DEBUG_TAG "tinyWRAP"
+#endif
+
+/* Very Important ==> never call functions which could raise debug callbacks into callback functions
+* Callbacks should not used with Android (JNI).
+*/
+
+enum cb_type{
+ cb_info,
+ cb_warn,
+ cb_error,
+ cb_fatal
+};
+
+int debug_xxx_cb(const void* arg, const char* fmt, enum cb_type type, va_list *app)
+{
+ int ret = -1;
+ if(!arg){
+ return -1;
+ }
+
+ const SipStack* stack = dyn_cast<const SipStack*>((const SipStack*)arg);
+
+ if(stack && stack->getDebugCallback()){
+ char* message = tsk_null;
+ tsk_sprintf_2(&message, fmt, app);
+
+ switch(type){
+ case cb_info:
+ ret=
+#if ANDROID
+ __android_log_write(ANDROID_LOG_INFO, ANDROID_DEBUG_TAG, message);
+#else
+ stack->getDebugCallback()-> OnDebugInfo(message);
+#endif
+ break;
+ case cb_warn:
+ ret=
+#if ANDROID
+ __android_log_write(ANDROID_LOG_WARN, ANDROID_DEBUG_TAG, message);
+#else
+ stack->getDebugCallback()-> OnDebugWarn(message);
+#endif
+ break;
+ case cb_error:
+ ret=
+#if ANDROID
+ __android_log_write(ANDROID_LOG_ERROR, ANDROID_DEBUG_TAG, message);
+#else
+ stack->getDebugCallback()-> OnDebugError(message);
+#endif
+ break;
+ case cb_fatal:
+ ret=
+#if ANDROID
+ __android_log_write(ANDROID_LOG_FATAL, ANDROID_DEBUG_TAG, message);
+#else
+ stack->getDebugCallback()-> OnDebugFatal(message);
+#endif
+ break;
+ }
+
+ TSK_FREE(message);
+ }
+
+ return ret;
+}
+
+int DDebugCallback::debug_info_cb(const void* arg, const char* fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = debug_xxx_cb(arg, fmt, cb_info, &ap);
+ va_end(ap);
+
+ return ret;
+}
+
+int DDebugCallback::debug_warn_cb(const void* arg, const char* fmt, ...){
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = debug_xxx_cb(arg, fmt, cb_warn, &ap);
+ va_end(ap);
+
+ return ret;
+}
+
+int DDebugCallback::debug_error_cb(const void* arg, const char* fmt, ...){
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = debug_xxx_cb(arg, fmt, cb_error, &ap);
+ va_end(ap);
+
+ return ret;
+}
+
+int DDebugCallback::debug_fatal_cb(const void* arg, const char* fmt, ...){
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = debug_xxx_cb(arg, fmt, cb_fatal, &ap);
+ va_end(ap);
+
+ return ret;
+}
+
diff --git a/bindings/_common/DDebug.h b/bindings/_common/DDebug.h
new file mode 100644
index 0000000..776015d
--- /dev/null
+++ b/bindings/_common/DDebug.h
@@ -0,0 +1,49 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#ifndef TINYWRAP_SIP_DEBUG_H
+#define TINYWRAP_SIP_DEBUG_H
+
+class DDebugCallback
+{
+public:
+ DDebugCallback() { }
+ virtual ~DDebugCallback() {}
+
+
+ virtual int OnDebugInfo(const char* message) { return -1; }
+ virtual int OnDebugWarn(const char* message) { return -1; }
+ virtual int OnDebugError(const char* message) { return -1; }
+ virtual int OnDebugFatal(const char* message) { return -1; }
+
+#if !defined(SWIG)
+public:
+ static int debug_info_cb(const void* arg, const char* fmt, ...);
+ static int debug_warn_cb(const void* arg, const char* fmt, ...);
+ static int debug_error_cb(const void* arg, const char* fmt, ...);
+ static int debug_fatal_cb(const void* arg, const char* fmt, ...);
+#endif
+
+private:
+
+};
+
+#endif /* TINYWRAP_SIP_DEBUG_H */
diff --git a/bindings/_common/MediaContent.cxx b/bindings/_common/MediaContent.cxx
new file mode 100644
index 0000000..8af5bcb
--- /dev/null
+++ b/bindings/_common/MediaContent.cxx
@@ -0,0 +1,169 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#include "MediaContent.h"
+
+
+
+MediaContent::MediaContent(tmedia_content_t* _content)
+: data(tsk_null)
+{
+ this->content = (tmedia_content_t*)tsk_object_ref(_content);
+}
+
+MediaContent::~MediaContent()
+{
+ TSK_OBJECT_SAFE_FREE(this->content);
+ TSK_OBJECT_SAFE_FREE(this->data);
+}
+
+const char* MediaContent::getType()
+{
+ if(this->content){
+ return this->content->type;
+ }
+ return tsk_null;
+}
+
+unsigned MediaContent::getDataLength()
+{
+ if(!this->content){
+ TSK_DEBUG_ERROR("Invalid internal object");
+ return 0;
+ }
+
+ if(!this->data){
+ this->data = tmedia_content_get_data(this->content);
+ }
+
+ return (this->data ? this->data->size : 0);
+}
+
+unsigned MediaContent::getData(void* output, unsigned maxsize)
+{
+ unsigned retsize = 0;
+
+ if(!this->content){
+ TSK_DEBUG_ERROR("Invalid internal object");
+ return 0;
+ }
+
+ if(!this->data){
+ this->data = tmedia_content_get_data(this->content);
+ }
+
+ if(output && maxsize && this->data){
+ retsize = (this->data->size > maxsize) ? maxsize : this->data->size;
+ memcpy(output, this->data->data, retsize);
+ }
+
+ return retsize;
+}
+
+MediaContent* MediaContent::parse(const void* data, unsigned size, const char* type)
+{
+ MediaContent* mediaContent = tsk_null;
+
+ tmedia_content_t* _content = tmedia_content_parse(data, (tsk_size_t)size, type);
+ if(_content){
+ if(TMEDIA_CONTENT_IS_CPIM(_content)){
+ mediaContent = new MediaContentCPIM(_content);
+ }
+ else if(TMEDIA_CONTENT_IS_DUMMY(_content)){
+ // Todo
+ }
+ TSK_OBJECT_SAFE_FREE(_content);
+ }
+
+ return mediaContent;
+}
+
+MediaContentCPIM* MediaContent::parse(const void* data, unsigned size)
+{
+ MediaContent* mediaContent;
+ if((mediaContent = MediaContent::parse(data, size, TMEDIA_CONTENT_CPIM_TYPE))){
+ return dyn_cast<MediaContentCPIM*>(mediaContent);
+ }
+ return tsk_null;
+}
+
+/* ============ message/CPIM ================= */
+
+MediaContentCPIM::MediaContentCPIM(tmedia_content_t* _content)
+: MediaContent(_content)
+{
+}
+
+MediaContentCPIM::~MediaContentCPIM()
+{
+}
+
+unsigned MediaContentCPIM::getPayloadLength()
+{
+ if(!this->content || !TMEDIA_CONTENT_IS_CPIM(this->content)){
+ TSK_DEBUG_ERROR("Invalid internal object");
+ return 0;
+ }
+
+ return (TMEDIA_CONTENT_CPIM(this->content)->e ? TMEDIA_CONTENT_CPIM(this->content)->e->size : 0);
+}
+
+unsigned MediaContentCPIM::getPayload(void* output, unsigned maxsize)
+{
+ unsigned retsize = 0;
+
+ if(!this->content || !TMEDIA_CONTENT_IS_CPIM(this->content)){
+ TSK_DEBUG_ERROR("Invalid internal object");
+ return 0;
+ }
+
+ if(output && maxsize && TMEDIA_CONTENT_CPIM(this->content)->e){
+ retsize = (TMEDIA_CONTENT_CPIM(this->content)->e->size > maxsize) ? maxsize : TMEDIA_CONTENT_CPIM(this->content)->e->size;
+ memcpy(output, TMEDIA_CONTENT_CPIM(this->content)->e->data, retsize);
+ }
+
+ return retsize;
+}
+
+const char* MediaContentCPIM::getHeaderValue(const char* name)
+{
+ const tmedia_content_cpim_t* cpim;
+ const tsk_list_item_t* item;
+
+ if(!this->content || !TMEDIA_CONTENT_IS_CPIM(this->content)){
+ TSK_DEBUG_ERROR("Invalid internal object");
+ return tsk_null;
+ }
+
+ cpim = TMEDIA_CONTENT_CPIM(this->content);
+ tsk_list_foreach(item, cpim->h_headers){
+ if(tsk_striequals(name, TMEDIA_CONTENT_HEADER(item->data)->name)){
+ return TMEDIA_CONTENT_HEADER(item->data)->value;
+ }
+ }
+ tsk_list_foreach(item, cpim->m_headers){
+ if(tsk_striequals(name, TMEDIA_CONTENT_HEADER(item->data)->name)){
+ return TMEDIA_CONTENT_HEADER(item->data)->value;
+ }
+ }
+
+ return tsk_null;
+} \ No newline at end of file
diff --git a/bindings/_common/MediaContent.h b/bindings/_common/MediaContent.h
new file mode 100644
index 0000000..77d7160
--- /dev/null
+++ b/bindings/_common/MediaContent.h
@@ -0,0 +1,73 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#ifndef TINYWRAP_MEDIA_CONTENT_H
+#define TINYWRAP_MEDIA_CONTENT_H
+
+#include "tinymedia.h"
+#include "Common.h"
+
+class MediaContentCPIM;
+
+class MediaContent
+{
+public:
+#if !defined(SWIG)
+ MediaContent(tmedia_content_t* content);
+#endif
+ virtual ~MediaContent();
+
+public:
+ const char* getType();
+ virtual unsigned getDataLength();
+ virtual unsigned getData(void* output, unsigned maxsize);
+
+ // SWIG %newobject()
+ static MediaContent* parse(const void* data, unsigned size, const char* type);
+ static MediaContentCPIM* parse(const void* data, unsigned size);
+
+ virtual unsigned getPayloadLength() = 0;
+ virtual unsigned getPayload(void* output, unsigned maxsize) = 0;
+
+protected:
+ tmedia_content_t* content;
+
+private:
+ tsk_buffer_t* data;
+};
+
+
+/* ============ message/CPIM ================= */
+class MediaContentCPIM : public MediaContent
+{
+public:
+#if !defined(SWIG)
+ MediaContentCPIM(tmedia_content_t* content);
+#endif
+ virtual ~MediaContentCPIM();
+
+public:
+ virtual unsigned getPayloadLength();
+ virtual unsigned getPayload(void* output, unsigned maxsize);
+ const char* getHeaderValue(const char* name);
+};
+
+#endif /*TINYWRAP_MEDIA_CONTENT_H*/
diff --git a/bindings/_common/MediaSessionMgr.cxx b/bindings/_common/MediaSessionMgr.cxx
new file mode 100644
index 0000000..8bb6756
--- /dev/null
+++ b/bindings/_common/MediaSessionMgr.cxx
@@ -0,0 +1,114 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#include "MediaSessionMgr.h"
+
+extern tmedia_type_t _get_media_type(twrap_media_type_t type);
+
+MediaSessionMgr::MediaSessionMgr(tmedia_session_mgr_t* _mgr)
+{
+ this->mgr = (tmedia_session_mgr_t*)tsk_object_ref(_mgr);
+}
+
+MediaSessionMgr::~MediaSessionMgr()
+{
+ TSK_OBJECT_SAFE_FREE(this->mgr);
+}
+
+bool MediaSessionMgr::sessionSetInt32(twrap_media_type_t media, const char* key, int32_t value)
+{
+ TSK_DEBUG_ERROR("Not implemented");
+ return false;
+}
+
+bool MediaSessionMgr::consumerSetInt32(twrap_media_type_t media, const char* key, int32_t value)
+{
+ TSK_DEBUG_ERROR("Not implemented");
+ return false;
+}
+
+bool MediaSessionMgr::consumerSetInt64(twrap_media_type_t media, const char* key, int64_t value)
+{
+ tmedia_type_t _media = _get_media_type(media);
+ return (tmedia_session_mgr_set(this->mgr,
+ TMEDIA_SESSION_CONSUMER_SET_INT64(_media, key, value),
+ TMEDIA_SESSION_SET_NULL()) == 0);
+}
+
+bool MediaSessionMgr::producerSetInt32(twrap_media_type_t media, const char* key, int32_t value)
+{
+ TSK_DEBUG_ERROR("Not implemented");
+ return false;
+}
+
+bool MediaSessionMgr::producerSetInt64(twrap_media_type_t media, const char* key, int64_t value)
+{
+ tmedia_type_t _media = _get_media_type(media);
+ return (tmedia_session_mgr_set(this->mgr,
+ TMEDIA_SESSION_PRODUCER_SET_INT64(_media, key, value),
+ TMEDIA_SESSION_SET_NULL()) == 0);
+}
+
+#include "tinydav/audio/tdav_session_audio.h"
+#include "tinydav/video/tdav_session_video.h"
+#include "ProxyPluginMgr.h"
+
+
+ProxyPlugin* MediaSessionMgr::findProxyPlugin(twrap_media_type_t media, bool consumer)
+{
+ ProxyPlugin* plugin = tsk_null;
+ ProxyPluginMgr* manager = ProxyPluginMgr::getInstance();
+
+ if(media != twrap_media_audio && media != twrap_media_video){
+ TSK_DEBUG_ERROR("Invalid media type");
+ return tsk_null;
+ }
+
+ if(manager && this->mgr){
+ tmedia_type_t _media = _get_media_type(media);
+ tmedia_session_t* session = tmedia_session_mgr_find(this->mgr, _media);
+ if(session){
+ if(session->plugin == tdav_session_audio_plugin_def_t){
+ if(consumer){
+ plugin = manager->findPlugin(TDAV_SESSION_AUDIO(session)->consumer);
+ }
+ else{
+ plugin = manager->findPlugin(TDAV_SESSION_AUDIO(session)->producer);
+ }
+ }
+ else if(session->plugin == tdav_session_video_plugin_def_t){
+ if(consumer){
+ plugin = manager->findPlugin(TDAV_SESSION_VIDEO(session)->consumer);
+ }
+ else{
+ plugin = manager->findPlugin(TDAV_SESSION_VIDEO(session)->producer);
+ }
+ }
+ tsk_object_unref(session);
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("Invalid state");
+ }
+
+ return plugin;
+}
+
diff --git a/bindings/_common/MediaSessionMgr.h b/bindings/_common/MediaSessionMgr.h
new file mode 100644
index 0000000..7770785
--- /dev/null
+++ b/bindings/_common/MediaSessionMgr.h
@@ -0,0 +1,62 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#ifndef TINYWRAP_MEDIA_SESSIONMGR_H
+#define TINYWRAP_MEDIA_SESSIONMGR_H
+
+#include "tinymedia.h"
+#include "Common.h"
+
+class ProxyPlugin;
+
+class MediaSessionMgr
+{
+public:
+#if !defined(SWIG)
+ MediaSessionMgr(tmedia_session_mgr_t* mgr);
+#endif
+ virtual ~MediaSessionMgr();
+
+public:
+ bool sessionSetInt32(twrap_media_type_t media, const char* key, int32_t value);
+
+ bool consumerSetInt32(twrap_media_type_t media, const char* key, int32_t value);
+ bool consumerSetInt64(twrap_media_type_t media, const char* key, int64_t value);
+
+ bool producerSetInt32(twrap_media_type_t media, const char* key, int32_t value);
+ bool producerSetInt64(twrap_media_type_t media, const char* key, int64_t value);
+
+#if !defined(SWIG)
+ ProxyPlugin* findProxyPlugin(twrap_media_type_t media, bool consumer);
+#endif
+
+ ProxyPlugin* findProxyPluginConsumer(twrap_media_type_t media){
+ return this->findProxyPlugin(media, true);
+ }
+ ProxyPlugin* findProxyPluginProducer(twrap_media_type_t media){
+ return this->findProxyPlugin(media, false);
+ }
+
+private:
+ tmedia_session_mgr_t* mgr;
+};
+
+#endif /* TINYWRAP_MEDIA_SESSIONMGR_H */
diff --git a/bindings/_common/Msrp.cxx b/bindings/_common/Msrp.cxx
new file mode 100644
index 0000000..fc24413
--- /dev/null
+++ b/bindings/_common/Msrp.cxx
@@ -0,0 +1,273 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#include "Msrp.h"
+
+#include "SipSession.h"
+#include "Common.h"
+
+/* ======================== MsrpMessage ========================*/
+MsrpMessage::MsrpMessage()
+:message(tsk_null)
+{
+}
+
+MsrpMessage::MsrpMessage(tmsrp_message_t *_message)
+{
+ this->message = (tmsrp_message_t *)tsk_object_ref(_message);
+}
+
+MsrpMessage::~MsrpMessage()
+{
+ TSK_OBJECT_SAFE_FREE(this->message);
+}
+
+bool MsrpMessage::isRequest()
+{
+ return (this->message->type == tmsrp_request);
+}
+
+short MsrpMessage::getCode()
+{
+ return TMSRP_RESPONSE_CODE(this->message);
+}
+
+const char* MsrpMessage::getPhrase()
+{
+ return TMSRP_RESPONSE_PHRASE(this->message);
+}
+
+tmsrp_request_type_t MsrpMessage::getRequestType()
+{
+ if(TMSRP_MESSAGE_IS_REQUEST(this->message)){
+ return this->message->line.request.type;
+ }
+ return tmsrp_NONE;
+}
+
+void MsrpMessage::getByteRange(int64_t* start, int64_t* end, int64_t* total)
+{
+ if(this->message->ByteRange){
+ *start = this->message->ByteRange->start;
+ *end = this->message->ByteRange->end;
+ *total = this->message->ByteRange->total;
+ }
+ else{
+ *start = *end = *total = -1;
+ }
+}
+
+bool MsrpMessage::isLastChunck()
+{
+ if(TMSRP_MESSAGE_IS_REQUEST(this->message)){
+ return (this->message->end_line.cflag == '$');
+ }
+ else{
+ if(this->message->ByteRange){
+ return (this->message->ByteRange->end >= this->message->ByteRange->total);
+ }
+ }
+ return false;
+}
+
+bool MsrpMessage::isFirstChunck()
+{
+ return (this->message && this->message->ByteRange->start == 1);
+}
+
+char* MsrpMessage::getMsrpHeaderValue(const char* name)
+{
+ const tmsrp_header_t* header = this->getMsrpHeader(name, 0);
+ if(header){
+ return tmsrp_header_tostring(header);
+ }
+ return tsk_null;
+}
+
+char* MsrpMessage::getMsrpHeaderParamValue(const char* name, const char* param)
+{
+ return tsk_null;
+}
+
+unsigned MsrpMessage::getMsrpContentLength()
+{
+ if(this->message &&
+ this->message->Content &&
+ this->message->Content->data &&
+ this->message->Content->size){
+ return this->message->Content->size;
+ }
+ return 0;
+}
+
+unsigned MsrpMessage::getMsrpContent(void* output, unsigned maxsize)
+{
+ unsigned retsize = 0;
+ if(!output ||
+ !this->message ||
+ !this->message->Content ||
+ !this->message->Content->data ||
+ !this->message->Content->size){
+ return 0;
+ }
+
+
+ retsize = (this->message->Content->size > maxsize) ? maxsize : this->message->Content->size;
+ memcpy(output, this->message->Content->data, retsize);
+ return retsize;
+}
+
+const tmsrp_header_t* MsrpMessage::getMsrpHeader(const char* name, unsigned index /*= 0*/)
+{
+ tsk_size_t pos = 0;
+ const tmsrp_header_t* hdr = tsk_null;
+ const tsk_list_item_t *item;
+
+ /* From tmsrp_message_get_headerAt() */
+ if(!this->message || !name){
+ return tsk_null;
+ }
+
+ if(tsk_striequals(name, "To-Path")){
+ if(index == 0){
+ hdr = (const tmsrp_header_t*)this->message->To;
+ goto bail;
+ }else pos++; }
+ if(tsk_striequals(name, "From-Path")){
+ if(index == 0){
+ hdr = (const tmsrp_header_t*)this->message->From;
+ goto bail;
+ }else pos++; }
+ if(tsk_striequals(name, "Message-ID")){
+ if(index == 0){
+ hdr = (const tmsrp_header_t*)this->message->MessageID;
+ goto bail;
+ }else pos++; }
+ if(tsk_striequals(name, "Byte-Range")){
+ if(index == 0){
+ hdr = (const tmsrp_header_t*)this->message->ByteRange;
+ goto bail;
+ }else pos++; }
+ if(tsk_striequals(name, "Failure-Report")){
+ if(index == 0){
+ hdr = (const tmsrp_header_t*)this->message->FailureReport;
+ goto bail;
+ }else pos++; }
+ if(tsk_striequals(name, "Success-Report")){
+ if(index == 0){
+ hdr = (const tmsrp_header_t*)this->message->SuccessReport;
+ goto bail;
+ }else pos++; }
+ if(tsk_striequals(name, "Status")){
+ if(index == 0){
+ hdr = (const tmsrp_header_t*)this->message->Status;
+ goto bail;
+ }else pos++; }
+ if(tsk_striequals(name, "Content-Type")){
+ if(index == 0){
+ hdr = (const tmsrp_header_t*)this->message->ContentType;
+ goto bail;
+ }else pos++; }
+
+
+ /* All other headers */
+ tsk_list_foreach(item, this->message->headers){
+ if(tsk_striequals(tmsrp_header_get_nameex(TMSRP_HEADER(item->data)), name)){
+ if(pos++ >= index){
+ hdr = (const tmsrp_header_t*)item->data;
+ break;
+ }
+ }
+ }
+
+
+bail:
+ return hdr;
+
+}
+
+
+
+/* ======================== MsrpEvent ========================*/
+MsrpEvent::MsrpEvent(const tmsrp_event_t *_msrpevent)
+{
+ this->_event = _msrpevent;
+ if(this->_event && this->_event->message){
+ this->message = new MsrpMessage((tmsrp_message_t *)this->_event->message);
+ }
+ else{
+ this->message = tsk_null;
+ }
+}
+
+MsrpEvent::~MsrpEvent()
+{
+ if(this->message){
+ delete this->message;
+ }
+}
+
+tmsrp_event_type_t MsrpEvent::getType()
+{
+ if(this->_event){
+ return this->_event->type;
+ }
+ return tmsrp_event_type_none;
+}
+
+const MsrpSession* MsrpEvent::getSipSession()
+{
+ if(this->_event && this->_event->callback_data){
+ return dyn_cast<const MsrpSession*>((const MsrpSession*)this->_event->callback_data);
+ }
+ return tsk_null;
+}
+
+const MsrpMessage* MsrpEvent::getMessage() const
+{
+ return this->message;
+}
+
+
+
+
+int twrap_msrp_cb(const tmsrp_event_t* _event)
+{
+ const MsrpSession* session = (const MsrpSession*)_event->callback_data;
+ MsrpCallback* callback;
+ int ret = -1;
+
+ if(session){
+ if((callback = session->getCallback())){
+ MsrpEvent* e = new MsrpEvent(_event);
+ ret = callback->OnEvent(e);
+ delete e;
+ }
+ else{
+ return 0;
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("Invalid parameter");
+ }
+
+ return ret;
+} \ No newline at end of file
diff --git a/bindings/_common/Msrp.h b/bindings/_common/Msrp.h
new file mode 100644
index 0000000..d0b6448
--- /dev/null
+++ b/bindings/_common/Msrp.h
@@ -0,0 +1,91 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#ifndef TINYWRAP_MSRP_H
+#define TINYWRAP_MSRP_H
+
+#include "tinymsrp.h"
+
+class MsrpSession;
+
+class MsrpMessage
+{
+public:
+ MsrpMessage();
+#if !defined(SWIG)
+ MsrpMessage(tmsrp_message_t *message);
+#endif
+ virtual ~MsrpMessage();
+
+ bool isRequest();
+ short getCode();
+ const char* getPhrase();
+ tmsrp_request_type_t getRequestType();
+#if defined(SWIG)
+ void getByteRange(int64_t* OUTPUT, int64_t* OUTPUT, int64_t* OUTPUT);
+#else
+ void getByteRange(int64_t* start, int64_t* end, int64_t* total);
+#endif
+ bool isLastChunck();
+ bool isFirstChunck();
+ char* getMsrpHeaderValue(const char* name);
+ char* getMsrpHeaderParamValue(const char* name, const char* param);
+ unsigned getMsrpContentLength();
+ unsigned getMsrpContent(void* output, unsigned maxsize);
+
+private:
+ const tmsrp_header_t* getMsrpHeader(const char* name, unsigned index = 0);
+
+private:
+ tmsrp_message_t *message;
+};
+
+class MsrpEvent
+{
+public:
+#if !defined(SWIG)
+ MsrpEvent(const tmsrp_event_t *_event);
+#endif
+ virtual ~MsrpEvent();
+
+ tmsrp_event_type_t getType();
+ const MsrpSession* getSipSession();
+ const MsrpMessage* getMessage() const;
+
+protected:
+ const tmsrp_event_t *_event;
+ MsrpMessage* message;
+};
+
+class MsrpCallback
+{
+public:
+ MsrpCallback() { }
+ virtual ~MsrpCallback() {}
+ virtual int OnEvent(const MsrpEvent* e) { return -1; }
+};
+
+
+#if !defined(SWIG)
+int twrap_msrp_cb(const tmsrp_event_t* _event);
+#endif
+
+#endif /* TINYWRAP_MSRP_H */
diff --git a/bindings/_common/Msrp.i b/bindings/_common/Msrp.i
new file mode 100644
index 0000000..9d32cc4
--- /dev/null
+++ b/bindings/_common/Msrp.i
@@ -0,0 +1,34 @@
+%{
+#include "Msrp.h"
+%}
+
+/* Callbacks */
+%feature("director") MsrpCallback;
+
+
+%nodefaultctor;
+%include "Msrp.h"
+%clearnodefaultctor;
+
+/* From tinyMSRP/tmsrp_message.h */
+typedef enum tmsrp_request_type_e
+{
+ tmsrp_NONE = 0,
+
+ tmsrp_SEND,
+ tmsrp_REPORT,
+ tmsrp_AUTH
+ //...
+}
+tmsrp_request_type_t;
+
+
+/* From tinyMSRP/tmsrp_event.h */
+typedef enum tmsrp_event_type_e
+{
+ tmsrp_event_type_none,
+ tmsrp_event_type_connected,
+ tmsrp_event_type_disconnected,
+ tmsrp_event_type_message,
+}
+tmsrp_event_type_t; \ No newline at end of file
diff --git a/bindings/_common/ProxyConsumer.cxx b/bindings/_common/ProxyConsumer.cxx
new file mode 100644
index 0000000..d7aa49b
--- /dev/null
+++ b/bindings/_common/ProxyConsumer.cxx
@@ -0,0 +1,519 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+
+/**@file ProxyConsumer.c
+ * @brief Audio/Video proxy consumers.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "ProxyConsumer.h"
+
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+#include "tinydav/audio/tdav_consumer_audio.h"
+
+#define twrap_consumer_proxy_audio_set tsk_null
+#define twrap_consumer_proxy_video_set tsk_null
+
+/* ============ Audio Consumer Interface ================= */
+
+typedef struct twrap_consumer_proxy_audio_s
+{
+ TDAV_DECLARE_CONSUMER_AUDIO;
+
+ uint64_t id;
+ tsk_bool_t started;
+}
+twrap_consumer_proxy_audio_t;
+#define TWRAP_CONSUMER_PROXY_AUDIO(self) ((twrap_consumer_proxy_audio_t*)(self))
+
+
+int twrap_consumer_proxy_audio_prepare(tmedia_consumer_t* self, const tmedia_codec_t* codec)
+{
+ ProxyPluginMgr* manager;
+ int ret = -1;
+ if(codec && (manager = ProxyPluginMgr::getInstance())){
+ ProxyAudioConsumer* audioConsumer;
+ if((audioConsumer = manager->findAudioConsumer(TWRAP_CONSUMER_PROXY_AUDIO(self)->id)) && audioConsumer->getCallback()){
+ ret = audioConsumer->getCallback()->prepare((int)codec->plugin->audio.ptime, codec->plugin->rate, codec->plugin->audio.channels);
+ }
+ }
+
+ return ret;
+}
+
+int twrap_consumer_proxy_audio_start(tmedia_consumer_t* self)
+{
+ ProxyPluginMgr* manager;
+ int ret = -1;
+ if((manager = ProxyPluginMgr::getInstance())){
+ ProxyAudioConsumer* audioConsumer;
+ if((audioConsumer = manager->findAudioConsumer(TWRAP_CONSUMER_PROXY_AUDIO(self)->id)) && audioConsumer->getCallback()){
+ ret = audioConsumer->getCallback()->start();
+ }
+ }
+
+ TWRAP_CONSUMER_PROXY_AUDIO(self)->started = (ret == 0);
+ return ret;
+}
+
+int twrap_consumer_proxy_audio_consume(tmedia_consumer_t* self, void** buffer, tsk_size_t size, const tsk_object_t* proto_hdr)
+{
+ ProxyPluginMgr* manager;
+ int ret = -1;
+ if((manager = ProxyPluginMgr::getInstance())){
+ ProxyAudioConsumer* audioConsumer;
+ if((audioConsumer = manager->findAudioConsumer(TWRAP_CONSUMER_PROXY_AUDIO(self)->id)) && audioConsumer->getCallback()){
+ ret = tdav_consumer_audio_put(TDAV_CONSUMER_AUDIO(self), buffer, size, proto_hdr);
+ }
+ }
+
+ return ret;
+}
+
+int twrap_consumer_proxy_audio_pause(tmedia_consumer_t* self)
+{
+ ProxyPluginMgr* manager;
+ int ret = -1;
+ if((manager = ProxyPluginMgr::getInstance())){
+ ProxyAudioConsumer* audioConsumer;
+ if((audioConsumer = manager->findAudioConsumer(TWRAP_CONSUMER_PROXY_AUDIO(self)->id)) && audioConsumer->getCallback()){
+ ret = audioConsumer->getCallback()->pause();
+ }
+ }
+
+ return ret;
+}
+
+int twrap_consumer_proxy_audio_stop(tmedia_consumer_t* self)
+{
+ ProxyPluginMgr* manager;
+ int ret = -1;
+ if((manager = ProxyPluginMgr::getInstance())){
+ ProxyAudioConsumer* audioConsumer;
+ if((audioConsumer = manager->findAudioConsumer(TWRAP_CONSUMER_PROXY_AUDIO(self)->id)) && audioConsumer->getCallback()){
+ ret = audioConsumer->getCallback()->stop();
+ }
+ }
+
+ TWRAP_CONSUMER_PROXY_AUDIO(self)->started = (ret == 0) ? tsk_false : tsk_true;
+ return ret;
+}
+
+
+//
+// Audio consumer object definition
+//
+/* constructor */
+static tsk_object_t* twrap_consumer_proxy_audio_ctor(tsk_object_t * self, va_list * app)
+{
+ twrap_consumer_proxy_audio_t *consumer = (twrap_consumer_proxy_audio_t *)self;
+ if(consumer){
+ /* init base */
+ tdav_consumer_audio_init(TDAV_CONSUMER_AUDIO(consumer));
+ /* init self */
+
+ /* Add the plugin to the manager */
+ ProxyPluginMgr* manager = ProxyPluginMgr::getInstance();
+ if(manager){
+ ProxyPlugin* proxyConsumer = new ProxyAudioConsumer(consumer);
+ uint64_t id = proxyConsumer->getId();
+ manager->addPlugin(&proxyConsumer);
+ manager->getCallback()->OnPluginCreated(id, twrap_proxy_plugin_audio_consumer);
+ }
+ }
+ return self;
+}
+/* destructor */
+static tsk_object_t* twrap_consumer_proxy_audio_dtor(tsk_object_t * self)
+{
+ twrap_consumer_proxy_audio_t *consumer = (twrap_consumer_proxy_audio_t *)self;
+ if(consumer){
+ /* stop */
+ if(consumer->started){
+ twrap_consumer_proxy_audio_stop(TMEDIA_CONSUMER(consumer));
+ }
+
+ /* deinit base */
+ tdav_consumer_audio_deinit(TDAV_CONSUMER_AUDIO(consumer));
+ /* deinit self */
+
+
+ /* Remove plugin from the manager */
+ ProxyPluginMgr* manager = ProxyPluginMgr::getInstance();
+ if(manager){
+ manager->getCallback()->OnPluginDestroyed(consumer->id, twrap_proxy_plugin_audio_consumer);
+ manager->removePlugin(consumer->id);
+ }
+ }
+
+ return self;
+}
+/* object definition */
+static const tsk_object_def_t twrap_consumer_proxy_audio_def_s =
+{
+ sizeof(twrap_consumer_proxy_audio_t),
+ twrap_consumer_proxy_audio_ctor,
+ twrap_consumer_proxy_audio_dtor,
+ tdav_consumer_audio_cmp,
+};
+/* plugin definition*/
+static const tmedia_consumer_plugin_def_t twrap_consumer_proxy_audio_plugin_def_s =
+{
+ &twrap_consumer_proxy_audio_def_s,
+
+ tmedia_audio,
+ "Audio Proxy Consumer",
+
+ twrap_consumer_proxy_audio_set,
+ twrap_consumer_proxy_audio_prepare,
+ twrap_consumer_proxy_audio_start,
+ twrap_consumer_proxy_audio_consume,
+ twrap_consumer_proxy_audio_pause,
+ twrap_consumer_proxy_audio_stop
+};
+
+TINYWRAP_GEXTERN const tmedia_consumer_plugin_def_t *twrap_consumer_proxy_audio_plugin_def_t = &twrap_consumer_proxy_audio_plugin_def_s;
+
+
+
+/* ============ ProxyAudioConsumer Class ================= */
+ProxyAudioConsumer::ProxyAudioConsumer(twrap_consumer_proxy_audio_t* _consumer)
+:ProxyPlugin(twrap_proxy_plugin_audio_consumer), consumer(_consumer), callback(tsk_null)
+{
+ this->consumer->id = this->getId();
+}
+
+ProxyAudioConsumer::~ProxyAudioConsumer()
+{
+}
+
+unsigned ProxyAudioConsumer::pull(void* output, unsigned size)
+{
+ tsk_size_t out_size = 0;
+ if(this->consumer){
+ void* data;
+ if((data = tdav_consumer_audio_get(TDAV_CONSUMER_AUDIO(this->consumer), &out_size))){
+ memcpy(output, data, TSK_MIN(size, out_size));
+ TSK_FREE(data);
+ return TSK_MIN(size, out_size);
+ }
+ }
+ return out_size;
+}
+
+bool ProxyAudioConsumer::reset()
+{
+ if(this->consumer){
+ return (tdav_consumer_audio_reset(TDAV_CONSUMER_AUDIO(this->consumer)) == 0);
+ }
+ return false;
+}
+
+bool ProxyAudioConsumer::registerPlugin()
+{
+ /* HACK: Unregister all other audio plugins */
+ tmedia_consumer_plugin_unregister_by_type(tmedia_audio);
+ /* Register our proxy plugin */
+ return (tmedia_consumer_plugin_register(twrap_consumer_proxy_audio_plugin_def_t) == 0);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* ============ Video Consumer Interface ================= */
+
+typedef struct twrap_consumer_proxy_video_s
+{
+ TMEDIA_DECLARE_CONSUMER;
+
+ uint64_t id;
+ tsk_bool_t started;
+}
+twrap_consumer_proxy_video_t;
+#define TWRAP_CONSUMER_PROXY_VIDEO(self) ((twrap_consumer_proxy_video_t*)(self))
+
+
+int twrap_consumer_proxy_video_prepare(tmedia_consumer_t* self, const tmedia_codec_t* codec)
+{
+ ProxyPluginMgr* manager;
+ int ret = -1;
+ if(codec && (manager = ProxyPluginMgr::getInstance())){
+ ProxyVideoConsumer* videoConsumer;
+ if((videoConsumer = manager->findVideoConsumer(TWRAP_CONSUMER_PROXY_VIDEO(self)->id)) && videoConsumer->getCallback()){
+ self->video.fps = TMEDIA_CODEC_VIDEO(codec)->fps;
+ // in
+ self->video.in.chroma = tmedia_yuv420p;
+ self->video.in.width = TMEDIA_CODEC_VIDEO(codec)->width;
+ self->video.in.height = TMEDIA_CODEC_VIDEO(codec)->height;
+ // display (out)
+ self->video.display.chroma = videoConsumer->getChroma();
+ if(!self->video.display.width){
+ self->video.display.width = self->video.in.width;
+ }
+ if(!self->video.display.height){
+ self->video.display.height = self->video.in.height;
+ }
+ ret = videoConsumer->getCallback()->prepare(TMEDIA_CODEC_VIDEO(codec)->width, TMEDIA_CODEC_VIDEO(codec)->height, TMEDIA_CODEC_VIDEO(codec)->fps);
+ }
+ }
+
+ return ret;
+}
+
+int twrap_consumer_proxy_video_start(tmedia_consumer_t* self)
+{
+ ProxyPluginMgr* manager;
+ int ret = -1;
+ if((manager = ProxyPluginMgr::getInstance())){
+ ProxyVideoConsumer* videoConsumer;
+ if((videoConsumer = manager->findVideoConsumer(TWRAP_CONSUMER_PROXY_VIDEO(self)->id)) && videoConsumer->getCallback()){
+ ret = videoConsumer->getCallback()->start();
+ }
+ }
+
+ TWRAP_CONSUMER_PROXY_VIDEO(self)->started = (ret == 0);
+ return ret;
+}
+
+int twrap_consumer_proxy_video_consume(tmedia_consumer_t* self, void** buffer, tsk_size_t size, const tsk_object_t* proto_hdr)
+{
+ ProxyPluginMgr* manager;
+ int ret = -1;
+
+ if(!self || !buffer || !*buffer || !size){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if((manager = ProxyPluginMgr::getInstance())){
+ ProxyVideoConsumer* videoConsumer;
+ if((videoConsumer = manager->findVideoConsumer(TWRAP_CONSUMER_PROXY_VIDEO(self)->id)) && videoConsumer->getCallback()){
+ ProxyVideoFrame* frame = new ProxyVideoFrame(*buffer, size);
+ ret = videoConsumer->getCallback()->consume(frame);
+ delete frame, frame = tsk_null;
+ }
+ }
+
+ return ret;
+}
+
+int twrap_consumer_proxy_video_pause(tmedia_consumer_t* self)
+{
+ ProxyPluginMgr* manager;
+ int ret = -1;
+ if((manager = ProxyPluginMgr::getInstance())){
+ ProxyVideoConsumer* videoConsumer;
+ if((videoConsumer = manager->findVideoConsumer(TWRAP_CONSUMER_PROXY_VIDEO(self)->id)) && videoConsumer->getCallback()){
+ ret = videoConsumer->getCallback()->pause();
+ }
+ }
+
+ return ret;
+}
+
+int twrap_consumer_proxy_video_stop(tmedia_consumer_t* self)
+{
+ ProxyPluginMgr* manager;
+ int ret = -1;
+ if((manager = ProxyPluginMgr::getInstance())){
+ ProxyVideoConsumer* videoConsumer;
+ if((videoConsumer = manager->findVideoConsumer(TWRAP_CONSUMER_PROXY_VIDEO(self)->id)) && videoConsumer->getCallback()){
+ ret = videoConsumer->getCallback()->stop();
+ }
+ }
+
+ TWRAP_CONSUMER_PROXY_VIDEO(self)->started = (ret == 0) ? tsk_false : tsk_true;
+ return ret;
+}
+
+
+//
+// Video consumer object definition
+//
+/* constructor */
+static tsk_object_t* twrap_consumer_proxy_video_ctor(tsk_object_t * self, va_list * app)
+{
+ twrap_consumer_proxy_video_t *consumer = (twrap_consumer_proxy_video_t *)self;
+ if(consumer){
+ /* init base */
+ tmedia_consumer_init(TMEDIA_CONSUMER(consumer));
+ /* init self */
+
+ /* Add the plugin to the manager */
+ ProxyPluginMgr* manager = ProxyPluginMgr::getInstance();
+ if(manager){
+ ProxyPlugin* proxyConsumer = new ProxyVideoConsumer(ProxyVideoConsumer::getDefaultChroma(), consumer);
+ uint64_t id = proxyConsumer->getId();
+ manager->addPlugin(&proxyConsumer);
+ manager->getCallback()->OnPluginCreated(id, twrap_proxy_plugin_video_consumer);
+ }
+ }
+ return self;
+}
+/* destructor */
+static tsk_object_t* twrap_consumer_proxy_video_dtor(tsk_object_t * self)
+{
+ twrap_consumer_proxy_video_t *consumer = (twrap_consumer_proxy_video_t *)self;
+ if(consumer){
+
+ /* stop */
+ if(consumer->started){
+ twrap_consumer_proxy_video_stop(TMEDIA_CONSUMER(consumer));
+ }
+
+ /* deinit base */
+ tmedia_consumer_deinit(TMEDIA_CONSUMER(consumer));
+ /* deinit self */
+
+ /* Remove plugin from the manager */
+ ProxyPluginMgr* manager = ProxyPluginMgr::getInstance();
+ if(manager){
+ manager->getCallback()->OnPluginDestroyed(consumer->id, twrap_proxy_plugin_video_consumer);
+ manager->removePlugin(consumer->id);
+ }
+ }
+
+ return self;
+}
+/* object definition */
+static const tsk_object_def_t twrap_consumer_proxy_video_def_s =
+{
+ sizeof(twrap_consumer_proxy_video_t),
+ twrap_consumer_proxy_video_ctor,
+ twrap_consumer_proxy_video_dtor,
+ tsk_null,
+};
+/* plugin definition*/
+static const tmedia_consumer_plugin_def_t twrap_consumer_proxy_video_plugin_def_s =
+{
+ &twrap_consumer_proxy_video_def_s,
+
+ tmedia_video,
+ "Video Proxy Consumer",
+
+ twrap_consumer_proxy_video_set,
+ twrap_consumer_proxy_video_prepare,
+ twrap_consumer_proxy_video_start,
+ twrap_consumer_proxy_video_consume,
+ twrap_consumer_proxy_video_pause,
+ twrap_consumer_proxy_video_stop
+};
+
+TINYWRAP_GEXTERN const tmedia_consumer_plugin_def_t *twrap_consumer_proxy_video_plugin_def_t = &twrap_consumer_proxy_video_plugin_def_s;
+
+
+
+/* ============ ProxyVideoConsumer Class ================= */
+tmedia_chroma_t ProxyVideoConsumer::defaultChroma = tmedia_rgb565le;
+
+ProxyVideoConsumer::ProxyVideoConsumer(tmedia_chroma_t _chroma, struct twrap_consumer_proxy_video_s* _consumer)
+: chroma(_chroma), consumer(_consumer), callback(tsk_null), ProxyPlugin(twrap_proxy_plugin_video_consumer)
+{
+ this->consumer->id = this->getId();
+}
+
+ProxyVideoConsumer::~ProxyVideoConsumer()
+{
+}
+
+bool ProxyVideoConsumer::setDisplaySize(int width, int height)
+{
+ if((this->consumer = (twrap_consumer_proxy_video_t*)tsk_object_ref(this->consumer))){
+ TMEDIA_CONSUMER(this->consumer)->video.display.width = width;
+ TMEDIA_CONSUMER(this->consumer)->video.display.height = height;
+ this->consumer = (twrap_consumer_proxy_video_t*)tsk_object_unref(this->consumer);
+ return true;
+ }
+ return false;
+}
+
+tmedia_chroma_t ProxyVideoConsumer::getChroma()
+{
+ return this->chroma;
+}
+
+bool ProxyVideoConsumer::registerPlugin()
+{
+ /* HACK: Unregister all other video plugins */
+ tmedia_consumer_plugin_unregister_by_type(tmedia_video);
+ /* Register our proxy plugin */
+ return (tmedia_consumer_plugin_register(twrap_consumer_proxy_video_plugin_def_t) == 0);
+}
+
+
+
+ProxyVideoFrame::ProxyVideoFrame(const void* _buffer, unsigned size)
+{
+ this->buffer = _buffer;
+ this->size = size;
+}
+
+ProxyVideoFrame::~ProxyVideoFrame()
+{
+}
+
+unsigned ProxyVideoFrame::getSize()
+{
+ return this->size;
+}
+
+unsigned ProxyVideoFrame::getContent(void* output, unsigned maxsize)
+{
+ unsigned retsize = 0;
+ if(output && maxsize && this->buffer){
+ retsize = (this->size > maxsize) ? maxsize : this->size;
+ memcpy(output, this->buffer, retsize);
+ }
+ return retsize;
+}
diff --git a/bindings/_common/ProxyConsumer.h b/bindings/_common/ProxyConsumer.h
new file mode 100644
index 0000000..d47b36f
--- /dev/null
+++ b/bindings/_common/ProxyConsumer.h
@@ -0,0 +1,161 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+
+/**@file ProxyConsumer.h
+ * @brief Audio/Video proxy consumers.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TINYWRAP_CONSUMER_PROXY_H
+#define TINYWRAP_CONSUMER_PROXY_H
+
+#include "tinyWRAP_config.h"
+
+#include "ProxyPluginMgr.h"
+
+#include "tinymedia/tmedia_common.h"
+#include "tinymedia/tmedia_consumer.h"
+
+/* ============ ProxyAudioConsumerCallback Class ================= */
+class ProxyAudioConsumerCallback
+{
+public:
+ ProxyAudioConsumerCallback() { }
+ virtual ~ProxyAudioConsumerCallback(){ }
+
+ virtual int prepare(int ptime, int rate, int channels) { return -1; }
+ virtual int start() { return -1; }
+ virtual int pause() { return -1; }
+ virtual int stop() { return -1; }
+};
+
+/* ============ ProxyAudioConsumer Class ================= */
+class ProxyAudioConsumer : public ProxyPlugin
+{
+public:
+#if !defined(SWIG)
+ ProxyAudioConsumer(struct twrap_consumer_proxy_audio_s* consumer);
+#endif
+ virtual ~ProxyAudioConsumer();
+
+ unsigned pull(void* output, unsigned size);
+ bool reset();
+ void setCallback(ProxyAudioConsumerCallback* _callback) { this->callback = _callback; }
+#if !defined(SWIG)
+ inline ProxyAudioConsumerCallback* getCallback() { return this->callback; }
+ virtual inline bool isWrapping(tsk_object_t* wrapped_plugin){
+ return this->consumer == wrapped_plugin;
+ }
+#endif
+ virtual inline uint64_t getMediaSessionId(){
+ return this->consumer ? TMEDIA_CONSUMER(this->consumer)->session_id : 0;
+ }
+
+public:
+ static bool registerPlugin();
+
+private:
+ struct twrap_consumer_proxy_audio_s* consumer;
+ ProxyAudioConsumerCallback* callback;
+};
+
+class ProxyVideoFrame;
+
+/* ============ ProxyVideoConsumerCallback Class ================= */
+class ProxyVideoConsumerCallback
+{
+public:
+ ProxyVideoConsumerCallback(){}
+ virtual ~ProxyVideoConsumerCallback() {}
+
+ virtual int prepare(int width, int height, int fps) { return -1; }
+ virtual int consume(const ProxyVideoFrame* frame) { return -1; }
+ virtual int start() { return -1; }
+ virtual int pause() { return -1; }
+ virtual int stop() { return -1; }
+};
+
+/* ============ ProxyVideoConsumer Class ================= */
+class ProxyVideoConsumer : public ProxyPlugin
+{
+public:
+#if !defined(SWIG)
+ ProxyVideoConsumer(tmedia_chroma_t chroma, struct twrap_consumer_proxy_video_s* consumer);
+#endif
+ virtual ~ProxyVideoConsumer();
+
+ bool setDisplaySize(int width, int height);
+ void setCallback(ProxyVideoConsumerCallback* _callback) { this->callback = _callback; }
+#if !defined(SWIG)
+ inline ProxyVideoConsumerCallback* getCallback() { return this->callback; }
+ virtual inline bool isWrapping(tsk_object_t* wrapped_plugin){
+ return this->consumer == wrapped_plugin;
+ }
+#endif
+ virtual inline uint64_t getMediaSessionId(){
+ return this->consumer ? TMEDIA_CONSUMER(this->consumer)->session_id : 0;
+ }
+
+public:
+ static bool registerPlugin();
+ static void setDefaultChroma(tmedia_chroma_t chroma){ ProxyVideoConsumer::defaultChroma = chroma; }
+
+#if !defined(SWIG)
+ tmedia_chroma_t getChroma();
+ static tmedia_chroma_t getDefaultChroma() { return ProxyVideoConsumer::defaultChroma; }
+#endif
+
+private:
+ struct twrap_consumer_proxy_video_s* consumer;
+ tmedia_chroma_t chroma;
+ ProxyVideoConsumerCallback* callback;
+ static tmedia_chroma_t defaultChroma;
+};
+
+/* ============ ProxyVideoFrame Class ================= */
+class ProxyVideoFrame
+{
+public:
+#if !defined(SWIG)
+ ProxyVideoFrame(const void* buffer, unsigned size);
+#endif
+ virtual ~ProxyVideoFrame();
+
+public: /* For Java/C# applications */
+ unsigned getSize();
+ unsigned getContent(void* output, unsigned maxsize);
+
+#if !defined(SWIG) /* For C/C++ applications */
+public:
+ inline unsigned fastGetSize()const{ return size; }
+ inline const void* fastGetContent()const{ return buffer; }
+#endif
+
+private:
+ const void* buffer;
+ unsigned size;
+};
+
+
+#endif /* TINYWRAP_CONSUMER_PROXY_H */
diff --git a/bindings/_common/ProxyPluginMgr.cxx b/bindings/_common/ProxyPluginMgr.cxx
new file mode 100644
index 0000000..39f2cac
--- /dev/null
+++ b/bindings/_common/ProxyPluginMgr.cxx
@@ -0,0 +1,290 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#include "ProxyPluginMgr.h"
+
+#include "ProxyConsumer.h"
+#include "ProxyProducer.h"
+
+//
+// "twrap_proxy_plugin_t" Declarations
+//
+typedef struct twrap_proxy_plugin_s
+{
+ TSK_DECLARE_OBJECT;
+ ProxyPlugin* plugin;
+}
+twrap_proxy_plugin_t;
+#define TWRAP_PROXY_PLUGIN(self) ((twrap_proxy_plugin_t*)(self))
+static int pred_find_plugin_by_value(const tsk_list_item_t *item, const void *proxyPlugin);
+static twrap_proxy_plugin_t* twrap_proxy_plugin_create(ProxyPlugin** plugin);
+
+
+//
+// "ProxyPluginMgr" Class Implementation
+//
+ProxyPluginMgr* ProxyPluginMgr::instance = tsk_null;
+static uint64_t __uniqueId = 0;
+
+ProxyPluginMgr::ProxyPluginMgr(ProxyPluginMgrCallback* _callback)
+:callback(_callback)
+{
+ this->plugins = tsk_list_create();
+ if(!this->callback){
+ TSK_DEBUG_WARN("Callback function is Null => You will have big problems as we won't check it before call");
+ }
+}
+
+ProxyPluginMgr::~ProxyPluginMgr()
+{
+ if(this == ProxyPluginMgr::instance){
+ ProxyPluginMgr::instance = tsk_null;
+ }
+ TSK_OBJECT_SAFE_FREE(this->plugins);
+}
+
+ProxyPluginMgr* ProxyPluginMgr::createInstance(ProxyPluginMgrCallback* _callback)
+{
+ if(!ProxyPluginMgr::instance){
+ ProxyPluginMgr::instance = new ProxyPluginMgr(_callback);
+ }
+ else{
+ TSK_DEBUG_WARN("Plugin instance already exist");
+ ProxyPluginMgr::instance->callback = _callback;
+ }
+ return ProxyPluginMgr::instance;
+}
+
+ProxyPluginMgr* ProxyPluginMgr::getInstance()
+{
+ if(!ProxyPluginMgr::instance){
+ TSK_DEBUG_ERROR("No instance of the manager could be found");
+ }
+ return ProxyPluginMgr::instance;
+}
+
+uint64_t ProxyPluginMgr::getUniqueId()
+{
+ return ++__uniqueId;
+}
+
+int ProxyPluginMgr::addPlugin(ProxyPlugin** plugin)
+{
+ twrap_proxy_plugin_t* twrap_plugin;
+ int ret = -1;
+
+ tsk_list_lock(this->plugins);
+
+ if(!plugin || !*plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ goto bail;
+ }
+
+ if(tsk_list_find_item_by_pred(this->plugins, pred_find_plugin_by_value, *plugin)){
+ TSK_DEBUG_ERROR("Plugin already exist");
+ goto bail;
+ }
+
+ if((twrap_plugin = twrap_proxy_plugin_create(plugin))){
+ tsk_list_push_back_data(this->plugins, (void**)&twrap_plugin);
+ ret = 0;
+ }
+ else{
+ TSK_DEBUG_ERROR("Failed to create plugin");
+ goto bail;
+ }
+
+bail:
+ tsk_list_unlock(this->plugins);
+
+ return ret;
+}
+
+int ProxyPluginMgr::removePlugin(ProxyPlugin** plugin)
+{
+ if(!plugin || !*plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ return this->removePlugin((*plugin)->getId());
+}
+
+ProxyPlugin* ProxyPluginMgr::findPlugin(uint64_t id)
+{
+ ProxyPlugin* ret = tsk_null;
+
+ tsk_list_item_t* item;
+
+ tsk_list_lock(this->plugins);
+ tsk_list_foreach(item, this->plugins){
+ if(TWRAP_PROXY_PLUGIN(item->data)->plugin->getId() == id){
+ ret = TWRAP_PROXY_PLUGIN(item->data)->plugin;
+ break;
+ }
+ }
+ tsk_list_unlock(this->plugins);
+
+ return ret;
+}
+
+ProxyPlugin* ProxyPluginMgr::findPlugin(tsk_object_t* wrapped_plugin)
+{
+ ProxyPlugin* ret = tsk_null;
+
+ tsk_list_item_t* item;
+
+ tsk_list_lock(this->plugins);
+ tsk_list_foreach(item, this->plugins){
+ if(TWRAP_PROXY_PLUGIN(item->data)->plugin->isWrapping(wrapped_plugin)){
+ ret = TWRAP_PROXY_PLUGIN(item->data)->plugin;
+ break;
+ }
+ }
+ tsk_list_unlock(this->plugins);
+
+ return ret;
+}
+
+int ProxyPluginMgr::removePlugin(uint64_t id)
+{
+ tsk_list_item_t* item;
+
+ tsk_list_lock(this->plugins);
+
+ tsk_list_foreach(item, this->plugins){
+ if(TWRAP_PROXY_PLUGIN(item->data)->plugin->getId() == id){
+ tsk_list_remove_item(this->plugins, item);
+ break;
+ }
+ }
+
+ tsk_list_unlock(this->plugins);
+ return 0;
+}
+
+ProxyAudioConsumer* ProxyPluginMgr::findAudioConsumer(uint64_t id)
+{
+ ProxyPlugin* audioConsumer = this->findPlugin(id);
+ if(audioConsumer && audioConsumer->getType() == twrap_proxy_plugin_audio_consumer){
+ return dyn_cast<ProxyAudioConsumer*>(audioConsumer);
+ }
+ return tsk_null;
+}
+
+ProxyVideoConsumer* ProxyPluginMgr::findVideoConsumer(uint64_t id)
+{
+ ProxyPlugin* videoConsumer = this->findPlugin(id);
+ if(videoConsumer && videoConsumer->getType() == twrap_proxy_plugin_video_consumer){
+ return dyn_cast<ProxyVideoConsumer*>(videoConsumer);
+ }
+ return tsk_null;
+}
+
+ProxyAudioProducer* ProxyPluginMgr::findAudioProducer(uint64_t id)
+{
+ ProxyPlugin* audioProducer = this->findPlugin(id);
+ if(audioProducer && audioProducer->getType() == twrap_proxy_plugin_audio_producer){
+ return dyn_cast<ProxyAudioProducer*>(audioProducer);
+ }
+ return tsk_null;
+}
+
+ProxyVideoProducer* ProxyPluginMgr::findVideoProducer(uint64_t id)
+{
+ ProxyPlugin* videoProducer = this->findPlugin(id);
+ if(videoProducer && videoProducer->getType() == twrap_proxy_plugin_video_producer){
+ return dyn_cast<ProxyVideoProducer*>(videoProducer);
+ }
+ return tsk_null;
+}
+
+
+//
+// "twrap_proxy_plugin_t" Implementations
+//
+static tsk_object_t* twrap_proxy_plugin_ctor(tsk_object_t * self, va_list * app)
+{
+ twrap_proxy_plugin_t *_self = dyn_cast<twrap_proxy_plugin_t *>(TWRAP_PROXY_PLUGIN(self));
+ if(_self){
+ }
+ return self;
+}
+
+static tsk_object_t* twrap_proxy_plugin_dtor(tsk_object_t * self)
+{
+ twrap_proxy_plugin_t *_self = dyn_cast<twrap_proxy_plugin_t *>(TWRAP_PROXY_PLUGIN(self));
+ if(_self){
+ if(_self->plugin){
+ delete _self->plugin, _self->plugin = tsk_null;
+ }
+ }
+
+ return self;
+}
+
+static int twrap_proxy_plugin_cmp(const tsk_object_t *_c1, const tsk_object_t *_c2)
+{
+ const twrap_proxy_plugin_t *c1 = dyn_cast<const twrap_proxy_plugin_t *>(TWRAP_PROXY_PLUGIN(_c1));
+ const twrap_proxy_plugin_t *c2 = dyn_cast<const twrap_proxy_plugin_t *>(TWRAP_PROXY_PLUGIN(_c2));
+
+ if(c1 && c2){
+ return (c1->plugin == c2->plugin); // See "ProxyPlugin::operator =="
+ }
+ else if(!c1 && !c2) return 0;
+ else return -1;
+}
+
+static const tsk_object_def_t twrap_proxy_plugin_def_s =
+{
+ sizeof(twrap_proxy_plugin_t),
+ twrap_proxy_plugin_ctor,
+ twrap_proxy_plugin_dtor,
+ twrap_proxy_plugin_cmp,
+};
+const tsk_object_def_t *twrap_proxy_plugin_def_t = &twrap_proxy_plugin_def_s;
+
+static int pred_find_plugin_by_value(const tsk_list_item_t *item, const void *proxyPlugin)
+{
+ if(item && item->data){
+ const twrap_proxy_plugin_t *twrap_plugin = dyn_cast<const twrap_proxy_plugin_t *>(TWRAP_PROXY_PLUGIN(item->data));
+ return (twrap_plugin->plugin == dyn_cast<const ProxyPlugin *>((const ProxyPlugin*)proxyPlugin)) ? 0 : -1;
+ }
+ return -1;
+}
+
+static twrap_proxy_plugin_t* twrap_proxy_plugin_create(ProxyPlugin** plugin)
+{
+ if(!plugin || !*plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_null;
+ }
+
+ twrap_proxy_plugin_t* twrap_plugin = (twrap_proxy_plugin_t*)tsk_object_new(twrap_proxy_plugin_def_t);
+ if(!twrap_plugin){
+ TSK_DEBUG_ERROR("Failed to create new instance of 'twrap_proxy_plugin_t'");
+ return tsk_null;
+ }
+
+ twrap_plugin->plugin = *plugin,
+ *plugin = tsk_null;
+ return twrap_plugin;
+}
+
diff --git a/bindings/_common/ProxyPluginMgr.h b/bindings/_common/ProxyPluginMgr.h
new file mode 100644
index 0000000..38e7cf1
--- /dev/null
+++ b/bindings/_common/ProxyPluginMgr.h
@@ -0,0 +1,124 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#ifndef TINYWRAP_PROXY_PLUGIN_MGR_H
+#define TINYWRAP_PROXY_PLUGIN_MGR_H
+
+#include "tinymedia.h"
+#include "Common.h"
+
+class ProxyPlugin;
+class ProxyConsumer;
+class ProxyAudioConsumer;
+class ProxyVideoConsumer;
+class ProxyAudioProducer;
+class ProxyVideoProducer;
+class ProxyPluginMgrCallback;
+
+typedef enum twrap_proxy_plugin_type_e
+{
+ twrap_proxy_plugin_audio_producer,
+ twrap_proxy_plugin_video_producer,
+ twrap_proxy_plugin_audio_consumer,
+ twrap_proxy_plugin_video_consumer,
+}
+twrap_proxy_plugin_type_t;
+
+/* ============ ProxyPluginMgr Class ================= */
+
+typedef tsk_list_t twrap_proxy_plungins_L_t; // contains "twrap_proxy_plungin_t" elements
+
+class ProxyPluginMgr
+{
+private:
+ ProxyPluginMgr(ProxyPluginMgrCallback* callback);
+public:
+ virtual ~ProxyPluginMgr();
+
+ // SWIG %newobject
+ static ProxyPluginMgr* createInstance(ProxyPluginMgrCallback* callback);
+ static ProxyPluginMgr* getInstance();
+
+#if !defined(SWIG)
+ static uint64_t getUniqueId();
+
+ int addPlugin(ProxyPlugin**);
+ ProxyPlugin* findPlugin(uint64_t id);
+ ProxyPlugin* findPlugin(tsk_object_t* wrapped_plugin);
+ int removePlugin(uint64_t id);
+ int removePlugin(ProxyPlugin**);
+
+ inline ProxyPluginMgrCallback* getCallback(){ return this->callback; }
+#endif
+
+ ProxyAudioConsumer* findAudioConsumer(uint64_t id);
+ ProxyVideoConsumer* findVideoConsumer(uint64_t id);
+ ProxyAudioProducer* findAudioProducer(uint64_t id);
+ ProxyVideoProducer* findVideoProducer(uint64_t id);
+
+private:
+ static ProxyPluginMgr* instance;
+ ProxyPluginMgrCallback* callback;
+
+ twrap_proxy_plungins_L_t* plugins;
+};
+
+
+/* ============ ProxyPluginMgrCallback Class ================= */
+class ProxyPluginMgrCallback
+{
+public:
+ ProxyPluginMgrCallback() { }
+ virtual ~ProxyPluginMgrCallback() { }
+
+ virtual int OnPluginCreated(uint64_t id, enum twrap_proxy_plugin_type_e type) { return -1; }
+ virtual int OnPluginDestroyed(uint64_t id, enum twrap_proxy_plugin_type_e type) { return -1; }
+};
+
+/* ============ ProxyPlugin Class ================= */
+class ProxyPlugin
+{
+public:
+#if !defined SWIG
+ ProxyPlugin(twrap_proxy_plugin_type_t _type) {
+ this->type=_type;
+ this->id = ProxyPluginMgr::getUniqueId();
+ }
+#endif
+ virtual ~ProxyPlugin() {}
+
+#if !defined(SWIG)
+ virtual bool operator ==(const ProxyPlugin &plugin)const{
+ return this->getId() == plugin.getId();
+ }
+ virtual inline bool isWrapping(tsk_object_t* wrapped_plugin) = 0;
+ virtual inline uint64_t getMediaSessionId() = 0;
+#endif
+
+ inline twrap_proxy_plugin_type_t getType()const{ return this->type; }
+ inline uint64_t getId()const{ return this->id; }
+
+protected:
+ uint64_t id;
+ twrap_proxy_plugin_type_t type;
+};
+
+#endif /* TINYWRAP_PROXY_PLUGIN_MGR_H */
diff --git a/bindings/_common/ProxyProducer.cxx b/bindings/_common/ProxyProducer.cxx
new file mode 100644
index 0000000..6a88ddd
--- /dev/null
+++ b/bindings/_common/ProxyProducer.cxx
@@ -0,0 +1,438 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+
+/**@file ProxyProducer.c
+ * @brief Audio/Video proxy producers.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "ProxyProducer.h"
+
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+#include "tinydav/audio/tdav_producer_audio.h"
+
+#define twrap_producer_proxy_audio_set tsk_null
+#define twrap_producer_proxy_video_set tsk_null
+
+
+/* ============ Audio Media Producer Interface ================= */
+typedef struct twrap_producer_proxy_audio_s
+{
+ TDAV_DECLARE_PRODUCER_AUDIO;
+
+ uint64_t id;
+ tsk_bool_t started;
+}
+twrap_producer_proxy_audio_t;
+#define TWRAP_PRODUCER_PROXY_AUDIO(self) ((twrap_producer_proxy_audio_t*)(self))
+
+int twrap_producer_proxy_audio_prepare(tmedia_producer_t* self, const tmedia_codec_t* codec)
+{
+ ProxyPluginMgr* manager;
+ int ret = -1;
+ if(codec && (manager = ProxyPluginMgr::getInstance())){
+ ProxyAudioProducer* audioProducer;
+ if((audioProducer = manager->findAudioProducer(TWRAP_PRODUCER_PROXY_AUDIO(self)->id)) && audioProducer->getCallback()){
+ ret = audioProducer->getCallback()->prepare((int)codec->plugin->audio.ptime, codec->plugin->rate, codec->plugin->audio.channels);
+ }
+ }
+ return ret;
+}
+
+int twrap_producer_proxy_audio_start(tmedia_producer_t* self)
+{
+ ProxyPluginMgr* manager;
+ int ret = -1;
+ if((manager = ProxyPluginMgr::getInstance())){
+ ProxyAudioProducer* audioProducer;
+ if((audioProducer = manager->findAudioProducer(TWRAP_PRODUCER_PROXY_AUDIO(self)->id)) && audioProducer->getCallback()){
+ ret = audioProducer->getCallback()->start();
+ }
+ }
+
+ TWRAP_PRODUCER_PROXY_AUDIO(self)->started = (ret == 0);
+ return ret;
+}
+
+int twrap_producer_proxy_audio_pause(tmedia_producer_t* self)
+{
+ ProxyPluginMgr* manager;
+ int ret = -1;
+ if((manager = ProxyPluginMgr::getInstance())){
+ ProxyAudioProducer* audioProducer;
+ if((audioProducer = manager->findAudioProducer(TWRAP_PRODUCER_PROXY_AUDIO(self)->id)) && audioProducer->getCallback()){
+ ret = audioProducer->getCallback()->pause();
+ }
+ }
+ return ret;
+}
+
+int twrap_producer_proxy_audio_stop(tmedia_producer_t* self)
+{
+ ProxyPluginMgr* manager;
+ int ret = -1;
+ if((manager = ProxyPluginMgr::getInstance())){
+ ProxyAudioProducer* audioProducer;
+ if((audioProducer = manager->findAudioProducer(TWRAP_PRODUCER_PROXY_AUDIO(self)->id)) && audioProducer->getCallback()){
+ ret = audioProducer->getCallback()->stop();
+ }
+ }
+ TWRAP_PRODUCER_PROXY_AUDIO(self)->started = (ret == 0) ? tsk_false : tsk_true;
+ return ret;
+}
+
+
+//
+// Audio producer object definition
+//
+/* constructor */
+static tsk_object_t* twrap_producer_proxy_audio_ctor(tsk_object_t * self, va_list * app)
+{
+ twrap_producer_proxy_audio_t *producer = (twrap_producer_proxy_audio_t *)self;
+ if(producer){
+ /* init base */
+ tdav_producer_audio_init(TDAV_PRODUCER_AUDIO(producer));
+ /* init self */
+
+ /* Add the plugin to the manager */
+ ProxyPluginMgr* manager = ProxyPluginMgr::getInstance();
+ if(manager){
+ ProxyPlugin* proxyProducer = new ProxyAudioProducer(producer);
+ uint64_t id = proxyProducer->getId();
+ manager->addPlugin(&proxyProducer);
+ manager->getCallback()->OnPluginCreated(id, twrap_proxy_plugin_audio_producer);
+ }
+ }
+ return self;
+}
+/* destructor */
+static tsk_object_t* twrap_producer_proxy_audio_dtor(tsk_object_t * self)
+{
+ twrap_producer_proxy_audio_t *producer = (twrap_producer_proxy_audio_t *)self;
+ if(producer){
+
+ /* stop */
+ if(producer->started){
+ twrap_producer_proxy_audio_stop(TMEDIA_PRODUCER(producer));
+ }
+
+ /* deinit base */
+ tdav_producer_audio_deinit(TDAV_PRODUCER_AUDIO(producer));
+ /* deinit self */
+
+ /* Remove plugin from the manager */
+ ProxyPluginMgr* manager = ProxyPluginMgr::getInstance();
+ if(manager){
+ manager->getCallback()->OnPluginDestroyed(producer->id, twrap_proxy_plugin_audio_producer);
+ manager->removePlugin(producer->id);
+ }
+ }
+
+ return self;
+}
+/* object definition */
+static const tsk_object_def_t twrap_producer_proxy_audio_def_s =
+{
+ sizeof(twrap_producer_proxy_audio_t),
+ twrap_producer_proxy_audio_ctor,
+ twrap_producer_proxy_audio_dtor,
+ tdav_producer_audio_cmp,
+};
+/* plugin definition*/
+static const tmedia_producer_plugin_def_t twrap_producer_proxy_audio_plugin_def_s =
+{
+ &twrap_producer_proxy_audio_def_s,
+
+ tmedia_audio,
+ "Audio Proxy Producer",
+
+ twrap_producer_proxy_audio_set,
+ twrap_producer_proxy_audio_prepare,
+ twrap_producer_proxy_audio_start,
+ twrap_producer_proxy_audio_pause,
+ twrap_producer_proxy_audio_stop
+};
+
+TINYWRAP_GEXTERN const tmedia_producer_plugin_def_t *twrap_producer_proxy_audio_plugin_def_t = &twrap_producer_proxy_audio_plugin_def_s;
+
+
+
+/* ============ ProxyAudioProducer Class ================= */
+ProxyAudioProducer::ProxyAudioProducer(twrap_producer_proxy_audio_t* _producer)
+:callback(tsk_null), producer(_producer), ProxyPlugin(twrap_proxy_plugin_audio_producer)
+{
+ this->producer->id = this->getId();
+}
+
+ProxyAudioProducer::~ProxyAudioProducer()
+{
+}
+
+int ProxyAudioProducer::push(const void* buffer, unsigned size)
+{
+ if(this->producer && TMEDIA_PRODUCER(this->producer)->enc_cb.callback){
+ return TMEDIA_PRODUCER(this->producer)->enc_cb.callback(TMEDIA_PRODUCER(this->producer)->enc_cb.callback_data, buffer, size);
+ }
+ return 0;
+}
+
+bool ProxyAudioProducer::registerPlugin()
+{
+ /* HACK: Unregister all other audio plugins */
+ tmedia_producer_plugin_unregister_by_type(tmedia_audio);
+ /* Register our proxy plugin */
+ return (tmedia_producer_plugin_register(twrap_producer_proxy_audio_plugin_def_t) == 0);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* ============ Video Media Producer Interface ================= */
+typedef struct twrap_producer_proxy_video_s
+{
+ TMEDIA_DECLARE_PRODUCER;
+
+ int rotation;
+ uint64_t id;
+ tsk_bool_t started;
+}
+twrap_producer_proxy_video_t;
+#define TWRAP_PRODUCER_PROXY_VIDEO(self) ((twrap_producer_proxy_video_t*)(self))
+
+int twrap_producer_proxy_video_prepare(tmedia_producer_t* self, const tmedia_codec_t* codec)
+{
+ ProxyPluginMgr* manager;
+ int ret = -1;
+ if(codec && (manager = ProxyPluginMgr::getInstance())){
+ ProxyVideoProducer* videoProducer;
+ if((videoProducer = manager->findVideoProducer(TWRAP_PRODUCER_PROXY_VIDEO(self)->id)) && videoProducer->getCallback()){
+ self->video.chroma = videoProducer->getChroma();
+ self->video.rotation = videoProducer->getRotation();
+ ret = videoProducer->getCallback()->prepare(TMEDIA_CODEC_VIDEO(codec)->width, TMEDIA_CODEC_VIDEO(codec)->height, TMEDIA_CODEC_VIDEO(codec)->fps);
+ }
+ }
+
+ return ret;
+}
+
+int twrap_producer_proxy_video_start(tmedia_producer_t* self)
+{
+ ProxyPluginMgr* manager;
+ int ret = -1;
+ if((manager = ProxyPluginMgr::getInstance())){
+ ProxyVideoProducer* videoProducer;
+ if((videoProducer = manager->findVideoProducer(TWRAP_PRODUCER_PROXY_VIDEO(self)->id)) && videoProducer->getCallback()){
+ ret = videoProducer->getCallback()->start();
+ }
+ }
+
+ TWRAP_PRODUCER_PROXY_VIDEO(self)->started = (ret == 0);
+ return ret;
+}
+
+int twrap_producer_proxy_video_pause(tmedia_producer_t* self)
+{
+ ProxyPluginMgr* manager;
+ int ret = -1;
+ if((manager = ProxyPluginMgr::getInstance())){
+ ProxyVideoProducer* videoProducer;
+ if((videoProducer = manager->findVideoProducer(TWRAP_PRODUCER_PROXY_VIDEO(self)->id)) && videoProducer->getCallback()){
+ ret = videoProducer->getCallback()->pause();
+ }
+ }
+
+ return ret;
+}
+
+int twrap_producer_proxy_video_stop(tmedia_producer_t* self)
+{
+ ProxyPluginMgr* manager;
+ int ret = -1;
+ if((manager = ProxyPluginMgr::getInstance())){
+ ProxyVideoProducer* videoProducer;
+ if((videoProducer = manager->findVideoProducer(TWRAP_PRODUCER_PROXY_VIDEO(self)->id)) && videoProducer->getCallback()){
+ ret = videoProducer->getCallback()->stop();
+ }
+ }
+
+ TWRAP_PRODUCER_PROXY_VIDEO(self)->started = (ret == 0) ? tsk_false : tsk_true;
+ return ret;
+}
+
+
+//
+// Video producer object definition
+//
+/* constructor */
+static tsk_object_t* twrap_producer_proxy_video_ctor(tsk_object_t * self, va_list * app)
+{
+ twrap_producer_proxy_video_t *producer = (twrap_producer_proxy_video_t *)self;
+ if(producer){
+ /* init base */
+ tmedia_producer_init(TMEDIA_PRODUCER(producer));
+ /* init self */
+
+ /* Add the plugin to the manager */
+ ProxyPluginMgr* manager = ProxyPluginMgr::getInstance();
+ if(manager){
+ ProxyPlugin* proxyProducer = new ProxyVideoProducer(ProxyVideoProducer::getDefaultChroma(), producer);
+ uint64_t id = proxyProducer->getId();
+ manager->addPlugin(&proxyProducer);
+ manager->getCallback()->OnPluginCreated(id, twrap_proxy_plugin_video_producer);
+ }
+ }
+ return self;
+}
+/* destructor */
+static tsk_object_t* twrap_producer_proxy_video_dtor(tsk_object_t * self)
+{
+ twrap_producer_proxy_video_t *producer = (twrap_producer_proxy_video_t *)self;
+ if(producer){
+
+ /* stop */
+ if(producer->started){
+ twrap_producer_proxy_video_stop(TMEDIA_PRODUCER(producer));
+ }
+
+ /* deinit base */
+ tmedia_producer_deinit(TMEDIA_PRODUCER(producer));
+ /* deinit self */
+
+ /* Remove plugin from the manager */
+ ProxyPluginMgr* manager = ProxyPluginMgr::getInstance();
+ if(manager){
+ manager->getCallback()->OnPluginDestroyed(producer->id, twrap_proxy_plugin_video_producer);
+ manager->removePlugin(producer->id);
+ }
+ }
+
+ return self;
+}
+/* object definition */
+static const tsk_object_def_t twrap_producer_proxy_video_def_s =
+{
+ sizeof(twrap_producer_proxy_video_t),
+ twrap_producer_proxy_video_ctor,
+ twrap_producer_proxy_video_dtor,
+ tsk_null,
+};
+/* plugin definition*/
+static const tmedia_producer_plugin_def_t twrap_producer_proxy_video_plugin_def_s =
+{
+ &twrap_producer_proxy_video_def_s,
+
+ tmedia_video,
+ "Video Proxy Producer",
+
+ twrap_producer_proxy_video_set,
+ twrap_producer_proxy_video_prepare,
+ twrap_producer_proxy_video_start,
+ twrap_producer_proxy_video_pause,
+ twrap_producer_proxy_video_stop
+};
+
+TINYWRAP_GEXTERN const tmedia_producer_plugin_def_t *twrap_producer_proxy_video_plugin_def_t = &twrap_producer_proxy_video_plugin_def_s;
+
+
+
+/* ============ ProxyVideoProducer Class ================= */
+tmedia_chroma_t ProxyVideoProducer::defaultChroma = tmedia_nv21;
+
+ProxyVideoProducer::ProxyVideoProducer(tmedia_chroma_t _chroma, struct twrap_producer_proxy_video_s* _producer)
+:callback(tsk_null), chroma(_chroma), rotation(0), producer(_producer), ProxyPlugin(twrap_proxy_plugin_video_producer)
+{
+ this->producer->id = this->getId();
+}
+
+ProxyVideoProducer::~ProxyVideoProducer()
+{
+}
+
+int ProxyVideoProducer::getRotation()
+{
+ return this->rotation;
+}
+
+void ProxyVideoProducer::setRotation(int rot)
+{
+ this->rotation = rot;
+ if(this->producer){
+ TMEDIA_PRODUCER(this->producer)->video.rotation = this->rotation;
+ }
+}
+
+// encode() then send()
+int ProxyVideoProducer::push(const void* buffer, unsigned size)
+{
+ if(this->producer && TMEDIA_PRODUCER(this->producer)->enc_cb.callback){
+ return TMEDIA_PRODUCER(this->producer)->enc_cb.callback(TMEDIA_PRODUCER(this->producer)->enc_cb.callback_data, buffer, size);
+ }
+ return 0;
+}
+
+// send() "as is"
+int ProxyVideoProducer::send(const void* buffer, unsigned size, unsigned duration, bool marker)
+{
+ if(this->producer && TMEDIA_PRODUCER(this->producer)->raw_cb.callback){
+ return TMEDIA_PRODUCER(this->producer)->raw_cb.callback(TMEDIA_PRODUCER(this->producer)->raw_cb.callback_data, buffer, size, duration, marker);
+ }
+ return 0;
+}
+
+tmedia_chroma_t ProxyVideoProducer::getChroma()
+{
+ return this->chroma;
+}
+
+bool ProxyVideoProducer::registerPlugin()
+{
+ /* HACK: Unregister all other video plugins */
+ tmedia_producer_plugin_unregister_by_type(tmedia_video);
+ /* Register our proxy plugin */
+ return (tmedia_producer_plugin_register(twrap_producer_proxy_video_plugin_def_t) == 0);
+}
diff --git a/bindings/_common/ProxyProducer.h b/bindings/_common/ProxyProducer.h
new file mode 100644
index 0000000..95d9b65
--- /dev/null
+++ b/bindings/_common/ProxyProducer.h
@@ -0,0 +1,137 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+
+/**@file ProxyProducer.h
+ * @brief Audio/Video proxy consumers.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TINYWRAP_PRODUCER_PROXY_H
+#define TINYWRAP_PRODUCER_PROXY_H
+
+#include "tinyWRAP_config.h"
+
+#include "ProxyPluginMgr.h"
+
+#include "tinymedia/tmedia_common.h"
+#include "tinymedia/tmedia_producer.h"
+
+/* ============ ProxyAudioProducerCallback Class ================= */
+class ProxyAudioProducerCallback
+{
+public:
+ ProxyAudioProducerCallback() { }
+ virtual ~ProxyAudioProducerCallback(){ }
+
+ virtual int prepare(int ptime, int rate, int channels) { return -1; }
+ virtual int start() { return -1; }
+ virtual int pause() { return -1; }
+ virtual int stop() { return -1; }
+};
+
+
+/* ============ ProxyAudioProducer Class ================= */
+class ProxyAudioProducer : public ProxyPlugin
+{
+public:
+#if !defined(SWIG)
+ ProxyAudioProducer(struct twrap_producer_proxy_audio_s* producer);
+#endif
+ virtual ~ProxyAudioProducer();
+
+ int push(const void* buffer, unsigned size);
+ void setCallback(ProxyAudioProducerCallback* _callback) { this->callback = _callback; }
+#if !defined(SWIG)
+ inline ProxyAudioProducerCallback* getCallback() { return this->callback; }
+ virtual inline bool isWrapping(tsk_object_t* wrapped_plugin){
+ return this->producer == wrapped_plugin;
+ }
+#endif
+ virtual inline uint64_t getMediaSessionId(){
+ return this->producer ? TMEDIA_PRODUCER(this->producer)->session_id : 0;
+ }
+
+public:
+ static bool registerPlugin();
+
+private:
+ struct twrap_producer_proxy_audio_s* producer;
+ ProxyAudioProducerCallback* callback;
+};
+
+/* ============ ProxyVideoProducerCallback Class ================= */
+class ProxyVideoProducerCallback
+{
+public:
+ ProxyVideoProducerCallback() { }
+ virtual ~ProxyVideoProducerCallback(){ }
+
+ virtual int prepare(int width, int height, int fps) { return -1; }
+ virtual int start() { return -1; }
+ virtual int pause() { return -1; }
+ virtual int stop() { return -1; }
+};
+
+/* ============ ProxyVideoProducer Class ================= */
+class ProxyVideoProducer : public ProxyPlugin
+{
+public:
+#if !defined(SWIG)
+ ProxyVideoProducer(tmedia_chroma_t chroma, struct twrap_producer_proxy_video_s* producer);
+#endif
+ virtual ~ProxyVideoProducer();
+
+ int getRotation();
+ void setRotation(int rot);
+ int push(const void* buffer, unsigned size);
+ int send(const void* buffer, unsigned size, unsigned duration, bool marker);
+ void setCallback(ProxyVideoProducerCallback* _callback) { this->callback = _callback; }
+#if !defined(SWIG)
+ inline ProxyVideoProducerCallback* getCallback() { return this->callback; }
+ virtual inline bool isWrapping(tsk_object_t* wrapped_plugin){
+ return this->producer == wrapped_plugin;
+ }
+#endif
+ virtual inline uint64_t getMediaSessionId(){
+ return this->producer ? TMEDIA_PRODUCER(this->producer)->session_id : 0;
+ }
+
+public:
+ static bool registerPlugin();
+ static void setDefaultChroma(tmedia_chroma_t chroma){ ProxyVideoProducer::defaultChroma = chroma; }
+
+#if !defined(SWIG)
+ tmedia_chroma_t getChroma();
+ static tmedia_chroma_t getDefaultChroma() { return ProxyVideoProducer::defaultChroma; }
+#endif
+
+private:
+ struct twrap_producer_proxy_video_s* producer;
+ ProxyVideoProducerCallback* callback;
+ tmedia_chroma_t chroma;
+ static tmedia_chroma_t defaultChroma;
+ int rotation;
+};
+
+#endif /* TINYWRAP_PRODUCER_PROXY_H */
diff --git a/bindings/_common/SMS.i b/bindings/_common/SMS.i
new file mode 100644
index 0000000..d25744d
--- /dev/null
+++ b/bindings/_common/SMS.i
@@ -0,0 +1,7 @@
+%{
+#include "SMSEncoder.h"
+%}
+
+%nodefaultctor;
+%include "SMSEncoder.h"
+%clearnodefaultctor; \ No newline at end of file
diff --git a/bindings/_common/SMSEncoder.cxx b/bindings/_common/SMSEncoder.cxx
new file mode 100644
index 0000000..161d5c5
--- /dev/null
+++ b/bindings/_common/SMSEncoder.cxx
@@ -0,0 +1,376 @@
+/*
+* Copyright (C) 2009 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou@doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#include "SMSEncoder.h"
+
+// Short description: http://betelco.blogspot.com/2009/10/sms-over-3gpp-ims-network.html
+
+
+RPMessage::RPMessage(twrap_rpmessage_type_t _type, tsms_rpdu_message_t* _rp_message)
+{
+ this->rp_message = (tsms_rpdu_message_t*)tsk_object_ref(_rp_message);
+ this->type = _type;
+ this->tmpBuffer = tsk_null;
+}
+
+RPMessage::RPMessage() :
+ rp_message(tsk_null),
+ type(twrap_rpmessage_type_sms_none),
+ tmpBuffer(tsk_null)
+{
+}
+
+twrap_rpmessage_type_t RPMessage::getType()
+{
+ return this->type;
+}
+
+unsigned RPMessage::getPayloadLength()
+{
+ if(!this->tmpBuffer){
+ if((this->tmpBuffer = tsk_buffer_create_null())){
+ tsms_rpdu_data_serialize(this->rp_message, this->tmpBuffer);
+ }
+ }
+ return this->tmpBuffer ? this->tmpBuffer->size : 0;
+}
+
+unsigned RPMessage::getPayload(void* output, unsigned maxsize)
+{
+ unsigned retsize = 0;
+
+ if(!this->tmpBuffer){
+ if((this->tmpBuffer = tsk_buffer_create_null())){
+ tsms_rpdu_message_serialize(this->rp_message, this->tmpBuffer);
+ }
+ }
+
+ if(output && maxsize && this->tmpBuffer && this->tmpBuffer->data){
+ retsize = (this->tmpBuffer->size > maxsize) ? maxsize : this->tmpBuffer->size;
+ memcpy(output, this->tmpBuffer->data, retsize);
+ }
+ return retsize;
+}
+
+RPMessage::~RPMessage()
+{
+ TSK_OBJECT_SAFE_FREE(this->rp_message);
+ TSK_OBJECT_SAFE_FREE(this->tmpBuffer);
+}
+
+
+SMSData::SMSData(twrap_sms_type_t _type, int _mr, const void* _ascii, tsk_size_t _size): oa(tsk_null), da(tsk_null)
+{
+ this->type = _type;
+ this->mr = _mr;
+ if((this->size = _size)){
+ if((this->ascii = tsk_calloc(size+1, 1))){
+ memcpy(this->ascii, _ascii, _size);
+ }
+ }
+ else{
+ this->ascii = tsk_null;
+ }
+}
+
+SMSData::SMSData(): oa(tsk_null), da(tsk_null)
+{
+ this->type = twrap_sms_type_none;
+ this->mr = 0;
+ this->size = 0;
+ this->ascii = tsk_null;
+}
+
+SMSData::~SMSData()
+{
+ TSK_FREE(this->ascii);
+ TSK_FREE(this->oa);
+ TSK_FREE(this->da);
+}
+
+twrap_sms_type_t SMSData::getType()
+{
+ return this->type;
+}
+
+int SMSData::getMR()
+{
+ return this->mr;
+}
+
+unsigned SMSData::getPayloadLength()
+{
+ return this->size;
+}
+
+unsigned SMSData::getPayload(void* output, unsigned maxsize)
+{
+ unsigned retsize = 0;
+
+ if(output && maxsize && this->ascii){
+ retsize = (this->size > maxsize) ? maxsize : this->size;
+ memcpy(output, this->ascii, retsize);
+ }
+ return retsize;
+}
+
+const char* SMSData::getOA()
+{
+ return this->oa;
+}
+
+const char* SMSData::getDA()
+{
+ return this->da;
+}
+
+void SMSData::setOA(const char* _oa)
+{
+ TSK_FREE(this->oa);
+ this->oa = tsk_strdup(_oa);
+}
+
+void SMSData::setDA(const char* _da)
+{
+ TSK_FREE(this->da);
+ this->da = tsk_strdup(_da);
+}
+
+
+// More information about RP-DATA: http://www.doubango.org/API/tinySMS/group__tsms__rpdu__group.html#tsms_rpdu_group_DATA
+RPMessage* SMSEncoder::encodeSubmit(int mr, const char *smsc, const char *destination, const char *ascii)
+{
+ int ret;
+ tsk_buffer_t* buffer = tsk_null;
+ tsms_tpdu_submit_t* sms_submit = tsk_null;
+ tsms_rpdu_data_t* rp_data = tsk_null;
+
+ RPMessage* encodedData = tsk_null;
+
+ if(!smsc || ! destination || !ascii){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_null;
+ }
+
+ if(mr<0 || mr>0xFF){
+ TSK_DEBUG_WARN("Invalid Message Reference");
+ mr &= 0xFF;
+ }
+
+ // create SMS-SUBMIT message
+ if(!(sms_submit = tsms_tpdu_submit_create(mr, (const uint8_t*)smsc, (const uint8_t*)destination))){
+ TSK_DEBUG_ERROR("Failed to create the TPDU SMS-SUBMIT message");
+ goto bail;
+ }
+ // Set content for SMS-SUBMIT
+ if((buffer = tsms_pack_to_7bit(ascii))){
+ ret = tsms_tpdu_submit_set_userdata(sms_submit, buffer, tsms_alpha_7bit);
+ TSK_OBJECT_SAFE_FREE(buffer);
+ }
+ else{
+ TSK_DEBUG_ERROR("Failed to encode the TPDU SMS-SUBMIT message");
+ goto bail;
+ }
+
+ // create RP-DATA(SMS-SUBMIT)
+ if((rp_data = tsms_rpdu_data_create_mo(mr, (const uint8_t*)smsc, TSMS_TPDU_MESSAGE(sms_submit)))){
+ encodedData = new RPMessage(twrap_rpmessage_type_sms_submit, TSMS_RPDU_MESSAGE(rp_data));
+ }
+ else{
+ TSK_DEBUG_ERROR("Failed to create the RP-DATA(SMS-SUBMIT) message");
+ goto bail;
+ }
+
+bail:
+ TSK_OBJECT_SAFE_FREE(buffer);
+ TSK_OBJECT_SAFE_FREE(sms_submit);
+ TSK_OBJECT_SAFE_FREE(rp_data);
+
+ return encodedData;
+}
+
+// More information about RP-DATA: http://www.doubango.org/API/tinySMS/group__tsms__rpdu__group.html#tsms_rpdu_group_DATA
+RPMessage* SMSEncoder::encodeDeliver(int mr, const char* smsc, const char* originator, const char* ascii)
+{
+ int ret;
+ tsk_buffer_t* buffer = tsk_null;
+ tsms_tpdu_deliver_t* sms_deliver = tsk_null;
+ tsms_rpdu_data_t* rp_data = tsk_null;
+
+ RPMessage* encodedData = tsk_null;
+
+ if(!smsc || ! originator || !ascii){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_null;
+ }
+
+ if(mr<0 || mr>0xFF){
+ TSK_DEBUG_WARN("Invalid Message Reference");
+ mr &= 0xFF;
+ }
+
+ // create SMS-DELIVER message
+ sms_deliver = tsms_tpdu_deliver_create((const uint8_t*)smsc, (const uint8_t*)originator);
+ // Set content for SMS-DELIVER
+ if((buffer = tsms_pack_to_7bit(ascii))){
+ ret = tsms_tpdu_deliver_set_userdata(sms_deliver, buffer, tsms_alpha_7bit);
+ TSK_OBJECT_SAFE_FREE(buffer);
+ }
+ // create RP-DATA message
+ if((rp_data = tsms_rpdu_data_create_mt(mr, (const uint8_t*)smsc, TSMS_TPDU_MESSAGE(sms_deliver)))){
+ encodedData = new RPMessage(twrap_rpmessage_type_sms_deliver, TSMS_RPDU_MESSAGE(rp_data));
+ }
+ else{
+ TSK_DEBUG_ERROR("Failed to create the RP-DATA(SMS-DELIVER) message");
+ goto bail;
+ }
+
+bail:
+ TSK_OBJECT_SAFE_FREE(buffer);
+ TSK_OBJECT_SAFE_FREE(sms_deliver);
+ TSK_OBJECT_SAFE_FREE(rp_data);
+
+ return encodedData;
+}
+
+RPMessage* SMSEncoder::encodeACK(int mr, const char* smsc, const char* destination, bool forSUBMIT)
+{
+ tsms_tpdu_report_t* sms_report = tsk_null;
+ tsms_rpdu_ack_t* rp_ack = tsk_null;
+ tsk_bool_t isSUBMIT = forSUBMIT ? tsk_true : tsk_false;
+ tsk_bool_t isERROR = tsk_false;
+
+ RPMessage* encodedData = tsk_null;
+
+ // create SMS-DELIVER(or SUBMIT)-REPORT message
+ sms_report = tsms_tpdu_report_create((const uint8_t*)smsc, isSUBMIT, isERROR);
+ // create RP-ACK message (From MS to SC)
+ if((rp_ack = tsms_rpdu_ack_create_mo(mr, TSMS_TPDU_MESSAGE(sms_report)))){
+ encodedData = new RPMessage(twrap_rpmessage_type_sms_ack, TSMS_RPDU_MESSAGE(rp_ack));
+ }
+
+ TSK_OBJECT_SAFE_FREE(sms_report);
+ TSK_OBJECT_SAFE_FREE(rp_ack);
+
+ return encodedData;
+}
+
+RPMessage* SMSEncoder::encodeError(int mr, const char* smsc, const char* destination, bool forSUBMIT)
+{
+ tsms_tpdu_report_t* sms_report = tsk_null;
+ tsms_rpdu_error_t* rp_error= tsk_null;
+ tsk_bool_t isSUBMIT = forSUBMIT ? tsk_true : tsk_false;
+ tsk_bool_t isERROR = tsk_true;
+
+ RPMessage* encodedData = tsk_null;
+
+ // create SMS-DELIVER-REPORT message
+ sms_report = tsms_tpdu_report_create((const uint8_t*)smsc, isSUBMIT, isERROR);
+ // create RP-ERROR message
+ if((rp_error = tsms_rpdu_error_create_mo(mr, TSMS_TPDU_MESSAGE(sms_report), 0x0A/*call barred*/))){
+ encodedData = new RPMessage(twrap_rpmessage_type_sms_error, TSMS_RPDU_MESSAGE(rp_error));
+ }
+
+ TSK_OBJECT_SAFE_FREE(sms_report);
+ TSK_OBJECT_SAFE_FREE(rp_error);
+
+ return encodedData;
+}
+
+SMSData* SMSEncoder::decode(const void* data, unsigned size, bool MobOrig)
+{
+ tsms_rpdu_message_t* rp_message = tsk_null;
+ tsms_tpdu_message_t* tpdu = tsk_null;
+
+ SMSData* decodedData = tsk_null;
+
+ if(!(rp_message = tsms_rpdu_message_deserialize(data, size))){
+ TSK_DEBUG_ERROR("Failed to deserialize the RP-MESSAGE");
+ goto bail;
+ }
+
+ switch(rp_message->mti){
+ case tsms_rpdu_type_data_mo:
+ case tsms_rpdu_type_data_mt:
+ {
+ char* ascii = tsk_null;
+ tsms_rpdu_data_t* rp_data = TSMS_RPDU_DATA(rp_message);
+ if((tpdu = tsms_tpdu_message_deserialize(rp_data->udata->data, rp_data->udata->size, MobOrig))){
+ if(tpdu->mti == tsms_tpdu_mti_deliver_mt || tpdu->mti == tsms_tpdu_mti_submit_mo){ /* SMS-SUBMIT or SMS-DELIVER? */
+ ascii = tsms_tpdu_message_get_payload(tpdu);
+ decodedData = new SMSData(twrap_sms_type_rpdata, rp_message->mr, ascii, tsk_strlen(ascii));
+
+ if(tpdu->mti == tsms_tpdu_mti_deliver_mt){
+ tsms_tpdu_deliver_t* tpdu_deliver = (tsms_tpdu_deliver_t*)tpdu;
+ decodedData->setOA(tpdu_deliver->oa ? tpdu_deliver->oa->digits : tsk_null);
+ }
+ /* IMPORTANT: to not uncomment
+ else if(TSK_OBJECT_DEF(tpdu) == tsms_tpdu_submit_def_t){
+ tsms_tpdu_submit_t* tpdu_submit = (tsms_tpdu_submit_t*)tpdu;
+ decodedData->setDA(tpdu_submit->da ? tpdu_submit->da->digits : tsk_null);
+ }*/
+ TSK_FREE(ascii);
+ }
+ }
+ break;
+ }
+ case tsms_rpdu_type_ack_mo:
+ case tsms_rpdu_type_ack_mt:
+ {
+ tsms_rpdu_ack_t* rp_ack = TSMS_RPDU_ACK(rp_message);
+ // ...do whatever you want
+ if(rp_ack->udata && (tpdu = tsms_tpdu_message_deserialize(rp_ack->udata->data, rp_ack->udata->size, MobOrig))){
+ // ...do whatever you want
+ }
+ decodedData = new SMSData(twrap_sms_type_ack, rp_message->mr, tsk_null, 0);
+ break;
+ }
+ case tsms_rpdu_type_error_mo:
+ case tsms_rpdu_type_error_mt:
+ {
+ tsms_rpdu_error_t* rp_error = TSMS_RPDU_ERROR(rp_message);
+ // ...do whatever you want
+ if(rp_error->udata && (tpdu = tsms_tpdu_message_deserialize(rp_error->udata->data, rp_error->udata->size, MobOrig))){
+ // ...do whatever you want
+ }
+ decodedData = new SMSData(twrap_sms_type_error, rp_message->mr, tsk_null, 0);
+ break;
+ }
+ case tsms_rpdu_type_smma_mo:
+ {
+ tsms_rpdu_smma_t* rp_smma = TSMS_RPDU_SMMA(rp_message);
+ // ...do whatever you want
+ decodedData = new SMSData(twrap_sms_type_smma, rp_message->mr, tsk_null, 0);
+ break;
+ }
+ default:
+ {
+ TSK_DEBUG_INFO("Unknown RP-Message type (%u).", rp_message->mti);
+ break;
+ }
+ }
+
+bail:
+ TSK_OBJECT_SAFE_FREE(rp_message);
+ TSK_OBJECT_SAFE_FREE(tpdu);
+
+ return decodedData;
+} \ No newline at end of file
diff --git a/bindings/_common/SMSEncoder.h b/bindings/_common/SMSEncoder.h
new file mode 100644
index 0000000..8026741
--- /dev/null
+++ b/bindings/_common/SMSEncoder.h
@@ -0,0 +1,115 @@
+/*
+* Copyright (C) 2009 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou@doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#ifndef TINYWRAP_SMSENCODER_H
+#define TINYWRAP_SMSENCODER_H
+
+#include "tinyWRAP_config.h"
+
+#include "tinysip.h" /* SIP/IMS */
+#include "tinysms.h" /* Binary SMS API*/
+
+typedef enum twrap_rpmessage_type_e
+{
+ twrap_rpmessage_type_sms_none,
+ twrap_rpmessage_type_sms_submit,
+ twrap_rpmessage_type_sms_deliver,
+ twrap_rpmessage_type_sms_ack,
+ twrap_rpmessage_type_sms_error,
+}
+twrap_rpmessage_type_t;
+
+typedef enum twrap_sms_type_e
+{
+ twrap_sms_type_none,
+ twrap_sms_type_rpdata,
+ twrap_sms_type_smma,
+ twrap_sms_type_ack,
+ twrap_sms_type_error,
+}
+twrap_sms_type_t;
+
+class RPMessage
+{
+public:
+#if !defined(SWIG)
+ RPMessage(twrap_rpmessage_type_t type, tsms_rpdu_message_t* rp_message);
+#endif
+ RPMessage();
+
+ virtual ~RPMessage();
+
+public:
+ /* Public API functions */
+ twrap_rpmessage_type_t getType();
+ unsigned getPayloadLength();
+ unsigned getPayload(void* output, unsigned maxsize);
+
+private:
+ twrap_rpmessage_type_t type;
+ tsms_rpdu_message_t* rp_message;
+
+ tsk_buffer_t* tmpBuffer;
+};
+
+class SMSData
+{
+public:
+#if !defined(SWIG)
+ SMSData(twrap_sms_type_t type, int mr, const void* ascii, tsk_size_t size);
+#endif
+ SMSData();
+
+ virtual ~SMSData();
+
+public:
+ /* Public API functions */
+ twrap_sms_type_t getType();
+ int getMR();
+ unsigned getPayloadLength();
+ unsigned getPayload(void* output, unsigned maxsize);
+ const char* getOA();
+ const char* getDA();
+#if !defined(SWIG)
+ void setOA(const char* oa);
+ void setDA(const char* da);
+#endif
+
+private:
+ twrap_sms_type_t type;
+ int mr;
+ void* ascii;
+ char* oa;
+ char* da;
+ tsk_size_t size;
+};
+
+class SMSEncoder
+{
+public:
+ static RPMessage* encodeSubmit(int mr, const char* smsc, const char* destination, const char* ascii);
+ static RPMessage* encodeDeliver(int mr, const char* smsc, const char* originator, const char* ascii);
+ static RPMessage* encodeACK(int mr, const char* smsc, const char* destination, bool forSUBMIT);
+ static RPMessage* encodeError(int mr, const char* smsc, const char* destination, bool forSUBMIT);
+ static SMSData* decode(const void* data, unsigned size, bool MobOrig);
+};
+
+#endif /* TINYWRAP_SMSENCODER_H */
diff --git a/bindings/_common/SafeObject.cxx b/bindings/_common/SafeObject.cxx
new file mode 100644
index 0000000..587a4cb
--- /dev/null
+++ b/bindings/_common/SafeObject.cxx
@@ -0,0 +1,42 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#include "SafeObject.h"
+
+SafeObject::SafeObject()
+{
+ this->mutex = tsk_mutex_create();
+}
+
+int SafeObject::Lock()const
+{
+ return tsk_mutex_lock(this->mutex);
+}
+
+int SafeObject::UnLock()const
+{
+ return tsk_mutex_unlock(this->mutex);
+}
+
+SafeObject::~SafeObject()
+{
+ tsk_mutex_destroy(&this->mutex);
+}
diff --git a/bindings/_common/SafeObject.h b/bindings/_common/SafeObject.h
new file mode 100644
index 0000000..4713263
--- /dev/null
+++ b/bindings/_common/SafeObject.h
@@ -0,0 +1,41 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#ifndef TINYWRAP_SAFEOBJECT_H
+#define TINYWRAP_SAFEOBJECT_H
+
+#include "tsk_mutex.h"
+
+class SafeObject
+{
+public:
+ SafeObject();
+ virtual ~SafeObject();
+
+/* protected: */
+ int Lock()const;
+ int UnLock()const;
+
+private:
+ tsk_mutex_handle_t *mutex;
+};
+
+#endif /* TINYWRAP_SAFEOBJECT_H */
diff --git a/bindings/_common/SipCallback.cxx b/bindings/_common/SipCallback.cxx
new file mode 100644
index 0000000..d2bb1eb
--- /dev/null
+++ b/bindings/_common/SipCallback.cxx
@@ -0,0 +1,31 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#include "SipCallback.h"
+
+
+
+
+
+
+
+
+
diff --git a/bindings/_common/SipCallback.h b/bindings/_common/SipCallback.h
new file mode 100644
index 0000000..f046a77
--- /dev/null
+++ b/bindings/_common/SipCallback.h
@@ -0,0 +1,54 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#ifndef TINYWRAP_SIPCALLBACK_H
+#define TINYWRAP_SIPCALLBACK_H
+
+class DialogEvent;
+class StackEvent;
+
+class InviteEvent;
+class MessagingEvent;
+class OptionsEvent;
+class PublicationEvent;
+class RegistrationEvent;
+class SubscriptionEvent;
+
+class SipCallback
+{
+public:
+ SipCallback() { }
+ virtual ~SipCallback() {}
+ virtual int OnDialogEvent(const DialogEvent* e) { return -1; }
+ virtual int OnStackEvent(const StackEvent* e) { return -1; }
+
+ virtual int OnInviteEvent(const InviteEvent* e) { return -1; }
+ virtual int OnMessagingEvent(const MessagingEvent* e) { return -1; }
+ virtual int OnOptionsEvent(const OptionsEvent* e) { return -1; }
+ virtual int OnPublicationEvent(const PublicationEvent* e) { return -1; }
+ virtual int OnRegistrationEvent(const RegistrationEvent* e) { return -1; }
+ virtual int OnSubscriptionEvent(const SubscriptionEvent* e) { return -1; }
+
+private:
+
+};
+
+#endif /* TINYWRAP_SIPCALLBACK_H */
diff --git a/bindings/_common/SipEvent.cxx b/bindings/_common/SipEvent.cxx
new file mode 100644
index 0000000..42e06e2
--- /dev/null
+++ b/bindings/_common/SipEvent.cxx
@@ -0,0 +1,306 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#include "SipEvent.h"
+#include "SipSession.h"
+#include "SipMessage.h"
+
+#include "SipStack.h"
+
+/* ======================== SipEvent ========================*/
+SipEvent::SipEvent(const tsip_event_t *_sipevent)
+{
+ this->sipevent = _sipevent;
+ if(_sipevent){
+ this->sipmessage = new SipMessage(_sipevent->sipmessage);
+ }
+ else{
+ this->sipmessage = tsk_null;
+ }
+}
+
+SipEvent::~SipEvent()
+{
+ if(this->sipmessage){
+ delete this->sipmessage;
+ }
+}
+
+short SipEvent::getCode() const
+{
+ return this->sipevent->code;
+}
+
+const char* SipEvent::getPhrase() const
+{
+ return this->sipevent->phrase;
+}
+
+const SipSession* SipEvent::getBaseSession() const
+{
+ const void* userdata = tsip_ssession_get_userdata(this->sipevent->ss);
+ if(userdata){
+ return dyn_cast<const SipSession*>((const SipSession*)userdata);
+ }
+ return tsk_null;
+}
+
+const SipMessage* SipEvent::getSipMessage() const
+{
+ return this->sipmessage;
+}
+
+SipStack* SipEvent::getStack()const
+{
+ const tsip_stack_handle_t* stack_handle = tsip_ssession_get_stack(sipevent->ss);
+ const void* userdata;
+ if(stack_handle && (userdata = tsip_stack_get_userdata(stack_handle))){
+ return dyn_cast<SipStack*>((SipStack*)userdata);
+ }
+ return tsk_null;
+}
+
+
+/* ======================== DialogEvent ========================*/
+DialogEvent::DialogEvent(const tsip_event_t *_sipevent)
+:SipEvent(_sipevent){ }
+
+DialogEvent::~DialogEvent(){ }
+
+
+/* ======================== DialogEvent ========================*/
+StackEvent::StackEvent(const tsip_event_t *_sipevent)
+:SipEvent(_sipevent){ }
+
+StackEvent::~StackEvent(){ }
+
+
+/* ======================== InviteEvent ========================*/
+InviteEvent::InviteEvent(const tsip_event_t *_sipevent)
+:SipEvent(_sipevent)
+{
+}
+
+InviteEvent::~InviteEvent()
+{
+}
+
+tsip_invite_event_type_t InviteEvent::getType() const
+{
+ return TSIP_INVITE_EVENT(this->sipevent)->type;
+}
+
+twrap_media_type_t InviteEvent::getMediaType()
+{
+ // Ignore Mixed session (both audio/video and MSRP) as specified by GSMA RCS.
+ if(this->sipevent && this->sipevent->ss){
+ tmedia_type_t type = tsip_ssession_get_mediatype(this->sipevent->ss);
+ if(type & tmedia_msrp){
+ return twrap_media_msrp;
+ }
+ else{
+ switch(type){
+ case tmedia_audio:
+ return twrap_media_audio;
+ case tmedia_video:
+ return twrap_media_video;
+ case tmedia_audiovideo:
+ return twrap_media_audiovideo;
+ }
+ }
+ }
+ return twrap_media_none;
+}
+
+const InviteSession* InviteEvent::getSession() const
+{
+ return dyn_cast<const InviteSession*>(this->getBaseSession());
+}
+
+CallSession* InviteEvent::takeCallSessionOwnership() const
+{
+ // TODO: Factor all takeSessionOwnership() functions
+ if(this->sipevent && this->sipevent->ss && !tsip_ssession_have_ownership(this->sipevent->ss)){
+ SipStack* stack = this->getStack();
+ if(stack){
+ /* The constructor will call take_ownerhip() */
+ return new CallSession(stack, this->sipevent->ss);
+ }
+ }
+ return tsk_null;
+}
+
+MsrpSession* InviteEvent::takeMsrpSessionOwnership() const
+{
+ // TODO: Factor all takeSessionOwnership() functions
+ if(this->sipevent && this->sipevent->ss && !tsip_ssession_have_ownership(this->sipevent->ss)){
+ SipStack* stack = this->getStack();
+ if(stack){
+ /* The constructor will call take_ownerhip() */
+ return new MsrpSession(stack, this->sipevent->ss);
+ }
+ }
+ return tsk_null;
+}
+
+/* ======================== MessagingEvent ========================*/
+MessagingEvent::MessagingEvent(const tsip_event_t *_sipevent)
+:SipEvent(_sipevent)
+{
+}
+
+MessagingEvent::~MessagingEvent()
+{
+}
+
+tsip_message_event_type_t MessagingEvent::getType() const
+{
+ return TSIP_MESSAGE_EVENT(this->sipevent)->type;
+}
+
+const MessagingSession* MessagingEvent::getSession() const
+{
+ return dyn_cast<const MessagingSession*>(this->getBaseSession());
+}
+
+MessagingSession* MessagingEvent::takeSessionOwnership() const
+{
+ // TODO: Factor all takeSessionOwnership() functions
+ if(!this->sipevent || !this->sipevent->ss){
+ return tsk_null;
+ }
+
+ if(tsip_ssession_have_ownership(this->sipevent->ss)){
+ // already have ownership
+ return tsk_null;
+ }
+ else{
+ const tsip_stack_handle_t* stack_handle = tsip_ssession_get_stack(sipevent->ss);
+ const void* userdata;
+ if(stack_handle && (userdata = tsip_stack_get_userdata(stack_handle))){
+ SipStack* stack = dyn_cast<SipStack*>((SipStack*)userdata);
+ if(stack){
+ // FIXME: Memory Leak ?
+ /* The constructor will call take_ownerhip() */
+ return new MessagingSession(stack, this->sipevent->ss);
+ }
+ }
+ return tsk_null;
+ }
+}
+
+/* ======================== OptionsEvent ========================*/
+OptionsEvent::OptionsEvent(const tsip_event_t *_sipevent)
+:SipEvent(_sipevent)
+{
+}
+
+OptionsEvent::~OptionsEvent()
+{
+}
+
+tsip_options_event_type_t OptionsEvent::getType() const
+{
+ return TSIP_OPTIONS_EVENT(this->sipevent)->type;
+}
+
+const OptionsSession* OptionsEvent::getSession() const
+{
+ return dyn_cast<const OptionsSession*>(this->getBaseSession());
+}
+
+
+
+/* ======================== PublicationEvent ========================*/
+PublicationEvent::PublicationEvent(const tsip_event_t *_sipevent)
+:SipEvent(_sipevent)
+{
+}
+
+PublicationEvent::~PublicationEvent()
+{
+}
+
+tsip_publish_event_type_t PublicationEvent::getType() const
+{
+ return TSIP_PUBLISH_EVENT(this->sipevent)->type;
+}
+
+const PublicationSession* PublicationEvent::getSession() const
+{
+ return dyn_cast<const PublicationSession*>(this->getBaseSession());
+}
+
+
+
+/* ======================== RegistrationEvent ========================*/
+RegistrationEvent::RegistrationEvent(const tsip_event_t *_sipevent)
+:SipEvent(_sipevent)
+{
+}
+
+RegistrationEvent::~RegistrationEvent()
+{
+}
+
+tsip_register_event_type_t RegistrationEvent::getType() const
+{
+ return TSIP_REGISTER_EVENT(this->sipevent)->type;
+}
+
+const RegistrationSession* RegistrationEvent::getSession() const
+{
+ return dyn_cast<const RegistrationSession*>(this->getBaseSession());
+}
+
+RegistrationSession* RegistrationEvent::takeSessionOwnership() const
+{
+ // TODO: Factor all takeSessionOwnership() functions
+ if(this->sipevent && this->sipevent->ss && !tsip_ssession_have_ownership(this->sipevent->ss)){
+ SipStack* stack = this->getStack();
+ if(stack){
+ /* The constructor will call take_ownerhip() */
+ return new RegistrationSession(stack, this->sipevent->ss);
+ }
+ }
+ return tsk_null;
+}
+
+
+/* ======================== SubscriptionEvent ========================*/
+SubscriptionEvent::SubscriptionEvent(const tsip_event_t *sipevent)
+:SipEvent(sipevent)
+{
+}
+
+SubscriptionEvent::~SubscriptionEvent()
+{
+}
+
+tsip_subscribe_event_type_t SubscriptionEvent::getType() const
+{
+ return TSIP_SUBSCRIBE_EVENT(this->sipevent)->type;
+}
+
+const SubscriptionSession* SubscriptionEvent::getSession() const
+{
+ return dyn_cast<const SubscriptionSession*>(this->getBaseSession());
+} \ No newline at end of file
diff --git a/bindings/_common/SipEvent.h b/bindings/_common/SipEvent.h
new file mode 100644
index 0000000..11b919e
--- /dev/null
+++ b/bindings/_common/SipEvent.h
@@ -0,0 +1,193 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#ifndef TINYWRAP_SIPEVENT_H
+#define TINYWRAP_SIPEVENT_H
+
+#include "tinysip.h"
+#include "Common.h"
+
+class SipStack;
+
+class SipSession;
+class InviteSession;
+class CallSession;
+class MsrpSession;
+class MessagingSession;
+class OptionsSession;
+class PublicationSession;
+class RegistrationSession;
+class SubscriptionSession;
+
+class SipMessage;
+
+
+/* ======================== SipEvent ========================*/
+class SipEvent
+{
+public:
+#if !defined(SWIG)
+ SipEvent(const tsip_event_t *sipevent);
+#endif
+ virtual ~SipEvent();
+
+public:
+ short getCode() const;
+ const char* getPhrase() const;
+ const SipSession* getBaseSession() const;
+ const SipMessage* getSipMessage() const;
+
+protected:
+#if !defined(SWIG)
+ SipStack* getStack()const;
+#endif
+
+protected:
+ const tsip_event_t *sipevent;
+ SipMessage* sipmessage;
+};
+
+
+/* ======================== DialogEvent ========================*/
+class DialogEvent: public SipEvent
+{
+public:
+#if !defined(SWIG)
+ DialogEvent(const tsip_event_t *sipevent);
+#endif
+ virtual ~DialogEvent();
+
+public: /* Public API functions */
+};
+
+/* ======================== StackEvent ========================*/
+class StackEvent: public SipEvent
+{
+public:
+#if !defined(SWIG)
+ StackEvent(const tsip_event_t *sipevent);
+#endif
+ virtual ~StackEvent();
+
+public: /* Public API functions */
+};
+
+
+
+/* ======================== InviteEvent ========================*/
+class InviteEvent: public SipEvent
+{
+public:
+#if !defined(SWIG)
+ InviteEvent(const tsip_event_t *sipevent);
+#endif
+ virtual ~InviteEvent();
+
+public: /* Public API functions */
+ tsip_invite_event_type_t getType() const;
+ twrap_media_type_t getMediaType();
+ const InviteSession* getSession() const;
+ CallSession* takeCallSessionOwnership() const;
+ MsrpSession* takeMsrpSessionOwnership() const;
+};
+
+
+
+/* ======================== MessagingEvent ========================*/
+class MessagingEvent: public SipEvent
+{
+public:
+#if !defined(SWIG)
+ MessagingEvent(const tsip_event_t *sipevent);
+#endif
+ virtual ~MessagingEvent();
+
+public: /* Public API functions */
+ tsip_message_event_type_t getType() const;
+ const MessagingSession* getSession() const;
+ MessagingSession* takeSessionOwnership() const;
+};
+
+
+/* ======================== OptionsEvent ========================*/
+class OptionsEvent: public SipEvent
+{
+public:
+#if !defined(SWIG)
+ OptionsEvent(const tsip_event_t *sipevent);
+#endif
+ virtual ~OptionsEvent();
+
+public: /* Public API functions */
+ tsip_options_event_type_t getType() const;
+ const OptionsSession* getSession() const;
+};
+
+
+
+/* ======================== PublicationEvent ========================*/
+class PublicationEvent: public SipEvent
+{
+public:
+#if !defined(SWIG)
+ PublicationEvent(const tsip_event_t *sipevent);
+#endif
+ virtual ~PublicationEvent();
+
+public: /* Public API functions */
+ tsip_publish_event_type_t getType() const;
+ const PublicationSession* getSession() const;
+};
+
+
+
+/* ======================== RegistrationEvent ========================*/
+class RegistrationEvent: public SipEvent
+{
+public:
+#if !defined(SWIG)
+ RegistrationEvent(const tsip_event_t *sipevent);
+#endif
+ virtual ~RegistrationEvent();
+
+public: /* Public API functions */
+ tsip_register_event_type_t getType() const;
+ const RegistrationSession* getSession() const;
+ RegistrationSession* takeSessionOwnership() const;
+
+};
+
+
+/* ======================== SubscriptionEvent ========================*/
+class SubscriptionEvent: public SipEvent
+{
+public:
+#if !defined(SWIG)
+ SubscriptionEvent(const tsip_event_t *sipevent);
+#endif
+ virtual ~SubscriptionEvent();
+
+public: /* Public API functions */
+ tsip_subscribe_event_type_t getType() const;
+ const SubscriptionSession* getSession() const;
+};
+
+#endif /* TINYWRAP_SIPEVENT_H */
diff --git a/bindings/_common/SipMessage.cxx b/bindings/_common/SipMessage.cxx
new file mode 100644
index 0000000..24f129a
--- /dev/null
+++ b/bindings/_common/SipMessage.cxx
@@ -0,0 +1,258 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#include "SipMessage.h"
+
+
+SdpMessage::SdpMessage()
+:sdpmessage(tsk_null)
+{
+}
+
+SdpMessage::SdpMessage(tsdp_message_t *_sdpmessage)
+{
+ this->sdpmessage = (tsdp_message_t *)tsk_object_ref(_sdpmessage);
+}
+
+SdpMessage::~SdpMessage()
+{
+ TSK_OBJECT_SAFE_FREE(this->sdpmessage);
+}
+
+char* SdpMessage::getSdpHeaderValue(const char* media, char name, unsigned index /*= 0*/)
+{
+ const tsdp_header_M_t* M;
+
+ if((M = (const tsdp_header_M_t*)tsdp_message_get_header(this->sdpmessage, tsdp_htype_M))){
+ tsdp_header_type_t type = tsdp_htype_Dummy;
+ const tsdp_header_t* header;
+ switch(name){
+ case 'a': type = tsdp_htype_A; break;
+ case 'b': type = tsdp_htype_B; break;
+ case 'c': type = tsdp_htype_C; break;
+ case 'e': type = tsdp_htype_E; break;
+ case 'i': type = tsdp_htype_I; break;
+ case 'k': type = tsdp_htype_K; break;
+ case 'm': type = tsdp_htype_M; break;
+ case 'o': type = tsdp_htype_O; break;
+
+
+ case 'p': type = tsdp_htype_P; break;
+ case 'r': type = tsdp_htype_R; break;
+ case 's': type = tsdp_htype_S; break;
+ case 't': type = tsdp_htype_T; break;
+ case 'u': type = tsdp_htype_U; break;
+ case 'v': type = tsdp_htype_V; break;
+ case 'z': type = tsdp_htype_Z; break;
+ }
+
+ if((header = tsdp_message_get_headerAt(this->sdpmessage, type, index))){
+ return tsdp_header_tostring(header);
+ }
+ }
+
+ return tsk_null;
+}
+
+char* SdpMessage::getSdpHeaderAValue(const char* media, const char* attributeName)
+{
+ const tsdp_header_M_t* M;
+ tsk_size_t i;
+
+ for(i = 0; (M = (const tsdp_header_M_t*)tsdp_message_get_headerAt(this->sdpmessage, tsdp_htype_M, i)); i++){
+ if(tsk_striequals(M->media, media)){
+ const tsdp_header_A_t* A;
+ if((A = tsdp_header_M_findA(M, attributeName))){
+ return tsk_strdup(A->value);
+ }
+ }
+ }
+
+ return tsk_null;
+}
+
+
+SipMessage::SipMessage()
+:sipmessage(tsk_null), sdpmessage(tsk_null)
+{
+}
+
+SipMessage::SipMessage(tsip_message_t *_sipmessage)
+: sdpmessage(tsk_null)
+{
+ this->sipmessage = (tsip_message_t *)tsk_object_ref(_sipmessage);
+}
+
+SipMessage::~SipMessage()
+{
+ TSK_OBJECT_SAFE_FREE(this->sipmessage);
+ if(this->sdpmessage){
+ delete this->sdpmessage;
+ }
+}
+
+const tsip_header_t* SipMessage::getSipHeader(const char* name, unsigned index /* =0 */)
+{
+ /* Do not worry about calling tsk_striequals() several times because the function
+ * is fully optimized.
+ */
+ /* Code below comes from tsip_message_get_headerAt() */
+ tsk_size_t pos = 0;
+ const tsk_list_item_t *item;
+ const tsip_header_t* hdr = tsk_null;
+ if(!this->sipmessage || !name){
+ return tsk_null;
+ }
+
+ if(tsk_striequals(name, "v") || tsk_striequals(name, "via")){
+ if(index == 0){
+ hdr = (const tsip_header_t*)this->sipmessage->firstVia;
+ goto bail;
+ }else pos++; }
+ if(tsk_striequals(name, "f") || tsk_striequals(name, "from")){
+ if(index == 0){
+ hdr = (const tsip_header_t*)this->sipmessage->From;
+ goto bail;
+ }else pos++; }
+ if(tsk_striequals(name, "t") || tsk_striequals(name, "to")){
+ if(index == 0){
+ hdr = (const tsip_header_t*)this->sipmessage->To;
+ goto bail;
+ }else pos++; }
+ if(tsk_striequals(name, "m") || tsk_striequals(name, "contact")){
+ if(index == 0){
+ hdr = (const tsip_header_t*)this->sipmessage->Contact;
+ goto bail;
+ }else pos++; }
+ if(tsk_striequals(name, "i") || tsk_striequals(name, "call-id")){
+ if(index == 0){
+ hdr = (const tsip_header_t*)this->sipmessage->Call_ID;
+ goto bail;
+ }else pos++; }
+ if(tsk_striequals(name, "cseq")){
+ if(index == 0){
+ hdr = (const tsip_header_t*)this->sipmessage->CSeq;
+ goto bail;
+ }else pos++; }
+ if(tsk_striequals(name, "expires")){
+ if(index == 0){
+ hdr = (const tsip_header_t*)this->sipmessage->Expires;
+ goto bail;
+ }else pos++; }
+ if(tsk_striequals(name, "c") || tsk_striequals(name, "content-type")){
+ if(index == 0){
+ hdr = (const tsip_header_t*)this->sipmessage->Content_Type;
+ goto bail;
+ }else pos++; }
+ if(tsk_striequals(name, "l") || tsk_striequals(name, "content-length")){
+ if(index == 0){
+ hdr = (const tsip_header_t*)this->sipmessage->Content_Length;
+ goto bail;
+ }else pos++; }
+
+
+ tsk_list_foreach(item, this->sipmessage->headers){
+ if(tsk_striequals(tsip_header_get_name_2(TSIP_HEADER(item->data)), name)){
+ if(pos++ >= index){
+ hdr = (const tsip_header_t*)item->data;
+ break;
+ }
+ }
+ }
+
+
+bail:
+ return hdr;
+}
+
+// e.g. getHeaderParamValue("content-type");
+char* SipMessage::getSipHeaderValue(const char* name, unsigned index /* = 0*/)
+{
+ const tsip_header_t* header;
+ if((header = this->getSipHeader(name, index))){
+
+ switch(header->type){
+ case tsip_htype_From:
+ return tsip_uri_tostring(((const tsip_header_From_t*)header)->uri, tsk_false, tsk_false);
+ case tsip_htype_To:
+ return tsip_uri_tostring(((const tsip_header_To_t*)header)->uri, tsk_false, tsk_false);
+ break;
+ case tsip_htype_P_Asserted_Identity:
+ return tsip_uri_tostring(((const tsip_header_P_Asserted_Identity_t*)header)->uri, tsk_false, tsk_false);
+ break;
+
+ default:
+ return tsip_header_value_tostring(header);
+ }
+ }
+ // SWIG: %newobject getHeaderValueAt;
+ return tsk_null;
+}
+
+// e.g. getHeaderParamValue("content-type", "charset");
+char* SipMessage::getSipHeaderParamValue(const char* name, const char* param, unsigned index /*=0*/)
+{
+ const tsip_header_t* header;
+
+ if((header = this->getSipHeader(name, index))){
+ return tsip_header_get_param_value(header, param);
+ }
+
+ // SWIG: %newobject getSipHeaderParamValue;
+ return tsk_null;
+}
+
+/** Returns the content length.
+*/
+unsigned SipMessage::getSipContentLength()
+{
+ return TSIP_MESSAGE_CONTENT_DATA_LENGTH(this->sipmessage);
+}
+
+/** Gets the message content
+* @param output A pointer to the output buffer where to copy the data. MUST
+* be allocated by the caller.
+* @param maxsize The maximum number of octets to copy. Should be less than the size of the
+* @a output buffer. You can use @a getSipContentLength() to get the right value to use.
+* @retval The number of octet copied in the @a output buffer.
+*/
+unsigned SipMessage::getSipContent(void* output, unsigned maxsize)
+{
+ unsigned retsize = 0;
+ if(output && maxsize && TSIP_MESSAGE_HAS_CONTENT(this->sipmessage)){
+ retsize = (this->sipmessage->Content->size > maxsize) ? maxsize : this->sipmessage->Content->size;
+ memcpy(output, this->sipmessage->Content->data, retsize);
+ }
+ return retsize;
+}
+
+const SdpMessage* SipMessage::getSdpMessage()
+{
+ if(!this->sdpmessage && TSIP_MESSAGE_HAS_CONTENT(this->sipmessage)){
+ tsdp_message_t* sdp = tsdp_message_parse(this->sipmessage->Content->data, this->sipmessage->Content->size);
+ if(sdp){
+ this->sdpmessage = new SdpMessage(sdp);
+ TSK_OBJECT_SAFE_FREE(sdp);
+ }
+ }
+
+ return this->sdpmessage;
+}
diff --git a/bindings/_common/SipMessage.h b/bindings/_common/SipMessage.h
new file mode 100644
index 0000000..803285e
--- /dev/null
+++ b/bindings/_common/SipMessage.h
@@ -0,0 +1,66 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#ifndef TINYWRAP_SIPMESSAGE_H
+#define TINYWRAP_SIPMESSAGE_H
+
+#include "tinysip.h"
+
+class SdpMessage
+{
+public:
+ SdpMessage();
+#if !defined(SWIG)
+ SdpMessage(tsdp_message_t *sdpmessage);
+#endif
+ virtual ~SdpMessage();
+
+ char* getSdpHeaderValue(const char* media, char name, unsigned index = 0);
+ char* getSdpHeaderAValue(const char* media, const char* attributeName);
+
+private:
+ tsdp_message_t *sdpmessage;
+};
+
+class SipMessage
+{
+public:
+ SipMessage();
+#if !defined(SWIG)
+ SipMessage(tsip_message_t *sipmessage);
+#endif
+ virtual ~SipMessage();
+
+ char* getSipHeaderValue(const char* name, unsigned index = 0);
+ char* getSipHeaderParamValue(const char* name, const char* param, unsigned index = 0);
+ unsigned getSipContentLength();
+ unsigned getSipContent(void* output, unsigned maxsize);
+ const SdpMessage* getSdpMessage();
+
+private:
+ const tsip_header_t* getSipHeader(const char* name, unsigned index = 0);
+
+private:
+ tsip_message_t *sipmessage;
+ SdpMessage *sdpmessage;
+};
+
+#endif /* TINYWRAP_SIPMESSAGE_H */
diff --git a/bindings/_common/SipSession.cxx b/bindings/_common/SipSession.cxx
new file mode 100644
index 0000000..f8dbe72
--- /dev/null
+++ b/bindings/_common/SipSession.cxx
@@ -0,0 +1,727 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#include "SipSession.h"
+#include "SipStack.h"
+#include "MediaSessionMgr.h"
+
+#include "Msrp.h"
+
+/* ======================== AsyncAction ========================*/
+typedef struct twrap_async_action_s
+{
+ const tsip_ssession_handle_t *session;
+ const ActionConfig* config;
+}
+twrap_async_action_t;
+
+
+
+
+/* ======================== SipSession ========================*/
+SipSession::SipSession(SipStack* stack)
+{
+ this->init(stack);
+}
+
+SipSession::SipSession(SipStack* stack, tsip_ssession_handle_t* handle)
+{
+ this->init(stack, handle);
+}
+
+SipSession::~SipSession()
+{
+ tsip_ssession_set(this->handle,
+ TSIP_SSESSION_SET_USERDATA(tsk_null),
+ TSIP_SSESSION_SET_NULL());
+
+ TSK_OBJECT_SAFE_FREE(this->handle);
+}
+
+void SipSession::init(SipStack* _stack, tsip_ssession_handle_t* _handle/*=tsk_null*/)
+{
+ if(_handle){
+ /* "server-side-session" */
+ if(tsip_ssession_take_ownership(_handle)){ /* should never happen */
+ TSK_DEBUG_ERROR("Failed to take ownership");
+ return;
+ }
+ this->handle = _handle;
+ }
+ else{
+ /* "client-side-session" */
+ this->handle = tsip_ssession_create(_stack->getHandle(),
+ TSIP_SSESSION_SET_USERDATA(this),
+ TSIP_SSESSION_SET_NULL());
+ }
+
+ /* set userdata (context) and ref. the stack handle */
+ tsip_ssession_set(this->handle,
+ TSIP_SSESSION_SET_USERDATA(this),
+ TSIP_SSESSION_SET_NULL());
+ this->stack = _stack;
+}
+
+bool SipSession::addHeader(const char* name, const char* value)
+{
+ return (tsip_ssession_set(this->handle,
+ TSIP_SSESSION_SET_HEADER(name, value),
+ TSIP_SSESSION_SET_NULL()) == 0);
+}
+
+bool SipSession::haveOwnership()
+{
+ return (tsip_ssession_have_ownership(this->handle) == tsk_true);
+}
+
+bool SipSession::removeHeader(const char* name)
+{
+ return (tsip_ssession_set(this->handle,
+ TSIP_SSESSION_UNSET_HEADER(name),
+ TSIP_SSESSION_SET_NULL()) == 0);
+}
+
+bool SipSession::addCaps(const char* name, const char* value)
+{
+ return (tsip_ssession_set(this->handle,
+ TSIP_SSESSION_SET_CAPS(name, value),
+ TSIP_SSESSION_SET_NULL()) == 0);
+}
+
+bool SipSession::addCaps(const char* name)
+{
+ return (tsip_ssession_set(this->handle,
+ TSIP_SSESSION_SET_CAPS(name, tsk_null),
+ TSIP_SSESSION_SET_NULL()) == 0);
+}
+
+bool SipSession::removeCaps(const char* name)
+{
+ return (tsip_ssession_set(this->handle,
+ TSIP_SSESSION_UNSET_CAPS(name),
+ TSIP_SSESSION_SET_NULL()) == 0);
+}
+
+bool SipSession::setExpires(unsigned expires)
+{
+ return (tsip_ssession_set(this->handle,
+ TSIP_SSESSION_SET_EXPIRES(expires),
+ TSIP_SSESSION_SET_NULL()) == 0);
+}
+
+bool SipSession::setFromUri(const char* fromUri)
+{
+ return (tsip_ssession_set(this->handle,
+ TSIP_SSESSION_SET_FROM(fromUri),
+ TSIP_SSESSION_SET_NULL()) == 0);
+}
+
+bool SipSession::setToUri(const char* toUri)
+{
+ return (tsip_ssession_set(this->handle,
+ TSIP_SSESSION_SET_TO(toUri),
+ TSIP_SSESSION_SET_NULL()) == 0);
+}
+
+bool SipSession::setSilentHangup(bool silent)
+{
+ return (tsip_ssession_set(this->handle,
+ TSIP_SSESSION_SET_SILENT_HANGUP(silent ? tsk_true : tsk_false),
+ TSIP_SSESSION_SET_NULL()) == 0);
+}
+
+bool SipSession::addSigCompCompartment(const char* compId)
+{
+ return (tsip_ssession_set(this->handle,
+ TSIP_SSESSION_SET_SIGCOMP_COMPARTMENT(compId),
+ TSIP_SSESSION_SET_NULL()) == 0);
+}
+
+bool SipSession::removeSigCompCompartment()
+{
+ return (tsip_ssession_set(this->handle,
+ TSIP_SSESSION_UNSET_SIGCOMP_COMPARTMENT(),
+ TSIP_SSESSION_SET_NULL()) == 0);
+}
+
+unsigned SipSession::getId()
+{
+ return (unsigned)tsip_ssession_get_id(this->handle);
+}
+
+const SipStack* SipSession::getStack()const
+{
+ return this->stack;
+}
+
+
+/* ======================== InviteSession ========================*/
+
+InviteSession::InviteSession(SipStack* Stack)
+: SipSession(Stack), mediaMgr(tsk_null)
+{
+}
+
+InviteSession::InviteSession(SipStack* Stack, tsip_ssession_handle_t* handle)
+: SipSession(Stack, handle), mediaMgr(tsk_null)
+{
+
+}
+
+InviteSession::~InviteSession()
+{
+ if(this->mediaMgr){
+ delete this->mediaMgr, this->mediaMgr = tsk_null;
+ }
+}
+
+#if ANDROID
+static void *__droid_hangup(void *param)
+{
+ twrap_async_action_t* asyn_action = (twrap_async_action_t*)param;
+ const tsip_action_handle_t* action_cfg = asyn_action->config ? asyn_action->config->getHandle() : tsk_null;
+
+ tsip_action_BYE(asyn_action->session,
+ TSIP_ACTION_SET_CONFIG(action_cfg),
+ TSIP_ACTION_SET_NULL());
+
+ return tsk_null;
+}
+
+bool InviteSession::hangup(ActionConfig* config/*=tsk_null*/)
+{
+ void* tid[1] = {0};
+ tsip_ssession_handle_t *handle;
+ int ret;
+ twrap_async_action_t asyn_action = {0};
+
+ handle = tsk_object_ref(this->handle);
+ asyn_action.config = config;
+ asyn_action.session = handle;
+ ret = tsk_thread_create(tid, __droid_hangup, &asyn_action);
+ tsk_thread_join(tid);
+ tsk_object_unref(handle);
+
+ return (ret == 0);
+}
+#else
+bool InviteSession::hangup(ActionConfig* config/*=tsk_null*/)
+{
+ return (tsip_action_BYE(this->handle,
+ TSIP_ACTION_SET_NULL()) == 0);
+}
+#endif
+
+#if ANDROID
+static void *__droid_reject(void *param)
+{
+ twrap_async_action_t* asyn_action = (twrap_async_action_t*)param;
+ const tsip_action_handle_t* action_cfg = asyn_action->config ? asyn_action->config->getHandle() : tsk_null;
+
+ tsip_action_REJECT(asyn_action->session,
+ TSIP_ACTION_SET_CONFIG(action_cfg),
+ TSIP_ACTION_SET_NULL());
+
+ return tsk_null;
+}
+
+bool InviteSession::reject(ActionConfig* config/*=tsk_null*/)
+{
+ void* tid[1] = {0};
+ tsip_ssession_handle_t *handle;
+ int ret;
+ twrap_async_action_t asyn_action = {0};
+
+ handle = tsk_object_ref(this->handle);
+ asyn_action.config = config;
+ asyn_action.session = handle;
+ ret = tsk_thread_create(tid, __droid_reject, &asyn_action);
+ tsk_thread_join(tid);
+ tsk_object_unref(handle);
+
+ return (ret == 0);
+}
+#else
+bool InviteSession::reject(ActionConfig* config/*=tsk_null*/)
+{
+ const tsip_action_handle_t* action_cfg = config ? config->getHandle() : tsk_null;
+
+ return (tsip_action_REJECT(this->handle,
+ TSIP_ACTION_SET_CONFIG(action_cfg),
+ TSIP_ACTION_SET_NULL()) == 0);
+}
+#endif
+
+#if ANDROID
+static void *__droid_accept(void *param)
+{
+ twrap_async_action_t* asyn_action = (twrap_async_action_t*)param;
+ const tsip_action_handle_t* action_cfg = asyn_action->config ? asyn_action->config->getHandle() : tsk_null;
+
+ tsip_action_ACCEPT(asyn_action->session,
+ TSIP_ACTION_SET_CONFIG(action_cfg),
+ TSIP_ACTION_SET_NULL());
+
+ return tsk_null;
+}
+
+bool InviteSession::accept(ActionConfig* config/*=tsk_null*/)
+{
+ void* tid[1] = {0};
+ tsip_ssession_handle_t *handle;
+ int ret;
+ twrap_async_action_t asyn_action = {0};
+
+
+ handle = tsk_object_ref(this->handle);
+ asyn_action.config = config;
+ asyn_action.session = handle;
+ ret = tsk_thread_create(tid, __droid_accept, &asyn_action);
+ tsk_thread_join(tid);
+ tsk_object_unref(handle);
+
+ return (ret == 0);
+}
+#else
+bool InviteSession::accept(ActionConfig* config/*=tsk_null*/)
+{
+ const tsip_action_handle_t* action_cfg = config ? config->getHandle() : tsk_null;
+
+ return (tsip_action_ACCEPT(this->handle,
+ TSIP_ACTION_SET_CONFIG(action_cfg),
+ TSIP_ACTION_SET_NULL()) == 0);
+}
+#endif
+
+const MediaSessionMgr* InviteSession::getMediaMgr()
+{
+ if(!this->mediaMgr && this->handle){
+ tmedia_session_mgr_t* mgr = tsip_session_get_mediamgr(this->handle);
+ if(mgr){
+ this->mediaMgr = new MediaSessionMgr(mgr);
+ tsk_object_unref(mgr);
+ }
+ else{
+ TSK_DEBUG_WARN("No media session associated to this session");
+ }
+ }
+ return this->mediaMgr;
+}
+
+
+/* ======================== CallSession ========================*/
+CallSession::CallSession(SipStack* Stack)
+: InviteSession(Stack)
+{
+}
+
+CallSession::CallSession(SipStack* Stack, tsip_ssession_handle_t* handle)
+: InviteSession(Stack, handle)
+{
+}
+
+CallSession::~CallSession()
+{
+}
+
+#define ANDROID32 1
+
+#if ANDROID
+typedef struct twrap_async_action_call_s
+{
+ const tsip_ssession_handle_t *session;
+ const ActionConfig* config;
+ tmedia_type_t media_type;
+}
+twrap_async_action_call_t;
+
+static void *__droid_call_thread(void *param)
+{
+ twrap_async_action_call_t* asyn_action = (twrap_async_action_call_t*)param;
+ const tsip_action_handle_t* action_cfg = asyn_action->config ? asyn_action->config->getHandle() : tsk_null;
+
+ tsip_action_INVITE(asyn_action->session, asyn_action->media_type,
+ TSIP_ACTION_SET_CONFIG(action_cfg),
+ TSIP_ACTION_SET_NULL());
+
+ return tsk_null;
+}
+
+static bool __droid_call(tsip_ssession_handle_t * session_handle, tmedia_type_t type, ActionConfig* config/*=tsk_null*/)
+{
+ void* tid[1] = {0};
+ tsip_ssession_handle_t *handle;
+ int ret;
+ twrap_async_action_call_t asyn_action = {0};
+
+ handle = tsk_object_ref(session_handle);
+ asyn_action.config = config;
+ asyn_action.session = handle;
+ asyn_action.media_type = type;
+
+ ret = tsk_thread_create(tid, __droid_call_thread, &asyn_action);
+ tsk_thread_join(tid);
+ tsk_object_unref(handle);
+
+ return (ret == 0);
+}
+#endif
+
+bool CallSession::callAudio(const char* remoteUri, ActionConfig* config/*=tsk_null*/)
+{
+ tsip_ssession_set(this->handle,
+ TSIP_SSESSION_SET_TO(remoteUri),
+ TSIP_SSESSION_SET_NULL());
+#if ANDROID
+ __droid_call(this->handle, tmedia_audio, config);
+ return true;
+#else
+ const tsip_action_handle_t* action_cfg = config ? config->getHandle() : tsk_null;
+ return (tsip_action_INVITE(this->handle, tmedia_audio,
+ TSIP_ACTION_SET_CONFIG(action_cfg),
+ TSIP_ACTION_SET_NULL()) == 0);
+#endif
+}
+
+bool CallSession::callAudioVideo(const char* remoteUri, ActionConfig* config/*=tsk_null*/)
+{
+ tsip_ssession_set(this->handle,
+ TSIP_SSESSION_SET_TO(remoteUri),
+ TSIP_SSESSION_SET_NULL());
+#if ANDROID
+ __droid_call(this->handle, (tmedia_type_t)(tmedia_audio | tmedia_video), config);
+ return true;
+#else
+ const tsip_action_handle_t* action_cfg = config ? config->getHandle() : tsk_null;
+ return (tsip_action_INVITE(this->handle, (tmedia_type_t)(tmedia_audio | tmedia_video),
+ TSIP_ACTION_SET_CONFIG(action_cfg),
+ TSIP_ACTION_SET_NULL()) == 0);
+#endif
+}
+
+bool CallSession::callVideo(const char* remoteUri, ActionConfig* config/*=tsk_null*/)
+{
+ tsip_ssession_set(this->handle,
+ TSIP_SSESSION_SET_TO(remoteUri),
+ TSIP_SSESSION_SET_NULL());
+#if ANDROID
+ __droid_call(this->handle, tmedia_video, config);
+ return true;
+#else
+ const tsip_action_handle_t* action_cfg = config ? config->getHandle() : tsk_null;
+ return (tsip_action_INVITE(this->handle, tmedia_video,
+ TSIP_ACTION_SET_CONFIG(action_cfg),
+ TSIP_ACTION_SET_NULL()) == 0);
+#endif
+}
+
+bool CallSession::setSessionTimer(unsigned timeout, const char* refresher)
+{
+ return (tsip_ssession_set(this->handle,
+ TSIP_SSESSION_SET_MEDIA(
+ TSIP_MSESSION_SET_TIMERS(timeout, refresher),
+ TSIP_MSESSION_SET_NULL()
+ ),
+ TSIP_SSESSION_SET_NULL()) == 0);
+}
+
+bool CallSession::set100rel(bool enabled)
+{
+ if(enabled){
+ return (tsip_ssession_set(this->handle,
+ TSIP_SSESSION_SET_MEDIA(
+ TSIP_MSESSION_SET_100rel(),
+ TSIP_MSESSION_SET_NULL()
+ ),
+ TSIP_SSESSION_SET_NULL()) == 0);
+ }
+ else{
+ return (tsip_ssession_set(this->handle,
+ TSIP_SSESSION_SET_MEDIA(
+ TSIP_MSESSION_UNSET_100rel(),
+ TSIP_MSESSION_SET_NULL()
+ ),
+ TSIP_SSESSION_SET_NULL()) == 0);
+ }
+}
+
+bool CallSession::setQoS(tmedia_qos_stype_t type, tmedia_qos_strength_t strength)
+{
+ return (tsip_ssession_set(this->handle,
+ TSIP_SSESSION_SET_MEDIA(
+ TSIP_MSESSION_SET_QOS(type, strength),
+ TSIP_MSESSION_SET_NULL()
+ ),
+ TSIP_SSESSION_SET_NULL()) == 0);
+}
+
+bool CallSession::hold(ActionConfig* config/*=tsk_null*/)
+{
+ const tsip_action_handle_t* action_cfg = config ? config->getHandle() : tsk_null;
+
+ return (tsip_action_HOLD(this->handle, tmedia_all,
+ TSIP_ACTION_SET_CONFIG(action_cfg),
+ TSIP_ACTION_SET_NULL()) ==0 );
+}
+
+bool CallSession::resume(ActionConfig* config/*=tsk_null*/)
+{
+ const tsip_action_handle_t* action_cfg = config ? config->getHandle() : tsk_null;
+
+ return (tsip_action_RESUME(this->handle, tmedia_all,
+ TSIP_ACTION_SET_CONFIG(action_cfg),
+ TSIP_ACTION_SET_NULL()) == 0);
+}
+
+bool CallSession::sendDTMF(int number)
+{
+ return (tsip_action_DTMF(this->handle, number,
+ TSIP_ACTION_SET_NULL()) == 0);
+}
+
+
+/* ======================== MsrpSession ========================*/
+
+MsrpSession::MsrpSession(SipStack* Stack, MsrpCallback* _callback)
+: InviteSession(Stack), callback(_callback)
+{
+ tsip_ssession_set(this->handle,
+ TSIP_SSESSION_SET_MEDIA(
+ TSIP_MSESSION_SET_MSRP_CB(twrap_msrp_cb),
+ TSIP_MSESSION_SET_NULL()
+ ),
+ TSIP_SSESSION_SET_NULL());
+}
+
+MsrpSession::MsrpSession(SipStack* Stack, tsip_ssession_handle_t* handle)
+: InviteSession(Stack, handle), callback(tsk_null)
+{
+ tsip_ssession_set(this->handle,
+ TSIP_SSESSION_SET_MEDIA(
+ TSIP_MSESSION_SET_MSRP_CB(twrap_msrp_cb),
+ TSIP_MSESSION_SET_NULL()
+ ),
+ TSIP_SSESSION_SET_NULL());
+}
+
+MsrpSession::~MsrpSession()
+{
+}
+
+bool MsrpSession::setCallback(MsrpCallback* _callback)
+{
+ this->callback = _callback;
+ return true;
+}
+
+bool MsrpSession::callMsrp(const char* remoteUri, ActionConfig* config/*=tsk_null*/)
+{
+ const tsip_action_handle_t* action_cfg = config ? config->getHandle() : tsk_null;
+
+ tsip_ssession_set(this->handle,
+ TSIP_SSESSION_SET_TO(remoteUri),
+ TSIP_SSESSION_SET_NULL());
+
+ return (tsip_action_INVITE(this->handle, tmedia_msrp,
+ TSIP_ACTION_SET_CONFIG(action_cfg),
+ TSIP_ACTION_SET_NULL()) == 0);
+}
+
+bool MsrpSession::sendMessage(const void* payload, unsigned len, ActionConfig* config/*=tsk_null*/)
+{
+ const tsip_action_handle_t* action_cfg = config ? config->getHandle() : tsk_null;
+
+ return (tsip_action_LARGE_MESSAGE(this->handle,
+ TSIP_ACTION_SET_PAYLOAD(payload, len),
+ TSIP_ACTION_SET_CONFIG(action_cfg),
+ TSIP_ACTION_SET_NULL()) == 0);
+}
+
+bool MsrpSession::sendFile(ActionConfig* config/*=tsk_null*/)
+{
+ return false;
+}
+
+/* ======================== MessagingSession ========================*/
+MessagingSession::MessagingSession(SipStack* Stack)
+: SipSession(Stack)
+{
+}
+
+MessagingSession::MessagingSession(SipStack* Stack, tsip_ssession_handle_t* handle)
+: SipSession(Stack, handle)
+{
+}
+
+MessagingSession::~MessagingSession()
+{
+}
+
+bool MessagingSession::send(const void* payload, unsigned len)
+{
+ TSK_DEBUG_INFO("MessagingSession::Send()");
+ int ret;
+ if(payload && len){
+ ret = tsip_action_MESSAGE(this->handle,
+ TSIP_ACTION_SET_PAYLOAD(payload, len),
+ TSIP_ACTION_SET_NULL());
+ }
+ else{
+ ret = tsip_action_PUBLISH(this->handle,
+ TSIP_ACTION_SET_NULL());
+ }
+ return (ret == 0);
+}
+
+bool MessagingSession::accept()
+{
+ return (tsip_action_ACCEPT(this->handle,
+ TSIP_ACTION_SET_NULL()) == 0);
+}
+
+bool MessagingSession::reject()
+{
+ return (tsip_action_REJECT(this->handle,
+ TSIP_ACTION_SET_NULL()) == 0);
+}
+
+
+/* ======================== OptionsSession ========================*/
+OptionsSession::OptionsSession(SipStack* Stack)
+: SipSession(Stack)
+{
+}
+
+OptionsSession::~OptionsSession()
+{
+}
+
+bool OptionsSession::send()
+{
+ return (tsip_action_OPTIONS(this->handle,
+ TSIP_ACTION_SET_NULL()) == 0);
+}
+
+
+
+
+
+/* ======================== PublicationSession ========================*/
+PublicationSession::PublicationSession(SipStack* Stack)
+: SipSession(Stack)
+{
+}
+
+PublicationSession::~PublicationSession()
+{
+}
+
+bool PublicationSession::publish(const void* payload, unsigned len)
+{
+ int ret;
+ if(payload && len){
+ ret = tsip_action_PUBLISH(this->handle,
+ TSIP_ACTION_SET_PAYLOAD(payload, len),
+ TSIP_ACTION_SET_NULL());
+ }
+ else{
+ ret = tsip_action_PUBLISH(this->handle,
+ TSIP_ACTION_SET_NULL());
+ }
+ return (ret == 0);
+}
+
+bool PublicationSession::unPublish()
+{
+ return (tsip_action_UNPUBLISH(this->handle,
+ TSIP_ACTION_SET_NULL()) == 0);
+}
+
+
+
+/* ======================== RegistrationSession ========================*/
+RegistrationSession::RegistrationSession(SipStack* Stack)
+: SipSession(Stack)
+{
+}
+
+RegistrationSession::RegistrationSession(SipStack* Stack, tsip_ssession_handle_t* handle)
+: SipSession(Stack, handle)
+{
+
+}
+
+RegistrationSession::~RegistrationSession()
+{
+}
+
+bool RegistrationSession::register_()
+{
+ return (tsip_action_REGISTER(this->handle,
+ TSIP_ACTION_SET_NULL()) == 0);
+}
+
+bool RegistrationSession::unRegister()
+{
+ return (tsip_action_UNREGISTER(this->handle,
+ TSIP_ACTION_SET_NULL()) == 0);
+}
+
+bool RegistrationSession::accept(ActionConfig* config/*=tsk_null*/)
+{
+ const tsip_action_handle_t* action_cfg = config ? config->getHandle() : tsk_null;
+
+ return (tsip_action_ACCEPT(this->handle,
+ TSIP_ACTION_SET_CONFIG(action_cfg),
+ TSIP_ACTION_SET_NULL()) == 0);
+}
+
+bool RegistrationSession::reject(ActionConfig* config/*=tsk_null*/)
+{
+ const tsip_action_handle_t* action_cfg = config ? config->getHandle() : tsk_null;
+
+ return (tsip_action_REJECT(this->handle,
+ TSIP_ACTION_SET_CONFIG(action_cfg),
+ TSIP_ACTION_SET_NULL()) == 0);
+}
+
+
+/* ======================== SubscriptionSession ========================*/
+SubscriptionSession::SubscriptionSession(SipStack* Stack)
+: SipSession(Stack)
+{
+}
+
+SubscriptionSession::~SubscriptionSession()
+{
+}
+
+bool SubscriptionSession::subscribe()
+{
+ return (tsip_action_SUBSCRIBE(this->handle,
+ TSIP_ACTION_SET_NULL()) == 0);
+}
+
+bool SubscriptionSession::unSubscribe()
+{
+ return (tsip_action_UNSUBSCRIBE(this->handle,
+ TSIP_ACTION_SET_NULL()) == 0);
+}
diff --git a/bindings/_common/SipSession.h b/bindings/_common/SipSession.h
new file mode 100644
index 0000000..3f53db4
--- /dev/null
+++ b/bindings/_common/SipSession.h
@@ -0,0 +1,216 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#ifndef TINYWRAP_SIPSESSION_H
+#define TINYWRAP_SIPSESSION_H
+
+#include "tinysip.h"
+#include "tinymedia/tmedia_qos.h"
+#include "ActionConfig.h"
+
+class SipStack;
+class MsrpCallback;
+class MediaSessionMgr;
+
+/* ======================== SipSession ========================*/
+class SipSession
+{
+public:
+ SipSession(SipStack* stack);
+#if !defined(SWIG)
+ SipSession(SipStack* stack, tsip_ssession_handle_t* handle);
+#endif
+ virtual ~SipSession();
+
+public:
+ bool haveOwnership();
+ bool addHeader(const char* name, const char* value);
+ bool removeHeader(const char* name);
+ bool addCaps(const char* name, const char* value);
+ bool addCaps(const char* name);
+ bool removeCaps(const char* name);
+ bool setExpires(unsigned expires);
+ bool setFromUri(const char* fromUri);
+ bool setToUri(const char* toUri);
+ bool setSilentHangup(bool silent);
+ bool addSigCompCompartment(const char* compId);
+ bool removeSigCompCompartment();
+ unsigned getId();
+
+#if !defined(SWIG)
+ const SipStack* getStack() const;
+#endif
+
+private:
+ void init(SipStack* stack, tsip_ssession_handle_t* handle=tsk_null);
+
+protected:
+ tsip_ssession_handle_t* handle;
+ const SipStack* stack;
+};
+
+/* ======================== InviteSession ========================*/
+class InviteSession : public SipSession
+{
+public: /* ctor() and dtor() */
+ InviteSession(SipStack* Stack);
+#if !defined(SWIG)
+ InviteSession(SipStack* Stack, tsip_ssession_handle_t* handle);
+#endif
+ virtual ~InviteSession();
+
+public: /* Public functions */
+ bool accept(ActionConfig* config=tsk_null);
+ bool hangup(ActionConfig* config=tsk_null);
+ bool reject(ActionConfig* config=tsk_null);
+ const MediaSessionMgr* getMediaMgr();
+
+private:
+ MediaSessionMgr* mediaMgr;
+};
+
+
+/* ======================== CallSession ========================*/
+class CallSession : public InviteSession
+{
+public: /* ctor() and dtor() */
+ CallSession(SipStack* Stack);
+#if !defined(SWIG)
+ CallSession(SipStack* Stack, tsip_ssession_handle_t* handle);
+#endif
+ virtual ~CallSession();
+
+public: /* Public functions */
+ bool callAudio(const char* remoteUri, ActionConfig* config=tsk_null);
+ bool callAudioVideo(const char* remoteUri, ActionConfig* config=tsk_null);
+ bool callVideo(const char* remoteUri, ActionConfig* config=tsk_null);
+ bool setSessionTimer(unsigned timeout, const char* refresher);
+ bool set100rel(bool enabled);
+ bool setQoS(tmedia_qos_stype_t type, tmedia_qos_strength_t strength);
+ bool hold(ActionConfig* config=tsk_null);
+ bool resume(ActionConfig* config=tsk_null);
+ bool sendDTMF(int number);
+};
+
+/* ======================== MsrpSession ========================*/
+class MsrpSession : public InviteSession
+{
+public: /* ctor() and dtor() */
+ MsrpSession(SipStack* Stack, MsrpCallback* callback);
+#if !defined(SWIG)
+ MsrpSession(SipStack* Stack, tsip_ssession_handle_t* handle);
+#endif
+ virtual ~MsrpSession();
+
+public: /* Public functions */
+ bool setCallback(MsrpCallback* callback);
+ bool callMsrp(const char* remoteUri, ActionConfig* config=tsk_null);
+ bool sendMessage(const void* payload, unsigned len, ActionConfig* config=tsk_null);
+ bool sendFile(ActionConfig* config=tsk_null);
+
+ public: /* Public helper function */
+#if !defined(SWIG)
+ inline MsrpCallback* getCallback()const{
+ return this->callback;
+ }
+#endif
+
+private:
+ MsrpCallback* callback;
+};
+
+
+
+/* ======================== MessagingSession ========================*/
+class MessagingSession : public SipSession
+{
+public: /* ctor() and dtor() */
+ MessagingSession(SipStack* Stack);
+#if !defined(SWIG)
+ MessagingSession(SipStack* Stack, tsip_ssession_handle_t* handle);
+#endif
+ virtual ~MessagingSession();
+
+public: /* Public functions */
+ bool send(const void* payload, unsigned len);
+ bool accept();
+ bool reject();
+};
+
+/* ======================== OptionsSession ========================*/
+class OptionsSession : public SipSession
+{
+public: /* ctor() and dtor() */
+ OptionsSession(SipStack* Stack);
+ virtual ~OptionsSession();
+
+public: /* Public functions */
+ bool send();
+ /* bool Accept(); */
+ /* bool Reject(); */
+};
+
+
+
+/* ======================== PublicationSession ========================*/
+class PublicationSession : public SipSession
+{
+public: /* ctor() and dtor() */
+ PublicationSession(SipStack* Stack);
+ virtual ~PublicationSession();
+
+public: /* Public functions */
+ bool publish(const void* payload, unsigned len);
+ bool unPublish();
+};
+
+
+/* ======================== RegistrationSession ========================*/
+class RegistrationSession : public SipSession
+{
+public: /* ctor() and dtor() */
+ RegistrationSession(SipStack* Stack);
+#if !defined(SWIG)
+ RegistrationSession(SipStack* Stack, tsip_ssession_handle_t* handle);
+#endif
+ virtual ~RegistrationSession();
+
+public: /* Public functions */
+ bool register_();
+ bool unRegister();
+ bool accept(ActionConfig* config=tsk_null);
+ bool reject(ActionConfig* config=tsk_null);
+};
+
+
+/* ======================== SubscriptionSession ========================*/
+class SubscriptionSession : public SipSession
+{
+public: /* ctor() and dtor() */
+ SubscriptionSession(SipStack* Stack);
+ virtual ~SubscriptionSession();
+
+public: /* Public functions */
+ bool subscribe();
+ bool unSubscribe();
+};
+
+#endif /* TINYWRAP_SIPSESSION_H */
diff --git a/bindings/_common/SipStack.cxx b/bindings/_common/SipStack.cxx
new file mode 100644
index 0000000..22640f9
--- /dev/null
+++ b/bindings/_common/SipStack.cxx
@@ -0,0 +1,524 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#include "SipStack.h"
+
+#include "SipSession.h"
+#include "SipEvent.h"
+
+#include "DDebug.h"
+
+#include "Common.h"
+
+unsigned SipStack::count = 0;
+
+
+/* === ANSI-C functions (local use) === */
+static int stack_callback(const tsip_event_t *sipevent);
+static int session_handle_event(const tsip_event_t *sipevent);
+
+/* === default values === */
+#ifndef DEFAULT_LOCAL_IP
+//# ifdef ANDROID /* On the emulator */
+//# define DEFAULT_LOCAL_IP "10.0.2.15"
+//# else
+# define DEFAULT_LOCAL_IP TNET_SOCKET_HOST_ANY
+//# endif
+#endif
+
+SipStack::SipStack(SipCallback* callback_, const char* realm_uri, const char* impi_uri, const char* impu_uri)
+:SafeObject()
+{
+ this->debugCallback = tsk_null;
+ this->callback = callback_;
+
+ /* Initialize network layer */
+ if(SipStack::count == 0){
+ tdav_init();
+ tnet_startup();
+ }
+
+ /* Creates stack handle */
+ this->handle = tsip_stack_create(stack_callback, realm_uri, impi_uri, impu_uri,
+ TSIP_STACK_SET_LOCAL_IP(DEFAULT_LOCAL_IP),
+ TSIP_STACK_SET_USERDATA(this), /* used as context (useful for server-initiated requests) */
+ TSIP_STACK_SET_NULL());
+
+ SipStack::count++;
+}
+
+SipStack::~SipStack()
+{
+ this->stop();
+
+ /* Destroy stack handle */
+ TSK_OBJECT_SAFE_FREE(this->handle);
+
+ /* DeInitialize the network layer (only if last stack) */
+ if(--SipStack::count == 0){
+ tdav_deinit();
+ tnet_cleanup();
+ }
+}
+
+bool SipStack::start()
+{
+ return (tsip_stack_start(this->handle) == 0);
+}
+
+bool SipStack::setDebugCallback(DDebugCallback* callback)
+{
+ if(this && callback){
+ this->debugCallback = callback;
+ tsk_debug_set_arg_data(this);
+ tsk_debug_set_info_cb(DDebugCallback::debug_info_cb);
+ tsk_debug_set_warn_cb(DDebugCallback::debug_warn_cb);
+ tsk_debug_set_error_cb(DDebugCallback::debug_error_cb);
+ tsk_debug_set_fatal_cb(DDebugCallback::debug_fatal_cb);
+ }
+ else if(this){
+ this->debugCallback = tsk_null;
+ tsk_debug_set_arg_data(tsk_null);
+ tsk_debug_set_info_cb(tsk_null);
+ tsk_debug_set_warn_cb(tsk_null);
+ tsk_debug_set_error_cb(tsk_null);
+ tsk_debug_set_fatal_cb(tsk_null);
+ }
+
+ return true;
+}
+
+bool SipStack::setRealm(const char* realm_uri)
+{
+ int ret = tsip_stack_set(this->handle,
+ TSIP_STACK_SET_REALM(realm_uri),
+ TSIP_STACK_SET_NULL());
+ return (ret == 0);
+}
+
+bool SipStack::setIMPI(const char* impi)
+{
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_IMPI(impi),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::setIMPU(const char* impu_uri)
+{
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_IMPU(impu_uri),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::setPassword(const char* password)
+{
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_PASSWORD(password),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::setAMF(const char* amf)
+{
+ uint16_t _amf = (uint16_t)tsk_atox(amf);
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_IMS_AKA_AMF(_amf),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::setOperatorId(const char* opid)
+{
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_IMS_AKA_OPERATOR_ID(opid),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::setProxyCSCF(const char* fqdn, unsigned short port, const char* transport, const char* ipversion)
+{
+ unsigned _port = port;//promote
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_PROXY_CSCF(fqdn, _port, transport, ipversion),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::setLocalIP(const char* ip)
+{
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_LOCAL_IP(ip),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::setLocalPort(unsigned short port)
+{
+ unsigned _port = port;//promote
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_LOCAL_PORT(_port),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::setEarlyIMS(bool enabled){
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_EARLY_IMS(enabled? tsk_true : tsk_false),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::addHeader(const char* name, const char* value)
+{
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_HEADER(name, value),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::removeHeader(const char* name)
+{
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_UNSET_HEADER(name),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::addDnsServer(const char* ip)
+{
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_DNS_SERVER(ip),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::setDnsDiscovery(bool enabled)
+{
+ tsk_bool_t _enabled = enabled;// 32bit/64bit workaround
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_DISCOVERY_NAPTR(_enabled),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::setAoR(const char* ip, int port)
+{
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_AOR(ip, port),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::setModeServer()
+{
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_MODE_SERVER(),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::setSigCompParams(unsigned dms, unsigned sms, unsigned cpb, bool enablePresDict)
+{
+ tsk_bool_t _enablePresDict= enablePresDict;// 32bit/64bit workaround
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_SIGCOMP(dms, sms, cpb, _enablePresDict),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::addSigCompCompartment(const char* compId)
+{
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_SIGCOMP_NEW_COMPARTMENT(compId),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::removeSigCompCompartment(const char* compId)
+{
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_UNSET_SIGCOMP_COMPARTMENT(compId),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::setSTUNServer(const char* ip, unsigned short port)
+{
+ unsigned _port = port;//promote
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_STUN_SERVER(ip, _port),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::setSTUNCred(const char* login, const char* password)
+{
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_STUN_CRED(login, password),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::setTLSSecAgree(bool enabled)
+{
+ tsk_bool_t _enable = enabled;
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_SECAGREE_TLS(_enable),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::setSSLCretificates(const char* privKey, const char* pubKey, const char* caKey)
+{
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_TLS_CERTS(caKey, pubKey, privKey),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::setIPSecSecAgree(bool enabled)
+{
+ tsk_bool_t _enable = enabled;
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_SECAGREE_IPSEC(_enable),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+bool SipStack::setIPSecParameters(const char* algo, const char* ealgo, const char* mode, const char* proto)
+{
+ return (tsip_stack_set(this->handle,
+ TSIP_STACK_SET_IPSEC_PARAMS(algo, ealgo, mode, proto),
+ TSIP_STACK_SET_NULL()) == 0);
+}
+
+char* SipStack::dnsENUM(const char* service, const char* e164num, const char* domain)
+{
+ tnet_dns_ctx_t* dnsctx = tsip_stack_get_dnsctx(this->handle);
+ char* uri = tsk_null;
+
+ if(dnsctx){
+ if(!(uri = tnet_dns_enum_2(dnsctx, service, e164num, domain))){
+ TSK_DEBUG_ERROR("ENUM(%s) failed", e164num);
+ }
+ tsk_object_unref(dnsctx);
+ return uri;
+ }
+ else{
+ TSK_DEBUG_ERROR("No DNS Context could be found");
+ return tsk_null;
+ }
+}
+
+char* SipStack::dnsNaptrSrv(const char* domain, const char* service, unsigned short *OUTPUT)
+{
+ tnet_dns_ctx_t* dnsctx = tsip_stack_get_dnsctx(this->handle);
+ char* ip = tsk_null;
+ tnet_port_t port;
+ *OUTPUT = 0;
+
+
+ if(dnsctx){
+ if(!tnet_dns_query_naptr_srv(dnsctx, domain, service, &ip, &port)){
+ *OUTPUT = port;
+ }
+ tsk_object_unref(dnsctx);
+ return ip;
+ }
+ else{
+ TSK_DEBUG_ERROR("No DNS Context could be found");
+ return tsk_null;
+ }
+}
+
+char* SipStack::dnsSrv(const char* service, unsigned short* OUTPUT)
+{
+ tnet_dns_ctx_t* dnsctx = tsip_stack_get_dnsctx(this->handle);
+ char* ip = tsk_null;
+ tnet_port_t port = 0;
+ *OUTPUT = 0;
+
+ if(dnsctx){
+ if(!tnet_dns_query_srv(dnsctx, service, &ip, &port)){
+ *OUTPUT = port;
+ }
+ tsk_object_unref(dnsctx);
+ return ip;
+ }
+ else{
+ TSK_DEBUG_ERROR("No DNS Context could be found");
+ return tsk_null;
+ }
+}
+
+char* SipStack::getLocalIPnPort(const char* protocol, unsigned short* OUTPUT)
+{
+ tnet_ip_t ip;
+ tnet_port_t port;
+ int ret;
+
+ if(!OUTPUT || !protocol){
+ TSK_DEBUG_ERROR("invalid parameter");
+ return tsk_null;
+ }
+
+ if((ret = tsip_stack_get_local_ip_n_port(this->handle, protocol, &port, &ip))){
+ TSK_DEBUG_ERROR("Failed to get local ip and port with error code=%d", ret);
+ return tsk_null;
+ }
+
+ *OUTPUT = port;
+ return tsk_strdup(ip); // See Swig %newobject
+}
+
+char* SipStack::getPreferredIdentity()
+{
+ tsip_uri_t* ppid = tsip_stack_get_preferred_id(this->handle);
+ char* str_ppid = tsk_null;
+ if(ppid){
+ str_ppid = tsip_uri_tostring(ppid, tsk_false, tsk_false);
+ TSK_OBJECT_SAFE_FREE(ppid);
+ }
+ return str_ppid;
+}
+
+bool SipStack::isValid()
+{
+ return (this->handle != tsk_null);
+}
+
+bool SipStack::stop()
+{
+ int ret = tsip_stack_stop(this->handle);
+ return (ret == 0);
+}
+
+void SipStack::setCodecs(tdav_codec_id_t codecs)
+{
+ tdav_set_codecs(codecs);
+}
+
+void SipStack::setCodecs_2(int codecs) // For stupid languages
+{
+ tdav_set_codecs((tdav_codec_id_t)codecs);
+}
+
+bool SipStack::isCodecSupported(tdav_codec_id_t codec)
+{
+ return tdav_codec_is_supported(codec) ? true : false;
+}
+
+int stack_callback(const tsip_event_t *sipevent)
+{
+ int ret = 0;
+ const SipStack* Stack = tsk_null;
+ SipEvent* e = tsk_null;
+
+ if(!sipevent){ /* should never happen ...but who know? */
+ TSK_DEBUG_WARN("Null SIP event.");
+ return -1;
+ }
+ else {
+ if(sipevent->type == tsip_event_stack && sipevent->userdata){
+ /* sessionless event */
+ Stack = dyn_cast<const SipStack*>((const SipStack*)sipevent->userdata);
+ }
+ else {
+ const void* userdata;
+ /* gets the stack from the session */
+ const tsip_stack_handle_t* stack_handle = tsip_ssession_get_stack(sipevent->ss);
+ if(stack_handle && (userdata = tsip_stack_get_userdata(stack_handle))){
+ Stack = dyn_cast<const SipStack*>((const SipStack*)userdata);
+ }
+ }
+ }
+
+ if(!Stack){
+ TSK_DEBUG_WARN("Invalid SIP event (Stack is Null).");
+ return -2;
+ }
+
+ Stack->Lock();
+
+ switch(sipevent->type){
+ case tsip_event_register:
+ { /* REGISTER */
+ if(Stack->getCallback()){
+ e = new RegistrationEvent(sipevent);
+ Stack->getCallback()->OnRegistrationEvent((const RegistrationEvent*)e);
+ }
+ break;
+ }
+ case tsip_event_invite:
+ { /* INVITE */
+ if(Stack->getCallback()){
+ e = new InviteEvent(sipevent);
+ Stack->getCallback()->OnInviteEvent((const InviteEvent*)e);
+ }
+ break;
+ }
+ case tsip_event_message:
+ { /* MESSAGE */
+ if(Stack->getCallback()){
+ e = new MessagingEvent(sipevent);
+ Stack->getCallback()->OnMessagingEvent((const MessagingEvent*)e);
+ }
+ break;
+ }
+ case tsip_event_options:
+ { /* OPTIONS */
+ if(Stack->getCallback()){
+ e = new OptionsEvent(sipevent);
+ Stack->getCallback()->OnOptionsEvent((const OptionsEvent*)e);
+ }
+ break;
+ }
+ case tsip_event_publish:
+ { /* PUBLISH */
+ if(Stack->getCallback()){
+ e = new PublicationEvent(sipevent);
+ Stack->getCallback()->OnPublicationEvent((const PublicationEvent*)e);
+ }
+ break;
+ }
+ case tsip_event_subscribe:
+ { /* SUBSCRIBE */
+ if(Stack->getCallback()){
+ e = new SubscriptionEvent(sipevent);
+ Stack->getCallback()->OnSubscriptionEvent((const SubscriptionEvent*)e);
+ }
+ break;
+ }
+
+ case tsip_event_dialog:
+ { /* Common to all dialogs */
+ if(Stack->getCallback()){
+ e = new DialogEvent(sipevent);
+ Stack->getCallback()->OnDialogEvent((const DialogEvent*)e);
+ }
+ break;
+ }
+
+ case tsip_event_stack:
+ { /* Stack event */
+ if(Stack->getCallback()){
+ e = new StackEvent(sipevent);
+ Stack->getCallback()->OnStackEvent((const StackEvent*)e);
+ }
+ break;
+ }
+
+ default:
+ { /* Unsupported */
+ TSK_DEBUG_WARN("%d not supported as SIP event.", sipevent->type);
+ ret = -3;
+ break;
+ }
+ }
+
+ Stack->UnLock();
+
+ if(e){
+ delete e;
+ }
+
+ return ret;
+}
+
diff --git a/bindings/_common/SipStack.h b/bindings/_common/SipStack.h
new file mode 100644
index 0000000..bba308e
--- /dev/null
+++ b/bindings/_common/SipStack.h
@@ -0,0 +1,109 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#ifndef TINYWRAP_SIPSTACK_H
+#define TINYWRAP_SIPSTACK_H
+
+#include "SipCallback.h"
+#include "SafeObject.h"
+
+#include "tinydav/tdav.h"
+#include "tinysip.h"
+
+class DDebugCallback;
+
+class SipStack: public SafeObject
+{
+public: /* ctor() and dtor() */
+ SipStack(SipCallback* callback, const char* realm_uri, const char* impi_uri, const char* impu_uri);
+ ~SipStack();
+
+public: /* API functions */
+ bool start();
+ bool setDebugCallback(DDebugCallback* callback);
+ bool setRealm(const char* realm_uri);
+ bool setIMPI(const char* impi);
+ bool setIMPU(const char* impu_uri);
+ bool setPassword(const char* password);
+ bool setAMF(const char* amf);
+ bool setOperatorId(const char* opid);
+ bool setProxyCSCF(const char* fqdn, unsigned short port, const char* transport, const char* ipversion);
+ bool setLocalIP(const char* ip);
+ bool setLocalPort(unsigned short port);
+ bool setEarlyIMS(bool enabled);
+ bool addHeader(const char* name, const char* value);
+ bool removeHeader(const char* name);
+ bool addDnsServer(const char* ip);
+ bool setDnsDiscovery(bool enabled);
+ bool setAoR(const char* ip, int port);
+#if !defined(SWIG)
+ bool setModeServer();
+#endif
+
+ bool setSigCompParams(unsigned dms, unsigned sms, unsigned cpb, bool enablePresDict);
+ bool addSigCompCompartment(const char* compId);
+ bool removeSigCompCompartment(const char* compId);
+
+ bool setSTUNServer(const char* ip, unsigned short port);
+ bool setSTUNCred(const char* login, const char* password);
+
+ bool setTLSSecAgree(bool enabled);
+ bool setSSLCretificates(const char* privKey, const char* pubKey, const char* caKey);
+ bool setIPSecSecAgree(bool enabled);
+ bool setIPSecParameters(const char* algo, const char* ealgo, const char* mode, const char* proto);
+
+ char* dnsENUM(const char* service, const char* e164num, const char* domain);
+ char* dnsNaptrSrv(const char* domain, const char* service, unsigned short *OUTPUT);
+ char* dnsSrv(const char* service, unsigned short* OUTPUT);
+
+ char* getLocalIPnPort(const char* protocol, unsigned short* OUTPUT);
+
+ char* getPreferredIdentity();
+
+ bool isValid();
+ bool stop();
+
+ static void setCodecs(tdav_codec_id_t codecs);
+ static void setCodecs_2(int codecs); // For stupid languages
+ static bool isCodecSupported(tdav_codec_id_t codec);
+
+public: /* Public helper function */
+#if !defined(SWIG)
+ inline tsip_stack_handle_t* getHandle()const{
+ return this->handle;
+ }
+ inline SipCallback* getCallback()const{
+ return this->callback;
+ }
+ inline DDebugCallback* getDebugCallback() const{
+ return this->debugCallback;
+ }
+#endif
+
+private:
+ SipCallback* callback;
+ DDebugCallback* debugCallback;
+ tsip_stack_handle_t *handle;
+
+ static unsigned count;
+};
+
+#endif /* TINYWRAP_SIPSTACK_H */
diff --git a/bindings/_common/SipStack.i b/bindings/_common/SipStack.i
new file mode 100644
index 0000000..9e9b633
--- /dev/null
+++ b/bindings/_common/SipStack.i
@@ -0,0 +1,258 @@
+
+%{
+#include "ActionConfig.h"
+#include "MediaSessionMgr.h"
+#include "MediaContent.h"
+#include "SipUri.h"
+#include "SipMessage.h"
+#include "SipEvent.h"
+#include "SipSession.h"
+
+#include "ProxyPluginMgr.h"
+#include "ProxyConsumer.h"
+#include "ProxyProducer.h"
+
+#include "SipCallback.h"
+#include "SafeObject.h"
+#include "SipStack.h"
+%}
+
+/* Callbacks */
+%feature("director") SipCallback;
+%feature("director") ProxyPluginMgrCallback;
+%feature("director") ProxyAudioConsumerCallback;
+%feature("director") ProxyVideoConsumerCallback;
+%feature("director") ProxyAudioProducerCallback;
+%feature("director") ProxyVideoProducerCallback;
+
+
+%nodefaultctor;
+%include "ActionConfig.h"
+%include "MediaSessionMgr.h"
+%include "MediaContent.h"
+%include "SipUri.h"
+%include "SipMessage.h"
+%include "SipEvent.h"
+%include "SipSession.h"
+
+%include "ProxyPluginMgr.h"
+%include "ProxyConsumer.h"
+%include "ProxyProducer.h"
+
+%include "SipCallback.h"
+%include "SafeObject.h"
+%include "SipStack.h"
+%clearnodefaultctor;
+
+
+
+
+
+/* ====== From "tinySIP\include\tinysip\tsip_event.h" ====== */
+typedef enum tsip_event_type_e
+{
+ tsip_event_invite,
+ tsip_event_message,
+ tsip_event_options,
+ tsip_event_publish,
+ tsip_event_register,
+ tsip_event_subscribe,
+
+ tsip_event_dialog
+}
+tsip_event_type_t;
+
+// 7xx ==> errors
+#define tsip_event_code_dialog_transport_error 702
+#define tsip_event_code_dialog_global_error 703
+#define tsip_event_code_dialog_message_error 704
+
+// 8xx ==> success
+#define tsip_event_code_dialog_request_incoming 800
+#define tsip_event_code_dialog_request_cancelled 801
+#define tsip_event_code_dialog_request_sent 802
+
+// 9xx ==> Informational
+#define tsip_event_code_dialog_connecting 900
+#define tsip_event_code_dialog_connected 901
+#define tsip_event_code_dialog_terminating 902
+#define tsip_event_code_dialog_terminated 903
+#define tsip_event_code_stack_started 950
+#define tsip_event_code_stack_stopped 951
+#define tsip_event_code_stack_failed_to_start 952
+#define tsip_event_code_stack_failed_to_stop 953
+
+/* ====== From "tinySIP\include\tinysip\tsip_api_register.h" ====== */
+typedef enum tsip_register_event_type_e
+{
+ tsip_i_newreg,
+
+ tsip_i_register, // refresh
+ tsip_ao_register,
+
+ tsip_i_unregister,
+ tsip_ao_unregister,
+}
+tsip_register_event_type_t;
+
+/* ====== From "tinySIP\include\tinysip\tsip_api_subscribe.h" ====== */
+typedef enum tsip_subscribe_event_type_e
+{
+ tsip_i_subscribe,
+ tsip_ao_subscribe,
+
+ tsip_i_unsubscribe,
+ tsip_ao_unsubscribe,
+
+ tsip_i_notify,
+ tsip_ao_notify
+}
+tsip_subscribe_event_type_t;
+
+/* ====== From "tinySIP\include\tinysip\tsip_api_publish.h" ====== */
+typedef enum tsip_publish_event_type_e
+{
+ tsip_i_publish,
+ tsip_ao_publish,
+
+ tsip_i_unpublish,
+ tsip_ao_unpublish
+}
+tsip_publish_event_type_t;
+
+/* ====== From "tinySIP\include\tinysip\tsip_api_message.h" ====== */
+typedef enum tsip_message_event_type_e
+{
+ tsip_i_message,
+ tsip_ao_message,
+}
+tsip_message_event_type_t;
+
+/* ====== From "tinySIP\include\tinysip\tsip_api_options.h" ====== */
+typedef enum tsip_options_event_type_e
+{
+ tsip_i_options,
+ tsip_ao_options,
+}
+tsip_options_event_type_t;
+
+
+/* ====== From "tinySIP\include\tinysip\tsip_api_invite.h" ====== */
+typedef enum tsip_invite_event_type_e
+{
+ // ============================
+ // Sip Events
+ //
+ tsip_i_newcall,
+
+ //! in-dialog requests/reponses
+ tsip_i_request,
+ tsip_ao_request,
+
+ /* Explicit Call Transfer (ECT) */
+ tsip_o_ect_ok,
+ tsip_o_ect_nok,
+ tsip_i_ect,
+
+ // ============================
+ // Media Events
+ //
+
+ tsip_m_early_media,
+
+ /* 3GPP TS 24.610: Communication Hold */
+ tsip_m_local_hold_ok,
+ tsip_m_local_hold_nok,
+ tsip_m_local_resume_ok,
+ tsip_m_local_resume_nok,
+ tsip_m_remote_hold,
+ tsip_m_remote_resume,
+}
+tsip_invite_event_type_t;
+
+
+
+/* ====== From "tinymedia/tmedia_common.h" ====== */
+// used by tinyWRAP
+typedef enum tmedia_chroma_e
+{
+ tmedia_rgb24, // will be stored as bgr24 on x86 (little endians) machines; e.g. WindowsPhone7
+ tmedia_bgr24, // used by windows consumer (DirectShow) -
+ tmedia_rgb32, // used by iOS4 consumer (iPhone and iPod touch)
+ tmedia_rgb565le, // (used by both android and wince consumers)
+ tmedia_rgb565be,
+ tmedia_nv12, // used by iOS4 producer (iPhone and iPod Touch 3GS and 4)
+ tmedia_nv21, // Yuv420 SP (used by android producer)
+ tmedia_yuv422p,
+ tmedia_uyvy422, // used by iOS4 producer (iPhone and iPod Touch 3G)
+ tmedia_yuv420p, // Default
+}
+tmedia_chroma_t;
+
+/* ====== From "tinymedia/tmedia_qos.h" ====== */
+typedef enum tmedia_qos_stype_e
+{
+ tmedia_qos_stype_none,/* not part of the RFC */
+
+ tmedia_qos_stype_segmented,
+ tmedia_qos_stype_e2e,
+}
+tmedia_qos_stype_t;
+
+/* ====== From "tinymedia/tmedia_qos.h" ====== */
+typedef enum tmedia_qos_strength_e
+{
+ /* do no change the order (none -> optional -> manadatory) */
+ tmedia_qos_strength_none,
+ tmedia_qos_strength_failure,
+ tmedia_qos_strength_unknown,
+ tmedia_qos_strength_optional,
+ tmedia_qos_strength_mandatory
+}
+tmedia_qos_strength_t;
+
+/* ====== From "tinymedia/tmedia_common.h" ====== */
+typedef enum tmedia_bandwidth_level_e
+{
+ tmedia_bl_low,
+ tmedia_bl_medium,
+ tmedia_bl_hight
+}
+tmedia_bandwidth_level_t;
+
+
+/* ====== From "tinydav/tdav.h" ====== */
+typedef enum tdav_codec_id_e
+{
+ tdav_codec_id_none = 0x00000000,
+
+ tdav_codec_id_amr_nb_oa = 0x00000001<<0,
+ tdav_codec_id_amr_nb_be = 0x00000001<<1,
+ tdav_codec_id_amr_wb_oa = 0x00000001<<2,
+ tdav_codec_id_amr_wb_be = 0x00000001<<3,
+ tdav_codec_id_gsm = 0x00000001<<4,
+ tdav_codec_id_pcma = 0x00000001<<5,
+ tdav_codec_id_pcmu = 0x00000001<<6,
+ tdav_codec_id_ilbc = 0x00000001<<7,
+ tdav_codec_id_speex_nb = 0x00000001<<8,
+ tdav_codec_id_speex_wb = 0x00000001<<9,
+ tdav_codec_id_speex_uwb = 0x00000001<<10,
+ tdav_codec_id_bv16 = 0x00000001<<11,
+ tdav_codec_id_bv32 = 0x00000001<<12,
+ tdav_codec_id_evrc = 0x00000001<<13,
+ tdav_codec_id_g729ab = 0x00000001<<14,
+
+ /* room for new Audio codecs */
+
+ tdav_codec_id_h261 = 0x00010000<<0,
+ tdav_codec_id_h263 = 0x00010000<<1,
+ tdav_codec_id_h263p = 0x00010000<<2,
+ tdav_codec_id_h263pp = 0x00010000<<3,
+ tdav_codec_id_h264_bp10 = 0x00010000<<4,
+ tdav_codec_id_h264_bp20 = 0x00010000<<5,
+ tdav_codec_id_h264_bp30 = 0x00010000<<6,
+ tdav_codec_id_theora = 0x00010000<<7,
+ tdav_codec_id_mp4ves_es = 0x00010000<<8,
+
+}
+tdav_codec_id_t; \ No newline at end of file
diff --git a/bindings/_common/SipUri.cxx b/bindings/_common/SipUri.cxx
new file mode 100644
index 0000000..1508d11
--- /dev/null
+++ b/bindings/_common/SipUri.cxx
@@ -0,0 +1,93 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#include "SipUri.h"
+
+SipUri::SipUri(const char* uristring)
+{
+ this->uri = tsip_uri_parse(uristring, tsk_strlen(uristring));
+}
+
+SipUri::~SipUri()
+{
+ TSK_OBJECT_SAFE_FREE(this->uri);
+}
+
+bool SipUri::isValid(const char* uriString)
+{
+ tsip_uri_t* _uri;
+ bool ret = false;
+
+ if((_uri = tsip_uri_parse(uriString, tsk_strlen(uriString)))){
+ ret = (_uri->type != uri_unknown)
+ && (!tsk_strnullORempty(_uri->host));
+ TSK_OBJECT_SAFE_FREE(_uri);
+ }
+ return ret;
+}
+
+bool SipUri::isValid()
+{
+ return (this->uri != tsk_null);
+}
+
+const char* SipUri::getScheme()
+{
+ if(this->uri){
+ return this->uri->scheme;
+ }
+ return tsk_null;
+}
+
+const char* SipUri::getHost()
+{
+ return this->uri ? this->uri->host : tsk_null;
+}
+
+unsigned short SipUri::getPort()
+{
+ return this->uri ? this->uri->port : 0;
+}
+
+const char* SipUri::getUserName()
+{
+ return this->uri ? this->uri->user_name : tsk_null;
+}
+
+const char* SipUri::getPassword()
+{
+ return this->uri ? this->uri->password : tsk_null;
+}
+
+const char* SipUri::getDisplayName()
+{
+ return this->uri ? this->uri->display_name : tsk_null;
+}
+
+const char* SipUri::getParamValue(const char* pname)
+{
+ if(this->uri && this->uri->params){
+ const char* pvalue = tsk_params_get_param_value(this->uri->params, pname);
+ return pvalue;
+ }
+ return tsk_null;
+}
+
diff --git a/bindings/_common/SipUri.h b/bindings/_common/SipUri.h
new file mode 100644
index 0000000..e4a9727
--- /dev/null
+++ b/bindings/_common/SipUri.h
@@ -0,0 +1,49 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#ifndef TINYWRAP_SIPURI_H
+#define TINYWRAP_SIPURI_H
+
+#include "tinysip.h"
+
+class SipUri
+{
+public:
+ SipUri(const char*);
+ ~SipUri();
+
+public:
+ static bool isValid(const char*);
+
+ bool isValid();
+ const char* getScheme();
+ const char* getHost();
+ unsigned short getPort();
+ const char* getUserName();
+ const char* getPassword();
+ const char* getDisplayName();
+ const char* getParamValue(const char* pname);
+
+private:
+ tsip_uri_t* uri;
+};
+
+#endif /* TINYWRAP_SIPURI_H */
diff --git a/bindings/_common/Xcap.cxx b/bindings/_common/Xcap.cxx
new file mode 100644
index 0000000..c459179
--- /dev/null
+++ b/bindings/_common/Xcap.cxx
@@ -0,0 +1,564 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#include "Xcap.h"
+
+#include "Common.h"
+
+unsigned XcapStack::count = 0;
+
+/* === ANSI-C functions (local use) === */
+static int stack_callback(const thttp_event_t *httpevent);
+
+/* =================================== XCAP Event ==================================== */
+typedef enum twrap_xcap_step_type_e
+{
+ txst_name,
+ txst_pos,
+ txst_att,
+ txst_pos_n_att,
+ txst_ns
+}
+twrap_xcap_step_type_t;
+
+typedef struct twrap_xcap_step_s
+{
+ TSK_DECLARE_OBJECT;
+
+ twrap_xcap_step_type_t type;
+ char* qname;
+ char* att_qname;
+ char* att_value;
+ unsigned pos;
+ struct{
+ char* prefix;
+ char* value;
+ } ns;
+}
+twrap_xcap_step_t;
+
+static tsk_object_t* twrap_xcap_step_ctor(tsk_object_t * self, va_list * app)
+{
+ twrap_xcap_step_t *step = (twrap_xcap_step_t *)self;
+ if(step){
+ }
+ return self;
+}
+
+static tsk_object_t* twrap_xcap_step_dtor(tsk_object_t * self)
+{
+ twrap_xcap_step_t *step = (twrap_xcap_step_t *)self;
+ if(step){
+ TSK_FREE(step->qname);
+ TSK_FREE(step->att_qname);
+ TSK_FREE(step->att_value);
+ TSK_FREE(step->ns.prefix);
+ TSK_FREE(step->ns.value);
+ }
+
+ return self;
+}
+
+static const tsk_object_def_t twrap_xcap_step_def_s =
+{
+ sizeof(twrap_xcap_step_t),
+ twrap_xcap_step_ctor,
+ twrap_xcap_step_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *twrap_xcap_step_def_t = &twrap_xcap_step_def_s;
+
+twrap_xcap_step_t* twrap_xcap_step_create(twrap_xcap_step_type_t type){
+ twrap_xcap_step_t* step;
+ if((step = (twrap_xcap_step_t*)tsk_object_new(twrap_xcap_step_def_t))){
+ step->type = type;
+ }
+ return step;
+}
+
+XcapSelector::XcapSelector(XcapStack* stack)
+: auid(tsk_null)
+{
+ if(stack){
+ this->stack_handle = tsk_object_ref(stack->getHandle());
+ }
+ this->steps = tsk_list_create();
+}
+
+
+XcapSelector* XcapSelector::setAUID(const char* auid)
+{
+ tsk_strupdate(&this->auid, auid);
+ return this;
+}
+
+XcapSelector* XcapSelector::setName(const char* qname)
+{
+ twrap_xcap_step_t* step;
+ if((step = twrap_xcap_step_create(txst_name))){
+ step->qname = tsk_strdup(qname);
+ tsk_list_push_back_data(this->steps, (void**)&step);
+ }
+ return this;
+}
+
+XcapSelector* XcapSelector::setAttribute(const char* qname, const char* att_qname, const char* att_value)
+{
+ twrap_xcap_step_t* step;
+ if((step = twrap_xcap_step_create(txst_att))){
+ step->qname = tsk_strdup(qname);
+ step->att_qname = tsk_strdup(att_qname);
+ step->att_value = tsk_strdup(att_value);
+ tsk_list_push_back_data(this->steps, (void**)&step);
+ }
+ return this;
+}
+
+XcapSelector* XcapSelector::setPos(const char* qname, unsigned pos)
+{
+ twrap_xcap_step_t* step;
+ if((step = twrap_xcap_step_create(txst_pos))){
+ step->qname = tsk_strdup(qname);
+ step->pos = pos;
+ tsk_list_push_back_data(this->steps, (void**)&step);
+ }
+ return this;
+}
+
+XcapSelector* XcapSelector::setPosAttribute(const char* qname, unsigned pos, const char* att_qname, const char* att_value)
+{
+ twrap_xcap_step_t* step;
+ if((step = twrap_xcap_step_create(txst_pos))){
+ step->qname = tsk_strdup(qname);
+ step->pos = pos;
+ step->att_qname = tsk_strdup(att_qname);
+ step->att_value = tsk_strdup(att_value);
+ tsk_list_push_back_data(this->steps, (void**)&step);
+ }
+ return this;
+}
+
+XcapSelector* XcapSelector::setNamespace(const char* prefix, const char* value)
+{
+ twrap_xcap_step_t* step;
+ if((step = twrap_xcap_step_create(txst_ns))){
+ step->ns.prefix = tsk_strdup(prefix);
+ step->ns.value = tsk_strdup(value);
+ tsk_list_push_back_data(this->steps, (void**)&step);
+ }
+ return this;
+}
+
+/* From tinyXCAP::txcap_selector_get_node_2() */
+char* XcapSelector::getString()
+{
+ char* node = tsk_null;
+ char* temp = tsk_null;
+ char* _namespace = tsk_null;
+ tsk_buffer_t* buffer = tsk_buffer_create_null();
+ const tsk_list_item_t* item;
+ const twrap_xcap_step_t* step;
+
+ /* Node */
+ tsk_list_foreach(item, this->steps){
+ step = (twrap_xcap_step_t*)item->data;
+ switch(step->type){
+ case txst_name:
+ if(tsk_buffer_append_2(buffer, "/%s", step->qname)){
+ goto bail;
+ }
+ break;
+
+ case txst_pos:
+ tsk_buffer_append_2(buffer, "/%s%%5B%u%%5D",
+ step->att_qname, step->pos);
+ break;
+
+ case txst_att:
+ tsk_buffer_append_2(buffer, "/%s%%5B@%s=%%22%s%%22%%5D",
+ step->qname, step->att_qname, step->att_value);
+ break;
+
+ case txst_pos_n_att:
+ tsk_buffer_append_2(buffer, "/%s%%5B%u%%5D%%5B@%s=%%22%s%%22%%5D",
+ step->qname, step->pos, step->att_qname, step->att_value);
+ break;
+
+ case txst_ns:
+ tsk_sprintf(&temp, "%sxmlns(%s=%%22%s%%22)",
+ _namespace?"":"%3F", step->ns.prefix, step->ns.value);
+ tsk_strcat(&_namespace, temp);
+ TSK_FREE(temp);
+ break;
+
+
+ } /* switch */
+ } /* for */
+
+ /* append the namespace */
+ if(_namespace){
+ tsk_buffer_append(buffer, _namespace, strlen(_namespace));
+ TSK_FREE(_namespace);
+ }
+
+bail:
+ if(TSK_BUFFER_DATA(buffer) && TSK_BUFFER_SIZE(buffer)){
+ node = tsk_strndup((const char*)TSK_BUFFER_DATA(buffer), TSK_BUFFER_SIZE(buffer));
+ }
+ TSK_OBJECT_SAFE_FREE(buffer);
+
+
+ /* Document */
+ if(this->auid){
+ char* document;
+ if((document = txcap_selector_get_document(this->stack_handle, this->auid))){
+ if(node){
+ tsk_strcat_2(&document, "/~~/%s%s", this->auid, node);
+ TSK_FREE(node);
+ }
+ return document;
+ }
+ }
+
+ return node;
+}
+
+void XcapSelector::reset()
+{
+ TSK_FREE(this->auid);
+ tsk_list_clear_items(this->steps);
+}
+
+XcapSelector::~XcapSelector()
+{
+ this->reset();
+ TSK_OBJECT_SAFE_FREE(this->steps);
+
+ tsk_object_unref(this->stack_handle);
+}
+
+/* =================================== XCAP Message ==================================== */
+XcapMessage::XcapMessage() :
+httpmessage(tsk_null)
+{
+}
+
+XcapMessage::XcapMessage(const thttp_message_t *_httpmessage)
+{
+ this->httpmessage = _httpmessage;
+}
+
+XcapMessage::~XcapMessage()
+{
+}
+
+short XcapMessage::getCode() const
+{
+ if(this->httpmessage){
+ return this->httpmessage->line.response.status_code;
+ }
+ return 0;
+}
+
+const char* XcapMessage::getPhrase() const
+{
+ if(this->httpmessage){
+ return this->httpmessage->line.response.reason_phrase;
+ }
+ return tsk_null;
+}
+
+char* XcapMessage::getXcapHeaderValue(const char* name, unsigned index /*= 0*/)
+{
+ const thttp_header_t* header;
+ if((header = thttp_message_get_headerByName(this->httpmessage, name))){
+ return thttp_header_value_tostring(header);
+ }
+ return tsk_null;
+}
+
+char* XcapMessage::getXcapHeaderParamValue(const char* name, const char* pname, unsigned index /*= 0*/)
+{
+ const thttp_header_t* header;
+ if((header = thttp_message_get_headerByName(this->httpmessage, name))){
+ const tsk_param_t* param;
+ if((param = tsk_params_get_param_by_name(header->params, pname))){
+ return tsk_strdup(param->value);
+ }
+ }
+ return tsk_null;
+}
+
+unsigned XcapMessage::getXcapContentLength()
+{
+ if(this->httpmessage && this->httpmessage->Content){
+ return this->httpmessage->Content->size;
+ }
+ return 0;
+}
+
+unsigned XcapMessage::getXcapContent(void* output, unsigned maxsize)
+{
+ unsigned retsize = 0;
+ if(output && maxsize && this->httpmessage->Content){
+ retsize = (this->httpmessage->Content->size > maxsize) ? maxsize : this->httpmessage->Content->size;
+ memcpy(output, this->httpmessage->Content->data, retsize);
+ }
+ return retsize;
+}
+
+
+/* =================================== XCAP Event ==================================== */
+XcapEvent::XcapEvent(const thttp_event_t *_httpevent)
+{
+ this->httpevent = _httpevent;
+ if(_httpevent){
+ this->httpmessage = new XcapMessage(_httpevent->message);
+ }
+ else{
+ this->httpmessage = tsk_null;
+ }
+}
+
+XcapEvent::~XcapEvent()
+{
+ if(this->httpmessage){
+ delete this->httpmessage;
+ }
+}
+
+thttp_event_type_t XcapEvent::getType()
+{
+ return this->httpevent->type;
+}
+
+const XcapMessage* XcapEvent::getXcapMessage() const
+{
+ return this->httpmessage;
+}
+
+
+
+
+/* =================================== XCAP Callback ==================================== */
+XcapCallback::XcapCallback()
+{
+}
+
+XcapCallback::~XcapCallback()
+{
+}
+
+
+
+
+
+/* =================================== XCAP Stack ==================================== */
+XcapStack::XcapStack(XcapCallback* _callback, const char* xui, const char* password, const char* xcap_root)
+{
+ /* Initialize network layer */
+ if(XcapStack::count == 0){
+ tnet_startup();
+ }
+
+ this->callback = _callback;
+ this->handle = txcap_stack_create(stack_callback, xui, password, xcap_root,
+ TXCAP_STACK_SET_USERDATA(this),
+ TXCAP_STACK_SET_NULL());
+}
+
+XcapStack::~XcapStack()
+{
+ TSK_OBJECT_SAFE_FREE(this->handle);
+
+ /* DeInitialize the network layer (only if last stack) */
+ if(--XcapStack::count == 0){
+ tnet_cleanup();
+ }
+}
+
+bool XcapStack::registerAUID(const char* id, const char* mime_type, const char* ns, const char* document_name, bool is_global)
+{
+ txcap_stack_t* stack = (txcap_stack_t*)this->handle;
+ if(stack){
+ tsk_bool_t _global = is_global?tsk_true:tsk_false; // 32bit <-> 64bit workaround
+ return (txcap_auid_register(stack->auids, id, mime_type, ns, document_name, _global) == 0);
+ }
+ return false;
+}
+
+bool XcapStack::start()
+{
+ return (txcap_stack_start(this->handle) == 0);
+}
+
+bool XcapStack::setCredentials(const char* xui, const char* password)
+{
+ return txcap_stack_set(this->handle,
+ TXCAP_STACK_SET_XUI(xui),
+ TXCAP_STACK_SET_PASSWORD(password),
+ TXCAP_STACK_SET_NULL()) == 0;
+}
+
+bool XcapStack::setXcapRoot(const char* xcap_root)
+{
+ return txcap_stack_set(this->handle,
+ TXCAP_STACK_SET_ROOT(xcap_root),
+ TXCAP_STACK_SET_NULL()) == 0;
+}
+
+bool XcapStack::setLocalIP(const char* ip)
+{
+ return txcap_stack_set(this->handle,
+ TXCAP_STACK_SET_LOCAL_IP(ip),
+ TXCAP_STACK_SET_NULL()) == 0;
+}
+
+bool XcapStack::setLocalPort(unsigned port)
+{
+ tsk_istr_t port_str;
+ tsk_itoa(port, &port_str);
+ return txcap_stack_set(this->handle,
+ TXCAP_STACK_SET_LOCAL_PORT(port_str),
+ TXCAP_STACK_SET_NULL()) == 0;
+}
+
+bool XcapStack::addHeader(const char* name, const char* value)
+{
+ return txcap_stack_set(this->handle,
+ TXCAP_STACK_SET_HEADER(name, value),
+ TXCAP_STACK_SET_NULL()) == 0;
+}
+
+bool XcapStack::removeHeader(const char* name)
+{
+ return txcap_stack_set(this->handle,
+ TXCAP_STACK_UNSET_HEADER(name),
+ TXCAP_STACK_SET_NULL()) == 0;
+}
+
+bool XcapStack::setTimeout(unsigned timeout)
+{
+ tsk_istr_t timeout_str;
+ tsk_itoa(timeout, &timeout_str);
+ return txcap_stack_set(this->handle,
+ TXCAP_STACK_SET_TIMEOUT(timeout_str),
+ TXCAP_STACK_SET_NULL()) == 0;
+}
+
+bool XcapStack::getDocument(const char* url)
+{
+ return txcap_action_fetch_document(this->handle,
+ TXCAP_ACTION_SET_REQUEST_URI(url),
+ TXCAP_ACTION_SET_NULL()) == 0;
+}
+
+bool XcapStack::getElement(const char* url)
+{
+ return txcap_action_fetch_element(this->handle,
+ TXCAP_ACTION_SET_REQUEST_URI(url),
+ TXCAP_ACTION_SET_NULL()) == 0;
+}
+
+bool XcapStack::getAttribute(const char* url)
+{
+ return txcap_action_fetch_attribute(this->handle,
+ TXCAP_ACTION_SET_REQUEST_URI(url),
+ TXCAP_ACTION_SET_NULL()) == 0;
+}
+
+bool XcapStack::deleteDocument(const char* url)
+{
+ return txcap_action_delete_document(this->handle,
+ TXCAP_ACTION_SET_REQUEST_URI(url),
+ TXCAP_ACTION_SET_NULL()) == 0;
+}
+
+bool XcapStack::deleteElement(const char* url)
+{
+ return txcap_action_delete_element(this->handle,
+ TXCAP_ACTION_SET_REQUEST_URI(url),
+ TXCAP_ACTION_SET_NULL()) == 0;
+}
+
+bool XcapStack::deleteAttribute(const char* url)
+{
+ return txcap_action_delete_attribute(this->handle,
+ TXCAP_ACTION_SET_REQUEST_URI(url),
+ TXCAP_ACTION_SET_NULL()) == 0;
+}
+
+
+bool XcapStack::putDocument(const char* url, const void* payload, unsigned len, const char* contentType)
+{
+ return txcap_action_create_document(this->handle,
+ TXCAP_ACTION_SET_REQUEST_URI(url),
+ TXCAP_ACTION_SET_PAYLOAD(payload, len),
+ TXCAP_ACTION_SET_HEADER("Content-Type", contentType),
+ TXCAP_ACTION_SET_NULL()) == 0;
+}
+
+bool XcapStack::putElement(const char* url, const void* payload, unsigned len)
+{
+ return txcap_action_create_element(this->handle,
+ TXCAP_ACTION_SET_REQUEST_URI(url),
+ TXCAP_ACTION_SET_PAYLOAD(payload, len),
+ TXCAP_ACTION_SET_NULL()) == 0;
+}
+
+bool XcapStack::putAttribute(const char* url, const void* payload, unsigned len)
+{
+ return txcap_action_create_attribute(this->handle,
+ TXCAP_ACTION_SET_REQUEST_URI(url),
+ TXCAP_ACTION_SET_PAYLOAD(payload, len),
+ TXCAP_ACTION_SET_NULL()) == 0;
+}
+
+
+bool XcapStack::stop()
+{
+ return (txcap_stack_stop(this->handle) == 0);
+}
+
+
+int stack_callback(const thttp_event_t *httpevent)
+{
+ int ret = 0;
+ const XcapStack* stack = tsk_null;
+ XcapEvent* e = tsk_null;
+
+ const txcap_stack_handle_t* stack_handle = thttp_session_get_userdata(httpevent->session);
+ if(!stack_handle || !(stack = dyn_cast<const XcapStack*>((const XcapStack*)stack_handle))){
+ TSK_DEBUG_ERROR("Invalid user data");
+ return -1;
+ }
+
+ if(stack->getCallback()){
+ if((e = new XcapEvent(httpevent))){
+ stack->getCallback()->onEvent(e);
+ delete e;
+ }
+ }
+ return 0;
+}
+
+
+
diff --git a/bindings/_common/Xcap.h b/bindings/_common/Xcap.h
new file mode 100644
index 0000000..786300f
--- /dev/null
+++ b/bindings/_common/Xcap.h
@@ -0,0 +1,165 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+#ifndef TINYWRAP_XCAP_H
+#define TINYWRAP_XCAP_H
+
+#include "tinyxcap.h"
+
+class XcapStack;
+
+typedef tsk_list_t twrap_xcap_steps_L_t;
+
+//
+// XcapSelector
+//
+class XcapSelector
+{
+public:
+ XcapSelector(XcapStack* stack);
+ virtual ~XcapSelector();
+
+public: /* API functions */
+ XcapSelector* setAUID(const char* auid);
+ XcapSelector* setName(const char* qname);
+ XcapSelector* setAttribute(const char* qname, const char* att_qname, const char* att_value);
+ XcapSelector* setPos(const char* qname, unsigned pos);
+ XcapSelector* setPosAttribute(const char* qname, unsigned pos, const char* att_qname, const char* att_value);
+ XcapSelector* setNamespace(const char* prefix, const char* value);
+
+ char* getString();// %newobject
+ void reset();
+
+private:
+ txcap_stack_handle_t* stack_handle;
+ char* auid;
+ twrap_xcap_steps_L_t* steps;
+};
+
+//
+// XcapMessage
+//
+class XcapMessage
+{
+public:
+ XcapMessage();
+#if !defined(SWIG)
+ XcapMessage(const thttp_message_t *httpmessage);
+#endif
+ virtual ~XcapMessage();
+
+ short getCode() const;
+ const char* getPhrase() const;
+
+ char* getXcapHeaderValue(const char* name, unsigned index = 0);
+ char* getXcapHeaderParamValue(const char* name, const char* param, unsigned index = 0);
+ unsigned getXcapContentLength();
+ unsigned getXcapContent(void* output, unsigned maxsize);
+
+private:
+ const thttp_message_t *httpmessage;
+};
+
+//
+// XcapEvent
+//
+class XcapEvent
+{
+public:
+#if !defined(SWIG)
+ XcapEvent(const thttp_event_t *httpevent);
+#endif
+ virtual ~XcapEvent();
+ thttp_event_type_t getType();
+ const XcapMessage* getXcapMessage() const;
+
+private:
+ const thttp_event_t *httpevent;
+ const XcapMessage* httpmessage;
+};
+
+
+//
+// XcapCallback
+//
+class XcapCallback
+{
+public:
+ XcapCallback();
+ virtual ~XcapCallback();
+
+ virtual int onEvent(const XcapEvent* e)const { return -1; }
+};
+
+
+//
+// XcapStack
+//
+class XcapStack
+{
+public:
+ XcapStack(XcapCallback* callback, const char* xui, const char* password, const char* xcap_root);
+ virtual ~XcapStack();
+
+public: /* API functions */
+ bool registerAUID(const char* id, const char* mime_type, const char* ns, const char* document_name, bool is_global);
+ bool start();
+ bool setCredentials(const char* xui, const char* password);
+ bool setXcapRoot(const char* xcap_root);
+ bool setLocalIP(const char* ip);
+ bool setLocalPort(unsigned port);
+ bool addHeader(const char* name, const char* value);
+ bool removeHeader(const char* name);
+ bool setTimeout(unsigned timeout);
+
+ bool getDocument(const char* url);
+ bool getElement(const char* url);
+ bool getAttribute(const char* url);
+
+ bool deleteDocument(const char* url);
+ bool deleteElement(const char* url);
+ bool deleteAttribute(const char* url);
+
+ bool putDocument(const char* url, const void* payload, unsigned len, const char* contentType);
+ bool putElement(const char* url, const void* payload, unsigned len);
+ bool putAttribute(const char* url, const void* payload, unsigned len);
+
+ bool stop();
+
+public: /* Public helper function */
+#if !defined(SWIG)
+ txcap_stack_handle_t* getHandle(){
+ return this->handle;
+ }
+ XcapCallback* getCallback()const{
+ return this->callback;
+ }
+#endif
+
+private:
+ txcap_stack_handle_t* handle;
+ XcapCallback* callback;
+
+ static unsigned count;
+};
+
+
+#endif /* TINYWRAP_XCAP_H */
diff --git a/bindings/_common/Xcap.i b/bindings/_common/Xcap.i
new file mode 100644
index 0000000..2c69147
--- /dev/null
+++ b/bindings/_common/Xcap.i
@@ -0,0 +1,22 @@
+%{
+#include "Xcap.h"
+%}
+
+/* Callbacks */
+%feature("director") XcapCallback;
+
+
+%nodefaultctor;
+%include "Xcap.h"
+%clearnodefaultctor;
+
+typedef enum thttp_event_type_e
+{
+ thttp_event_dialog_started,
+ thttp_event_message,
+ thttp_event_auth_failed,
+ thttp_event_closed,
+ thttp_event_transport_error,
+ thttp_event_dialog_terminated
+}
+thttp_event_type_t; \ No newline at end of file
diff --git a/bindings/_common/tinyWRAP.i b/bindings/_common/tinyWRAP.i
new file mode 100644
index 0000000..0b89742
--- /dev/null
+++ b/bindings/_common/tinyWRAP.i
@@ -0,0 +1,67 @@
+/* File : tinyWRAP.i */
+%module(directors="1") tinyWRAP
+%include "typemaps.i"
+%include <stdint.i>
+
+%{
+#include "DDebug.h"
+%}
+
+%feature("director") DDebugCallback;
+
+%nodefaultctor;
+%include "DDebug.h"
+%include "Common.h"
+%clearnodefaultctor;
+
+
+
+
+
+/* ========== Sip/Sdp Stack ========== */
+%newobject getSipHeaderValue;
+%newobject getSdpHeaderValue;
+%newobject getSdpHeaderAValue;
+%newobject getSipHeaderParamValue;
+%newobject SipStack::dnsENUM;
+%newobject SipStack::dnsNaptrSrv;
+%newobject SipStack::dnsSrv;
+%newobject SipStack::getPreferredIdentity;
+%newobject SipStack::getLocalIPnPort;
+
+%newobject MessagingEvent::takeSessionOwnership;
+%newobject InviteEvent::takeCallSessionOwnership;
+%newobject InviteEvent::takeMsrpSessionOwnership;
+%newobject RegistrationEvent::takeSessionOwnership;
+
+%newobject ProxyPluginMgr::createInstance;
+
+%newobject MediaContent::parse;
+
+%include SipStack.i
+
+
+/* ========== Xcap Stack ========== */
+%newobject XcapSelector::getString;
+
+%newobject getXcapHeaderValue;
+%newobject getXcapHeaderParamValue;
+
+%include Xcap.i
+
+
+/* ========== SMS ========== */
+%newobject SMSEncoder::encodeSubmit;
+%newobject SMSEncoder::encodeDeliver;
+%newobject SMSEncoder::encodeACK;
+%newobject SMSEncoder::encodeError;
+%newobject SMSEncoder::decode;
+
+%include SMS.i
+
+
+/* ========== MSRP ========== */
+%newobject getMsrpHeaderValue;
+%newobject getMsrpHeaderParamValue;
+
+%include Msrp.i
diff --git a/bindings/_common/tinyWRAP_config.h b/bindings/_common/tinyWRAP_config.h
new file mode 100644
index 0000000..493afb6
--- /dev/null
+++ b/bindings/_common/tinyWRAP_config.h
@@ -0,0 +1,68 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+
+#ifndef TINYWRAP_CONFIG_H
+#define TINYWRAP_CONFIG_H
+
+#ifdef __SYMBIAN32__
+#undef _WIN32 /* Because of WINSCW */
+#endif
+
+/* Windows (XP/Vista/7/CE and Windows Mobile) macro definition.
+*/
+#if defined(WIN32)|| defined(_WIN32) || defined(_WIN32_WCE)
+# define TWRAP_UNDER_WINDOWS 1
+#endif
+
+#if (TWRAP_UNDER_WINDOWS || defined(__SYMBIAN32__)) && defined(TINYWRAP_EXPORTS)
+# define TINYWRAP_API __declspec(dllexport)
+# define TINYWRAP_GEXTERN __declspec(dllexport)
+#elif (TWRAP_UNDER_WINDOWS || defined(__SYMBIAN32__)) /*&& defined(TINYWRAP_IMPORTS)*/
+# define TINYWRAP_API __declspec(dllimport)
+# define TINYWRAP_GEXTERN __declspec(dllimport)
+#else
+# define TINYWRAP_API
+# define TINYWRAP_GEXTERN extern
+#endif
+
+/* Guards against C++ name mangling
+*/
+#ifdef __cplusplus
+# define TWRAP_BEGIN_DECLS extern "C" {
+# define TWRAP_END_DECLS }
+#else
+# define TWRAP_BEGIN_DECLS
+# define TWRAP_END_DECLS
+#endif
+
+/* Disable some well-known warnings
+*/
+#ifdef _MSC_VER
+# define _CRT_SECURE_NO_WARNINGS
+#endif
+
+
+#if HAVE_CONFIG_H
+ #include "../config.h"
+#endif
+
+#endif // TINYWRAP_CONFIG_H
OpenPOWER on IntegriCloud