diff options
author | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-10-07 23:13:54 (GMT) |
---|---|---|
committer | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-10-07 23:13:54 (GMT) |
commit | 36b5c7614cc896d043ddeebae1cdb4e8e94afe18 (patch) | |
tree | e14ac52189363b252aa8ea10fdd66efef069d665 /src/uscxml/plugins/invoker | |
parent | 567df9318fff6d1bb570191c33ea68cd6ef88bee (diff) | |
download | uscxml-36b5c7614cc896d043ddeebae1cdb4e8e94afe18.zip uscxml-36b5c7614cc896d043ddeebae1cdb4e8e94afe18.tar.gz uscxml-36b5c7614cc896d043ddeebae1cdb4e8e94afe18.tar.bz2 |
Reduced compile times
- new commandline argument handling
- compiles on windows again
Diffstat (limited to 'src/uscxml/plugins/invoker')
-rw-r--r-- | src/uscxml/plugins/invoker/im/IMInvoker.cpp | 412 | ||||
-rw-r--r-- | src/uscxml/plugins/invoker/im/IMInvoker.h | 46 |
2 files changed, 331 insertions, 127 deletions
diff --git a/src/uscxml/plugins/invoker/im/IMInvoker.cpp b/src/uscxml/plugins/invoker/im/IMInvoker.cpp index cff9b5f..1e12650 100644 --- a/src/uscxml/plugins/invoker/im/IMInvoker.cpp +++ b/src/uscxml/plugins/invoker/im/IMInvoker.cpp @@ -7,12 +7,13 @@ #endif #define GET_INSTANCE_IN_CALLBACK(account) \ -tthread::lock_guard<tthread::mutex> lock(_accountMutex); \ +tthread::lock_guard<tthread::recursive_mutex> lock(_accountMutex); \ +IMInvoker* inst = NULL;\ if (_accountInstances.find(account) == _accountInstances.end()) { \ LOG(ERROR) << "Callback for unknown account called"; \ - return; \ -} \ -IMInvoker* inst = _accountInstances[account];\ +} else {\ + inst = _accountInstances[account];\ +} namespace uscxml { @@ -35,13 +36,19 @@ PurpleEventLoopUiOps IMInvoker::_uiEventLoopOps = purpleEventTimeoutRemove, purpleEventInputAdd, purpleEventInputRemove, - NULL, //purpleEventInputGetError, + purpleEventInputGetError, purpleEventTimeoutAddSec, NULL, NULL, NULL }; - + +PurpleDebugUiOps IMInvoker::_uiDebugOps = { + purpleDebugPrint, + purpleDebugIsEnabled, + NULL, NULL, NULL, NULL +}; + PurpleAccountUiOps IMInvoker::_uiAccountOps = { accountNotifyAdded, accountStatusChanged, @@ -181,7 +188,7 @@ PurpleWhiteboardUiOps IMInvoker::_uiWhiteboardOps = { }; PurpleCoreUiOps IMInvoker::_uiCoreOps = { - NULL, + purplePrefsInit, NULL, purpleUIInit, NULL, @@ -196,9 +203,39 @@ DelayedEventQueue* IMInvoker::_eventQueue = NULL; tthread::mutex IMInvoker::_initMutex; tthread::condition_variable IMInvoker::_initCond; -tthread::mutex IMInvoker::_accountMutex; +tthread::recursive_mutex IMInvoker::_accountMutex; std::map<PurpleAccount*, IMInvoker*> IMInvoker::_accountInstances; + +void IMInvoker::setupPurpleSignals() { + int handle; + // connection signals + purple_signal_connect(purple_connections_get_handle(), "signed-on", &handle, PURPLE_CALLBACK(signedOnCB), NULL); + + // conversation signals + purple_signal_connect(purple_conversations_get_handle(), "conversation-created", &handle, PURPLE_CALLBACK(conversationCreatedCB), NULL); + purple_signal_connect(purple_conversations_get_handle(), "chat-joined", &handle, PURPLE_CALLBACK(chatJoinedCB), NULL); + purple_signal_connect(purple_conversations_get_handle(), "chat-join-failed", &handle, PURPLE_CALLBACK(chatJoinFailedCB), NULL); + purple_signal_connect(purple_conversations_get_handle(), "buddy-typing", &handle, PURPLE_CALLBACK(buddyTypingCB), NULL); + purple_signal_connect(purple_conversations_get_handle(), "buddy-typed", &handle, PURPLE_CALLBACK(buddyTypedCB), NULL); + purple_signal_connect(purple_conversations_get_handle(), "buddy-typing-stopped", &handle, PURPLE_CALLBACK(buddyTypingStoppedCB), NULL); + + // buddy signals + purple_signal_connect(purple_blist_get_handle(), "buddy-signed-on", &handle, PURPLE_CALLBACK(buddyEventCB), GINT_TO_POINTER(PURPLE_BUDDY_SIGNON)); + purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off", &handle, PURPLE_CALLBACK(buddyEventCB), GINT_TO_POINTER(PURPLE_BUDDY_SIGNOFF)); + purple_signal_connect(purple_blist_get_handle(), "buddy-got-login-time", &handle, PURPLE_CALLBACK(buddyEventCB), GINT_TO_POINTER(PURPLE_BUDDY_SIGNON_TIME)); + purple_signal_connect(purple_blist_get_handle(), "buddy-idle-changed", &handle, PURPLE_CALLBACK(buddyIdleChangedCB), NULL); + purple_signal_connect(purple_blist_get_handle(), "buddy-status-changed", &handle, PURPLE_CALLBACK(buddyStatusChangedCB), NULL); + purple_signal_connect(purple_blist_get_handle(), "buddy-icon-changed", &handle, PURPLE_CALLBACK(buddyEventCB), GINT_TO_POINTER(PURPLE_BUDDY_ICON)); + 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(), "blist-node-aliased", &handle, PURPLE_CALLBACK(blistNodeAliasedCB), NULL); + purple_signal_connect(purple_blist_get_handle(), "buddy-caps-changed", &handle, PURPLE_CALLBACK(buddyCapsChangedCB), NULL); + + // xfer signals + purple_signal_connect(purple_xfers_get_handle(), "file-recv-request", &handle, PURPLE_CALLBACK(fileRecvRequestCB), NULL); +} + void IMInvoker::initLibPurple(void *userdata, const std::string event) { _initMutex.lock(); @@ -218,7 +255,6 @@ void IMInvoker::initLibPurple(void *userdata, const std::string event) { purple_debug_set_enabled(false); purple_core_set_ui_ops(&_uiCoreOps); -// purple_eventloop_set_ui_ops(&glib_eventloops); purple_eventloop_set_ui_ops(&_uiEventLoopOps); purple_plugins_add_search_path("/usr/local/lib/purple-3"); @@ -257,64 +293,153 @@ void IMInvoker::initLibPurple(void *userdata, const std::string event) { _initMutex.unlock(); _initCond.notify_all(); +} +// purple event callbacks +void IMInvoker::signedOnCB(PurpleConnection *gc, gpointer null) { + PurpleAccount *account = purple_connection_get_account(gc); + GET_INSTANCE_IN_CALLBACK(account); + if (!inst) + return; + +#if 0 + GSList *buddies = purple_find_buddies(purple_connection_get_account(gc), NULL); + GSList *cur; + for (cur = buddies; cur; cur = cur->next) { + buddyAddedCB((PurpleBuddy *)cur->data); + } + g_slist_free(buddies); +#endif + + // set my status to active + PurpleSavedStatus* status = purple_savedstatus_new(NULL, PURPLE_STATUS_AVAILABLE); + purple_savedstatus_activate(status); + + Event retEv("im.signed.on"); + inst->returnEvent(retEv); } -void IMInvoker::buddyStatusChangedCB(PurpleBuddy *buddy, PurpleStatus *old, PurpleStatus *newstatus) { +void IMInvoker::conversationCreatedCB(PurpleConversation *conv, void *data) {} +void IMInvoker::chatJoinedCB(PurpleConversation *conv, void *data) {} +void IMInvoker::chatJoinFailedCB(PurpleConnection *gc, GHashTable *components) {} +void IMInvoker::buddyTypingCB(PurpleAccount *account, const char *name, void *data) {} +void IMInvoker::buddyTypedCB(PurpleAccount *account, const char *name, void *data) {} +void IMInvoker::buddyTypingStoppedCB(PurpleAccount *account, const char *name, void *data) {} + +void IMInvoker::buddyEventCB(PurpleBuddy *buddy, PurpleBuddyEvent event) { + if (!buddy) + return; + PurpleAccount *account = purple_buddy_get_account(buddy); GET_INSTANCE_IN_CALLBACK(account); + if (!inst) + return; + + switch (event) { + case PURPLE_BUDDY_SIGNOFF: + case PURPLE_BUDDY_SIGNON: { + PurplePresence* presence = purple_buddy_get_presence(buddy); + PurpleStatus* status = purple_presence_get_active_status(presence); + buddyStatusChangedCB(buddy, NULL, status, event); + break; + } + case PURPLE_BUDDY_ICON: + break; + + default: + break; + } - std::string buddyName = purple_buddy_get_name(buddy); - inst->_dataModelVars.compound["buddies"].compound[buddyName] = buddyToData(buddy); } -void IMInvoker::buddyIdleChangeCB(PurpleBuddy *buddy, gboolean old_idle, gboolean idle) { +void IMInvoker::buddyIdleChangedCB(PurpleBuddy *buddy, gboolean old_idle, gboolean idle, PurpleBuddyEvent event) { +} + +void IMInvoker::buddyStatusChangedCB(PurpleBuddy *buddy, PurpleStatus *old, PurpleStatus *newstatus, PurpleBuddyEvent event) { PurpleAccount *account = purple_buddy_get_account(buddy); GET_INSTANCE_IN_CALLBACK(account); -} + + std::string buddyName = purple_buddy_get_name(buddy); + Data buddyData = buddyToData(buddy); + inst->_dataModelVars.compound["buddies"].compound[buddyName] = buddyData; + + Event retEv("im.buddy.status.changed"); + retEv.data = buddyData; + inst->returnEvent(retEv); -void IMInvoker::buddyUpdateIdleCB() { } void IMInvoker::buddyAddedCB(PurpleBuddy* buddy) { PurpleAccount *account = purple_buddy_get_account(buddy); GET_INSTANCE_IN_CALLBACK(account); + if (!inst) + return; + + std::string buddyName = purple_buddy_get_name(buddy); + + Event retEv("im.buddy.added"); + retEv.data.compound["name"] = Data(buddyName, Data::VERBATIM); + inst->returnEvent(retEv); + + buddyStatusChangedCB(buddy, NULL, purple_presence_get_active_status(purple_buddy_get_presence(buddy)), PURPLE_BUDDY_NONE); + } void IMInvoker::buddyRemovedCB(PurpleBuddy* buddy) { PurpleAccount *account = purple_buddy_get_account(buddy); GET_INSTANCE_IN_CALLBACK(account); + std::string buddyName = purple_buddy_get_name(buddy); + + Event retEv("im.buddy.removed"); + retEv.data.compound["name"] = Data(buddyName, Data::VERBATIM); + inst->returnEvent(retEv); + + inst->_dataModelVars.compound["buddies"].compound.erase(buddyName); + } -void IMInvoker::buddyCapsChangedCB(PurpleBuddy* buddy, PurpleMediaCaps newcaps, PurpleMediaCaps oldcaps) { - PurpleAccount *account = purple_buddy_get_account(buddy); - GET_INSTANCE_IN_CALLBACK(account); +void IMInvoker::blistNodeAliasedCB(PurpleBlistNode *node, char *old_alias) { } -gboolean IMInvoker::jabberRcvdPresenceCB(PurpleConnection *gc, const char *type, const char *from, xmlnode *presence) { - PurpleAccount *account = purple_connection_get_account(gc); - GET_INSTANCE_IN_CALLBACK(account); +void IMInvoker::fileRecvRequestCB(PurpleXfer *xfer) { + purple_xfer_set_local_filename(xfer, ""); } -void IMInvoker::buddySignOnOffCB(PurpleBuddy *buddy) { + +void IMInvoker::buddyCapsChangedCB(PurpleBuddy* buddy, PurpleMediaCaps newcaps, PurpleMediaCaps oldcaps) { 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 buddyName = purple_buddy_get_name(buddy); - inst->_dataModelVars.compound["buddies"].compound[buddyName] = buddyToData(buddy); + GET_INSTANCE_IN_CALLBACK(account); } -void IMInvoker::signedOnCB(PurpleConnection *gc, gpointer null) { - PurpleSavedStatus* status = purple_savedstatus_new(NULL, PURPLE_STATUS_AVAILABLE); - purple_savedstatus_activate(status); +Data IMInvoker::statusToData(PurpleStatus *status) { + Data data; + const char* statusName = purple_status_get_name(status); + if (statusName) data.compound["name"] = 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); + PurpleValue* statusValue = purple_status_get_attr_value(status, statusAttrId); + if (statusValue) { + data.compound[statusAttrId] = purpleValueToData(statusValue); + } + } + + data.compound["active"] = Data((bool)purple_status_is_active(status)); + data.compound["available"] = Data((bool)purple_status_is_available(status)); + data.compound["exclusive"] = Data((bool)purple_status_is_exclusive(status)); + data.compound["active"] = Data((bool)purple_status_is_active(status)); + data.compound["independent"] = Data((bool)purple_status_is_independent(status)); + data.compound["online"] = Data((bool)purple_status_is_online(status)); + + return data; } - Data IMInvoker::buddyToData(PurpleBuddy *buddy) { Data data; std::string buddyName = purple_buddy_get_name(buddy); @@ -346,53 +471,16 @@ Data IMInvoker::buddyToData(PurpleBuddy *buddy) { 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); - + data.compound["status"].compound[statusId] = statusToData(status); } } - std::cout << Data::toJSON(data); + return data; } @@ -407,7 +495,6 @@ Data IMInvoker::purpleValueToData(PurpleValue* value) { 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: @@ -480,7 +567,7 @@ boost::shared_ptr<InvokerImpl> IMInvoker::create(InterpreterImpl* interpreter) { } Data IMInvoker::getDataModelVariables() { - tthread::lock_guard<tthread::mutex> lock(_accountMutex); + tthread::lock_guard<tthread::recursive_mutex> lock(_accountMutex); return _dataModelVars; } @@ -497,7 +584,7 @@ void IMInvoker::send(const SendRequest& req) { 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; @@ -510,7 +597,6 @@ void IMInvoker::send(void *userdata, const std::string event) { 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; @@ -521,18 +607,30 @@ void IMInvoker::send(void *userdata, const std::string event) { 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); +// if (prpl_info && prpl_info->new_xfer) { +// PurpleXfer* xfer = (prpl_info->new_xfer)(purple_account_get_connection(ctx->instance->_account), receiver.c_str()); +// purple_xfer_set_local_filename(xfer, "/Users/sradomski/Documents/W3C Standards.pdf"); +// purple_xfer_set_filename(xfer, "asdfadsf.pdf"); +// purple_xfer_request(xfer); +// purple_xfer_request_accepted(xfer, "/Users/sradomski/Documents/W3C Standards.pdf"); +// } + + //Set the filename +// purple_xfer_set_local_filename(xfer, [[fileTransfer localFilename] UTF8String]); +// purple_xfer_set_filename(xfer, [[[fileTransfer localFilename] lastPathComponent] UTF8String]); +// xfer->ui_data +// purple_xfer_request(xfer); + + serv_send_file(gc, "sradomski@localhost", "/Users/sradomski/Documents/W3C Standards.pdf"); +// 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(), "/Users/sradomski/Documents/W3C Standards.pdf"); +// } +// prpl_info->send_raw(gc, data.binary->data, data.binary->size); } } -#endif } } -#endif delete(ctx); } @@ -565,23 +663,8 @@ void IMInvoker::invoke(void *userdata, const std::string event) { _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(); } @@ -616,24 +699,65 @@ guint IMInvoker::purpleEventInputAdd(int fd, PurpleInputCondition cond, PurpleIn short opMask = 0; if (cond & PURPLE_INPUT_READ) - opMask |= DelayedEventQueue::FD_READ; + opMask |= DelayedEventQueue::DEQ_READ; if (cond & PURPLE_INPUT_WRITE) - opMask |= DelayedEventQueue::FD_WRITE; + opMask |= DelayedEventQueue::DEQ_WRITE; guint eventId = g_rand_int(_gRand); +// std::cout << "-- Input add " << eventId << " --------" << fd << std::endl; _eventQueue->addEvent(toStr(eventId), fd, opMask, purpleCallback, ctx, true); return eventId; } gboolean IMInvoker::purpleEventInputRemove(guint handle) { +// std::cout << "-- Input del " << handle << std::endl; _eventQueue->cancelEvent(toStr(handle)); return true; } int IMInvoker::purpleEventInputGetError(int fd, int *error) { - // unused - std::cout << "purpleEventInputGetError" << std::endl; - return 0; + int ret; + socklen_t len; + len = sizeof(*error); + + ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, error, &len); + if (!ret && !(*error)) { + /* + * Taken from Fire's FaimP2PConnection.m: + * The job of this function is to detect if the connection failed or not + * There has to be a better way to do this + * + * Any socket that fails to connect will select for reading and writing + * and all reads and writes will fail + * Any listening socket will select for reading, and any read will fail + * So, select for writing, if you can write, and the write fails, not connected + */ + + { + fd_set thisfd; + struct timeval timeout; + + FD_ZERO(&thisfd); + FD_SET(fd, &thisfd); + timeout.tv_sec = 0; + timeout.tv_usec = 0; + select(fd+1, NULL, &thisfd, NULL, &timeout); + if(FD_ISSET(fd, &thisfd)){ + ssize_t length = 0; + char buffer[4] = {0, 0, 0, 0}; + + length = write(fd, buffer, length); + if(length == -1) + { + /* Not connected */ + ret = -1; + *error = ENOTCONN; + } + } + } + } + + return ret; } void IMInvoker::purpleCallback(void *userdata, const std::string event) { @@ -642,16 +766,20 @@ void IMInvoker::purpleCallback(void *userdata, const std::string event) { ctx->function(ctx->data); delete ctx; } else if(ctx->input) { +// std::cout << "operating on " << ctx->inputFD << std::endl; ctx->input(ctx->data, ctx->inputFD, ctx->cond); } } -void IMInvoker::purplePrefsInit(void) {} +void IMInvoker::purplePrefsInit(void) { + purple_prefs_add_bool("/auto-login", false); +} + void IMInvoker::purpleDebugInit(void) {} void IMInvoker::purpleUIInit(void) { purple_accounts_set_ui_ops(&_uiAccountOps); - purple_xfers_set_ui_ops(&_uiXferOps); +// purple_xfers_set_ui_ops(&_uiXferOps); // purple_blist_set_ui_ops(&_uiBuddyOps); // purple_notify_set_ui_ops(&_uiNotifyOps); // purple_privacy_set_ui_ops(&_uiPrivacyOps); @@ -659,6 +787,10 @@ void IMInvoker::purpleUIInit(void) { // purple_connections_set_ui_ops(&_uiConnectOps); // purple_whiteboard_set_ui_ops(&_uiWhiteboardOps); purple_conversations_set_ui_ops(&_uiConvOps); + purple_debug_set_ui_ops(&_uiDebugOps); + + setupPurpleSignals(); + } void IMInvoker::purpleQuit(void) {} @@ -697,7 +829,7 @@ void* IMInvoker::accountRequestAuthorize(PurpleAccount *account, PurpleAccountRequestAuthorizationCb authorize_cb, PurpleAccountRequestAuthorizationCb deny_cb, void *user_data) { - // always accept all requests + // always accept all "may I add you as a buddy?" requests authorize_cb(message, user_data); return user_data; } @@ -788,9 +920,11 @@ void IMInvoker::purpleCancelRemote(PurpleXfer *xfer) { } gssize IMInvoker::purpleWrite(PurpleXfer *xfer, const guchar *buffer, gssize size) { std::cout << "purpleWrite" << std::endl; + return 0; } gssize IMInvoker::purpleRead(PurpleXfer *xfer, guchar **buffer, gssize size) { std::cout << "purpleRead" << std::endl; + return 0; } void IMInvoker::purpleDataNotSent(PurpleXfer *xfer, const guchar *buffer, gsize size) { std::cout << "purpleDataNotSent" << std::endl; @@ -837,34 +971,66 @@ void* IMInvoker::purpleRequestInput(const char *title, const char *primary, 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) {} + PurpleRequestCommonParameters *cpar, void *user_data) { + return NULL; +} 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 *user_data, va_list choices) { + return NULL; +} 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) {} + size_t action_count, va_list actions) { + return NULL; +} void* IMInvoker::purpleRequestWait(const char *title, const char *primary, const char *secondary, gboolean with_progress, PurpleRequestCancelCb cancel_cb, - PurpleRequestCommonParameters *cpar, void *user_data) {} + PurpleRequestCommonParameters *cpar, void *user_data) { + return NULL; +} + +void IMInvoker::purpleRequestWaitUpdate(void *ui_handle, gboolean pulse, gfloat fraction) { -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) {} + PurpleRequestCommonParameters *cpar, void *user_data) { + return NULL; +} void* IMInvoker::purpleRequestFile(const char *title, const char *filename, gboolean savedialog, GCallback ok_cb, GCallback cancel_cb, - PurpleRequestCommonParameters *cpar, void *user_data) {} + PurpleRequestCommonParameters *cpar, void *user_data) { + // click ok + PurpleXfer *xfer = (PurpleXfer *)user_data; + PurpleXferType xferType = purple_xfer_get_type(xfer); + if (xferType == PURPLE_XFER_RECEIVE) { + ((PurpleRequestFileCb)ok_cb)(user_data, filename); + } else if (xferType == PURPLE_XFER_SEND) { + if (xfer->local_filename != NULL && xfer->filename != NULL) { + ((PurpleRequestFileCb)ok_cb)(user_data, xfer->local_filename); + } else { + ((PurpleRequestFileCb)cancel_cb)(user_data, xfer->local_filename); + } + } + return NULL; +} + 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) {} + PurpleRequestCommonParameters *cpar, void *user_data) { + return NULL; +} + +void IMInvoker::purpleRequestClose(PurpleRequestType type, void *ui_handle) { + +} // connection ui operations @@ -885,4 +1051,14 @@ void IMInvoker::purpleDrawPont(PurpleWhiteboard *wb, int x, int y, int color, in void IMInvoker::purpleDrawLine(PurpleWhiteboard *wb, int x1, int y1, int x2, int y2, int color, int size) {} void IMInvoker::purpleClearWB(PurpleWhiteboard *wb) {} +// debug ui operations +void IMInvoker::purpleDebugPrint(PurpleDebugLevel level, const char *category, const char *arg_s) { +// std::cout << category << ": " << arg_s << std::endl; +} + +gboolean IMInvoker::purpleDebugIsEnabled(PurpleDebugLevel level, const char *category) { + return true; +} + + }
\ 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 b8a57f6..51af8f8 100644 --- a/src/uscxml/plugins/invoker/im/IMInvoker.h +++ b/src/uscxml/plugins/invoker/im/IMInvoker.h @@ -13,6 +13,20 @@ extern "C" { namespace uscxml { +typedef enum { + PURPLE_BUDDY_NONE = 0x00, /**< No events. */ + PURPLE_BUDDY_SIGNON = 0x01, /**< The buddy signed on. */ + PURPLE_BUDDY_SIGNOFF = 0x02, /**< The buddy signed off. */ + PURPLE_BUDDY_INFO_UPDATED = 0x10, /**< The buddy's information (profile) changed. */ + PURPLE_BUDDY_ICON = 0x40, /**< The buddy's icon changed. */ + PURPLE_BUDDY_MISCELLANEOUS = 0x80, /**< The buddy's service-specific miscalleneous info changed. */ + PURPLE_BUDDY_SIGNON_TIME = 0x11, /**< The buddy's signon time changed. */ + PURPLE_BUDDY_EVIL = 0x12, /**< The buddy's warning level changed. */ + PURPLE_BUDDY_DIRECTIM_CONNECTED = 0x14, /**< Connected to the buddy via DirectIM. */ + PURPLE_BUDDY_DIRECTIM_DISCONNECTED = 0x18, /**< Disconnected from the buddy via DirectIM. */ + PURPLE_BUDDY_NAME = 0x20 /**<Buddy name (UID) changed. */ +} PurpleBuddyEvent; + class IMInvoker : public InvokerImpl { public: struct EventContext { @@ -38,13 +52,14 @@ public: virtual void cancel(const std::string sendId); virtual void invoke(const InvokeRequest& req); -protected: +private: static bool _libPurpleIsInitialized; static Data _pluginData; Data _dataModelVars; static Data buddyToData(PurpleBuddy *buddy); + static Data statusToData(PurpleStatus *status); static Data purpleValueToData(PurpleValue* value); static PurpleAccountUiOps _uiAccountOps; @@ -58,31 +73,39 @@ protected: static PurpleRequestUiOps _uiRequestOps; static PurpleConnectionUiOps _uiConnectOps; static PurpleWhiteboardUiOps _uiWhiteboardOps; + static PurpleDebugUiOps _uiDebugOps; static PurpleRequestFeature _features; static GHashTable* _uiInfo; static GRand* _gRand; - static tthread::mutex _accountMutex; + static tthread::recursive_mutex _accountMutex; static std::map<PurpleAccount*, IMInvoker*> _accountInstances; static tthread::mutex _initMutex; static tthread::condition_variable _initCond; static DelayedEventQueue* _eventQueue; - // event callbacks + // libpurple 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 conversationCreatedCB(PurpleConversation *conv, void *data); + static void chatJoinedCB(PurpleConversation *conv, void *data); + static void chatJoinFailedCB(PurpleConnection *gc, GHashTable *components); + static void buddyTypingCB(PurpleAccount *account, const char *name, void *data); + static void buddyTypedCB(PurpleAccount *account, const char *name, void *data); + static void buddyTypingStoppedCB(PurpleAccount *account, const char *name, void *data); + static void buddyIdleChangedCB(PurpleBuddy *buddy, gboolean old_idle, gboolean idle, PurpleBuddyEvent event); + static void blistNodeAliasedCB(PurpleBlistNode *node, char *old_alias); + static void buddyEventCB(PurpleBuddy *buddy, PurpleBuddyEvent event); + static void buddyStatusChangedCB(PurpleBuddy *buddy, PurpleStatus *oldstatus, PurpleStatus *newstatus, PurpleBuddyEvent event); static void buddyAddedCB(PurpleBuddy* buddy); static void buddyRemovedCB(PurpleBuddy* buddy); + static void fileRecvRequestCB(PurpleXfer *xfer); 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 setupPurpleSignals(); + static void send(void *userdata, const std::string event); static void invoke(void *userdata, const std::string event); @@ -104,6 +127,11 @@ protected: }; static void purpleCallback(void *userdata, const std::string event); + // libpurple debug + static void purpleDebugPrint(PurpleDebugLevel level, const char *category, const char *arg_s); + static gboolean purpleDebugIsEnabled(PurpleDebugLevel level, const char *category); + + // libpurple core operations static void purplePrefsInit(void); static void purpleDebugInit(void); |