summaryrefslogtreecommitdiffstats
path: root/src/uscxml/plugins/invoker/im
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-09-25 13:24:11 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-09-25 13:24:11 (GMT)
commit567df9318fff6d1bb570191c33ea68cd6ef88bee (patch)
tree72e310c422cea117abe859a6bddf0b613a2db589 /src/uscxml/plugins/invoker/im
parentbe3c180fec71866a91b5f9297708d581bc1d6435 (diff)
downloaduscxml-567df9318fff6d1bb570191c33ea68cd6ef88bee.zip
uscxml-567df9318fff6d1bb570191c33ea68cd6ef88bee.tar.gz
uscxml-567df9318fff6d1bb570191c33ea68cd6ef88bee.tar.bz2
More work on IMInvoker, renamed Blob attributes and some XPath datamodel fixes
Diffstat (limited to 'src/uscxml/plugins/invoker/im')
-rw-r--r--src/uscxml/plugins/invoker/im/IMInvoker.cpp697
-rw-r--r--src/uscxml/plugins/invoker/im/IMInvoker.h179
2 files changed, 767 insertions, 109 deletions
diff --git a/src/uscxml/plugins/invoker/im/IMInvoker.cpp b/src/uscxml/plugins/invoker/im/IMInvoker.cpp
index a7fd146..cff9b5f 100644
--- a/src/uscxml/plugins/invoker/im/IMInvoker.cpp
+++ b/src/uscxml/plugins/invoker/im/IMInvoker.cpp
@@ -1,12 +1,22 @@
#include "IMInvoker.h"
#include <glog/logging.h>
+#include "uscxml/UUID.h"
#ifdef BUILD_AS_PLUGINS
#include <Pluma/Connector.hpp>
#endif
-namespace uscxml {
+#define GET_INSTANCE_IN_CALLBACK(account) \
+tthread::lock_guard<tthread::mutex> lock(_accountMutex); \
+if (_accountInstances.find(account) == _accountInstances.end()) { \
+ LOG(ERROR) << "Callback for unknown account called"; \
+ return; \
+} \
+IMInvoker* inst = _accountInstances[account];\
+
+namespace uscxml {
+
#ifdef BUILD_AS_PLUGINS
PLUMA_CONNECTOR
bool connect(pluma::Host& host) {
@@ -25,16 +35,14 @@ PurpleEventLoopUiOps IMInvoker::_uiEventLoopOps =
purpleEventTimeoutRemove,
purpleEventInputAdd,
purpleEventInputRemove,
- purpleEventInputGetError,
+ NULL, //purpleEventInputGetError,
purpleEventTimeoutAddSec,
-
- /* padding */
NULL,
NULL,
NULL
};
-PurpleAccountUiOps IMInvoker::_accountUIOps = {
+PurpleAccountUiOps IMInvoker::_uiAccountOps = {
accountNotifyAdded,
accountStatusChanged,
accountRequestAdd,
@@ -44,66 +52,139 @@ PurpleAccountUiOps IMInvoker::_accountUIOps = {
NULL,
NULL
};
-
-/*** Conversation uiops ***/
-static void
-null_write_conv(PurpleConversation *conv, const char *who, const char *alias,
- const char *message, PurpleMessageFlags flags, time_t mtime)
-{
- const char *name;
- if (alias && *alias)
- name = alias;
- else if (who && *who)
- name = who;
- else
- name = NULL;
-
- printf("(%s) %s %s: %s\n", purple_conversation_get_name(conv),
- purple_utf8_strftime("(%H:%M:%S)", localtime(&mtime)),
- name, message);
-}
-static PurpleConversationUiOps null_conv_uiops =
+PurpleBlistUiOps IMInvoker::_uiBuddyOps = {
+ purpleNewList,
+ purpleNewNode,
+ purpleShow,
+ NULL, // purpleUpdate,
+ NULL, // purpleRemove,
+ NULL, // purpleDestroy,
+ NULL, // purpleSetVisible,
+ purpleRequestAddBuddy,
+ purpleRequestAddChat,
+ purpleRequestAddGroup,
+ NULL, // purpleSaveNode,
+ NULL, // purpleRemoveNode,
+ NULL, // purpleSaveAccount,
+};
+
+// file transfer
+PurpleXferUiOps IMInvoker::_uiXferOps = {
+ purpleNewXfer,
+ purpleDestroy,
+ purpleAddXfer,
+ purpleUpdateProgress,
+ purpleCancelLocal,
+ purpleCancelRemote,
+ purpleWrite,
+ purpleRead,
+ purpleDataNotSent,
+ purpleAddThumbnail
+};
+
+// connection info
+PurpleConnectionUiOps IMInvoker::_uiConnectOps = {
+ purpleConnectProgress,
+ purpleConnected,
+ purpleDisonnected,
+ purpleNotice,
+ purpleNetworkConnected,
+ purpleNetworkDisconnected,
+ purpleReportDisconnect,
+ NULL,
+ NULL,
+ NULL
+
+};
+
+//libpurple conversation operations
+PurpleConversationUiOps IMInvoker::_uiConvOps =
{
- NULL, /* create_conversation */
- NULL, /* destroy_conversation */
- NULL, /* write_chat */
- NULL, /* write_im */
- null_write_conv, /* write_conv */
- NULL, /* chat_add_users */
- NULL, /* chat_rename_user */
- NULL, /* chat_remove_users */
- NULL, /* chat_update_user */
- NULL, /* present */
- NULL, /* has_focus */
- NULL, /* custom_smiley_add */
- NULL, /* custom_smiley_write */
- NULL, /* custom_smiley_close */
- NULL, /* send_confirm */
+ NULL, //purpleCreateConversation,
+ NULL, //purpleDestroyConversation,
+ NULL, //purpleWriteChat,
+ NULL, //purpleWriteIm,
+ purpleWriteConv,
+ NULL, //purpleChatRenameUser,
+ NULL, //purpleChatRemoveUsers,
+ NULL, //purpleChatUpdateUser,
+ NULL, //purplePresentConversation,
+ NULL, //purpleHasFocus,
+ NULL, //purpleCustomSmileyAdd,
+ NULL, //purpleCustomSmileyWrite,
+ NULL, //purpleCustomSmileyClose,
+ NULL, //purpleSendConfirm,
NULL,
NULL,
NULL,
NULL
};
-static void
-null_ui_init(void)
-{
- /**
- * This should initialize the UI components for all the modules. Here we
- * just initialize the UI for conversations.
- */
- purple_conversations_set_ui_ops(&null_conv_uiops);
-}
+PurpleNotifyUiOps IMInvoker::_uiNotifyOps = {
+ purpeNotifyMessage,
+ purpeNotifyEmail,
+ purpeNotifyEmails,
+ purpeNotifyFormatted,
+ purpeNotifySearchResults,
+ purpeNotifySearchResultsNewRows,
+ purpeNotifyUserInfo,
+ purpeNotifyURI,
+ purpeNotifyClose,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
-static PurpleCoreUiOps null_core_uiops =
-{
+PurplePrivacyUiOps IMInvoker::_uiPrivacyOps = {
+ purplePermitAdded,
+ purplePermitRemoved,
+ purpleDebyAdded,
+ purpleDenyRemoved,
+ NULL,
+ NULL,
NULL,
+ NULL
+};
+
+PurpleRequestFeature IMInvoker::_features;
+PurpleRequestUiOps IMInvoker::_uiRequestOps = {
+ _features,
+ purpleRequestInput,
+ purpleRequestChoice,
+ purpleRequestAction,
+ purpleRequestWait,
+ purpleRequestWaitUpdate,
+ purpleRequestFields,
+ purpleRequestFile,
+ purpleRequestFolder,
+ purpleRequestClose,
NULL,
- null_ui_init,
NULL,
+ NULL,
+ NULL
+};
+
+PurpleWhiteboardUiOps IMInvoker::_uiWhiteboardOps = {
+ purpleCreateWB,
+ purpleDestroyWB,
+ purpleSetDimensions,
+ purpleSetBrush,
+ purpleDrawPont,
+ purpleDrawLine,
+ purpleClearWB,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
- /* padding */
+PurpleCoreUiOps IMInvoker::_uiCoreOps = {
+ NULL,
+ NULL,
+ purpleUIInit,
+ NULL,
NULL,
NULL,
NULL,
@@ -112,8 +193,22 @@ static PurpleCoreUiOps null_core_uiops =
DelayedEventQueue* IMInvoker::_eventQueue = NULL;
+tthread::mutex IMInvoker::_initMutex;
+tthread::condition_variable IMInvoker::_initCond;
+
+tthread::mutex IMInvoker::_accountMutex;
+std::map<PurpleAccount*, IMInvoker*> IMInvoker::_accountInstances;
+
void IMInvoker::initLibPurple(void *userdata, const std::string event) {
+ _initMutex.lock();
+
_uiInfo = g_hash_table_new(g_str_hash, g_str_equal);
+// g_hash_table_insert(_uiInfo, "name", (char*)"uscxml");
+// g_hash_table_insert(_uiInfo, "version", "0.0.3");
+// g_hash_table_insert(_uiInfo, "website", "http://uscxml.tk.informatik.tu-darmstadt.de");
+// g_hash_table_insert(_uiInfo, "dev_website", "http://uscxml.tk.informatik.tu-darmstadt.de");
+// g_hash_table_insert(_uiInfo, "client_type", "pc");
+
_gRand = g_rand_new();
/* Set a custom user directory (optional) */
@@ -122,7 +217,7 @@ void IMInvoker::initLibPurple(void *userdata, const std::string event) {
/* We do not want any debugging for now to keep the noise to a minimum. */
purple_debug_set_enabled(false);
- purple_core_set_ui_ops(&null_core_uiops);
+ purple_core_set_ui_ops(&_uiCoreOps);
// purple_eventloop_set_ui_ops(&glib_eventloops);
purple_eventloop_set_ui_ops(&_uiEventLoopOps);
@@ -160,63 +255,222 @@ void IMInvoker::initLibPurple(void *userdata, const std::string event) {
}
+ _initMutex.unlock();
+ _initCond.notify_all();
+
}
-void IMInvoker::send(void *userdata, const std::string event) {
- EventContext* ctx = (EventContext*)userdata;
- delete(ctx);
+void IMInvoker::buddyStatusChangedCB(PurpleBuddy *buddy, PurpleStatus *old, PurpleStatus *newstatus) {
+ PurpleAccount *account = purple_buddy_get_account(buddy);
+ GET_INSTANCE_IN_CALLBACK(account);
+
+ std::string buddyName = purple_buddy_get_name(buddy);
+ inst->_dataModelVars.compound["buddies"].compound[buddyName] = buddyToData(buddy);
}
-static void
-signed_on(PurpleConnection *gc, gpointer null)
-{
+void IMInvoker::buddyIdleChangeCB(PurpleBuddy *buddy, gboolean old_idle, gboolean idle) {
+ PurpleAccount *account = purple_buddy_get_account(buddy);
+ GET_INSTANCE_IN_CALLBACK(account);
+}
+
+void IMInvoker::buddyUpdateIdleCB() {
+}
+
+void IMInvoker::buddyAddedCB(PurpleBuddy* buddy) {
+ PurpleAccount *account = purple_buddy_get_account(buddy);
+ GET_INSTANCE_IN_CALLBACK(account);
+}
+
+void IMInvoker::buddyRemovedCB(PurpleBuddy* buddy) {
+ PurpleAccount *account = purple_buddy_get_account(buddy);
+ GET_INSTANCE_IN_CALLBACK(account);
+}
+
+void IMInvoker::buddyCapsChangedCB(PurpleBuddy* buddy, PurpleMediaCaps newcaps, PurpleMediaCaps oldcaps) {
+ PurpleAccount *account = purple_buddy_get_account(buddy);
+ GET_INSTANCE_IN_CALLBACK(account);
+}
+
+gboolean IMInvoker::jabberRcvdPresenceCB(PurpleConnection *gc, const char *type, const char *from, xmlnode *presence) {
PurpleAccount *account = purple_connection_get_account(gc);
- printf("Account connected: %s %s\n", purple_account_get_username(account), purple_account_get_protocol_id(account));
+ GET_INSTANCE_IN_CALLBACK(account);
}
-void IMInvoker::invoke(void *userdata, const std::string event) {
- EventContext* ctx = (EventContext*)userdata;
- IMInvoker* instance = ctx->instance;
+void IMInvoker::buddySignOnOffCB(PurpleBuddy *buddy) {
+ PurpleAccount *account = purple_buddy_get_account(buddy);
+ tthread::lock_guard<tthread::mutex> lock(_accountMutex);
+ if (_accountInstances.find(account) == _accountInstances.end()) {
+ LOG(ERROR) << "Callback for unknown account called";
+ return;
+ }
+ IMInvoker* inst = _accountInstances[account];
- std::string username;
- Event::getParam(ctx->invokeReq.params, "username", username);
- std::string protocolId;
- Event::getParam(ctx->invokeReq.params, "protocol", protocolId);
- std::string password;
- Event::getParam(ctx->invokeReq.params, "password", password);
+ std::string buddyName = purple_buddy_get_name(buddy);
+ inst->_dataModelVars.compound["buddies"].compound[buddyName] = buddyToData(buddy);
+}
+
+void IMInvoker::signedOnCB(PurpleConnection *gc, gpointer null) {
+ PurpleSavedStatus* status = purple_savedstatus_new(NULL, PURPLE_STATUS_AVAILABLE);
+ purple_savedstatus_activate(status);
+}
- instance->_account = purple_account_new(username.c_str(), protocolId.c_str());
- purple_account_set_password(instance->_account, password.c_str(), NULL, NULL);
- purple_accounts_set_ui_ops(&_accountUIOps);
+Data IMInvoker::buddyToData(PurpleBuddy *buddy) {
+ Data data;
+ std::string buddyName = purple_buddy_get_name(buddy);
- purple_account_set_enabled(instance->_account, "uscxml", true);
+ if (purple_buddy_get_name(buddy)) data.compound["name"] = Data(purple_buddy_get_name(buddy), Data::VERBATIM);
+ if (purple_buddy_get_alias(buddy)) data.compound["alias"] = Data(purple_buddy_get_alias(buddy), Data::VERBATIM);
+ if (purple_buddy_get_alias_only(buddy)) data.compound["aliasOnly"] = Data(purple_buddy_get_alias_only(buddy), Data::VERBATIM);
+ if (purple_buddy_get_server_alias(buddy)) data.compound["server"] = Data(purple_buddy_get_server_alias(buddy), Data::VERBATIM);
- PurpleSavedStatus* status = purple_savedstatus_new(NULL, PURPLE_STATUS_AVAILABLE);
- purple_savedstatus_activate(status);
-
- int handle;
- purple_signal_connect(purple_connections_get_handle(), "signed-on", &handle,
- PURPLE_CALLBACK(signed_on), NULL);
+ PurpleGroup* group = purple_buddy_get_group(buddy);
+ if (group) {
+ if (purple_group_get_name(group)) data.compound["group"] = Data(purple_group_get_name(group), Data::VERBATIM);
+ }
- delete(ctx);
+ PurpleBuddyIcon* icon = purple_buddy_get_icon(buddy);
+ if (icon) {
+ size_t iconSize = 0;
+ gconstpointer iconData = purple_buddy_icon_get_data(icon, &iconSize);
+ data.compound["icon"] = Data((char*)iconData, iconSize, false);
+ }
+
+ PurplePresence* presence = purple_buddy_get_presence(buddy);
+
+ if (presence) {
+ GList *statusElem;
+ GList *statusList = purple_presence_get_statuses(presence);
+ PurpleStatus* status;
+
+ for(statusElem = statusList; statusElem; statusElem = statusElem->next) {
+ status = (PurpleStatus*)statusElem->data;
+ const char* statusId = purple_status_get_id(status);
+ const char* statusName = purple_status_get_name(status);
+ PurpleStatusPrimitive statusPrimitive = purple_primitive_get_type_from_id(statusId);
+
+ // only include active states
+ if(statusPrimitive == PURPLE_STATUS_UNSET || !purple_presence_is_status_primitive_active(presence, statusPrimitive))
+ continue;
+
+ if (statusName) data.compound["status"].compound[statusId] = Data(statusName, Data::VERBATIM);
+
+ PurpleStatusType* statusType = purple_status_get_type(status);
+
+ GList *statusAttrElem;
+ GList *statusAttrList = purple_status_type_get_attrs(statusType);
+ PurpleStatusAttr* statusAttr;
+ for(statusAttrElem = statusAttrList; statusAttrElem; statusAttrElem = statusAttrElem->next) {
+ statusAttr = (PurpleStatusAttr*)statusAttrElem->data;
+ const char* statusAttrId = purple_status_attr_get_id(statusAttr);
+ const char* statusAttrName = purple_status_attr_get_name(statusAttr);
+
+ PurpleValue* statusAttrValue = purple_status_attr_get_value(statusAttr);
+ if (statusAttrValue) {
+ Data purpleValue = purpleValueToData(statusAttrValue);
+ if (purpleValue) {
+ data.compound["status"].compound[statusId].compound[statusAttrId].compound["value"] = purpleValue;
+ if (statusAttrName) {
+ data.compound["status"].compound[statusId].compound[statusAttrId].compound["name"] = Data(statusAttrName, Data::VERBATIM);
+ }
+ }
+ }
+ }
+
+ data.compound["status"].compound[statusId].compound["active"] = Data((bool)purple_status_is_active(status));
+ data.compound["status"].compound[statusId].compound["available"] = Data((bool)purple_status_is_available(status));
+ data.compound["status"].compound[statusId].compound["exclusive"] = Data((bool)purple_status_is_exclusive(status));
+ data.compound["status"].compound[statusId].compound["active"] = Data((bool)purple_status_is_active(status));
+ data.compound["status"].compound[statusId].compound["independent"] = Data((bool)purple_status_is_independent(status));
+ data.compound["status"].compound[statusId].compound["online"] = Data((bool)purple_status_is_online(status));
+
+
+ PurpleValue* statusValue = purple_status_get_attr_value(status, statusId);
+ if (statusValue)
+ data.compound["status"].compound[statusId].compound["value"] = purpleValueToData(statusValue);
+
+ }
+
+ }
+ std::cout << Data::toJSON(data);
+ return data;
}
+Data IMInvoker::purpleValueToData(PurpleValue* value) {
+ Data data;
+ switch (purple_value_get_type(value)) {
+ case PURPLE_TYPE_BOOLEAN:
+ if (purple_value_get_boolean(value))
+ data = Data("true");
+ data = Data("false");
+ break;
+ case PURPLE_TYPE_STRING:
+ if (purple_value_get_string(value)) {
+ data = Data(purple_value_get_string(value), Data::VERBATIM);
+ std::cout << purple_value_get_string(value) << std::endl;
+ }
+ break;
+ case PURPLE_TYPE_CHAR:
+ Data(purple_value_get_char(value));
+ break;
+ case PURPLE_TYPE_UCHAR:
+ Data(purple_value_get_uchar(value));
+ break;
+ case PURPLE_TYPE_SHORT:
+ Data(purple_value_get_short(value));
+ break;
+ case PURPLE_TYPE_USHORT:
+ Data(purple_value_get_ushort(value));
+ break;
+ case PURPLE_TYPE_INT:
+ Data(purple_value_get_int(value));
+ break;
+ case PURPLE_TYPE_UINT:
+ Data(purple_value_get_uint(value));
+ break;
+ case PURPLE_TYPE_LONG:
+ Data(purple_value_get_long(value));
+ break;
+ case PURPLE_TYPE_ULONG:
+ Data(purple_value_get_ulong(value));
+ break;
+ case PURPLE_TYPE_INT64:
+ Data(purple_value_get_int64(value));
+ break;
+ case PURPLE_TYPE_UINT64:
+ Data(purple_value_get_uint64(value));
+ break;
+ case PURPLE_TYPE_OBJECT:
+ case PURPLE_TYPE_POINTER:
+ case PURPLE_TYPE_ENUM:
+ case PURPLE_TYPE_BOXED:
+ case PURPLE_TYPE_UNKNOWN:
+ case PURPLE_TYPE_SUBTYPE:
+ LOG(ERROR) << "purple thingy not supported";
+ break;
+ }
+ return data;
+}
+
IMInvoker::IMInvoker() {
_account = NULL;
if (!_eventQueue) {
+ tthread::lock_guard<tthread::mutex> lock(_initMutex);
_eventQueue = new DelayedEventQueue();
_eventQueue->addEvent("initLibPurple", IMInvoker::initLibPurple, 0, NULL);
_eventQueue->start();
-
-
+ // make sure to have the shebang initialized when we leave
+ _initCond.wait(_initMutex);
}
}
IMInvoker::~IMInvoker() {
if (_account) {
+ _accountMutex.lock();
+ _accountInstances.erase(_account);
purple_account_destroy(_account);
+ _accountMutex.unlock();
}
};
@@ -226,17 +480,62 @@ boost::shared_ptr<InvokerImpl> IMInvoker::create(InterpreterImpl* interpreter) {
}
Data IMInvoker::getDataModelVariables() {
- return _pluginData;
+ tthread::lock_guard<tthread::mutex> lock(_accountMutex);
+ return _dataModelVars;
}
void IMInvoker::send(const SendRequest& req) {
EventContext* ctx = new EventContext();
ctx->sendReq = req;
ctx->instance = this;
- _eventQueue->addEvent(req.sendid, IMInvoker::invoke, 0, ctx);
+
+ std::string eventId = UUID::getUUID();
+ _eventQueue->addEvent(eventId, IMInvoker::send, 0, ctx);
return;
}
+void IMInvoker::send(void *userdata, const std::string event) {
+ // we are in the thread that manages all of libpurple
+ EventContext* ctx = (EventContext*)userdata;
+#if 0
+ if (boost::iequals(ctx->sendReq.name, "im.send")) {
+ if (ctx->instance->_account) {
+ std::string receiver;
+ Event::getParam(ctx->sendReq.params, "receiver", receiver);
+
+ Data data;
+ Event::getParam(ctx->sendReq.params, "data", data);
+
+ // purple_conv_im_send
+ PurpleConversation* conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, ctx->instance->_account, receiver.c_str());
+ purple_conv_im_send(purple_conversation_get_im_data(conv), ctx->sendReq.content.c_str());
+
+#if 0
+ if (data.binary) {
+ PurpleConnection *gc = purple_account_get_connection(ctx->instance->_account);
+ PurplePlugin *prpl;
+ PurplePluginProtocolInfo *prpl_info;
+
+
+ if (gc) {
+ prpl = purple_connection_get_prpl(gc);
+ prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+// if (prpl_info->send_file &&
+// (prpl_info->can_receive_file
+// && prpl_info->can_receive_file(gc, receiver.c_str())))
+// prpl_info->send_file(gc, receiver.c_str(), file);
+ prpl_info->send_raw(gc, data.binary->_data, data.binary->_size);
+ }
+
+ }
+#endif
+ }
+ }
+#endif
+ delete(ctx);
+}
+
void IMInvoker::cancel(const std::string sendId) {
}
@@ -249,6 +548,44 @@ void IMInvoker::invoke(const InvokeRequest& req) {
return;
}
+void IMInvoker::invoke(void *userdata, const std::string event) {
+ _accountMutex.lock();
+
+ EventContext* ctx = (EventContext*)userdata;
+ IMInvoker* instance = ctx->instance;
+
+ std::string username;
+ Event::getParam(ctx->invokeReq.params, "username", username);
+ std::string protocolId;
+ Event::getParam(ctx->invokeReq.params, "protocol", protocolId);
+ std::string password;
+ Event::getParam(ctx->invokeReq.params, "password", password);
+
+ instance->_account = purple_account_new(username.c_str(), protocolId.c_str());
+ _accountInstances[instance->_account] = instance;
+
+ purple_account_set_password(instance->_account, password.c_str(), NULL, NULL);
+
+ purple_account_set_enabled(instance->_account, "uscxml", true);
+
+ int handle;
+ purple_signal_connect(purple_connections_get_handle(), "signed-on", &handle, PURPLE_CALLBACK(signedOnCB), NULL);
+
+ purple_signal_connect(purple_blist_get_handle(), "buddy-signed-on", &handle, PURPLE_CALLBACK(buddySignOnOffCB), NULL);
+ purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off", &handle, PURPLE_CALLBACK(buddySignOnOffCB), NULL);
+ purple_signal_connect(purple_blist_get_handle(), "buddy-status-changed", &handle, PURPLE_CALLBACK(buddyStatusChangedCB), NULL);
+
+ purple_signal_connect(purple_blist_get_handle(), "buddy-idle-changed", &handle, PURPLE_CALLBACK(buddyIdleChangeCB), NULL);
+ purple_signal_connect(purple_blist_get_handle(), "update-idle", &handle, PURPLE_CALLBACK(buddyUpdateIdleCB), NULL);
+ purple_signal_connect(purple_blist_get_handle(), "buddy-added", &handle, PURPLE_CALLBACK(buddyAddedCB), NULL);
+ purple_signal_connect(purple_blist_get_handle(), "buddy-removed", &handle, PURPLE_CALLBACK(buddyRemovedCB), NULL);
+ purple_signal_connect(purple_blist_get_handle(), "buddy-caps-changed", &handle, PURPLE_CALLBACK(buddyCapsChangedCB), NULL);
+ purple_signal_connect(purple_blist_get_handle(), "jabber-receiving-presence", &handle, PURPLE_CALLBACK(jabberRcvdPresenceCB), NULL);
+
+ delete(ctx);
+ _accountMutex.unlock();
+}
+
guint IMInvoker::purpleEventTimeoutAdd(guint interval, GSourceFunc function, gpointer data) {
PurpleEventContext* ctx = new PurpleEventContext();
ctx->function = function;
@@ -294,6 +631,7 @@ gboolean IMInvoker::purpleEventInputRemove(guint handle) {
}
int IMInvoker::purpleEventInputGetError(int fd, int *error) {
+ // unused
std::cout << "purpleEventInputGetError" << std::endl;
return 0;
}
@@ -310,7 +648,18 @@ void IMInvoker::purpleCallback(void *userdata, const std::string event) {
void IMInvoker::purplePrefsInit(void) {}
void IMInvoker::purpleDebugInit(void) {}
-void IMInvoker::purpleUIInit(void) {}
+
+void IMInvoker::purpleUIInit(void) {
+ purple_accounts_set_ui_ops(&_uiAccountOps);
+ purple_xfers_set_ui_ops(&_uiXferOps);
+// purple_blist_set_ui_ops(&_uiBuddyOps);
+// purple_notify_set_ui_ops(&_uiNotifyOps);
+// purple_privacy_set_ui_ops(&_uiPrivacyOps);
+// purple_request_set_ui_ops(&_uiRequestOps);
+// purple_connections_set_ui_ops(&_uiConnectOps);
+// purple_whiteboard_set_ui_ops(&_uiWhiteboardOps);
+ purple_conversations_set_ui_ops(&_uiConvOps);
+}
void IMInvoker::purpleQuit(void) {}
GHashTable* IMInvoker::purpleGetUIInfo(void) {
@@ -357,5 +706,183 @@ void IMInvoker::accountCloseRequest(void *ui_handle) {
std::cout << "accountCloseRequest" << std::endl;
}
+//libpurple conversation operations
+void IMInvoker::purpleCreateConversation(PurpleConversation *conv) {}
+void IMInvoker::purpleDestroyConversation(PurpleConversation *conv) {}
+void IMInvoker::purpleWriteChat(PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime) {}
+void IMInvoker::purpleWriteIm(PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime) {}
+void IMInvoker::purpleWriteConv(PurpleConversation *conv, const char *name, const char *alias, const char *message, PurpleMessageFlags flags, time_t mtime) {
+ const char *who;
+ if (alias && *alias)
+ who = alias;
+ else if (name && *name)
+ who = name;
+ else
+ who = NULL;
+
+ printf("(%s) %s %s: %s\n", purple_conversation_get_name(conv),
+ purple_utf8_strftime("(%H:%M:%S)", localtime(&mtime)),
+ who, message);
+}
+void IMInvoker::purpleChatAddUsers(PurpleConversation *conv, GList *cbuddies, gboolean new_arrivals) {}
+void IMInvoker::purpleChatRenameUser(PurpleConversation *conv, const char *old_name, const char *new_name, const char *new_alias) {}
+void IMInvoker::purpleChatRemoveUsers(PurpleConversation *conv, GList *users) {}
+void IMInvoker::purpleChatUpdateUser(PurpleConversation *conv, const char *user) {}
+void IMInvoker::purplePresentConversation(PurpleConversation *conv) {}
+gboolean IMInvoker::purpleHasFocus(PurpleConversation *conv) {
+ return true;
+}
+gboolean IMInvoker::purpleCustomSmileyAdd(PurpleConversation *conv, const char *smile, gboolean remote) {
+ return true;
+}
+void IMInvoker::purpleCustomSmileyWrite(PurpleConversation *conv, const char *smile, const guchar *data, gsize size) {}
+void IMInvoker::purpleCustomSmileyClose(PurpleConversation *conv, const char *smile) {}
+void IMInvoker::purpleSendConfirm(PurpleConversation *conv, const char *message) {}
+
+// buddy operations
+void IMInvoker::purpleNewList(PurpleBuddyList *list) {
+ std::cout << "purpleNewList" << std::endl;
+}
+void IMInvoker::purpleNewNode(PurpleBlistNode *node) {
+ std::cout << "purpleNewNode" << std::endl;
+}
+void IMInvoker::purpleShow(PurpleBuddyList *list) {
+ std::cout << "purpleShow" << std::endl;
+}
+void IMInvoker::purpleUpdate(PurpleBuddyList *list, PurpleBlistNode *node) {
+}
+void IMInvoker::purpleRemove(PurpleBuddyList *list, PurpleBlistNode *node) {}
+void IMInvoker::purpleDestroy(PurpleBuddyList *list) {}
+void IMInvoker::purpleSetVisible(PurpleBuddyList *list, gboolean show) {}
+void IMInvoker::purpleRequestAddBuddy(PurpleAccount *account, const char *username, const char *group, const char *alias) {
+ std::cout << "purpleRequestAddBuddy" << std::endl;
+}
+void IMInvoker::purpleRequestAddChat(PurpleAccount *account, PurpleGroup *group, const char *alias, const char *name) {
+ std::cout << "purpleRequestAddChat" << std::endl;
+}
+void IMInvoker::purpleRequestAddGroup(void) {
+ std::cout << "purpleRequestAddGroup" << std::endl;
+}
+void IMInvoker::purpleSaveNode(PurpleBlistNode *node) {}
+void IMInvoker::purpleRemoveNode(PurpleBlistNode *node) {}
+void IMInvoker::purpleSaveAccount(PurpleAccount *account) {}
+
+// file transfer operations
+void IMInvoker::purpleNewXfer(PurpleXfer *xfer) {
+ std::cout << "purpleNewXfer" << std::endl;
+}
+void IMInvoker::purpleDestroy(PurpleXfer *xfer) {
+ std::cout << "purpleDestroy" << std::endl;
+}
+void IMInvoker::purpleAddXfer(PurpleXfer *xfer) {
+ std::cout << "purpleAddXfer" << std::endl;
+}
+void IMInvoker::purpleUpdateProgress(PurpleXfer *xfer, double percent) {
+ std::cout << "purpleUpdateProgress" << std::endl;
+}
+void IMInvoker::purpleCancelLocal(PurpleXfer *xfer) {
+ std::cout << "purpleCancelLocal" << std::endl;
+}
+void IMInvoker::purpleCancelRemote(PurpleXfer *xfer) {
+ std::cout << "purpleCancelRemote" << std::endl;
+}
+gssize IMInvoker::purpleWrite(PurpleXfer *xfer, const guchar *buffer, gssize size) {
+ std::cout << "purpleWrite" << std::endl;
+}
+gssize IMInvoker::purpleRead(PurpleXfer *xfer, guchar **buffer, gssize size) {
+ std::cout << "purpleRead" << std::endl;
+}
+void IMInvoker::purpleDataNotSent(PurpleXfer *xfer, const guchar *buffer, gsize size) {
+ std::cout << "purpleDataNotSent" << std::endl;
+}
+void IMInvoker::purpleAddThumbnail(PurpleXfer *xfer, const gchar *formats) {
+ std::cout << "purpleAddThumbnail" << std::endl;
+}
+
+// notification operations
+void* IMInvoker::purpeNotifyMessage(PurpleNotifyMsgType type, const char *title, const char *primary, const char *secondary, PurpleRequestCommonParameters *cpar) {
+ return NULL;
+}
+void* IMInvoker::purpeNotifyEmail(PurpleConnection *gc, const char *subject, const char *from, const char *to, const char *url) {
+ return NULL;
+}
+void* IMInvoker::purpeNotifyEmails(PurpleConnection *gc, size_t count, gboolean detailed, const char **subjects, const char **froms, const char **tos, const char **urls) {
+ return NULL;
+}
+void* IMInvoker::purpeNotifyFormatted(const char *title, const char *primary, const char *secondary, const char *text) {
+ return NULL;
+}
+void* IMInvoker::purpeNotifySearchResults(PurpleConnection *gc, const char *title, const char *primary, const char *secondary, PurpleNotifySearchResults *results, gpointer user_data) {
+ return NULL;
+}
+void IMInvoker::purpeNotifySearchResultsNewRows(PurpleConnection *gc, PurpleNotifySearchResults *results, void *data) {}
+void* IMInvoker::purpeNotifyUserInfo(PurpleConnection *gc, const char *who, PurpleNotifyUserInfo *user_info) {
+ return NULL;
+}
+void* IMInvoker::purpeNotifyURI(const char *uri) {
+ return NULL;
+}
+void IMInvoker::purpeNotifyClose(PurpleNotifyType type, void *ui_handle) {}
+
+// privacy ui operations
+void IMInvoker::purplePermitAdded(PurpleAccount *account, const char *name) {}
+void IMInvoker::purplePermitRemoved(PurpleAccount *account, const char *name) {}
+void IMInvoker::purpleDebyAdded(PurpleAccount *account, const char *name) {}
+void IMInvoker::purpleDenyRemoved(PurpleAccount *account, const char *name) {}
+
+// request ui operations
+void* IMInvoker::purpleRequestInput(const char *title, const char *primary,
+ const char *secondary, const char *default_value,
+ gboolean multiline, gboolean masked, gchar *hint,
+ const char *ok_text, GCallback ok_cb,
+ const char *cancel_text, GCallback cancel_cb,
+ PurpleRequestCommonParameters *cpar, void *user_data) {}
+void* IMInvoker::purpleRequestChoice(const char *title, const char *primary,
+ const char *secondary, gpointer default_value,
+ const char *ok_text, GCallback ok_cb, const char *cancel_text,
+ GCallback cancel_cb, PurpleRequestCommonParameters *cpar,
+ void *user_data, va_list choices) {}
+void* IMInvoker::purpleRequestAction(const char *title, const char *primary,
+ const char *secondary, int default_action,
+ PurpleRequestCommonParameters *cpar, void *user_data,
+ size_t action_count, va_list actions) {}
+void* IMInvoker::purpleRequestWait(const char *title, const char *primary,
+ const char *secondary, gboolean with_progress,
+ PurpleRequestCancelCb cancel_cb,
+ PurpleRequestCommonParameters *cpar, void *user_data) {}
+
+void IMInvoker::purpleRequestWaitUpdate(void *ui_handle, gboolean pulse, gfloat fraction) {}
+void* IMInvoker::purpleRequestFields(const char *title, const char *primary,
+ const char *secondary, PurpleRequestFields *fields,
+ const char *ok_text, GCallback ok_cb,
+ const char *cancel_text, GCallback cancel_cb,
+ PurpleRequestCommonParameters *cpar, void *user_data) {}
+void* IMInvoker::purpleRequestFile(const char *title, const char *filename,
+ gboolean savedialog, GCallback ok_cb, GCallback cancel_cb,
+ PurpleRequestCommonParameters *cpar, void *user_data) {}
+void* IMInvoker::purpleRequestFolder(const char *title, const char *dirname,
+ GCallback ok_cb, GCallback cancel_cb,
+ PurpleRequestCommonParameters *cpar, void *user_data) {}
+void IMInvoker::purpleRequestClose(PurpleRequestType type, void *ui_handle) {}
+
+
+// connection ui operations
+void IMInvoker::purpleConnectProgress(PurpleConnection *gc, const char *text, size_t step, size_t step_count) {}
+void IMInvoker::purpleConnected(PurpleConnection *gc) {}
+void IMInvoker::purpleDisonnected(PurpleConnection *gc) {}
+void IMInvoker::purpleNotice(PurpleConnection *gc, const char *text) {}
+void IMInvoker::purpleNetworkConnected(void) {}
+void IMInvoker::purpleNetworkDisconnected(void) {}
+void IMInvoker::purpleReportDisconnect(PurpleConnection *gc, PurpleConnectionError reason, const char *text) {}
+
+// whiteboard ui operations
+void IMInvoker::purpleCreateWB(PurpleWhiteboard *wb) {}
+void IMInvoker::purpleDestroyWB(PurpleWhiteboard *wb) {}
+void IMInvoker::purpleSetDimensions(PurpleWhiteboard *wb, int width, int height) {}
+void IMInvoker::purpleSetBrush(PurpleWhiteboard *wb, int size, int color) {}
+void IMInvoker::purpleDrawPont(PurpleWhiteboard *wb, int x, int y, int color, int size) {}
+void IMInvoker::purpleDrawLine(PurpleWhiteboard *wb, int x1, int y1, int x2, int y2, int color, int size) {}
+void IMInvoker::purpleClearWB(PurpleWhiteboard *wb) {}
+
} \ No newline at end of file
diff --git a/src/uscxml/plugins/invoker/im/IMInvoker.h b/src/uscxml/plugins/invoker/im/IMInvoker.h
index fb02e46..b8a57f6 100644
--- a/src/uscxml/plugins/invoker/im/IMInvoker.h
+++ b/src/uscxml/plugins/invoker/im/IMInvoker.h
@@ -3,9 +3,9 @@
#include <uscxml/Interpreter.h>
-//extern "C" {
+extern "C" {
#include <libpurple/purple.h>
-//}
+}
#ifdef BUILD_AS_PLUGINS
#include "uscxml/plugins/Plugins.h"
@@ -41,14 +41,46 @@ public:
protected:
static bool _libPurpleIsInitialized;
static Data _pluginData;
- static PurpleAccountUiOps _accountUIOps;
+
+ Data _dataModelVars;
+
+ static Data buddyToData(PurpleBuddy *buddy);
+ static Data purpleValueToData(PurpleValue* value);
+
+ static PurpleAccountUiOps _uiAccountOps;
static PurpleEventLoopUiOps _uiEventLoopOps;
static PurpleCoreUiOps _uiCoreOps;
+ static PurpleConversationUiOps _uiConvOps;
+ static PurpleBlistUiOps _uiBuddyOps;
+ static PurpleXferUiOps _uiXferOps;
+ static PurpleNotifyUiOps _uiNotifyOps;
+ static PurplePrivacyUiOps _uiPrivacyOps;
+ static PurpleRequestUiOps _uiRequestOps;
+ static PurpleConnectionUiOps _uiConnectOps;
+ static PurpleWhiteboardUiOps _uiWhiteboardOps;
+
+ static PurpleRequestFeature _features;
static GHashTable* _uiInfo;
static GRand* _gRand;
+ static tthread::mutex _accountMutex;
+ static std::map<PurpleAccount*, IMInvoker*> _accountInstances;
+ static tthread::mutex _initMutex;
+ static tthread::condition_variable _initCond;
static DelayedEventQueue* _eventQueue;
+ // event callbacks
+ static void signedOnCB(PurpleConnection *gc, gpointer null);
+ static void buddySignOnOffCB(PurpleBuddy *buddy);
+ static void buddyStatusChangedCB(PurpleBuddy *buddy, PurpleStatus *oldstatus, PurpleStatus *newstatus);
+ static void buddyIdleChangeCB(PurpleBuddy *buddy, gboolean old_idle, gboolean idle);
+ static void buddyUpdateIdleCB();
+ static void buddyAddedCB(PurpleBuddy* buddy);
+ static void buddyRemovedCB(PurpleBuddy* buddy);
+ static void buddyCapsChangedCB(PurpleBuddy* buddy, PurpleMediaCaps newcaps, PurpleMediaCaps oldcaps);
+ static gboolean jabberRcvdPresenceCB(PurpleConnection *gc, const char *type, const char *from, xmlnode *presence);
+
+
// these are only being called from the delayed queue's thread
static void initLibPurple(void *userdata, const std::string event);
static void send(void *userdata, const std::string event);
@@ -79,31 +111,130 @@ protected:
static void purpleQuit(void);
static GHashTable* purpleGetUIInfo(void);
+ //libpurple conversation operations
+ static void purpleCreateConversation(PurpleConversation *conv);
+ static void purpleDestroyConversation(PurpleConversation *conv);
+ static void purpleWriteChat(PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime);
+ static void purpleWriteIm(PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime);
+ static void purpleWriteConv(PurpleConversation *conv, const char *name, const char *alias, const char *message, PurpleMessageFlags flags, time_t mtime);
+ static void purpleChatAddUsers(PurpleConversation *conv, GList *cbuddies, gboolean new_arrivals);
+ static void purpleChatRenameUser(PurpleConversation *conv, const char *old_name, const char *new_name, const char *new_alias);
+ static void purpleChatRemoveUsers(PurpleConversation *conv, GList *users);
+ static void purpleChatUpdateUser(PurpleConversation *conv, const char *user);
+ static void purplePresentConversation(PurpleConversation *conv);
+ static gboolean purpleHasFocus(PurpleConversation *conv);
+ static gboolean purpleCustomSmileyAdd(PurpleConversation *conv, const char *smile, gboolean remote);
+ static void purpleCustomSmileyWrite(PurpleConversation *conv, const char *smile, const guchar *data, gsize size);
+ static void purpleCustomSmileyClose(PurpleConversation *conv, const char *smile);
+ static void purpleSendConfirm(PurpleConversation *conv, const char *message);
+
+ // buddy operations
+ static void purpleNewList(PurpleBuddyList *list);
+ static void purpleNewNode(PurpleBlistNode *node);
+ static void purpleShow(PurpleBuddyList *list);
+ static void purpleUpdate(PurpleBuddyList *list, PurpleBlistNode *node);
+ static void purpleRemove(PurpleBuddyList *list, PurpleBlistNode *node);
+ static void purpleDestroy(PurpleBuddyList *list);
+ static void purpleSetVisible(PurpleBuddyList *list, gboolean show);
+ static void purpleRequestAddBuddy(PurpleAccount *account, const char *username, const char *group, const char *alias);
+ static void purpleRequestAddChat(PurpleAccount *account, PurpleGroup *group, const char *alias, const char *name);
+ static void purpleRequestAddGroup(void);
+ static void purpleSaveNode(PurpleBlistNode *node);
+ static void purpleRemoveNode(PurpleBlistNode *node);
+ static void purpleSaveAccount(PurpleAccount *account);
+
+ // file transfer operations
+ static void purpleNewXfer(PurpleXfer *xfer);
+ static void purpleDestroy(PurpleXfer *xfer);
+ static void purpleAddXfer(PurpleXfer *xfer);
+ static void purpleUpdateProgress(PurpleXfer *xfer, double percent);
+ static void purpleCancelLocal(PurpleXfer *xfer);
+ static void purpleCancelRemote(PurpleXfer *xfer);
+ static gssize purpleWrite(PurpleXfer *xfer, const guchar *buffer, gssize size);
+ static gssize purpleRead(PurpleXfer *xfer, guchar **buffer, gssize size);
+ static void purpleDataNotSent(PurpleXfer *xfer, const guchar *buffer, gsize size);
+ static void purpleAddThumbnail(PurpleXfer *xfer, const gchar *formats);
+
+ // notification operations
+ static void* purpeNotifyMessage(PurpleNotifyMsgType type, const char *title, const char *primary, const char *secondary, PurpleRequestCommonParameters *cpar);
+ static void* purpeNotifyEmail(PurpleConnection *gc, const char *subject, const char *from, const char *to, const char *url);
+ static void* purpeNotifyEmails(PurpleConnection *gc, size_t count, gboolean detailed, const char **subjects, const char **froms, const char **tos, const char **urls);
+ static void* purpeNotifyFormatted(const char *title, const char *primary, const char *secondary, const char *text);
+ static void* purpeNotifySearchResults(PurpleConnection *gc, const char *title, const char *primary, const char *secondary, PurpleNotifySearchResults *results, gpointer user_data);
+ static void purpeNotifySearchResultsNewRows(PurpleConnection *gc, PurpleNotifySearchResults *results, void *data);
+ static void* purpeNotifyUserInfo(PurpleConnection *gc, const char *who, PurpleNotifyUserInfo *user_info);
+ static void* purpeNotifyURI(const char *uri);
+ static void purpeNotifyClose(PurpleNotifyType type, void *ui_handle);
+
// account operations
- static void accountNotifyAdded(PurpleAccount *account,
- const char *remote_user,
- const char *id,
- const char *alias,
- const char *message);
- static void accountStatusChanged(PurpleAccount *account,
- PurpleStatus *status);
- static void accountRequestAdd(PurpleAccount *account,
- const char *remote_user,
- const char *id,
- const char *alias,
- const char *message);
- static void* accountRequestAuthorize(PurpleAccount *account,
- const char *remote_user,
- const char *id,
- const char *alias,
- const char *message,
- gboolean on_list,
- PurpleAccountRequestAuthorizationCb authorize_cb,
- PurpleAccountRequestAuthorizationCb deny_cb,
- void *user_data);
+ static void accountNotifyAdded(PurpleAccount *account, const char *remote_user, const char *id, const char *alias, const char *message);
+ static void accountStatusChanged(PurpleAccount *account, PurpleStatus *status);
+ static void accountRequestAdd(PurpleAccount *account, const char *remote_user, const char *id, const char *alias, const char *message);
+ static void* accountRequestAuthorize(PurpleAccount *account, const char *remote_user, const char *id, const char *alias, const char *message, gboolean on_list, PurpleAccountRequestAuthorizationCb authorize_cb, PurpleAccountRequestAuthorizationCb deny_cb, void *user_data);
static void accountCloseRequest(void *ui_handle);
+ // privacy ui operations
+ static void purplePermitAdded(PurpleAccount *account, const char *name);
+ static void purplePermitRemoved(PurpleAccount *account, const char *name);
+ static void purpleDebyAdded(PurpleAccount *account, const char *name);
+ static void purpleDenyRemoved(PurpleAccount *account, const char *name);
+
+ // request ui operations
+ static void* purpleRequestInput(const char *title, const char *primary,
+ const char *secondary, const char *default_value,
+ gboolean multiline, gboolean masked, gchar *hint,
+ const char *ok_text, GCallback ok_cb,
+ const char *cancel_text, GCallback cancel_cb,
+ PurpleRequestCommonParameters *cpar, void *user_data);
+ static void* purpleRequestChoice(const char *title, const char *primary,
+ const char *secondary, gpointer default_value,
+ const char *ok_text, GCallback ok_cb, const char *cancel_text,
+ GCallback cancel_cb, PurpleRequestCommonParameters *cpar,
+ void *user_data, va_list choices);
+ static void* purpleRequestAction(const char *title, const char *primary,
+ const char *secondary, int default_action,
+ PurpleRequestCommonParameters *cpar, void *user_data,
+ size_t action_count, va_list actions);
+ static void* purpleRequestWait(const char *title, const char *primary,
+ const char *secondary, gboolean with_progress,
+ PurpleRequestCancelCb cancel_cb,
+ PurpleRequestCommonParameters *cpar, void *user_data);
+
+ static void purpleRequestWaitUpdate(void *ui_handle, gboolean pulse, gfloat fraction);
+ static void* purpleRequestFields(const char *title, const char *primary,
+ const char *secondary, PurpleRequestFields *fields,
+ const char *ok_text, GCallback ok_cb,
+ const char *cancel_text, GCallback cancel_cb,
+ PurpleRequestCommonParameters *cpar, void *user_data);
+ static void* purpleRequestFile(const char *title, const char *filename,
+ gboolean savedialog, GCallback ok_cb, GCallback cancel_cb,
+ PurpleRequestCommonParameters *cpar, void *user_data);
+ static void* purpleRequestFolder(const char *title, const char *dirname,
+ GCallback ok_cb, GCallback cancel_cb,
+ PurpleRequestCommonParameters *cpar, void *user_data);
+ static void purpleRequestClose(PurpleRequestType type, void *ui_handle);
+
+ // connection ui operations
+ static void purpleConnectProgress(PurpleConnection *gc, const char *text, size_t step, size_t step_count);
+ static void purpleConnected(PurpleConnection *gc);
+ static void purpleDisonnected(PurpleConnection *gc);
+ static void purpleNotice(PurpleConnection *gc, const char *text);
+ static void purpleNetworkConnected(void);
+ static void purpleNetworkDisconnected(void);
+ static void purpleReportDisconnect(PurpleConnection *gc, PurpleConnectionError reason, const char *text);
+
+
+ // whiteboard ui operations
+ static void purpleCreateWB(PurpleWhiteboard *wb);
+ static void purpleDestroyWB(PurpleWhiteboard *wb);
+ static void purpleSetDimensions(PurpleWhiteboard *wb, int width, int height);
+ static void purpleSetBrush(PurpleWhiteboard *wb, int size, int color);
+ static void purpleDrawPont(PurpleWhiteboard *wb, int x, int y, int color, int size);
+ static void purpleDrawLine(PurpleWhiteboard *wb, int x1, int y1, int x2, int y2, int color, int size);
+ static void purpleClearWB(PurpleWhiteboard *wb);
+
+
PurpleAccount* _account;
};