From 2ce47c31248731fe8dff3ae534d6ca3feef75dc4 Mon Sep 17 00:00:00 2001 From: Jakub Adam Date: Tue, 4 Sep 2012 14:36:00 +0200 Subject: [PATCH] media: set "In a call" status when media call is in progress --- src/core/sipe-media.c | 12 ++++++ src/core/sipe-notify.c | 6 +-- src/core/sipe-ocs2007.c | 94 +++++++++++++++++++++++++++++++++++++++------- src/core/sipe-ocs2007.h | 4 +- src/core/sipe-utils.c | 2 + src/core/sipe-utils.h | 10 ++++- src/purple/purple-plugin.c | 6 +++ 7 files changed, 116 insertions(+), 18 deletions(-) diff --git a/src/core/sipe-media.c b/src/core/sipe-media.c index 22f1bded..2594f768 100644 --- a/src/core/sipe-media.c +++ b/src/core/sipe-media.c @@ -41,6 +41,7 @@ #include "sipe-core-private.h" #include "sipe-dialog.h" #include "sipe-media.h" +#include "sipe-ocs2007.h" #include "sipe-session.h" #include "sipe-utils.h" #include "sipe-nls.h" @@ -562,12 +563,22 @@ candidates_prepared_cb(struct sipe_media_call *call, } } +static void phone_state_publish(struct sipe_core_private *sipe_private) +{ + if (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007)) { + sipe_ocs2007_phone_state_publish(sipe_private); + } else { + // TODO: OCS 2005 support. Is anyone still using it at all? + } +} + static void media_end_cb(struct sipe_media_call *call) { g_return_if_fail(call); SIPE_MEDIA_CALL_PRIVATE->sipe_private->media_call = NULL; + phone_state_publish(SIPE_MEDIA_CALL_PRIVATE->sipe_private); sipe_media_call_free(SIPE_MEDIA_CALL_PRIVATE); } @@ -577,6 +588,7 @@ call_accept_cb(struct sipe_media_call *call, gboolean local) if (local) { send_invite_response_if_ready(SIPE_MEDIA_CALL_PRIVATE); } + phone_state_publish(SIPE_MEDIA_CALL_PRIVATE->sipe_private); } static void diff --git a/src/core/sipe-notify.c b/src/core/sipe-notify.c index 2bab9129..5d849d71 100644 --- a/src/core/sipe-notify.c +++ b/src/core/sipe-notify.c @@ -304,7 +304,7 @@ static void process_incoming_notify_msrtc(struct sipe_core_private *sipe_private res_avail = sipe_ocs2007_availability_from_status(status_id, NULL); if (user_avail > res_avail) { res_avail = user_avail; - status_id = sipe_ocs2007_status_from_legacy_availability(user_avail); + status_id = sipe_ocs2007_status_from_legacy_availability(user_avail, NULL); } if (xn_display_name) { @@ -405,7 +405,7 @@ static void process_incoming_notify_msrtc(struct sipe_core_private *sipe_private } activity_since = dev_avail_since; } - status_id = sipe_ocs2007_status_from_legacy_availability(res_avail); + status_id = sipe_ocs2007_status_from_legacy_availability(res_avail, NULL); new_desc = sipe_ocs2007_legacy_activity_description(res_avail); if (new_desc) { g_free(activity); @@ -738,7 +738,7 @@ static void process_incoming_notify_rlmi(struct sipe_core_private *sipe_private, g_free(meeting_location); } - status = sipe_ocs2007_status_from_legacy_availability(availability); + status = sipe_ocs2007_status_from_legacy_availability(availability, NULL); tmp = sipe_ocs2007_legacy_activity_description(availability); if (sbuddy->activity && tmp) { gchar *tmp2 = sbuddy->activity; diff --git a/src/core/sipe-ocs2007.c b/src/core/sipe-ocs2007.c index dc18eef4..71b7d23f 100644 --- a/src/core/sipe-ocs2007.c +++ b/src/core/sipe-ocs2007.c @@ -91,7 +91,11 @@ struct sipe_publication { #define SIPE_OCS2007_LEGACY_AVAILIBILITY_BRB 12000 /* be right back */ #define SIPE_OCS2007_LEGACY_AVAILIBILITY_AWAY 15000 #define SIPE_OCS2007_LEGACY_AVAILIBILITY_OFFLINE 18000 -const gchar *sipe_ocs2007_status_from_legacy_availability(guint availability) + +#define SIPE_OCS2007_ACTIVITY_ON_PHONE "on-the-phone" + +const gchar *sipe_ocs2007_status_from_legacy_availability(guint availability, + const gchar *activity) { guint type; @@ -102,7 +106,11 @@ const gchar *sipe_ocs2007_status_from_legacy_availability(guint availability) } else if (availability < SIPE_OCS2007_LEGACY_AVAILIBILITY_BUSY) { type = SIPE_ACTIVITY_INACTIVE; } else if (availability < SIPE_OCS2007_LEGACY_AVAILIBILITY_BUSYIDLE) { - type = SIPE_ACTIVITY_BUSY; + if (sipe_strequal(activity, SIPE_OCS2007_ACTIVITY_ON_PHONE)) { + type = SIPE_ACTIVITY_ON_PHONE; + } else { + type = SIPE_ACTIVITY_BUSY; + } } else if (availability < SIPE_OCS2007_LEGACY_AVAILIBILITY_DND) { type = SIPE_ACTIVITY_BUSYIDLE; } else if (availability < SIPE_OCS2007_LEGACY_AVAILIBILITY_BRB) { @@ -783,11 +791,11 @@ static void schedule_publish_update(struct sipe_core_private *sipe_private, ""\ "" /** - * Publishes to clear 'calendarState' category + * Publishes to clear 'calendarState' and 'phoneState' category * @param instance (%u) Ex.: 1251210982 * @param version (%u) Ex.: 1 */ -#define SIPE_PUB_XML_STATE_CALENDAR_CLEAR \ +#define SIPE_PUB_XML_STATE_CALENDAR_PHONE_CLEAR \ ""\ "" @@ -818,6 +826,27 @@ static void schedule_publish_update(struct sipe_core_private *sipe_private, "%s"\ ""\ "" +/** + * Publishes 'phoneState' category. + * @param instance (%u) Ex.: 1339299275 + * @param version (%u) Ex.: 1 + * + * @param instance (%u) Ex.: 1339299275 + * @param version (%u) Ex.: 1 + */ +#define SIPE_PUB_XML_STATE_PHONE \ + ""\ + ""\ + "6500"\ + ""\ + ""\ + ""\ + ""\ + ""\ + "6500"\ + ""\ + ""\ + "" /** * Only Busy and OOF calendar event are published. @@ -922,7 +951,7 @@ static gchar *sipe_publish_get_category_state_calendar(struct sipe_core_private } else /* including !event, SIPE_CAL_FREE, SIPE_CAL_TENTATIVE */ { - res = g_strdup_printf(SIPE_PUB_XML_STATE_CALENDAR_CLEAR, + res = g_strdup_printf(SIPE_PUB_XML_STATE_CALENDAR_PHONE_CLEAR, instance, publication_2 ? publication_2->version : 0, @@ -1767,6 +1796,30 @@ void sipe_ocs2007_category_publish(struct sipe_core_private *sipe_private) g_free(publications); } +void sipe_ocs2007_phone_state_publish(struct sipe_core_private *sipe_private) +{ + gchar *publications = NULL; + guint instance = sipe_get_pub_instance(sipe_private, SIPE_PUB_STATE_PHONE_VOIP); + + /* key is */ + gchar *key_2 = g_strdup_printf("<%s><%u><%u>", "state", instance, 2); + gchar *key_3 = g_strdup_printf("<%s><%u><%u>", "state", instance, 3); + struct sipe_publication *publication_2 = + g_hash_table_lookup(g_hash_table_lookup(sipe_private->our_publications, "state"), key_2); + struct sipe_publication *publication_3 = + g_hash_table_lookup(g_hash_table_lookup(sipe_private->our_publications, "state"), key_3); + g_free(key_2); + g_free(key_3); + + publications = g_strdup_printf((sipe_private->media_call) ? + SIPE_PUB_XML_STATE_PHONE : SIPE_PUB_XML_STATE_CALENDAR_PHONE_CLEAR, + instance, publication_2 ? publication_2->version : 0, + instance, publication_3 ? publication_3->version : 0); + + send_presence_publish(sipe_private, publications); + g_free(publications); +} + static void sipe_publish_get_cat_state_user_to_clear(SIPE_UNUSED_PARAMETER const char *name, gpointer value, GString* str) @@ -1808,13 +1861,14 @@ static gboolean sipe_is_our_publication(struct sipe_core_private *sipe_private, /* filling keys for our publications if not yet cached */ if (!sipe_private->our_publication_keys) { - guint device_instance = sipe_get_pub_instance(sipe_private, SIPE_PUB_DEVICE); - guint machine_instance = sipe_get_pub_instance(sipe_private, SIPE_PUB_STATE_MACHINE); - guint user_instance = sipe_get_pub_instance(sipe_private, SIPE_PUB_STATE_USER); - guint calendar_instance = sipe_get_pub_instance(sipe_private, SIPE_PUB_STATE_CALENDAR); - guint cal_oof_instance = sipe_get_pub_instance(sipe_private, SIPE_PUB_STATE_CALENDAR_OOF); - guint cal_data_instance = sipe_get_pub_instance(sipe_private, SIPE_PUB_CALENDAR_DATA); - guint note_oof_instance = sipe_get_pub_instance(sipe_private, SIPE_PUB_NOTE_OOF); + guint device_instance = sipe_get_pub_instance(sipe_private, SIPE_PUB_DEVICE); + guint machine_instance = sipe_get_pub_instance(sipe_private, SIPE_PUB_STATE_MACHINE); + guint user_instance = sipe_get_pub_instance(sipe_private, SIPE_PUB_STATE_USER); + guint calendar_instance = sipe_get_pub_instance(sipe_private, SIPE_PUB_STATE_CALENDAR); + guint cal_oof_instance = sipe_get_pub_instance(sipe_private, SIPE_PUB_STATE_CALENDAR_OOF); + guint phone_voip_instance = sipe_get_pub_instance(sipe_private, SIPE_PUB_STATE_PHONE_VOIP); + guint cal_data_instance = sipe_get_pub_instance(sipe_private, SIPE_PUB_CALENDAR_DATA); + guint note_oof_instance = sipe_get_pub_instance(sipe_private, SIPE_PUB_NOTE_OOF); SIPE_DEBUG_INFO_NOFORMAT("* Our Publication Instances *"); SIPE_DEBUG_INFO("\tDevice : %u\t0x%08X", device_instance, device_instance); @@ -1822,6 +1876,7 @@ static gboolean sipe_is_our_publication(struct sipe_core_private *sipe_private, SIPE_DEBUG_INFO("\tUser Stare : %u\t0x%08X", user_instance, user_instance); SIPE_DEBUG_INFO("\tCalendar State : %u\t0x%08X", calendar_instance, calendar_instance); SIPE_DEBUG_INFO("\tCalendar OOF State : %u\t0x%08X", cal_oof_instance, cal_oof_instance); + SIPE_DEBUG_INFO("\tVOIP Phone State : %u\t0x%08X", phone_voip_instance, phone_voip_instance); SIPE_DEBUG_INFO("\tCalendar FreeBusy : %u\t0x%08X", cal_data_instance, cal_data_instance); SIPE_DEBUG_INFO("\tOOF Note : %u\t0x%08X", note_oof_instance, note_oof_instance); SIPE_DEBUG_INFO("\tNote : %u", 0); @@ -1855,6 +1910,12 @@ static gboolean sipe_is_our_publication(struct sipe_core_private *sipe_private, sipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys, g_strdup_printf("<%s><%u><%u>", "state", cal_oof_instance, 3)); + /* state:phoneState */ + sipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys, + g_strdup_printf("<%s><%u><%u>", "state", phone_voip_instance, 2)); + sipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys, + g_strdup_printf("<%s><%u><%u>", "state", phone_voip_instance, 3)); + /* note */ sipe_private->our_publication_keys = g_slist_append(sipe_private->our_publication_keys, g_strdup_printf("<%s><%u><%u>", "note", 0, 200)); @@ -1956,6 +2017,7 @@ void sipe_ocs2007_process_roaming_self(struct sipe_core_private *sipe_private, char *uri; GSList *category_names = NULL; int aggreg_avail = 0; + gchar *activity_token = NULL; gboolean do_update_status = FALSE; gboolean has_note_cleaned = FALSE; GHashTable *devices; @@ -2163,6 +2225,7 @@ void sipe_ocs2007_process_roaming_self(struct sipe_core_private *sipe_private, /* aggregateState (not an our publication) from 2-nd container */ if (sipe_strequal(name, "state") && container == 2) { const sipe_xml *xn_state = sipe_xml_child(node, "state"); + const sipe_xml *xn_activity = sipe_xml_child(xn_state, "activity"); if (xn_state && sipe_strequal(sipe_xml_attribute(xn_state, "type"), "aggregateState")) { const sipe_xml *xn_avail = sipe_xml_child(xn_state, "availability"); @@ -2177,6 +2240,10 @@ void sipe_ocs2007_process_roaming_self(struct sipe_core_private *sipe_private, do_update_status = TRUE; } + + if (xn_activity) { + activity_token = g_strdup(sipe_xml_attribute(xn_activity, "token")); + } } /* userProperties published by server from AD */ @@ -2337,7 +2404,7 @@ void sipe_ocs2007_process_roaming_self(struct sipe_core_private *sipe_private, (aggreg_avail < SIPE_OCS2007_LEGACY_AVAILIBILITY_OFFLINE)) { /* not offline */ sipe_status_set_token(sipe_private, - sipe_ocs2007_status_from_legacy_availability(aggreg_avail)); + sipe_ocs2007_status_from_legacy_availability(aggreg_avail, activity_token)); } else { /* do not let offline status switch us off */ sipe_status_set_activity(sipe_private, @@ -2350,6 +2417,7 @@ void sipe_ocs2007_process_roaming_self(struct sipe_core_private *sipe_private, } g_free(to); + g_free(activity_token); } /** diff --git a/src/core/sipe-ocs2007.h b/src/core/sipe-ocs2007.h index 49625fa1..839716cc 100644 --- a/src/core/sipe-ocs2007.h +++ b/src/core/sipe-ocs2007.h @@ -37,7 +37,8 @@ struct sipe_core_private; */ guint sipe_ocs2007_availability_from_status(const gchar *sipe_status_id, const gchar **activity_token); -const gchar *sipe_ocs2007_status_from_legacy_availability(guint availability); +const gchar *sipe_ocs2007_status_from_legacy_availability(guint availability, + const gchar *activity); const gchar *sipe_ocs2007_legacy_activity_description(guint availability); gboolean sipe_ocs2007_status_is_busy(const gchar *status_id); gboolean sipe_ocs2007_availability_is_away(guint availability); @@ -49,6 +50,7 @@ void sipe_ocs2007_presence_publish(struct sipe_core_private *sipe_private, gpointer unused); void sipe_ocs2007_free(struct sipe_core_private *sipe_private); void sipe_ocs2007_category_publish(struct sipe_core_private *sipe_private); +void sipe_ocs2007_phone_state_publish(struct sipe_core_private *sipe_private); void sipe_ocs2007_reset_status(struct sipe_core_private *sipe_private); void sipe_ocs2007_process_roaming_self(struct sipe_core_private *sipe_private, struct sipmsg *msg); diff --git a/src/core/sipe-utils.c b/src/core/sipe-utils.c index 5a78a62b..2fab5b3e 100644 --- a/src/core/sipe-utils.c +++ b/src/core/sipe-utils.c @@ -191,6 +191,8 @@ sipe_get_pub_instance(struct sipe_core_private *sipe_private, sscanf(mail_hash, "%08x", &calendar_id); g_free(mail_hash); res = (calendar_id >> 4) | 0x40000000; + } else if (publication_key == SIPE_PUB_STATE_PHONE_VOIP) { /* First hexadecimal digit is 0x8 */ + res = (res >> 4) | 0x80000000; } return res; diff --git a/src/core/sipe-utils.h b/src/core/sipe-utils.h index 499e5bf1..5f3c1ac7 100644 --- a/src/core/sipe-utils.h +++ b/src/core/sipe-utils.h @@ -82,7 +82,15 @@ struct sipe_transport_connection; * Availability and activity for RCC call connect/disconnect or participant count changes from 0 to 2, 2 to N, N to 2, 2 to 0. * First hexadecimal digit is 0x7; remaining seven hexadecimal digits are unique per device. */ -#define SIPE_PUB_STATE_PHONE 7 +#define SIPE_PUB_STATE_PHONE_RCC 7 +/** + * state + * VOIP Phone State + * + * Availability and activity for VOIP call connect/disconnect or participant count changes from 0 to 2, 2 to N, N to 2, 2 to 0. + * First hexadecimal digit is 0x8; remaining seven hexadecimal digits uniquely define the SIP URI and device. + */ +#define SIPE_PUB_STATE_PHONE_VOIP 8 /** * calendarData * Free/busy data diff --git a/src/purple/purple-plugin.c b/src/purple/purple-plugin.c index 65999130..9b264c10 100644 --- a/src/purple/purple-plugin.c +++ b/src/purple/purple-plugin.c @@ -192,6 +192,12 @@ static GList *sipe_purple_status_types(SIPE_UNUSED_PARAMETER PurpleAccount *acc) NULL, TRUE); + /* In a call */ + SIPE_ADD_STATUS(PURPLE_STATUS_UNAVAILABLE, + sipe_purple_activity_to_token(SIPE_ACTIVITY_ON_PHONE), + sipe_core_activity_description(SIPE_ACTIVITY_ON_PHONE), + FALSE); + /* Away */ /* Goes first in the list as * purple picks the first status with the AWAY type -- 2.11.4.GIT