diff options
-rw-r--r-- | toxcore/Messenger.c | 60 | ||||
-rw-r--r-- | toxcore/Messenger.h | 26 | ||||
-rw-r--r-- | toxcore/tox.c | 34 | ||||
-rw-r--r-- | toxcore/tox.h | 20 |
4 files changed, 140 insertions, 0 deletions
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 692d3d0e..ee5213a7 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c | |||
@@ -268,6 +268,7 @@ int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length) | |||
268 | m->friendlist[i].statusmessage = calloc(1, 1); | 268 | m->friendlist[i].statusmessage = calloc(1, 1); |
269 | m->friendlist[i].statusmessage_length = 1; | 269 | m->friendlist[i].statusmessage_length = 1; |
270 | m->friendlist[i].userstatus = USERSTATUS_NONE; | 270 | m->friendlist[i].userstatus = USERSTATUS_NONE; |
271 | m->friendlist[i].is_typing = 0; | ||
271 | memcpy(m->friendlist[i].info, data, length); | 272 | memcpy(m->friendlist[i].info, data, length); |
272 | m->friendlist[i].info_size = length; | 273 | m->friendlist[i].info_size = length; |
273 | m->friendlist[i].message_id = 0; | 274 | m->friendlist[i].message_id = 0; |
@@ -315,6 +316,7 @@ int m_addfriend_norequest(Messenger *m, uint8_t *client_id) | |||
315 | m->friendlist[i].statusmessage = calloc(1, 1); | 316 | m->friendlist[i].statusmessage = calloc(1, 1); |
316 | m->friendlist[i].statusmessage_length = 1; | 317 | m->friendlist[i].statusmessage_length = 1; |
317 | m->friendlist[i].userstatus = USERSTATUS_NONE; | 318 | m->friendlist[i].userstatus = USERSTATUS_NONE; |
319 | m->friendlist[i].is_typing = 0; | ||
318 | m->friendlist[i].message_id = 0; | 320 | m->friendlist[i].message_id = 0; |
319 | m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */ | 321 | m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */ |
320 | 322 | ||
@@ -615,6 +617,29 @@ USERSTATUS m_get_self_userstatus(Messenger *m) | |||
615 | return m->userstatus; | 617 | return m->userstatus; |
616 | } | 618 | } |
617 | 619 | ||
620 | int m_set_usertyping(Messenger *m, int friendnumber, uint8_t is_typing) | ||
621 | { | ||
622 | if (is_typing != 0 || is_typing != 1) { | ||
623 | return -1; | ||
624 | } | ||
625 | |||
626 | if (friend_not_valid(m, friendnumber)) | ||
627 | return -1; | ||
628 | |||
629 | m->friendlist[friendnumber].user_istyping = is_typing; | ||
630 | m->friendlist[friendnumber].user_istyping_sent = 0; | ||
631 | |||
632 | return 0; | ||
633 | } | ||
634 | |||
635 | uint8_t m_get_istyping(Messenger *m, int friendnumber) | ||
636 | { | ||
637 | if (friend_not_valid(m, friendnumber)) | ||
638 | return -1; | ||
639 | |||
640 | return m->friendlist[friendnumber].is_typing; | ||
641 | } | ||
642 | |||
618 | static int send_statusmessage(Messenger *m, int friendnumber, uint8_t *status, uint16_t length) | 643 | static int send_statusmessage(Messenger *m, int friendnumber, uint8_t *status, uint16_t length) |
619 | { | 644 | { |
620 | return write_cryptpacket_id(m, friendnumber, PACKET_ID_STATUSMESSAGE, status, length); | 645 | return write_cryptpacket_id(m, friendnumber, PACKET_ID_STATUSMESSAGE, status, length); |
@@ -626,6 +651,12 @@ static int send_userstatus(Messenger *m, int friendnumber, USERSTATUS status) | |||
626 | return write_cryptpacket_id(m, friendnumber, PACKET_ID_USERSTATUS, &stat, sizeof(stat)); | 651 | return write_cryptpacket_id(m, friendnumber, PACKET_ID_USERSTATUS, &stat, sizeof(stat)); |
627 | } | 652 | } |
628 | 653 | ||
654 | static int send_user_istyping(Messenger *m, int friendnumber, uint8_t is_typing) | ||
655 | { | ||
656 | uint8_t typing = is_typing; | ||
657 | return write_cryptpacket_id(m, friendnumber, PACKET_ID_TYPING, &typing, sizeof(typing)); | ||
658 | } | ||
659 | |||
629 | static int send_ping(Messenger *m, int friendnumber) | 660 | static int send_ping(Messenger *m, int friendnumber) |
630 | { | 661 | { |
631 | int ret = write_cryptpacket_id(m, friendnumber, PACKET_ID_PING, 0, 0); | 662 | int ret = write_cryptpacket_id(m, friendnumber, PACKET_ID_PING, 0, 0); |
@@ -654,6 +685,11 @@ static void set_friend_userstatus(Messenger *m, int friendnumber, USERSTATUS sta | |||
654 | m->friendlist[friendnumber].userstatus = status; | 685 | m->friendlist[friendnumber].userstatus = status; |
655 | } | 686 | } |
656 | 687 | ||
688 | static void set_friend_typing(Messenger *m, int friendnumber, uint8_t is_typing) | ||
689 | { | ||
690 | m->friendlist[friendnumber].is_typing = is_typing; | ||
691 | } | ||
692 | |||
657 | /* Sets whether we send read receipts for friendnumber. */ | 693 | /* Sets whether we send read receipts for friendnumber. */ |
658 | void m_set_sends_receipts(Messenger *m, int friendnumber, int yesno) | 694 | void m_set_sends_receipts(Messenger *m, int friendnumber, int yesno) |
659 | { | 695 | { |
@@ -707,6 +743,12 @@ void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, int, USE | |||
707 | m->friend_userstatuschange_userdata = userdata; | 743 | m->friend_userstatuschange_userdata = userdata; |
708 | } | 744 | } |
709 | 745 | ||
746 | void m_callback_typingchange(Messenger *m, void(*function)(Messenger *m, int, uint8_t, void *), void *userdata) | ||
747 | { | ||
748 | m->friend_typingchange = function; | ||
749 | m->friend_typingchange_userdata = userdata; | ||
750 | } | ||
751 | |||
710 | void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, int, uint32_t, void *), void *userdata) | 752 | void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, int, uint32_t, void *), void *userdata) |
711 | { | 753 | { |
712 | m->read_receipt = function; | 754 | m->read_receipt = function; |
@@ -1821,6 +1863,11 @@ void do_friends(Messenger *m) | |||
1821 | if (send_userstatus(m, i, m->userstatus)) | 1863 | if (send_userstatus(m, i, m->userstatus)) |
1822 | m->friendlist[i].userstatus_sent = 1; | 1864 | m->friendlist[i].userstatus_sent = 1; |
1823 | } | 1865 | } |
1866 | |||
1867 | if (m->friendlist[i].user_istyping_sent == 0) { | ||
1868 | if (send_user_istyping(m, i, m->friendlist[i].user_istyping)) | ||
1869 | m->friendlist[i].user_istyping_sent = 1; | ||
1870 | } | ||
1824 | 1871 | ||
1825 | if (m->friendlist[i].ping_lastsent + FRIEND_PING_INTERVAL < temp_time) { | 1872 | if (m->friendlist[i].ping_lastsent + FRIEND_PING_INTERVAL < temp_time) { |
1826 | send_ping(m, i); | 1873 | send_ping(m, i); |
@@ -1882,6 +1929,19 @@ void do_friends(Messenger *m) | |||
1882 | set_friend_userstatus(m, i, status); | 1929 | set_friend_userstatus(m, i, status); |
1883 | break; | 1930 | break; |
1884 | } | 1931 | } |
1932 | |||
1933 | case PACKET_ID_TYPING: { | ||
1934 | if (data_length != 1) | ||
1935 | break; | ||
1936 | |||
1937 | uint8_t typing = data[0]; | ||
1938 | |||
1939 | if (m->friend_typingchange) | ||
1940 | m->friend_typingchange(m, i, typing, m->friend_typingchange_userdata); | ||
1941 | |||
1942 | set_friend_typing(m, i, typing); | ||
1943 | break; | ||
1944 | } | ||
1885 | 1945 | ||
1886 | case PACKET_ID_MESSAGE: { | 1946 | case PACKET_ID_MESSAGE: { |
1887 | uint8_t *message_id = data; | 1947 | uint8_t *message_id = data; |
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index ccca8fba..952aa436 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h | |||
@@ -42,6 +42,7 @@ | |||
42 | #define PACKET_ID_NICKNAME 48 | 42 | #define PACKET_ID_NICKNAME 48 |
43 | #define PACKET_ID_STATUSMESSAGE 49 | 43 | #define PACKET_ID_STATUSMESSAGE 49 |
44 | #define PACKET_ID_USERSTATUS 50 | 44 | #define PACKET_ID_USERSTATUS 50 |
45 | #define PACKET_ID_TYPING 51 | ||
45 | #define PACKET_ID_RECEIPT 65 | 46 | #define PACKET_ID_RECEIPT 65 |
46 | #define PACKET_ID_MESSAGE 64 | 47 | #define PACKET_ID_MESSAGE 64 |
47 | #define PACKET_ID_ACTION 63 | 48 | #define PACKET_ID_ACTION 63 |
@@ -145,6 +146,9 @@ typedef struct { | |||
145 | uint8_t statusmessage_sent; | 146 | uint8_t statusmessage_sent; |
146 | USERSTATUS userstatus; | 147 | USERSTATUS userstatus; |
147 | uint8_t userstatus_sent; | 148 | uint8_t userstatus_sent; |
149 | uint8_t user_istyping; | ||
150 | uint8_t user_istyping_sent; | ||
151 | uint8_t is_typing; | ||
148 | uint16_t info_size; // Length of the info. | 152 | uint16_t info_size; // Length of the info. |
149 | uint32_t message_id; // a semi-unique id used in read receipts. | 153 | uint32_t message_id; // a semi-unique id used in read receipts. |
150 | uint8_t receives_read_receipts; // shall we send read receipts to this person? | 154 | uint8_t receives_read_receipts; // shall we send read receipts to this person? |
@@ -204,6 +208,8 @@ typedef struct Messenger { | |||
204 | void *friend_statusmessagechange_userdata; | 208 | void *friend_statusmessagechange_userdata; |
205 | void (*friend_userstatuschange)(struct Messenger *m, int, USERSTATUS, void *); | 209 | void (*friend_userstatuschange)(struct Messenger *m, int, USERSTATUS, void *); |
206 | void *friend_userstatuschange_userdata; | 210 | void *friend_userstatuschange_userdata; |
211 | void (*friend_typingchange)(struct Messenger *m, int, uint8_t, void *); | ||
212 | void *friend_typingchange_userdata; | ||
207 | void (*read_receipt)(struct Messenger *m, int, uint32_t, void *); | 213 | void (*read_receipt)(struct Messenger *m, int, uint32_t, void *); |
208 | void *read_receipt_userdata; | 214 | void *read_receipt_userdata; |
209 | void (*friend_statuschange)(struct Messenger *m, int, uint8_t, void *); | 215 | void (*friend_statuschange)(struct Messenger *m, int, uint8_t, void *); |
@@ -398,6 +404,21 @@ int m_copy_self_statusmessage(Messenger *m, uint8_t *buf, uint32_t maxlen); | |||
398 | USERSTATUS m_get_userstatus(Messenger *m, int friendnumber); | 404 | USERSTATUS m_get_userstatus(Messenger *m, int friendnumber); |
399 | USERSTATUS m_get_self_userstatus(Messenger *m); | 405 | USERSTATUS m_get_self_userstatus(Messenger *m); |
400 | 406 | ||
407 | /* Set our typing status for a friend. | ||
408 | * You are responsible for turning it on or off. | ||
409 | * | ||
410 | * returns 0 on success. | ||
411 | * returns -1 on failure. | ||
412 | */ | ||
413 | int m_set_usertyping(Messenger *m, int friendnumber, uint8_t is_typing); | ||
414 | |||
415 | /* Get the typing status of a friend. | ||
416 | * | ||
417 | * returns 0 if friend is not typing. | ||
418 | * returns -1 if friend is typing. | ||
419 | */ | ||
420 | uint8_t m_get_istyping(Messenger *m, int friendnumber); | ||
421 | |||
401 | /* Sets whether we send read receipts for friendnumber. | 422 | /* Sets whether we send read receipts for friendnumber. |
402 | * This function is not lazy, and it will fail if yesno is not (0 or 1). | 423 | * This function is not lazy, and it will fail if yesno is not (0 or 1). |
403 | */ | 424 | */ |
@@ -439,6 +460,11 @@ void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, int, | |||
439 | */ | 460 | */ |
440 | void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, int, USERSTATUS, void *), void *userdata); | 461 | void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, int, USERSTATUS, void *), void *userdata); |
441 | 462 | ||
463 | /* Set the callback for typing changes. | ||
464 | * Function(int friendnumber, uint8_t is_typing) | ||
465 | */ | ||
466 | void m_callback_typingchange(Messenger *m, void(*function)(Messenger *m, int, uint8_t, void *), void *userdata); | ||
467 | |||
442 | /* Set the callback for read receipts. | 468 | /* Set the callback for read receipts. |
443 | * Function(int friendnumber, uint32_t receipt) | 469 | * Function(int friendnumber, uint32_t receipt) |
444 | * | 470 | * |
diff --git a/toxcore/tox.c b/toxcore/tox.c index f4690080..3f2c1e92 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c | |||
@@ -270,6 +270,29 @@ TOX_USERSTATUS tox_get_self_user_status(Tox *tox) | |||
270 | return (TOX_USERSTATUS)m_get_self_userstatus(m); | 270 | return (TOX_USERSTATUS)m_get_self_userstatus(m); |
271 | } | 271 | } |
272 | 272 | ||
273 | /* Set our typing status for a friend. | ||
274 | * You are responsible for turning it on or off. | ||
275 | * | ||
276 | * returns 0 on success. | ||
277 | * returns -1 on failure. | ||
278 | */ | ||
279 | int tox_set_user_is_typing(Tox *tox, int friendnumber, uint8_t is_typing) | ||
280 | { | ||
281 | Messenger *m = tox; | ||
282 | return (int)m_set_usertyping(m, friendnumber, is_typing); | ||
283 | } | ||
284 | |||
285 | /* Get the typing status of a friend. | ||
286 | * | ||
287 | * returns 0 if friend is not typing. | ||
288 | * returns -1 if friend is typing. | ||
289 | */ | ||
290 | int tox_get_is_typing(Tox *tox, int friendnumber) | ||
291 | { | ||
292 | Messenger *m = tox; | ||
293 | return (int)m_get_istyping(m, friendnumber); | ||
294 | } | ||
295 | |||
273 | 296 | ||
274 | /* Sets whether we send read receipts for friendnumber. | 297 | /* Sets whether we send read receipts for friendnumber. |
275 | * This function is not lazy, and it will fail if yesno is not (0 or 1). | 298 | * This function is not lazy, and it will fail if yesno is not (0 or 1). |
@@ -370,6 +393,17 @@ void tox_callback_user_status(Tox *tox, void (*_function)(Tox *tox, int, TOX_USE | |||
370 | m_callback_userstatus(m, function, userdata); | 393 | m_callback_userstatus(m, function, userdata); |
371 | } | 394 | } |
372 | 395 | ||
396 | /* Set the callback for typing changes. | ||
397 | * function (int friendnumber, uint8_t is_typing) | ||
398 | */ | ||
399 | void tox_callback_typing_change(Tox *tox, void (*function)(Tox *tox, int, uint8_t, void *), void *userdata) | ||
400 | { | ||
401 | Messenger *m = tox; | ||
402 | typedef void (*function_type)(Messenger *, int, uint8_t, void *); | ||
403 | function_type function_new = (function_type)function; | ||
404 | m_callback_typingchange(m, function_new, userdata); | ||
405 | } | ||
406 | |||
373 | /* Set the callback for read receipts. | 407 | /* Set the callback for read receipts. |
374 | * function(int friendnumber, uint32_t receipt) | 408 | * function(int friendnumber, uint32_t receipt) |
375 | * | 409 | * |
diff --git a/toxcore/tox.h b/toxcore/tox.h index 447a1146..0a4e80f7 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h | |||
@@ -280,6 +280,21 @@ int tox_get_self_status_message(Tox *tox, uint8_t *buf, uint32_t maxlen); | |||
280 | */ | 280 | */ |
281 | TOX_USERSTATUS tox_get_user_status(Tox *tox, int friendnumber); | 281 | TOX_USERSTATUS tox_get_user_status(Tox *tox, int friendnumber); |
282 | TOX_USERSTATUS tox_get_self_user_status(Tox *tox); | 282 | TOX_USERSTATUS tox_get_self_user_status(Tox *tox); |
283 | |||
284 | /* Set our typing status for a friend. | ||
285 | * You are responsible for turning it on or off. | ||
286 | * | ||
287 | * returns 0 on success. | ||
288 | * returns -1 on failure. | ||
289 | */ | ||
290 | int tox_set_user_is_typing(Tox *tox, int friendnumber, uint8_t is_typing); | ||
291 | |||
292 | /* Get the typing status of a friend. | ||
293 | * | ||
294 | * returns 0 if friend is not typing. | ||
295 | * returns -1 if friend is typing. | ||
296 | */ | ||
297 | int tox_get_is_typing(Tox *tox, int friendnumber); | ||
283 | 298 | ||
284 | /* Sets whether we send read receipts for friendnumber. | 299 | /* Sets whether we send read receipts for friendnumber. |
285 | * This function is not lazy, and it will fail if yesno is not (0 or 1). | 300 | * This function is not lazy, and it will fail if yesno is not (0 or 1). |
@@ -335,6 +350,11 @@ void tox_callback_status_message(Tox *tox, void (*function)(Tox *tox, int, uint8 | |||
335 | * function(int friendnumber, USERSTATUS kind) | 350 | * function(int friendnumber, USERSTATUS kind) |
336 | */ | 351 | */ |
337 | void tox_callback_user_status(Tox *tox, void (*function)(Tox *tox, int, TOX_USERSTATUS, void *), void *userdata); | 352 | void tox_callback_user_status(Tox *tox, void (*function)(Tox *tox, int, TOX_USERSTATUS, void *), void *userdata); |
353 | |||
354 | /* Set the callback for typing changes. | ||
355 | * function (int friendnumber, uint8_t is_typing) | ||
356 | */ | ||
357 | void tox_callback_typing_change(Tox *tox, void (*function)(Tox *tox, int, uint8_t, void *), void *userdata); | ||
338 | 358 | ||
339 | /* Set the callback for read receipts. | 359 | /* Set the callback for read receipts. |
340 | * function(int friendnumber, uint32_t receipt) | 360 | * function(int friendnumber, uint32_t receipt) |