diff --git a/coreapi/friend.c b/coreapi/friend.c index fe33125d4..e02078319 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -359,11 +359,11 @@ LinphoneOnlineStatus linphone_friend_get_status(const LinphoneFriend *lf){ return online_status; } -LinphonePresenceModel * linphone_friend_get_presence(LinphoneFriend *lf) { +LinphonePresenceModel * linphone_friend_get_presence_model(LinphoneFriend *lf) { return lf->presence; } -void linphone_friend_set_presence(LinphoneFriend *lf, LinphonePresenceModel *model) { +void linphone_friend_set_presence_model(LinphoneFriend *lf, LinphonePresenceModel *model) { if (lf->presence != NULL) { linphone_presence_model_delete(lf->presence); } diff --git a/coreapi/help/buddy_status.c b/coreapi/help/buddy_status.c index 6fdb47f40..4f9db8ea7 100644 --- a/coreapi/help/buddy_status.c +++ b/coreapi/help/buddy_status.c @@ -51,9 +51,15 @@ static void stop(int signum){ * presence state change notification callback */ static void notify_presence_recv_updated (LinphoneCore *lc, LinphoneFriend *friend) { + LinphonePresenceActivity activity = LinphonePresenceActivityOffline; + const LinphonePresenceModel* model = linphone_friend_get_presence_model(friend); const LinphoneAddress* friend_address = linphone_friend_get_address(friend); - printf("New state state [%s] for user id [%s] \n" - ,linphone_online_status_to_string(linphone_friend_get_status(friend)) + char *description = NULL; + linphone_presence_model_get_activity(model, &activity, &description); + printf("New state state [%s%s%s] for user id [%s] \n" + ,linphone_presence_activity_to_string(activity) + ,(description == NULL) ? "" : ": " + ,(description == NULL) ? "" : description ,linphone_address_as_string (friend_address)); } static void new_subscription_request (LinphoneCore *lc, LinphoneFriend *friend, const char* url) { @@ -164,7 +170,8 @@ int main(int argc, char *argv[]){ } - linphone_core_set_presence_info(lc,0,NULL,LinphoneStatusOnline); /*set my status to online*/ + /*set my status to online*/ + linphone_core_set_presence_model(lc, 0, NULL, linphone_presence_model_new_with_activity(LinphonePresenceActivityOnline, NULL)); /* main loop for receiving notifications and doing background linphone core work: */ while(running){ @@ -172,7 +179,8 @@ int main(int argc, char *argv[]){ ms_usleep(50000); } - linphone_core_set_presence_info(lc,0,NULL,LinphoneStatusOffline); /* change my presence status to offline*/ + /* change my presence status to offline*/ + linphone_core_set_presence_model(lc, 0, NULL, linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline, NULL)); linphone_core_iterate(lc); /* just to make sure new status is initiate message is issued */ linphone_friend_edit(my_friend); /* start editing friend */ diff --git a/coreapi/help/doxygen.dox b/coreapi/help/doxygen.dox index 8b2e6b7b9..656f25e09 100644 --- a/coreapi/help/doxygen.dox +++ b/coreapi/help/doxygen.dox @@ -152,7 +152,7 @@ linphone_friend_done(my_friend); /*commit changes triggering an UNSUBSCRIBE mess Publishing presence status -
Local presence status can be changed using function linphone_core_set_presence_info() .New status is propagated to all friends \link linphone_core_add_friend() previously added \endlink to #LinphoneCore. +
Local presence status can be changed using function linphone_core_set_presence_model() .New status is propagated to all friends \link linphone_core_add_friend() previously added \endlink to #LinphoneCore. Handling incoming subscription request
New incoming subscription requests are process according to \link linphone_friend_set_inc_subscribe_policy() the incoming subscription policy state \endlink for subscription initiated by \link linphone_core_add_friend() members of the buddy list. \endlink diff --git a/coreapi/linphonefriend.h b/coreapi/linphonefriend.h index 8ea05e7b1..b4ee2e801 100644 --- a/coreapi/linphonefriend.h +++ b/coreapi/linphonefriend.h @@ -54,6 +54,7 @@ typedef enum { /** * Enum describing remote friend status + * @deprecated Use #LinphonePresenceModel and #LinphonePresenceActivity instead */ typedef enum _LinphoneOnlineStatus{ /** @@ -206,13 +207,26 @@ LINPHONE_PUBLIC void linphone_friend_done(LinphoneFriend *fr); /** - * get friend status + * @brief Get the status of a friend + * @param[in] lf A #LinphoneFriend object * @return #LinphoneOnlineStatus + * @deprecated Use linphone_friend_get_presence_model() instead */ LinphoneOnlineStatus linphone_friend_get_status(const LinphoneFriend *lf); -LinphonePresenceModel * linphone_friend_get_presence(LinphoneFriend *lf); -void linphone_friend_set_presence(LinphoneFriend *lf, LinphonePresenceModel *presence); +/** + * @brief Get the presence information of a friend + * @param[in] lf A #LinphoneFriend object + * @return A #LinphonePresenceModel object, or NULL if the friend to not have presence information (in which he is considered offline) + */ +LinphonePresenceModel * linphone_friend_get_presence_model(LinphoneFriend *lf); + +/** + * @brief Set the presence information of a friend + * @param[in] lf A #LinphoneFriend object + * @param[in] presence A #LinphonePresenceModel object. It can be NULL to remove the presence information of the friend. + */ +void linphone_friend_set_presence_model(LinphoneFriend *lf, LinphonePresenceModel *presence); BuddyInfo * linphone_friend_get_info(const LinphoneFriend *lf); void linphone_friend_set_ref_key(LinphoneFriend *lf, const char *key); @@ -222,41 +236,44 @@ bool_t linphone_friend_in_list(const LinphoneFriend *lf); #define linphone_friend_url(lf) ((lf)->url) /** - * return humain readable presence status + * Return humain readable presence status * @param ss + * @deprecated Use #LinphonePresenceModel, #LinphonePresenceActivity and linphone_presence_activity_to_string() instead. */ const char *linphone_online_status_to_string(LinphoneOnlineStatus ss); /** - * Set my presence status - * @param lc #LinphoneCore object - * @param minutes_away how long in away - * @param alternative_contact sip uri used to redirect call in state #LinphoneStatusMoved - * @param os #LinphoneOnlineStatus + * @brief Set my presence status + * @param[in] lc #LinphoneCore object + * @param[in] minutes_away how long in away + * @param[in] alternative_contact sip uri used to redirect call in state #LinphoneStatusMoved + * @param[in] os #LinphoneOnlineStatus + * @deprecated Use linphone_core_set_presence_model() instead */ LINPHONE_PUBLIC void linphone_core_set_presence_info(LinphoneCore *lc,int minutes_away,const char *alternative_contact,LinphoneOnlineStatus os); /** - * Set my presence status - * @param lc #LinphoneCore object - * @param minutes_away how long in away - * @param alternative_contact sip uri used to redirect call in state #LinphoneStatusMoved - * @param presence #LinphonePresenceModel + * @brief Set my presence status + * @param[in] lc #LinphoneCore object + * @param[in] minutes_away how long in away + * @param[in] alternative_contact sip uri used to redirect call in state #LinphoneStatusMoved + * @param[in] presence #LinphonePresenceModel */ LINPHONE_PUBLIC void linphone_core_set_presence_model(LinphoneCore *lc, int minutes_away, const char *alternative_contact, LinphonePresenceModel *presence); /** - * Get my presence status - * @param lc #LinphoneCore object + * @brief Get my presence status + * @param[in] lc #LinphoneCore object * @return #LinphoneOnlineStatus + * @deprecated Use linphone_core_get_presence_model() instead */ LinphoneOnlineStatus linphone_core_get_presence_info(const LinphoneCore *lc); /** - * Get my presence status - * @param lc #LinphoneCore object - * @return #LinphonePresenceModel + * @brief Get my presence status + * @param[in] lc #LinphoneCore object + * @return A #LinphonePresenceModel object, or NULL if no presence model has been set. */ LinphonePresenceModel * linphone_core_get_presence_model(const LinphoneCore *lc); diff --git a/coreapi/linphonepresence.h b/coreapi/linphonepresence.h index 869d39baf..95281bafc 100644 --- a/coreapi/linphonepresence.h +++ b/coreapi/linphonepresence.h @@ -20,68 +20,270 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef LINPHONEPRESENCE_H_ #define LINPHONEPRESENCE_H_ + #ifdef __cplusplus extern "C" { #endif +/** + * @addtogroup buddy_list + * @{ + */ + + /** Basic status as defined in section 4.1.4 of RFC 3863 */ typedef enum LinphonePresenceBasicStatus { + /** This value means that the associated contact element, if any, is ready to accept communication. */ LinphonePresenceBasicStatusOpen, + + /** This value means that the associated contact element, if any, is unable to accept communication. */ LinphonePresenceBasicStatusClosed } LinphonePresenceBasicStatus; /** Activities as defined in section 3.2 of RFC 4480 */ typedef enum LinphonePresenceActivity { + /** This value is not defined in the RFC, it corresponds to no activity with a basic status of "closed". */ LinphonePresenceActivityOffline, + + /** This value is not defined in the RFC, it corresponds to no activity with a basic status of "open". */ LinphonePresenceActivityOnline, + + /** The person has a calendar appointment, without specifying exactly of what type. This activity is + * indicated if more detailed information is not available or the person chooses not to reveal more + * information. */ LinphonePresenceActivityAppointment, + + /** The person is physically away from all interactive communication devices. */ LinphonePresenceActivityAway, + + /** The person is eating the first meal of the day, usually eaten in the morning. */ LinphonePresenceActivityBreakfast, + + /** The person is busy, without further details. */ LinphonePresenceActivityBusy, + + /** The person is having his or her main meal of the day, eaten in the evening or at midday. */ LinphonePresenceActivityDinner, + + /** This is a scheduled national or local holiday. */ LinphonePresenceActivityHoliday, + + /** The person is riding in a vehicle, such as a car, but not steering. */ LinphonePresenceActivityInTransit, + + /** The person is looking for (paid) work. */ LinphonePresenceActivityLookingForWork, + + /** The person is eating his or her midday meal. */ LinphonePresenceActivityLunch, + + /** The person is scheduled for a meal, without specifying whether it is breakfast, lunch, or dinner, + * or some other meal. */ LinphonePresenceActivityMeal, + + /** The person is in an assembly or gathering of people, as for a business, social, or religious purpose. + * A meeting is a sub-class of an appointment. */ LinphonePresenceActivityMeeting, + + /** The person is talking on the telephone. */ LinphonePresenceActivityOnThePhone, + + /** The person is engaged in an activity with no defined representation. A string describing the activity + * in plain text SHOULD be provided. */ LinphonePresenceActivityOther, + + /** A performance is a sub-class of an appointment and includes musical, theatrical, and cinematic + * performances as well as lectures. It is distinguished from a meeting by the fact that the person + * may either be lecturing or be in the audience, with a potentially large number of other people, + * making interruptions particularly noticeable. */ LinphonePresenceActivityPerformance, + + /** The person will not return for the foreseeable future, e.g., because it is no longer working for + * the company. */ LinphonePresenceActivityPermanentAbsence, + + /** The person is occupying himself or herself in amusement, sport, or other recreation. */ LinphonePresenceActivityPlaying, + + /** The person is giving a presentation, lecture, or participating in a formal round-table discussion. */ LinphonePresenceActivityPresentation, + + /** The person is visiting stores in search of goods or services. */ LinphonePresenceActivityShopping, + + /** The person is sleeping.*/ LinphonePresenceActivitySleeping, + + /** The person is observing an event, such as a sports event. */ LinphonePresenceActivitySpectator, + + /** The person is controlling a vehicle, watercraft, or plane. */ LinphonePresenceActivitySteering, + + /** The person is on a business or personal trip, but not necessarily in-transit. */ LinphonePresenceActivityTravel, + + /** The person is watching television. */ LinphonePresenceActivityTV, + + /** The activity of the person is unknown. */ LinphonePresenceActivityUnknown, + + /** A period of time devoted to pleasure, rest, or relaxation. */ LinphonePresenceActivityVacation, + + /** The person is engaged in, typically paid, labor, as part of a profession or job. */ LinphonePresenceActivityWorking, + + /** The person is participating in religious rites. */ LinphonePresenceActivityWorship } LinphonePresenceActivity; +/** + * Structure holding the information about the presence of a person. + */ struct _LinphonePresenceModel; + +/** + * Presence model type holding information about the presence of a person. + */ typedef struct _LinphonePresenceModel LinphonePresenceModel; + +/** + * @brief Creates a default presence model. + * @returns The created presence model, NULL on error. + * @see linphone_presence_model_new_with_activity + * @see linphone_presence_model_new_with_activity_and_note + * + * The created presence model is considered 'offline'. + */ LINPHONE_PUBLIC LinphonePresenceModel * linphone_presence_model_new(void); + +/** + * @brief Creates a presence model specifying an activity. + * @param[in] activity The activity to set for the created presence model. + * @param[in] description An additional description of the activity (mainly useful for the 'other' activity). Set it to NULL to not add a description. + * @returns The created presence model, or NULL if an error occured. + * @see linphone_presence_model_new + * @see linphone_presence_model_new_with_activity_and_note + * + * The created presence model has the activity specified in the parameters. + */ LINPHONE_PUBLIC LinphonePresenceModel * linphone_presence_model_new_with_activity(LinphonePresenceActivity activity, const char *description); + +/** + * @brief Creates a presence model specifying an activity and adding a note. + * @param[in] activity The activity to set for the created presence model. + * @param[in] description An additional description of the activity (mainly useful for the 'other' activity). Set it to NULL to not add a description. + * @param[in] note An additional note giving additional information about the contact presence. + * @param[in] lang The language the note is written in. It can be set to NULL in order to not specify the language of the note. + * @returns The created presence model, or NULL if an error occured. + * @see linphone_presence_model_new_with_activity + * @see linphone_presence_model_new_with_activity_and_note + * + * The created presence model has the activity and the note specified in the parameters. + */ LINPHONE_PUBLIC LinphonePresenceModel * linphone_presence_model_new_with_activity_and_note(LinphonePresenceActivity activity, const char *description, const char *note, const char *lang); + +/** + * @brief Deletes a presence model. + * @param[in] model The #LinphonePresenceModel object to delete. + */ LINPHONE_PUBLIC void linphone_presence_model_delete(LinphonePresenceModel *model); + +/** + * @brief Compares two presence models. + * @param[in] m1 The first #LinphonePresenceModel object. + * @param[in] m2 The second #LinphonePresenceModel object. + * @return TRUE if the #LinphonePresenceModel objects are equals, FALSE otherwise. + */ LINPHONE_PUBLIC bool_t linphone_presence_model_equals(const LinphonePresenceModel *m1, const LinphonePresenceModel *m2); + +/** + * @brief Gets the basic status of a presence model. + * @param[in] model The #LinphonePresenceModel object to get the basic status from. + * @return The #LinphonePresenceBasicStatus of the #LinphonePresenceModel object given as parameter. + */ LINPHONE_PUBLIC LinphonePresenceBasicStatus linphone_presence_model_get_basic_status(const LinphonePresenceModel *model); + +/** + * @brief Gets the number of activities included in the presence model. + * @param[in] model The #LinphonePresenceModel object to get the number of activities from. + * @return The number of activities included in the #LinphonePresenceModel object. + */ LINPHONE_PUBLIC unsigned int linphone_presence_model_nb_activities(const LinphonePresenceModel *model); + +/** + * @brief Gets the nth activity of a presence model. + * @param[in] model The #LinphonePresenceModel object to get the activity from. + * @param[in] idx The index of the activity to get (the first activity having the index 0). + * @param[out] activity The returned #LinphonePresenceActivity (may not be changed in case of error). + * @param[out] description The description of the returned #LinphonePresenceActivity (may not be changed in case of error). + * @return 0 if successful, a value < 0 in case of error. + */ LINPHONE_PUBLIC int linphone_presence_model_get_nth_activity(const LinphonePresenceModel *model, unsigned int idx, LinphonePresenceActivity *activity, char **description); + +/** + * @brief Gets the first activity of a presence model (there is usually only one). + * @param[in] model The #LinphonePresenceModel object to get the activity from. + * @param[out] activity The returned #LinphonePresenceActivity (may not be changed in case of error). + * @param[out] description The description of the returned #LinphonePresenceActivity (may not be changed in case of error). + * @return 0 if successful, a value < 0 in case of error. + */ LINPHONE_PUBLIC int linphone_presence_model_get_activity(const LinphonePresenceModel *model, LinphonePresenceActivity *activity, char **description); + +/** + * @brief Sets the activity of a presence model (limits to only one activity). + * @param[in] model The #LinphonePresenceModel object for which to set the activity. + * @param[in] activity The #LinphonePresenceActivity to set for the model. + * @param[in] description An additional description of the activity to set for the model. Can be NULL if no additional description is to be added. + * @return 0 if successful, a value < 0 in case of error. + */ LINPHONE_PUBLIC int linphone_presence_model_set_activity(LinphonePresenceModel *model, LinphonePresenceActivity activity, const char *description); + +/** + * @brief Gets the first note of a presence model (there is usually only one). + * @param[in] model The #LinphonePresenceModel object to get the note from. + * @param[in] lang The language of the note to get. Can be NULL to a note that has no language specified or to get the first note whatever language it is written into. + * @return A pointer to dynamically allocated string in case of success, NULL otherwise. + * + * The string that is returned MUST be freed using ms_free(). + */ LINPHONE_PUBLIC const char * linphone_presence_model_get_note(const LinphonePresenceModel *model, const char *lang); + +/** + * @brief Adds a note to a presence model. + * @param[in] model The #LinphonePresenceModel object to add a note to. + * @param[in] note_content The note to be added to the presence model. + * @param[in] lang The language of the note to be added. Can be NULL if no language is to be specified for the note. + * @return 0 if successful, a value < 0 in case of error. + * + * Only one note for each language can be set, so e.g. setting a note for the 'fr' language if there is only one will replace the existing one. + */ LINPHONE_PUBLIC int linphone_presence_model_add_note(LinphonePresenceModel *model, const char *note_content, const char *lang); + +/** + * @brief Clears all the notes of a presence model. + * @param[in] model The #LinphonePresenceModel for which to clear notes. + * @return 0 if successful, a value < 0 in case of error. + */ LINPHONE_PUBLIC int linphone_presence_model_clear_notes(LinphonePresenceModel *model); +/** + * @brief Gets the string representation of a presence activity. + * @param[in] activity The #LinphonePresenceActivity for which to get a string representation. + * @return A pointer to the string representing the given activity. + */ +LINPHONE_PUBLIC const char * linphone_presence_activity_to_string(LinphonePresenceActivity activity); + + +/** + * @} + */ + #ifdef __cplusplus } diff --git a/coreapi/presence.c b/coreapi/presence.c index 192dabb94..85fb2100f 100644 --- a/coreapi/presence.c +++ b/coreapi/presence.c @@ -945,6 +945,14 @@ static const char * presence_activity_to_string(LinphonePresenceActivity activit return NULL; } +const char * linphone_presence_activity_to_string(LinphonePresenceActivity activity) { + if (activity == LinphonePresenceActivityOffline) + return "offline"; + if (activity == LinphonePresenceActivityOnline) + return "online"; + return presence_activity_to_string(activity); +} + static int process_pidf_xml_presence_person_activities(xmlparsing_context_t *xml_ctx, struct _LinphonePresencePerson *person, unsigned int person_idx) { char xpath_str[MAX_XPATH_LENGTH]; xmlXPathObjectPtr activities_nodes_object; @@ -1162,7 +1170,13 @@ void linphone_core_reject_subscriber(LinphoneCore *lc, LinphoneFriend *lf){ void linphone_core_notify_all_friends(LinphoneCore *lc, LinphonePresenceModel *presence){ MSList *elem; - ms_message("Notifying all friends"); + LinphonePresenceActivity activity = LinphonePresenceActivityOffline; + char *description = NULL; + linphone_presence_model_get_activity(presence, &activity, &description); + ms_message("Notifying all friends that we are [%s%s%s]", + linphone_presence_activity_to_string(activity), + (description == NULL) ? "" : ": ", + (description == NULL) ? "" : description); for(elem=lc->friends;elem!=NULL;elem=elem->next){ LinphoneFriend *lf=(LinphoneFriend *)elem->data; if (lf->insub){ @@ -1501,19 +1515,28 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, Sa char *tmp; LinphoneFriend *lf; LinphoneAddress *friend=NULL; + LinphonePresenceModel *presence = (LinphonePresenceModel *)model; lf=linphone_find_friend_by_out_subscribe(lc->friends,op); if (lf!=NULL){ + LinphonePresenceActivity activity = LinphonePresenceActivityOffline; + char *description = NULL; friend=lf->uri; tmp=linphone_address_as_string(friend); - linphone_friend_set_presence(lf, (LinphonePresenceModel *)model); + linphone_presence_model_get_activity(presence, &activity, &description); + ms_message("We are notified that [%s] has presence [%s%s%s]", + tmp, + linphone_presence_activity_to_string(activity), + (description == NULL) ? "" : ": ", + (description == NULL) ? "" : description); + linphone_friend_set_presence_model(lf, presence); lf->subscribe_active=TRUE; if (lc->vtable.notify_presence_recv) lc->vtable.notify_presence_recv(lc,(LinphoneFriend*)lf); ms_free(tmp); }else{ ms_message("But this person is not part of our friend list, so we don't care."); - linphone_presence_model_delete((LinphonePresenceModel *)model); + linphone_presence_model_delete(presence); } if (ss==SalSubscribeTerminated){ sal_op_release(op);