mirror of
https://github.com/Tha14/toxic.git
synced 2024-11-22 20:13:04 +01:00
Update API
-Removed usage of deprecated API functions -Integrated conference changes with a few regressions
This commit is contained in:
parent
a290f0f7f8
commit
29f55c5277
@ -34,6 +34,7 @@
|
|||||||
#include "configdir.h"
|
#include "configdir.h"
|
||||||
#include "curl_util.h"
|
#include "curl_util.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
#include "prompt.h"
|
||||||
|
|
||||||
extern struct arg_opts arg_opts;
|
extern struct arg_opts arg_opts;
|
||||||
extern struct user_settings *user_settings;
|
extern struct user_settings *user_settings;
|
||||||
@ -580,7 +581,7 @@ static void DHT_bootstrap(Tox *m)
|
|||||||
void do_tox_connection(Tox *m)
|
void do_tox_connection(Tox *m)
|
||||||
{
|
{
|
||||||
static time_t last_bootstrap_time = 0;
|
static time_t last_bootstrap_time = 0;
|
||||||
bool connected = tox_self_get_connection_status(m) != TOX_CONNECTION_NONE;
|
bool connected = prompt_selfConnectionStatus() != TOX_CONNECTION_NONE;
|
||||||
|
|
||||||
if (!connected && timed_out(last_bootstrap_time, TRY_BOOTSTRAP_INTERVAL)) {
|
if (!connected && timed_out(last_bootstrap_time, TRY_BOOTSTRAP_INTERVAL)) {
|
||||||
DHT_bootstrap(m);
|
DHT_bootstrap(m);
|
||||||
|
@ -238,8 +238,6 @@ static void chat_onConnectionChange(ToxWindow *self, Tox *m, uint32_t num, TOX_C
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (prev_status == TOX_CONNECTION_NONE) {
|
if (prev_status == TOX_CONNECTION_NONE) {
|
||||||
Friends.list[num].is_typing = user_settings->show_typing_other == SHOW_TYPING_ON
|
|
||||||
? tox_friend_get_typing(m, num, NULL) : false;
|
|
||||||
chat_resume_file_senders(self, m, num);
|
chat_resume_file_senders(self, m, num);
|
||||||
|
|
||||||
msg = "has come online";
|
msg = "has come online";
|
||||||
@ -1160,9 +1158,8 @@ static void chat_onInit(ToxWindow *self, Tox *m)
|
|||||||
|
|
||||||
/* Init statusbar info */
|
/* Init statusbar info */
|
||||||
StatusBar *statusbar = self->stb;
|
StatusBar *statusbar = self->stb;
|
||||||
|
statusbar->status = get_friend_status(self->num);
|
||||||
statusbar->status = tox_friend_get_status(m, self->num, NULL);
|
statusbar->connection = get_friend_connection_status(self->num);
|
||||||
statusbar->connection = tox_friend_get_connection_status(m, self->num, NULL);
|
|
||||||
|
|
||||||
char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH];
|
char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH];
|
||||||
tox_friend_get_status_message(m, self->num, (uint8_t *) statusmsg, NULL);
|
tox_friend_get_status_message(m, self->num, (uint8_t *) statusmsg, NULL);
|
||||||
|
@ -1163,6 +1163,18 @@ static void friendlist_onAV(ToxWindow *self, ToxAV *av, uint32_t friend_number,
|
|||||||
}
|
}
|
||||||
#endif /* AUDIO */
|
#endif /* AUDIO */
|
||||||
|
|
||||||
|
/* Returns a friend's status */
|
||||||
|
TOX_USER_STATUS get_friend_status(uint32_t friendnumber)
|
||||||
|
{
|
||||||
|
return Friends.list[friendnumber].status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns a friend's connection status */
|
||||||
|
TOX_CONNECTION get_friend_connection_status(uint32_t friendnumber)
|
||||||
|
{
|
||||||
|
return Friends.list[friendnumber].connection_status;
|
||||||
|
}
|
||||||
|
|
||||||
ToxWindow new_friendlist(void)
|
ToxWindow new_friendlist(void)
|
||||||
{
|
{
|
||||||
ToxWindow ret;
|
ToxWindow ret;
|
||||||
|
@ -54,7 +54,7 @@ typedef struct {
|
|||||||
TOX_CONNECTION connection_status;
|
TOX_CONNECTION connection_status;
|
||||||
bool is_typing;
|
bool is_typing;
|
||||||
bool logging_on; /* saves preference for friend irrespective of global settings */
|
bool logging_on; /* saves preference for friend irrespective of global settings */
|
||||||
uint8_t status;
|
TOX_USER_STATUS status;
|
||||||
|
|
||||||
struct LastOnline last_online;
|
struct LastOnline last_online;
|
||||||
struct GroupChatInvite group_invite;
|
struct GroupChatInvite group_invite;
|
||||||
@ -87,6 +87,8 @@ int get_friendnum(uint8_t *name);
|
|||||||
int load_blocklist(char *data);
|
int load_blocklist(char *data);
|
||||||
void kill_friendlist(void);
|
void kill_friendlist(void);
|
||||||
void friendlist_onFriendAdded(ToxWindow *self, Tox *m, uint32_t num, bool sort);
|
void friendlist_onFriendAdded(ToxWindow *self, Tox *m, uint32_t num, bool sort);
|
||||||
|
TOX_USER_STATUS get_friend_status(uint32_t friendnumber);
|
||||||
|
TOX_CONNECTION get_friend_connection_status(uint32_t friendnumber);
|
||||||
|
|
||||||
/* sorts friendlist_index first by connection status then alphabetically */
|
/* sorts friendlist_index first by connection status then alphabetically */
|
||||||
void sort_friendlist_index(void);
|
void sort_friendlist_index(void);
|
||||||
|
305
src/groupchat.c
305
src/groupchat.c
@ -126,18 +126,6 @@ int init_groupchat_win(ToxWindow *prompt, Tox *m, uint32_t groupnum, uint8_t typ
|
|||||||
groupchats[i].type = type;
|
groupchats[i].type = type;
|
||||||
groupchats[i].start_time = get_unix_time();
|
groupchats[i].start_time = get_unix_time();
|
||||||
|
|
||||||
groupchats[i].peer_names = malloc(sizeof(uint8_t) * TOX_MAX_NAME_LENGTH);
|
|
||||||
groupchats[i].oldpeer_names = malloc(sizeof(uint8_t) * TOX_MAX_NAME_LENGTH);
|
|
||||||
groupchats[i].peer_name_lengths = malloc(sizeof(uint16_t));
|
|
||||||
groupchats[i].oldpeer_name_lengths = malloc(sizeof(uint16_t));
|
|
||||||
|
|
||||||
if (groupchats[i].peer_names == NULL || groupchats[i].oldpeer_names == NULL
|
|
||||||
|| groupchats[i].peer_name_lengths == NULL || groupchats[i].oldpeer_name_lengths == NULL)
|
|
||||||
exit_toxic_err("failed in init_groupchat_win", FATALERR_MEMORY);
|
|
||||||
|
|
||||||
memcpy(&groupchats[i].oldpeer_names[0], UNKNOWN_NAME, sizeof(UNKNOWN_NAME));
|
|
||||||
groupchats[i].oldpeer_name_lengths[0] = (uint16_t) strlen(UNKNOWN_NAME);
|
|
||||||
|
|
||||||
set_active_window(groupchats[i].chatwin);
|
set_active_window(groupchats[i].chatwin);
|
||||||
|
|
||||||
if (i == max_groupchat_index)
|
if (i == max_groupchat_index)
|
||||||
@ -165,14 +153,10 @@ static void kill_groupchat_window(ToxWindow *self)
|
|||||||
del_window(self);
|
del_window(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
void close_groupchat(ToxWindow *self, Tox *m, uint32_t groupnum)
|
void free_groupchat(ToxWindow *self, Tox *m, uint32_t groupnum)
|
||||||
{
|
{
|
||||||
tox_conference_delete(m, groupnum, NULL);
|
free(groupchats[groupnum].name_list);
|
||||||
|
free(groupchats[groupnum].peer_list);
|
||||||
free(groupchats[groupnum].peer_names);
|
|
||||||
free(groupchats[groupnum].oldpeer_names);
|
|
||||||
free(groupchats[groupnum].peer_name_lengths);
|
|
||||||
free(groupchats[groupnum].oldpeer_name_lengths);
|
|
||||||
memset(&groupchats[groupnum], 0, sizeof(GroupChat));
|
memset(&groupchats[groupnum], 0, sizeof(GroupChat));
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
@ -186,6 +170,13 @@ void close_groupchat(ToxWindow *self, Tox *m, uint32_t groupnum)
|
|||||||
kill_groupchat_window(self);
|
kill_groupchat_window(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void delete_groupchat(ToxWindow *self, Tox *m, uint32_t groupnum)
|
||||||
|
{
|
||||||
|
tox_conference_delete(m, groupnum, NULL);
|
||||||
|
free_groupchat(self, m, groupnum);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* destroys and re-creates groupchat window with or without the peerlist */
|
/* destroys and re-creates groupchat window with or without the peerlist */
|
||||||
void redraw_groupchat_win(ToxWindow *self)
|
void redraw_groupchat_win(ToxWindow *self)
|
||||||
{
|
{
|
||||||
@ -292,104 +283,102 @@ static void groupchat_onGroupTitleChange(ToxWindow *self, Tox *m, uint32_t group
|
|||||||
write_to_log(tmp_event, nick, ctx->log, true);
|
write_to_log(tmp_event, nick, ctx->log, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Puts two copies of peerlist/lengths in chat instance */
|
static void group_update_name_list(uint32_t groupnum)
|
||||||
static void copy_peernames(Tox *m, uint32_t gnum, size_t npeers)
|
|
||||||
{
|
{
|
||||||
/* Assumes these are initiated in init_groupchat_win */
|
GroupChat *chat = &groupchats[groupnum];
|
||||||
free(groupchats[gnum].peer_names);
|
|
||||||
free(groupchats[gnum].oldpeer_names);
|
|
||||||
free(groupchats[gnum].peer_name_lengths);
|
|
||||||
free(groupchats[gnum].oldpeer_name_lengths);
|
|
||||||
|
|
||||||
int N = TOX_MAX_NAME_LENGTH;
|
if (!chat) {
|
||||||
|
return;
|
||||||
groupchats[gnum].peer_names = calloc(1, sizeof(uint8_t) * npeers * N);
|
|
||||||
groupchats[gnum].oldpeer_names = calloc(1, sizeof(uint8_t) * npeers * N);
|
|
||||||
groupchats[gnum].peer_name_lengths = calloc(1, sizeof(uint16_t) * npeers);
|
|
||||||
groupchats[gnum].oldpeer_name_lengths = calloc(1, sizeof(uint16_t) * npeers);
|
|
||||||
|
|
||||||
if (groupchats[gnum].peer_names == NULL || groupchats[gnum].oldpeer_names == NULL
|
|
||||||
|| groupchats[gnum].peer_name_lengths == NULL || groupchats[gnum].oldpeer_name_lengths == NULL) {
|
|
||||||
exit_toxic_err("failed in copy_peernames()", FATALERR_MEMORY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t u_len = strlen(UNKNOWN_NAME);
|
if (chat->name_list) {
|
||||||
|
free(chat->name_list);
|
||||||
|
}
|
||||||
|
|
||||||
int i;
|
chat->name_list = malloc(sizeof(char *) * chat->num_peers * TOX_MAX_NAME_LENGTH);
|
||||||
|
|
||||||
|
if (chat->name_list == NULL) {
|
||||||
|
exit_toxic_err("failed in group_update_name_list", FATALERR_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t i, count = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < chat->max_idx; ++i) {
|
||||||
|
if (chat->peer_list[i].active) {
|
||||||
|
memcpy(&chat->name_list[count * TOX_MAX_NAME_LENGTH], chat->peer_list[i].name, chat->peer_list[i].name_length + 1);
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort_peerlist(groupnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reallocates groupnum's peer list. Increase is true if the list needs to grow.
|
||||||
|
*
|
||||||
|
* Returns 0 on success.
|
||||||
|
* Returns -1 on failure.
|
||||||
|
*/
|
||||||
|
static int realloc_peer_list(GroupChat *chat, uint32_t num_peers)
|
||||||
|
{
|
||||||
|
if (!chat) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_peers == 0) {
|
||||||
|
free(chat->peer_list);
|
||||||
|
chat->peer_list = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GroupPeer *tmp_list = realloc(chat->peer_list, num_peers * sizeof(struct GroupPeer));
|
||||||
|
|
||||||
|
if (!tmp_list) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
chat->peer_list = tmp_list;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_peer_list(Tox *m, uint32_t groupnum, uint32_t num_peers)
|
||||||
|
{
|
||||||
|
GroupChat *chat = &groupchats[groupnum];
|
||||||
|
|
||||||
|
if (!chat) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
realloc_peer_list(chat, num_peers);
|
||||||
|
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_peers; ++i) {
|
||||||
|
GroupPeer *peer = &chat->peer_list[i];
|
||||||
|
|
||||||
for (i = 0; i < npeers; ++i) {
|
|
||||||
uint8_t name[TOX_MAX_NAME_LENGTH];
|
|
||||||
TOX_ERR_CONFERENCE_PEER_QUERY err;
|
TOX_ERR_CONFERENCE_PEER_QUERY err;
|
||||||
|
size_t length = tox_conference_peer_get_name_size(m, groupnum, i, &err);
|
||||||
|
|
||||||
size_t n_len = tox_conference_peer_get_name_size(m, gnum, i, &err);
|
if (err != TOX_ERR_CONFERENCE_PEER_QUERY_OK || length >= TOX_MAX_NAME_LENGTH) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tox_conference_peer_get_name(m, groupnum, i, (uint8_t *) peer->name, &err);
|
||||||
|
peer->name[length] = 0;
|
||||||
|
|
||||||
if (err != TOX_ERR_CONFERENCE_PEER_QUERY_OK) {
|
if (err != TOX_ERR_CONFERENCE_PEER_QUERY_OK) {
|
||||||
memcpy(&groupchats[gnum].peer_names[i * N], UNKNOWN_NAME, u_len);
|
continue;
|
||||||
groupchats[gnum].peer_names[i * N + u_len] = '\0';
|
|
||||||
groupchats[gnum].peer_name_lengths[i] = u_len;
|
|
||||||
} else {
|
|
||||||
tox_conference_peer_get_name(m, gnum, i, name, NULL);
|
|
||||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH - 1);
|
|
||||||
memcpy(&groupchats[gnum].peer_names[i * N], name, n_len);
|
|
||||||
groupchats[gnum].peer_names[i * N + n_len] = '\0';
|
|
||||||
groupchats[gnum].peer_name_lengths[i] = n_len;
|
|
||||||
filter_str((char *) &groupchats[gnum].peer_names[i * N], n_len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(groupchats[gnum].oldpeer_names, groupchats[gnum].peer_names, N * npeers);
|
|
||||||
memcpy(groupchats[gnum].oldpeer_name_lengths, groupchats[gnum].peer_name_lengths, sizeof(uint16_t) * npeers);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct group_add_thrd {
|
|
||||||
Tox *m;
|
|
||||||
ToxWindow *self;
|
|
||||||
uint32_t peernum;
|
|
||||||
uint32_t groupnum;
|
|
||||||
time_t timestamp;
|
|
||||||
pthread_t tid;
|
|
||||||
pthread_attr_t attr;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Waits GROUP_EVENT_WAIT seconds for a new peer to set their name before announcing them */
|
|
||||||
void *group_add_wait(void *data)
|
|
||||||
{
|
|
||||||
struct group_add_thrd *thrd = (struct group_add_thrd *) data;
|
|
||||||
ToxWindow *self = thrd->self;
|
|
||||||
Tox *m = thrd->m;
|
|
||||||
char peername[TOX_MAX_NAME_LENGTH];
|
|
||||||
|
|
||||||
/* keep polling for a name that differs from the default until we run out of time */
|
|
||||||
while (true) {
|
|
||||||
usleep(100000);
|
|
||||||
|
|
||||||
pthread_mutex_lock(&Winthread.lock);
|
|
||||||
get_group_nick_truncate(m, peername, thrd->peernum, thrd->groupnum);
|
|
||||||
|
|
||||||
if (strcmp(peername, DEFAULT_TOX_NAME) || timed_out(thrd->timestamp, GROUP_EVENT_WAIT)) {
|
|
||||||
pthread_mutex_unlock(&Winthread.lock);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&Winthread.lock);
|
peer->active = true;
|
||||||
|
peer->name_length = length;
|
||||||
|
peer->peernumber = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *event = "has joined the room";
|
group_update_name_list(groupnum);
|
||||||
char timefrmt[TIME_STR_SIZE];
|
|
||||||
get_time_str(timefrmt, sizeof(timefrmt));
|
|
||||||
|
|
||||||
pthread_mutex_lock(&Winthread.lock);
|
|
||||||
line_info_add(self, timefrmt, (char *) peername, NULL, CONNECTION, 0, GREEN, event);
|
|
||||||
write_to_log(event, (char *) peername, self->chatwin->log, true);
|
|
||||||
pthread_mutex_unlock(&Winthread.lock);
|
|
||||||
|
|
||||||
pthread_attr_destroy(&thrd->attr);
|
|
||||||
free(thrd);
|
|
||||||
pthread_exit(NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, uint32_t groupnum, uint32_t peernum,
|
static void groupchat_onGroupNameListChange(ToxWindow *self, Tox *m, uint32_t groupnum)
|
||||||
TOX_CONFERENCE_STATE_CHANGE change)
|
|
||||||
{
|
{
|
||||||
if (self->num != groupnum)
|
if (self->num != groupnum)
|
||||||
return;
|
return;
|
||||||
@ -397,107 +386,28 @@ static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, uint32_t gr
|
|||||||
if (groupnum > max_groupchat_index)
|
if (groupnum > max_groupchat_index)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
GroupChat *chat = &groupchats[groupnum];
|
||||||
TOX_ERR_CONFERENCE_PEER_QUERY err;
|
TOX_ERR_CONFERENCE_PEER_QUERY err;
|
||||||
|
|
||||||
uint32_t num_peers = tox_conference_peer_count(m, groupnum, &err);
|
uint32_t num_peers = tox_conference_peer_count(m, groupnum, &err);
|
||||||
|
uint32_t old_num = chat->num_peers;
|
||||||
|
|
||||||
if (err == TOX_ERR_CONFERENCE_PEER_QUERY_OK) {
|
if (err == TOX_ERR_CONFERENCE_PEER_QUERY_OK) {
|
||||||
groupchats[groupnum].num_peers = num_peers;
|
chat->num_peers = num_peers;
|
||||||
} else {
|
} else {
|
||||||
num_peers = groupchats[groupnum].num_peers;
|
num_peers = old_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (peernum > num_peers)
|
chat->max_idx = num_peers;
|
||||||
return;
|
update_peer_list(m, groupnum, num_peers);
|
||||||
|
//qsort(groupchats[groupnum].name_list, groupchats[groupnum].num_peers, TOX_MAX_NAME_LENGTH, qsort_strcasecmp_hlpr);
|
||||||
|
}
|
||||||
|
|
||||||
/* get old peer name before updating name list */
|
static void groupchat_onGroupPeerNameChange(ToxWindow *self, Tox *m, uint32_t groupnum, uint32_t peernum,
|
||||||
uint8_t oldpeername[TOX_MAX_NAME_LENGTH];
|
const char *name, size_t length)
|
||||||
|
{
|
||||||
if (change != TOX_CONFERENCE_STATE_CHANGE_PEER_JOIN) {
|
// TODO: this is dumb because toxcore is dumb so make it not dumb pls
|
||||||
memcpy(oldpeername, &groupchats[groupnum].oldpeer_names[peernum * TOX_MAX_NAME_LENGTH], sizeof(oldpeername));
|
groupchat_onGroupNameListChange(self, m, groupnum);
|
||||||
uint16_t old_n_len = groupchats[groupnum].oldpeer_name_lengths[peernum];
|
|
||||||
oldpeername[old_n_len] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update name/len lists */
|
|
||||||
copy_peernames(m, groupnum, num_peers);
|
|
||||||
|
|
||||||
/* get current peername then sort namelist */
|
|
||||||
uint8_t peername[TOX_MAX_NAME_LENGTH];
|
|
||||||
|
|
||||||
if (change != TOX_CONFERENCE_STATE_CHANGE_PEER_EXIT) {
|
|
||||||
uint16_t n_len = groupchats[groupnum].peer_name_lengths[peernum];
|
|
||||||
memcpy(peername, &groupchats[groupnum].peer_names[peernum * TOX_MAX_NAME_LENGTH], sizeof(peername));
|
|
||||||
peername[n_len] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
qsort(groupchats[groupnum].peer_names, groupchats[groupnum].num_peers, TOX_MAX_NAME_LENGTH, qsort_strcasecmp_hlpr);
|
|
||||||
|
|
||||||
ChatContext *ctx = self->chatwin;
|
|
||||||
|
|
||||||
const char *event;
|
|
||||||
char timefrmt[TIME_STR_SIZE];
|
|
||||||
get_time_str(timefrmt, sizeof(timefrmt));
|
|
||||||
|
|
||||||
switch (change) {
|
|
||||||
case TOX_CONFERENCE_STATE_CHANGE_PEER_JOIN:
|
|
||||||
if (!timed_out(groupchats[groupnum].start_time, GROUP_EVENT_WAIT))
|
|
||||||
break;
|
|
||||||
|
|
||||||
struct group_add_thrd *thrd = malloc(sizeof(struct group_add_thrd));
|
|
||||||
thrd->m = m;
|
|
||||||
thrd->peernum = peernum;
|
|
||||||
thrd->groupnum = groupnum;
|
|
||||||
thrd->self = self;
|
|
||||||
thrd->timestamp = get_unix_time();
|
|
||||||
|
|
||||||
if (pthread_attr_init(&thrd->attr) != 0) {
|
|
||||||
free(thrd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pthread_attr_setdetachstate(&thrd->attr, PTHREAD_CREATE_DETACHED) != 0) {
|
|
||||||
pthread_attr_destroy(&thrd->attr);
|
|
||||||
free(thrd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pthread_create(&thrd->tid, &thrd->attr, group_add_wait, (void *) thrd) != 0) {
|
|
||||||
pthread_attr_destroy(&thrd->attr);
|
|
||||||
free(thrd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TOX_CONFERENCE_STATE_CHANGE_PEER_EXIT:
|
|
||||||
event = "has left the room";
|
|
||||||
line_info_add(self, timefrmt, (char *) oldpeername, NULL, DISCONNECTION, 0, RED, event);
|
|
||||||
|
|
||||||
if (groupchats[self->num].side_pos > 0)
|
|
||||||
--groupchats[self->num].side_pos;
|
|
||||||
|
|
||||||
write_to_log(event, (char *) oldpeername, ctx->log, true);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TOX_CONFERENCE_STATE_CHANGE_PEER_NAME_CHANGE:
|
|
||||||
if (!timed_out(groupchats[self->num].start_time, GROUP_EVENT_WAIT))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* ignore initial name change (TODO: this is a bad way to do this) */
|
|
||||||
if (strcmp((char *) oldpeername, DEFAULT_TOX_NAME) == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
event = " is now known as ";
|
|
||||||
line_info_add(self, timefrmt, (char *) oldpeername, (char *) peername, NAME_CHANGE, 0, 0, event);
|
|
||||||
|
|
||||||
char tmp_event[TOXIC_MAX_NAME_LENGTH * 2 + 32];
|
|
||||||
snprintf(tmp_event, sizeof(tmp_event), "is now known as %s", (char *) peername);
|
|
||||||
write_to_log(tmp_event, (char *) oldpeername, ctx->log, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
sound_notify(self, silent, NT_WNDALERT_2, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_group_action(ToxWindow *self, ChatContext *ctx, Tox *m, char *action)
|
static void send_group_action(ToxWindow *self, ChatContext *ctx, Tox *m, char *action)
|
||||||
@ -550,7 +460,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
|||||||
|
|
||||||
/* TODO: make this not suck */
|
/* TODO: make this not suck */
|
||||||
if (ctx->line[0] != L'/' || wcscmp(ctx->line, L"/me") == 0) {
|
if (ctx->line[0] != L'/' || wcscmp(ctx->line, L"/me") == 0) {
|
||||||
diff = complete_line(self, groupchats[self->num].peer_names, groupchats[self->num].num_peers,
|
diff = complete_line(self, groupchats[self->num].name_list, groupchats[self->num].num_peers,
|
||||||
TOX_MAX_NAME_LENGTH);
|
TOX_MAX_NAME_LENGTH);
|
||||||
} else if (wcsncmp(ctx->line, L"/avatar \"", wcslen(L"/avatar \"")) == 0) {
|
} else if (wcsncmp(ctx->line, L"/avatar \"", wcslen(L"/avatar \"")) == 0) {
|
||||||
diff = dir_match(self, m, ctx->line, L"/avatar");
|
diff = dir_match(self, m, ctx->line, L"/avatar");
|
||||||
@ -601,7 +511,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
|||||||
|
|
||||||
if (line[0] == '/') {
|
if (line[0] == '/') {
|
||||||
if (strcmp(line, "/close") == 0) {
|
if (strcmp(line, "/close") == 0) {
|
||||||
close_groupchat(self, m, self->num);
|
delete_groupchat(self, m, self->num);
|
||||||
return;
|
return;
|
||||||
} else if (strncmp(line, "/me ", strlen("/me ")) == 0) {
|
} else if (strncmp(line, "/me ", strlen("/me ")) == 0) {
|
||||||
send_group_action(self, ctx, m, line + strlen("/me "));
|
send_group_action(self, ctx, m, line + strlen("/me "));
|
||||||
@ -678,7 +588,7 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m)
|
|||||||
int maxlen = SIDEBAR_WIDTH - 2;
|
int maxlen = SIDEBAR_WIDTH - 2;
|
||||||
|
|
||||||
pthread_mutex_lock(&Winthread.lock);
|
pthread_mutex_lock(&Winthread.lock);
|
||||||
memcpy(tmpnck, &groupchats[self->num].peer_names[peer * TOX_MAX_NAME_LENGTH], maxlen);
|
memcpy(tmpnck, &groupchats[self->num].name_list[peer * TOX_MAX_NAME_LENGTH], maxlen);
|
||||||
pthread_mutex_unlock(&Winthread.lock);
|
pthread_mutex_unlock(&Winthread.lock);
|
||||||
|
|
||||||
tmpnck[maxlen] = '\0';
|
tmpnck[maxlen] = '\0';
|
||||||
@ -747,7 +657,8 @@ ToxWindow new_group_chat(Tox *m, uint32_t groupnum)
|
|||||||
ret.onDraw = &groupchat_onDraw;
|
ret.onDraw = &groupchat_onDraw;
|
||||||
ret.onInit = &groupchat_onInit;
|
ret.onInit = &groupchat_onInit;
|
||||||
ret.onGroupMessage = &groupchat_onGroupMessage;
|
ret.onGroupMessage = &groupchat_onGroupMessage;
|
||||||
ret.onGroupNamelistChange = &groupchat_onGroupNamelistChange;
|
ret.onGroupNameListChange = &groupchat_onGroupNameListChange;
|
||||||
|
ret.onGroupPeerNameChange = &groupchat_onGroupPeerNameChange;
|
||||||
ret.onGroupTitleChange = &groupchat_onGroupTitleChange;
|
ret.onGroupTitleChange = &groupchat_onGroupTitleChange;
|
||||||
|
|
||||||
snprintf(ret.name, sizeof(ret.name), "Group %d", groupnum);
|
snprintf(ret.name, sizeof(ret.name), "Group %d", groupnum);
|
||||||
|
@ -31,20 +31,31 @@
|
|||||||
#define MAX_GROUPCHAT_NUM MAX_WINDOWS_NUM - 2
|
#define MAX_GROUPCHAT_NUM MAX_WINDOWS_NUM - 2
|
||||||
#define GROUP_EVENT_WAIT 3
|
#define GROUP_EVENT_WAIT 3
|
||||||
|
|
||||||
|
typedef struct GroupPeer {
|
||||||
|
bool active;
|
||||||
|
char name[TOX_MAX_NAME_LENGTH];
|
||||||
|
size_t name_length;
|
||||||
|
uint32_t peernumber;
|
||||||
|
} GroupPeer;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int chatwin;
|
int chatwin;
|
||||||
bool active;
|
bool active;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint32_t num_peers;
|
|
||||||
int side_pos; /* current position of the sidebar - used for scrolling up and down */
|
int side_pos; /* current position of the sidebar - used for scrolling up and down */
|
||||||
time_t start_time;
|
time_t start_time;
|
||||||
uint8_t *peer_names;
|
|
||||||
uint8_t *oldpeer_names;
|
GroupPeer *peer_list;
|
||||||
uint16_t *peer_name_lengths;
|
size_t max_idx;
|
||||||
uint16_t *oldpeer_name_lengths;
|
|
||||||
|
char *name_list;
|
||||||
|
size_t num_peers;
|
||||||
|
|
||||||
} GroupChat;
|
} GroupChat;
|
||||||
|
|
||||||
void close_groupchat(ToxWindow *self, Tox *m, uint32_t groupnum);
|
/* Frees all Toxic associated data structures for a groupchat (does not call tox_conference_delete() ) */
|
||||||
|
void free_groupchat(ToxWindow *self, Tox *m, uint32_t groupnum);
|
||||||
|
|
||||||
int init_groupchat_win(ToxWindow *prompt, Tox *m, uint32_t groupnum, uint8_t type);
|
int init_groupchat_win(ToxWindow *prompt, Tox *m, uint32_t groupnum, uint8_t type);
|
||||||
|
|
||||||
/* destroys and re-creates groupchat window with or without the peerlist */
|
/* destroys and re-creates groupchat window with or without the peerlist */
|
||||||
|
@ -163,6 +163,13 @@ void prompt_update_status(ToxWindow *prompt, TOX_USER_STATUS status)
|
|||||||
statusbar->status = status;
|
statusbar->status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns our own connection status */
|
||||||
|
TOX_CONNECTION prompt_selfConnectionStatus(void)
|
||||||
|
{
|
||||||
|
StatusBar *statusbar = prompt->stb;
|
||||||
|
return statusbar->connection;
|
||||||
|
}
|
||||||
|
|
||||||
/* Adds friend request to pending friend requests.
|
/* Adds friend request to pending friend requests.
|
||||||
Returns request number on success, -1 if queue is full. */
|
Returns request number on success, -1 if queue is full. */
|
||||||
static int add_friend_request(const char *public_key, const char *data)
|
static int add_friend_request(const char *public_key, const char *data)
|
||||||
|
@ -53,4 +53,7 @@ void kill_prompt_window(ToxWindow *self);
|
|||||||
/* callback: Updates own connection status in prompt statusbar */
|
/* callback: Updates own connection status in prompt statusbar */
|
||||||
void prompt_onSelfConnectionChange(Tox *m, TOX_CONNECTION connection_status, void *userdata);
|
void prompt_onSelfConnectionChange(Tox *m, TOX_CONNECTION connection_status, void *userdata);
|
||||||
|
|
||||||
|
/* Returns our own connection status */
|
||||||
|
TOX_CONNECTION prompt_selfConnectionStatus(void);
|
||||||
|
|
||||||
#endif /* end of include guard: PROMPT_H */
|
#endif /* end of include guard: PROMPT_H */
|
||||||
|
39
src/toxic.c
39
src/toxic.c
@ -52,6 +52,7 @@
|
|||||||
#include "friendlist.h"
|
#include "friendlist.h"
|
||||||
#include "prompt.h"
|
#include "prompt.h"
|
||||||
#include "misc_tools.h"
|
#include "misc_tools.h"
|
||||||
|
#include "groupchat.h"
|
||||||
#include "file_transfers.h"
|
#include "file_transfers.h"
|
||||||
#include "line_info.h"
|
#include "line_info.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
@ -305,12 +306,42 @@ static void load_friendlist(Tox *m)
|
|||||||
size_t i;
|
size_t i;
|
||||||
size_t numfriends = tox_self_get_friend_list_size(m);
|
size_t numfriends = tox_self_get_friend_list_size(m);
|
||||||
|
|
||||||
for (i = 0; i < numfriends; ++i)
|
for (i = 0; i < numfriends; ++i) {
|
||||||
friendlist_onFriendAdded(NULL, m, i, false);
|
friendlist_onFriendAdded(NULL, m, i, false);
|
||||||
|
}
|
||||||
|
|
||||||
sort_friendlist_index();
|
sort_friendlist_index();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void load_groups(ToxWindow *prompt, Tox *m)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
size_t num_chats = tox_conference_get_chatlist_size(m);
|
||||||
|
uint32_t chatlist[num_chats];
|
||||||
|
|
||||||
|
for (i = 0; i < num_chats; ++i) {
|
||||||
|
uint32_t groupnum = chatlist[i];
|
||||||
|
|
||||||
|
if (get_num_active_windows() >= MAX_WINDOWS_NUM) {
|
||||||
|
tox_conference_delete(m, groupnum, NULL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOX_ERR_CONFERENCE_GET_TYPE err;
|
||||||
|
TOX_CONFERENCE_TYPE type = tox_conference_get_type(m, groupnum, &err);
|
||||||
|
|
||||||
|
if (err != TOX_ERR_CONFERENCE_GET_TYPE_OK) {
|
||||||
|
tox_conference_delete(m, groupnum, NULL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (init_groupchat_win(prompt, m, groupnum, type) == -1) {
|
||||||
|
tox_conference_delete(m, groupnum, NULL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* return length of password on success, 0 on failure */
|
/* return length of password on success, 0 on failure */
|
||||||
static int password_prompt(char *buf, int size)
|
static int password_prompt(char *buf, int size)
|
||||||
{
|
{
|
||||||
@ -551,7 +582,8 @@ static void init_tox_callbacks(Tox *m)
|
|||||||
tox_callback_friend_read_receipt(m, on_read_receipt);
|
tox_callback_friend_read_receipt(m, on_read_receipt);
|
||||||
tox_callback_conference_invite(m, on_groupinvite);
|
tox_callback_conference_invite(m, on_groupinvite);
|
||||||
tox_callback_conference_message(m, on_groupmessage);
|
tox_callback_conference_message(m, on_groupmessage);
|
||||||
tox_callback_conference_namelist_change(m, on_group_namelistchange);
|
tox_callback_conference_peer_list_changed(m, on_group_namelistchange);
|
||||||
|
tox_callback_conference_peer_name(m, on_group_peernamechange);
|
||||||
tox_callback_conference_title(m, on_group_titlechange);
|
tox_callback_conference_title(m, on_group_titlechange);
|
||||||
tox_callback_file_recv(m, on_file_recv);
|
tox_callback_file_recv(m, on_file_recv);
|
||||||
tox_callback_file_chunk_request(m, on_file_chunk_request);
|
tox_callback_file_chunk_request(m, on_file_chunk_request);
|
||||||
@ -816,7 +848,7 @@ void *thread_cqueue(void *data)
|
|||||||
ToxWindow *toxwin = get_window_ptr(i);
|
ToxWindow *toxwin = get_window_ptr(i);
|
||||||
|
|
||||||
if (toxwin != NULL && toxwin->is_chat
|
if (toxwin != NULL && toxwin->is_chat
|
||||||
&& tox_friend_get_connection_status(m, toxwin->num, NULL) != TOX_CONNECTION_NONE)
|
&& get_friend_connection_status(toxwin->num) != TOX_CONNECTION_NONE)
|
||||||
cqueue_try_send(toxwin, m);
|
cqueue_try_send(toxwin, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1198,6 +1230,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
prompt = init_windows(m);
|
prompt = init_windows(m);
|
||||||
prompt_init_statusbar(prompt, m);
|
prompt_init_statusbar(prompt, m);
|
||||||
|
load_groups(prompt, m);
|
||||||
|
|
||||||
/* thread for ncurses stuff */
|
/* thread for ncurses stuff */
|
||||||
if (pthread_mutex_init(&Winthread.lock, NULL) != 0)
|
if (pthread_mutex_init(&Winthread.lock, NULL) != 0)
|
||||||
|
@ -118,8 +118,9 @@ void on_groupmessage(Tox *m, uint32_t groupnumber, uint32_t peernumber, TOX_MESS
|
|||||||
const uint8_t *message, size_t length, void *userdata);
|
const uint8_t *message, size_t length, void *userdata);
|
||||||
void on_groupinvite(Tox *m, uint32_t friendnumber, TOX_CONFERENCE_TYPE type, const uint8_t *group_pub_key,
|
void on_groupinvite(Tox *m, uint32_t friendnumber, TOX_CONFERENCE_TYPE type, const uint8_t *group_pub_key,
|
||||||
size_t length, void *userdata);
|
size_t length, void *userdata);
|
||||||
void on_group_namelistchange(Tox *m, uint32_t groupnumber, uint32_t peernumber, TOX_CONFERENCE_STATE_CHANGE change,
|
void on_group_namelistchange(Tox *m, uint32_t groupnumber, void *userdata);
|
||||||
void *userdata);
|
void on_group_peernamechange(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *name,
|
||||||
|
size_t length, void *userdata);
|
||||||
void on_group_titlechange(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *title, size_t length,
|
void on_group_titlechange(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *title, size_t length,
|
||||||
void *userdata);
|
void *userdata);
|
||||||
void on_file_chunk_request(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length,
|
void on_file_chunk_request(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length,
|
||||||
|
@ -176,14 +176,24 @@ void on_groupinvite(Tox *m, uint32_t friendnumber, TOX_CONFERENCE_TYPE type, con
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_group_namelistchange(Tox *m, uint32_t groupnumber, uint32_t peernumber, TOX_CONFERENCE_STATE_CHANGE change,
|
void on_group_namelistchange(Tox *m, uint32_t groupnumber, void *userdata)
|
||||||
void *userdata)
|
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||||
if (windows[i].onGroupNamelistChange != NULL)
|
if (windows[i].onGroupNameListChange != NULL)
|
||||||
windows[i].onGroupNamelistChange(&windows[i], m, groupnumber, peernumber, change);
|
windows[i].onGroupNameListChange(&windows[i], m, groupnumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_group_peernamechange(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *name,
|
||||||
|
size_t length, void *userdata)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||||
|
if (windows[i].onGroupPeerNameChange != NULL)
|
||||||
|
windows[i].onGroupPeerNameChange(&windows[i], m, groupnumber, peernumber, (char *) name, length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -608,10 +618,11 @@ void kill_all_windows(Tox *m)
|
|||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||||
if (windows[i].is_chat)
|
if (windows[i].is_chat) {
|
||||||
kill_chat_window(&windows[i], m);
|
kill_chat_window(&windows[i], m);
|
||||||
else if (windows[i].is_groupchat)
|
} else if (windows[i].is_groupchat) {
|
||||||
close_groupchat(&windows[i], m, windows[i].num);
|
free_groupchat(&windows[i], m, windows[i].num);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kill_prompt_window(prompt);
|
kill_prompt_window(prompt);
|
||||||
|
@ -123,7 +123,8 @@ struct ToxWindow {
|
|||||||
void(*onStatusMessageChange)(ToxWindow *, uint32_t, const char *, size_t);
|
void(*onStatusMessageChange)(ToxWindow *, uint32_t, const char *, size_t);
|
||||||
void(*onGroupMessage)(ToxWindow *, Tox *, uint32_t, uint32_t, TOX_MESSAGE_TYPE, const char *, size_t);
|
void(*onGroupMessage)(ToxWindow *, Tox *, uint32_t, uint32_t, TOX_MESSAGE_TYPE, const char *, size_t);
|
||||||
void(*onGroupInvite)(ToxWindow *, Tox *, int32_t, uint8_t, const char *, uint16_t);
|
void(*onGroupInvite)(ToxWindow *, Tox *, int32_t, uint8_t, const char *, uint16_t);
|
||||||
void(*onGroupNamelistChange)(ToxWindow *, Tox *, uint32_t, uint32_t, TOX_CONFERENCE_STATE_CHANGE);
|
void(*onGroupNameListChange)(ToxWindow *, Tox *, uint32_t);
|
||||||
|
void(*onGroupPeerNameChange)(ToxWindow *, Tox *, uint32_t, uint32_t, const char *, size_t);
|
||||||
void(*onGroupTitleChange)(ToxWindow *, Tox *, uint32_t, uint32_t, const char *, size_t);
|
void(*onGroupTitleChange)(ToxWindow *, Tox *, uint32_t, uint32_t, const char *, size_t);
|
||||||
void(*onFileChunkRequest)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, size_t);
|
void(*onFileChunkRequest)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, size_t);
|
||||||
void(*onFileRecvChunk)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, const char *, size_t);
|
void(*onFileRecvChunk)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, const char *, size_t);
|
||||||
|
Loading…
Reference in New Issue
Block a user