Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ src/parser/scanner.cxx
src/sdp/sdp_parser.cxx
src/sdp/sdp_parser.hxx
src/sdp/sdp_scanner.cxx
/build

# Qt Creator files
CMakeLists.txt.user*
Expand Down
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 2.8.10...3.22 FATAL_ERROR)

project(twinkle)

set(PRODUCT_VERSION "1.10.3")
set(PRODUCT_DATE "February 18, 2022")
set(PRODUCT_VERSION "1.11.0-beta")
set(PRODUCT_DATE "March 12, 2024")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
# Add -DDEBUG for non-release builds, or uCommon will unilaterally define NDEBUG
# (https://lists.gnu.org/archive/html/bug-commoncpp/2019-12/msg00000.html)
Expand Down
59 changes: 43 additions & 16 deletions src/gui/buddylistview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,26 +26,50 @@
#include "qsize.h"
#include <QTextDocument>

void AbstractBLVItem::set_icon(t_presence_state::t_basic_state state) {
switch (state) {
case t_presence_state::ST_BASIC_UNKNOWN:
setData(0, Qt::DecorationRole, QPixmap(":/icons/images/presence_unknown.png"));

void AbstractBLVItem::set_icon( t_presence_state::t_basic_state basic_state,
t_presence_state::t_user_state user_state)
{
switch (user_state)
{
case t_presence_state::ST_USER_TALKING:
setData(0, Qt::DecorationRole, QPixmap(":/icons/images/presence_talking.png"));
break;
case t_presence_state::ST_BASIC_CLOSED:
setData(0, Qt::DecorationRole, QPixmap(":/icons/images/presence_offline.png"));
case t_presence_state::ST_USER_AFK:
setData(0, Qt::DecorationRole, QPixmap(":/icons/images/presence_afk.png"));
break;
case t_presence_state::ST_BASIC_OPEN:
setData(0, Qt::DecorationRole, QPixmap(":/icons/images/presence_online.png"));
case t_presence_state::ST_USER_BUSY:
setData(0, Qt::DecorationRole, QPixmap(":/icons/images/presence_busy.png"));
break;
case t_presence_state::ST_BASIC_FAILED:
setData(0, Qt::DecorationRole, QPixmap(":/icons/images/presence_failed.png"));
case t_presence_state::ST_USER_ONLINE:
setData(0, Qt::DecorationRole, QPixmap(":/icons/images/presence_online.png"));
break;
case t_presence_state::ST_BASIC_REJECTED:
setData(0, Qt::DecorationRole, QPixmap(":/icons/images/presence_rejected.png"));
case t_presence_state::ST_USER_OFFLINE:
setData(0, Qt::DecorationRole, QPixmap(":/icons/images/presence_offline.png"));
break;
default:
setData(0, Qt::DecorationRole, QPixmap(":/icons/images/presence_unknown.png"));
break;
// fallback to SIP basic states
switch (basic_state)
{
case t_presence_state::ST_BASIC_UNKNOWN:
setData(0, Qt::DecorationRole, QPixmap(":/icons/images/presence_unknown.png"));
break;
case t_presence_state::ST_BASIC_CLOSED:
setData(0, Qt::DecorationRole, QPixmap(":/icons/images/presence_offline.png"));
break;
case t_presence_state::ST_BASIC_OPEN:
setData(0, Qt::DecorationRole, QPixmap(":/icons/images/presence_online.png"));
break;
case t_presence_state::ST_BASIC_FAILED:
setData(0, Qt::DecorationRole, QPixmap(":/icons/images/presence_failed.png"));
break;
case t_presence_state::ST_BASIC_REJECTED:
setData(0, Qt::DecorationRole, QPixmap(":/icons/images/presence_rejected.png"));
break;
default:
setData(0, Qt::DecorationRole, QPixmap(":/icons/images/presence_unknown.png"));
break;
}
}
}

Expand Down Expand Up @@ -78,7 +102,9 @@ void BuddyListViewItem::set_icon(void) {
QString failure;
t_presence_state::t_basic_state basic_state = buddy->
get_presence_state()->get_basic_state();
AbstractBLVItem::set_icon(basic_state);
t_presence_state::t_user_state user_state = buddy->
get_presence_state()->get_user_state();
AbstractBLVItem::set_icon(basic_state, user_state);

tip += "<br>";
tip += "<b>";
Expand Down Expand Up @@ -155,6 +181,7 @@ t_buddy *BuddyListViewItem::get_buddy(void) {

void BLViewUserItem::set_icon(void) {
t_presence_state::t_basic_state basic_state;
t_presence_state::t_user_state user_state;
QString failure;
QString profile_name = QString::fromStdString(presence_epa->get_user_profile()->get_profile_name());

Expand All @@ -180,7 +207,7 @@ void BLViewUserItem::set_icon(void) {
break;
case t_presence_epa::EPA_PUBLISHED:
basic_state = presence_epa->get_basic_state();
AbstractBLVItem::set_icon(basic_state);
AbstractBLVItem::set_icon(basic_state, t_presence_state::ST_USER_UNKNOWN);

switch (presence_epa->get_basic_state()) {
case t_presence_state::ST_BASIC_CLOSED:
Expand Down
3 changes: 2 additions & 1 deletion src/gui/buddylistview.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ class AbstractBLVItem : public QTreeWidgetItem {
QString tip;

// Set the presence icon to reflect the presence state
virtual void set_icon(t_presence_state::t_basic_state state);
virtual void set_icon(t_presence_state::t_basic_state basic_state,
t_presence_state::t_user_state user_state);

public:
AbstractBLVItem(QTreeWidgetItem *parent, const QString &text);
Expand Down
3 changes: 3 additions & 0 deletions src/gui/icons.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@
<file>images/presence.png</file>
<file>images/presence_rejected.png</file>
<file>images/presence_unknown.png</file>
<file>images/presence_afk.png</file>
<file>images/presence_busy.png</file>
<file>images/presence_talking.png</file>
<file>images/print</file>
<file>images/qt-logo.png</file>
<file>images/redial-disabled.png</file>
Expand Down
Binary file modified src/gui/images/answer-disabled.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/answer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/bye-disabled.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/bye.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/dtmf-disabled.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/dtmf.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/hold-disabled.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/hold.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/invite-disabled.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/invite.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/missed-disabled.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/mute-disabled.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/mute.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/gui/images/presence_afk.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/gui/images/presence_busy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/presence_offline.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/presence_online.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/gui/images/presence_talking.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/redial-disabled.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/redial.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/redirect-disabled.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/redirect.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/reject-disabled.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/reject.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/transfer-disabled.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/gui/images/transfer.png
31 changes: 30 additions & 1 deletion src/presence/pidf_body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#define PIDF_XML_VERSION "1.0"
#define PIDF_NAMESPACE "urn:ietf:params:xml:ns:pidf"
#define SWYX_NAMESPACE "http://sip.lanphone.de/presence/"

#define IS_PIDF_TAG(node, tag) IS_XML_TAG(node, tag, PIDF_NAMESPACE)

Expand Down Expand Up @@ -56,6 +57,7 @@ bool t_pidf_xml_body::extract_status(void) {
pres_entity.clear();
tuple_id.clear();
basic_status.clear();
user_status.clear();

// Get presence entity
xmlChar *prop_entity = xmlGetProp(root_element, BAD_CAST "entity");
Expand Down Expand Up @@ -114,14 +116,32 @@ void t_pidf_xml_body::process_pidf_status(xmlNode *status) {

xmlNode *child = status->children;
for (xmlNode *cur_node = child; cur_node; cur_node = cur_node->next) {
// Process user status
if (IS_XML_TAG(cur_node, "userstatus", SWYX_NAMESPACE)) {
process_pidf_userstatus(cur_node);
}

// Process status
if (IS_PIDF_TAG(cur_node, "basic")) {
process_pidf_basic(cur_node);
break;
}
}
}

void t_pidf_xml_body::process_pidf_userstatus(xmlNode *userstatus)
{
assert(userstatus);

xmlNode *child = userstatus->children;
if (child && child->type == XML_TEXT_NODE) {
user_status = tolower((char *)child->content);
} else {
log_file->write_report("<userstatus> element has no content.",
"t_pidf_xml_body::process_pidf_userstatus",
LOG_NORMAL, LOG_WARNING);
}
}

void t_pidf_xml_body::process_pidf_basic(xmlNode *basic) {
assert(basic);

Expand Down Expand Up @@ -188,6 +208,10 @@ string t_pidf_xml_body::get_tuple_id(void) const {
return tuple_id;
}

string t_pidf_xml_body::get_user_status(void) const {
return user_status;
}

string t_pidf_xml_body::get_basic_status(void) const {
return basic_status;
}
Expand All @@ -202,6 +226,11 @@ void t_pidf_xml_body::set_tuple_id(const string &_tuple_id) {
tuple_id = _tuple_id;
}

void t_pidf_xml_body::set_user_status(const string &_user_status) {
clear_xml_doc();
user_status = _user_status;
}

void t_pidf_xml_body::set_basic_status(const string &_basic_status) {
clear_xml_doc();
basic_status = _basic_status;
Expand Down
21 changes: 18 additions & 3 deletions src/presence/pidf_body.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,20 @@

#define PIDF_STATUS_BASIC_OPEN "open"
#define PIDF_STATUS_BASIC_CLOSED "closed"
#define PIDF_STATUS_USER_ONLINE "logged on"
#define PIDF_STATUS_USER_OFFLINE "logged off"
#define PIDF_STATUS_USER_TALKING "active"
#define PIDF_STATUS_USER_AFK "away"
#define PIDF_STATUS_USER_BUSY "donotdisturb"
#define PIDF_STATUS_USER_UNKNOWN "UNKNOWN"

/** RFC 3863 pidf+xml body */
class t_pidf_xml_body : public t_sip_body_xml {
private:
string pres_entity; /**< Presence entity */
string tuple_id; /**< Id of tuple containing the basic status. */
string pres_entity; /**< Presence entity */
string tuple_id; /**< Id of tuple containing the basic status. */
string basic_status; /**< Value of basic-tag */
string user_status; /**< Vaue if ippbx:userstatus-tag */

/**
* Extract the status information from a PIDF document.
Expand Down Expand Up @@ -63,6 +70,12 @@ class t_pidf_xml_body : public t_sip_body_xml {
*/
void process_pidf_basic(xmlNode *basic);

/**
* Process userstatus element.
* @param userstatus [in] userstatus element.
*/
void process_pidf_userstatus(xmlNode *userstatus);

protected:
/**
* Create a pidf document from the values stored in the attributes.
Expand All @@ -81,14 +94,16 @@ class t_pidf_xml_body : public t_sip_body_xml {
//@{
string get_pres_entity(void) const;
string get_tuple_id(void) const;
string get_user_status(void) const;
string get_basic_status(void) const;
//@}

/** @name Setters */
//@{
void set_pres_entity(const string &_pres_entity);
void set_tuple_id(const string &_tuple_id);
void set_basic_status(const string &_basic_status);;
void set_user_status(const string &_user_status);
void set_basic_status(const string &_basic_status);
//@}

/**
Expand Down
85 changes: 84 additions & 1 deletion src/presence/presence_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,23 @@ string t_presence_state::basic_state2str(t_presence_state::t_basic_state state)
}
}

string t_presence_state::user_state2str(t_presence_state::t_user_state state) {
switch (state) {
case ST_USER_BUSY:
return "busy";
case ST_USER_AFK:
return "afk";
case ST_USER_OFFLINE:
return "offline";
case ST_USER_ONLINE:
return "online";
case ST_USER_TALKING:
return "talking";
default:
return "UNKNOWN";
}
}

string t_presence_state::basic_state2pidf_str(t_presence_state::t_basic_state state) {
if (state == ST_BASIC_OPEN) {
return PIDF_STATUS_BASIC_OPEN;
Expand All @@ -48,13 +65,52 @@ string t_presence_state::basic_state2pidf_str(t_presence_state::t_basic_state st
return PIDF_STATUS_BASIC_CLOSED;
}

string t_presence_state::user_state2pidf_str(t_presence_state::t_user_state state) {
switch (state) {
case ST_USER_OFFLINE:
return PIDF_STATUS_USER_OFFLINE;
case ST_USER_ONLINE:
return PIDF_STATUS_USER_ONLINE;
case ST_USER_TALKING:
return PIDF_STATUS_USER_TALKING;
case ST_USER_AFK:
return PIDF_STATUS_USER_AFK;
case ST_USER_BUSY:
return PIDF_STATUS_USER_BUSY;
default:
// Convert all other states to "closed".
return PIDF_STATUS_BASIC_CLOSED;
}
}

t_presence_state::t_user_state t_presence_state::pidf_str2user_state(string user_state) {
if (user_state == PIDF_STATUS_USER_OFFLINE) {
return ST_USER_OFFLINE;
}
else if (user_state == PIDF_STATUS_USER_ONLINE) {
return ST_USER_ONLINE;
}
else if (user_state == PIDF_STATUS_USER_TALKING) {
return ST_USER_TALKING;
}
else if (user_state == PIDF_STATUS_USER_AFK) {
return ST_USER_AFK;
}
else if (user_state == PIDF_STATUS_USER_BUSY) {
return ST_USER_BUSY;
} else {
return ST_USER_UNKNOWN;
}
}

t_presence_state::t_presence_state() {
assert(false);
}

t_presence_state::t_presence_state(t_buddy *_buddy) :
buddy(_buddy),
basic_state(ST_BASIC_UNKNOWN)
basic_state(ST_BASIC_UNKNOWN),
user_state(ST_USER_UNKNOWN)
{
}

Expand All @@ -66,6 +122,14 @@ t_presence_state::t_basic_state t_presence_state::get_basic_state(void) const {
return result;
}

t_presence_state::t_user_state t_presence_state::get_user_state(void) const {
t_user_state result;
mtx_state.lock();
result = user_state;
mtx_state.unlock();
return result;
}

string t_presence_state::get_failure_msg(void) const {
string result;
mtx_state.lock();
Expand All @@ -74,6 +138,25 @@ string t_presence_state::get_failure_msg(void) const {
return result;
}

void t_presence_state::set_user_state(t_presence_state::t_user_state state)
{
mtx_state.lock();
user_state = state;

log_file->write_header("t_presence_state::set_user_state", LOG_NORMAL, LOG_DEBUG);
log_file->write_raw("Presence state changed to: ");
log_file->write_raw(user_state2str(user_state));
log_file->write_endl();
log_file->write_raw(buddy->get_sip_address());
log_file->write_endl();
log_file->write_footer();

mtx_state.unlock();

// Notify the stat change to all observers of the buddy.
buddy->notify();
}

void t_presence_state::set_basic_state(t_presence_state::t_basic_state state) {
mtx_state.lock();
basic_state = state;
Expand Down
Loading