mirror of
https://github.com/Tha14/toxic.git
synced 2025-06-27 14:46:45 +02:00
Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
a223329815 | |||
3fec11d5f9 | |||
221edb0012 | |||
2710ab6034 | |||
bc3ffac0ba | |||
29f55c5277 | |||
a290f0f7f8 | |||
5cd196a769 | |||
b14d983a8c | |||
51f1daeec8 | |||
b799c6a8d7 | |||
b9f9546e2b | |||
846bc4613e | |||
a5a1f6015d | |||
fe6a7074ea | |||
db7c9fe426 | |||
0bd5b4ddee |
31
.travis.yml
Normal file
31
.travis.yml
Normal file
@ -0,0 +1,31 @@
|
||||
language: python
|
||||
python: nightly
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libalut-dev
|
||||
- libconfig-dev
|
||||
- libnotify-dev
|
||||
- libopenal-dev
|
||||
- libopus-dev
|
||||
- libqrencode-dev
|
||||
- libvpx-dev
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/cache
|
||||
|
||||
install:
|
||||
# Where to find libraries.
|
||||
- export LD_LIBRARY_PATH=$HOME/cache/usr/lib
|
||||
- export PKG_CONFIG_PATH=$HOME/cache/usr/lib/pkgconfig
|
||||
# c-sodium
|
||||
- git clone --depth=1 --branch=stable https://github.com/jedisct1/libsodium
|
||||
- test -f $HOME/cache/usr/lib/libsodium.so || (cd libsodium && ./configure --prefix=$HOME/cache/usr && make install -j$(nproc))
|
||||
# c-toxcore
|
||||
- git clone --depth=1 https://github.com/TokTok/c-toxcore
|
||||
- test -f $HOME/cache/usr/lib/libtoxcore.so || (cd c-toxcore && cmake -B_build -H. -DCMAKE_INSTALL_PREFIX:PATH=$HOME/cache/usr && make -C_build install -j$(nproc))
|
||||
|
||||
script:
|
||||
- make ENABLE_PYTHON=1
|
2
Makefile
2
Makefile
@ -3,7 +3,7 @@ CFG_DIR = $(BASE_DIR)/cfg
|
||||
|
||||
-include $(CFG_DIR)/global_vars.mk
|
||||
|
||||
LIBS = libtoxcore ncursesw libconfig libqrencode
|
||||
LIBS = toxcore ncursesw libconfig libqrencode
|
||||
|
||||
CFLAGS = -std=gnu99 -pthread -Wall -g -fstack-protector-all
|
||||
CFLAGS += '-DTOXICVER="$(VERSION)"' -DHAVE_WIDECHAR -D_XOPEN_SOURCE_EXTENDED -D_FILE_OFFSET_BITS=64
|
||||
|
@ -3,13 +3,12 @@
|
||||
src="https://scan.coverity.com/projects/4975/badge.svg"/>
|
||||
</a>
|
||||
|
||||
Toxic is a [Tox](https://tox.chat)-based instant messenging client which formerly resided in the [Tox core repository](https://github.com/toktok/c-toxcore), and is now available as a standalone application.
|
||||
Toxic is a [Tox](https://tox.chat)-based instant messenging and video chat client.
|
||||
|
||||
[](https://i.imgur.com/san99Z2.png)
|
||||
|
||||
## Installation
|
||||
[Use our repositories](https://wiki.tox.chat/binaries#other_linux)<br />
|
||||
[Compile it yourself](/INSTALL.md)
|
||||
[See the install instructions](/INSTALL.md)
|
||||
|
||||
## Settings
|
||||
Running Toxic for the first time creates an empty file called toxic.conf in your home configuration directory ("~/.config/tox" for Linux users). Adding options to this file allows you to enable auto-logging, change the time format (12/24 hour), and much more.
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Variables for audio call support
|
||||
AUDIO_LIBS = libtoxav openal
|
||||
AUDIO_LIBS = openal
|
||||
AUDIO_CFLAGS = -DAUDIO
|
||||
ifneq (, $(findstring audio_device.o, $(OBJ)))
|
||||
AUDIO_OBJ = audio_call.o
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Variables for video call support
|
||||
VIDEO_LIBS = libtoxav vpx x11
|
||||
VIDEO_LIBS = vpx x11
|
||||
VIDEO_CFLAGS = -DVIDEO
|
||||
ifneq (, $(findstring video_device.o, $(OBJ)))
|
||||
VIDEO_OBJ = video_call.o
|
||||
|
@ -36,7 +36,6 @@
|
||||
|
||||
#ifdef PYTHON
|
||||
#include "python_api.h"
|
||||
#endif /* PYTHON */
|
||||
|
||||
Tox *user_tox;
|
||||
static WINDOW *cur_window;
|
||||
@ -208,3 +207,4 @@ void invoke_autoruns(WINDOW *window, ToxWindow *self)
|
||||
|
||||
closedir(d);
|
||||
}
|
||||
#endif /* PYTHON */
|
||||
|
@ -56,6 +56,7 @@
|
||||
#endif
|
||||
|
||||
extern FriendsList Friends;
|
||||
struct CallControl CallControl;
|
||||
|
||||
#define cbend pthread_exit(NULL)
|
||||
|
||||
@ -133,8 +134,6 @@ ToxAV *init_audio(ToxWindow *self, Tox *tox)
|
||||
CallControl.video_frame_duration = 0;
|
||||
#endif /* VIDEO */
|
||||
|
||||
memset(CallControl.calls, 0, sizeof(CallControl.calls));
|
||||
|
||||
if ( !CallControl.av ) {
|
||||
CallControl.audio_errors |= ae_StartingCoreAudio;
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to init ToxAV");
|
||||
@ -160,7 +159,7 @@ void terminate_audio()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CALLS; ++i)
|
||||
for (i = 0; i < CallControl.max_calls; ++i)
|
||||
stop_transmission(&CallControl.calls[i], i);
|
||||
|
||||
if ( CallControl.av )
|
||||
@ -338,11 +337,10 @@ void receive_audio_frame_cb(ToxAV *av, uint32_t friend_number,
|
||||
write_device_callback(friend_number, pcm, sample_count, channels, sampling_rate);
|
||||
}
|
||||
|
||||
void audio_bit_rate_status_cb(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate,
|
||||
uint32_t video_bit_rate, void *user_data)
|
||||
void audio_bit_rate_status_cb(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, void *user_data)
|
||||
{
|
||||
CallControl.audio_bit_rate = audio_bit_rate;
|
||||
toxav_bit_rate_set(av, friend_number, audio_bit_rate, video_bit_rate, user_data);
|
||||
toxav_audio_set_bit_rate(av, friend_number, audio_bit_rate, user_data);
|
||||
}
|
||||
|
||||
void callback_recv_invite(Tox *m, uint32_t friend_number)
|
||||
@ -855,7 +853,7 @@ void cmd_bitrate(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)
|
||||
const uint32_t bitrate = strtol(argv[1], NULL, 10);
|
||||
|
||||
TOXAV_ERR_BIT_RATE_SET error;
|
||||
audio_bit_rate_status_cb(CallControl.av, self->num, bitrate, -1, &error);
|
||||
audio_bit_rate_status_cb(CallControl.av, self->num, bitrate, &error);
|
||||
|
||||
if (error != TOXAV_ERR_BIT_RATE_SET_OK) {
|
||||
switch (error) {
|
||||
@ -863,8 +861,8 @@ void cmd_bitrate(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)
|
||||
error_str = "Syncronization error occured";
|
||||
break;
|
||||
|
||||
case TOXAV_ERR_BIT_RATE_SET_INVALID_AUDIO_BIT_RATE:
|
||||
error_str = "Invalid audio bit rate value (valid is 6-510)";
|
||||
case TOXAV_ERR_BIT_RATE_SET_INVALID_BIT_RATE:
|
||||
error_str = "Invalid AV bit rate value (valid is 6-510)";
|
||||
break;
|
||||
|
||||
case TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_FOUND:
|
||||
@ -900,3 +898,47 @@ void stop_current_call(ToxWindow *self)
|
||||
|
||||
CallControl.pending_call = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reallocates the Calls list according to n.
|
||||
*/
|
||||
static void realloc_calls(uint32_t n)
|
||||
{
|
||||
if (n <= 0) {
|
||||
free(CallControl.calls);
|
||||
CallControl.calls = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
Call *temp = realloc(CallControl.calls, n * sizeof(Call));
|
||||
|
||||
if (temp == NULL) {
|
||||
exit_toxic_err("failed in realloc_calls", FATALERR_MEMORY);
|
||||
}
|
||||
|
||||
CallControl.calls = temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inits the call structure for a given friend. Called when a friend is added to the friends list.
|
||||
* Index must be equivalent to the friend's friendlist index.
|
||||
*/
|
||||
void init_friend_AV(uint32_t index)
|
||||
{
|
||||
realloc_calls(CallControl.max_calls + 1);
|
||||
memset(&CallControl.calls[CallControl.max_calls], 0, sizeof(Call));
|
||||
|
||||
if (index == CallControl.max_calls) {
|
||||
++CallControl.max_calls;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a call structure from the Calls list. Called when a friend is deleted from the friends list.
|
||||
* Index must be equivalent to the size of the Calls list.
|
||||
*/
|
||||
void del_friend_AV(uint32_t index)
|
||||
{
|
||||
realloc_calls(index);
|
||||
CallControl.max_calls = index;
|
||||
}
|
||||
|
@ -27,8 +27,6 @@
|
||||
|
||||
#include "audio_device.h"
|
||||
|
||||
#define MAX_CALLS 10
|
||||
|
||||
typedef enum _AudioError {
|
||||
ae_None = 0,
|
||||
ae_StartingCaptureDevice = 1 << 0,
|
||||
@ -65,7 +63,9 @@ struct CallControl {
|
||||
ToxAV *av;
|
||||
ToxWindow *prompt;
|
||||
|
||||
Call calls[MAX_CALLS];
|
||||
Call *calls;
|
||||
uint32_t max_calls;
|
||||
|
||||
uint32_t call_state;
|
||||
bool pending_call;
|
||||
bool audio_enabled;
|
||||
@ -79,9 +79,9 @@ struct CallControl {
|
||||
uint32_t video_bit_rate;
|
||||
int32_t video_frame_duration;
|
||||
|
||||
} CallControl;
|
||||
};
|
||||
|
||||
struct CallControl CallControl;
|
||||
extern struct CallControl CallControl;
|
||||
|
||||
/* You will have to pass pointer to first member of 'windows' declared in windows.c */
|
||||
ToxAV *init_audio(ToxWindow *self, Tox *tox);
|
||||
@ -89,5 +89,7 @@ void terminate_audio();
|
||||
int start_transmission(ToxWindow *self, Call *call);
|
||||
int stop_transmission(Call *call, uint32_t friend_number);
|
||||
void stop_current_call(ToxWindow *self);
|
||||
void init_friend_AV(uint32_t index);
|
||||
void del_friend_AV(uint32_t index);
|
||||
|
||||
#endif /* AUDIO_CALL_H */
|
||||
|
@ -38,16 +38,18 @@
|
||||
#include "execute.h"
|
||||
#include "configdir.h"
|
||||
|
||||
static void print_matches(ToxWindow *self, Tox *m, const void *list, int n_items, int size)
|
||||
static void print_matches(ToxWindow *self, Tox *m, const void *list, size_t n_items, size_t size)
|
||||
{
|
||||
if (m)
|
||||
if (m) {
|
||||
execute(self->chatwin->history, self, m, "/clear", GLOBAL_COMMAND_MODE);
|
||||
}
|
||||
|
||||
const char *L = (char *) list;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_items; ++i)
|
||||
for (i = 0; i < n_items; ++i) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", &L[i * size]);
|
||||
}
|
||||
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, ""); /* formatting */
|
||||
}
|
||||
@ -91,7 +93,7 @@ static size_t get_str_match(ToxWindow *self, char *match, size_t match_sz, char
|
||||
in the list, and size is the size of each item in the list.
|
||||
|
||||
Returns the difference between the old len and new len of line on success, -1 if error */
|
||||
int complete_line(ToxWindow *self, const void *list, int n_items, int size)
|
||||
int complete_line(ToxWindow *self, const void *list, size_t n_items, size_t size)
|
||||
{
|
||||
ChatContext *ctx = self->chatwin;
|
||||
|
||||
@ -148,7 +150,7 @@ int complete_line(ToxWindow *self, const void *list, int n_items, int size)
|
||||
}
|
||||
|
||||
int s_len = strlen(sub);
|
||||
int n_matches = 0;
|
||||
size_t n_matches = 0;
|
||||
char matches[n_items][MAX_STR_SIZE];
|
||||
int i = 0;
|
||||
|
||||
@ -287,7 +289,7 @@ int dir_match(ToxWindow *self, Tox *m, const wchar_t *line, const wchar_t *cmd)
|
||||
if (dp == NULL)
|
||||
return -1;
|
||||
|
||||
char dirnames[MAX_DIRS][NAME_MAX + 1];
|
||||
char dirnames[MAX_DIRS][NAME_MAX+1];
|
||||
struct dirent *entry;
|
||||
int dircount = 0;
|
||||
|
||||
@ -305,9 +307,9 @@ int dir_match(ToxWindow *self, Tox *m, const wchar_t *line, const wchar_t *cmd)
|
||||
return -1;
|
||||
|
||||
if (dircount > 1) {
|
||||
qsort(dirnames, dircount, NAME_MAX, qsort_strcasecmp_hlpr);
|
||||
print_matches(self, m, dirnames, dircount, NAME_MAX);
|
||||
qsort(dirnames, dircount, NAME_MAX + 1, qsort_strcasecmp_hlpr);
|
||||
print_matches(self, m, dirnames, dircount, NAME_MAX + 1);
|
||||
}
|
||||
|
||||
return complete_line(self, dirnames, dircount, NAME_MAX);
|
||||
return complete_line(self, dirnames, dircount, NAME_MAX + 1);
|
||||
}
|
||||
|
@ -31,7 +31,7 @@
|
||||
in the list, and size is the size of each item in the list.
|
||||
|
||||
Returns the difference between the old len and new len of line on success, -1 if error */
|
||||
int complete_line(ToxWindow *self, const void *list, int n_items, int size);
|
||||
int complete_line(ToxWindow *self, const void *list, size_t n_items, size_t size);
|
||||
|
||||
/* attempts to match /command "<incomplete-dir>" line to matching directories.
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "configdir.h"
|
||||
#include "curl_util.h"
|
||||
#include "settings.h"
|
||||
#include "prompt.h"
|
||||
|
||||
extern struct arg_opts arg_opts;
|
||||
extern struct user_settings *user_settings;
|
||||
@ -108,7 +109,10 @@ static struct DHT_Nodes {
|
||||
/* Determine if a node is offline by comparing the age of the nodeslist
|
||||
* to the last time the node was successfully pinged.
|
||||
*/
|
||||
#define NODE_IS_OFFLINE(last_scan, last_ping) ((last_ping + NODE_OFFLINE_TIMOUT) <= (last_ping))
|
||||
static bool node_is_offline(unsigned long long int last_ping)
|
||||
{
|
||||
return last_ping + NODE_OFFLINE_TIMOUT <= last_ping;
|
||||
}
|
||||
|
||||
/* Return true if nodeslist pointed to by fp needs to be updated.
|
||||
* This will be the case if the file is empty, has an invalid format,
|
||||
@ -377,7 +381,7 @@ static int extract_node(const char *line, struct Node *node)
|
||||
|
||||
long long int last_pinged = extract_val_last_pinged(last_pinged_str + LAST_PING_JSON_KEY_LEN);
|
||||
|
||||
if (last_pinged <= 0 || NODE_IS_OFFLINE(Nodes.last_scan, last_pinged)) {
|
||||
if (last_pinged <= 0 || node_is_offline(last_pinged)) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
@ -577,7 +581,7 @@ static void DHT_bootstrap(Tox *m)
|
||||
void do_tox_connection(Tox *m)
|
||||
{
|
||||
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)) {
|
||||
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) {
|
||||
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);
|
||||
|
||||
msg = "has come online";
|
||||
@ -1160,9 +1158,8 @@ static void chat_onInit(ToxWindow *self, Tox *m)
|
||||
|
||||
/* Init statusbar info */
|
||||
StatusBar *statusbar = self->stb;
|
||||
|
||||
statusbar->status = tox_friend_get_status(m, self->num, NULL);
|
||||
statusbar->connection = tox_friend_get_connection_status(m, self->num, NULL);
|
||||
statusbar->status = get_friend_status(self->num);
|
||||
statusbar->connection = get_friend_connection_status(self->num);
|
||||
|
||||
char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH];
|
||||
tox_friend_get_status_message(m, self->num, (uint8_t *) statusmsg, NULL);
|
||||
|
@ -466,6 +466,10 @@ void friendlist_onFriendAdded(ToxWindow *self, Tox *m, uint32_t num, bool sort)
|
||||
if (sort)
|
||||
sort_friendlist_index();
|
||||
|
||||
#ifdef AUDIO
|
||||
init_friend_AV(i);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -605,6 +609,10 @@ static void delete_friend(Tox *m, uint32_t f_num)
|
||||
Friends.max_idx = i;
|
||||
realloc_friends(i);
|
||||
|
||||
#ifdef AUDIO
|
||||
del_friend_AV(i);
|
||||
#endif
|
||||
|
||||
/* make sure num_selected stays within Friends.num_friends range */
|
||||
if (Friends.num_friends && Friends.num_selected == Friends.num_friends)
|
||||
--Friends.num_selected;
|
||||
@ -1155,6 +1163,18 @@ static void friendlist_onAV(ToxWindow *self, ToxAV *av, uint32_t friend_number,
|
||||
}
|
||||
#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 ret;
|
||||
|
@ -54,7 +54,7 @@ typedef struct {
|
||||
TOX_CONNECTION connection_status;
|
||||
bool is_typing;
|
||||
bool logging_on; /* saves preference for friend irrespective of global settings */
|
||||
uint8_t status;
|
||||
TOX_USER_STATUS status;
|
||||
|
||||
struct LastOnline last_online;
|
||||
struct GroupChatInvite group_invite;
|
||||
@ -87,6 +87,8 @@ int get_friendnum(uint8_t *name);
|
||||
int load_blocklist(char *data);
|
||||
void kill_friendlist(void);
|
||||
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 */
|
||||
void sort_friendlist_index(void);
|
||||
|
309
src/groupchat.c
309
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].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);
|
||||
|
||||
if (i == max_groupchat_index)
|
||||
@ -165,14 +153,10 @@ static void kill_groupchat_window(ToxWindow *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].peer_names);
|
||||
free(groupchats[groupnum].oldpeer_names);
|
||||
free(groupchats[groupnum].peer_name_lengths);
|
||||
free(groupchats[groupnum].oldpeer_name_lengths);
|
||||
free(groupchats[groupnum].name_list);
|
||||
free(groupchats[groupnum].peer_list);
|
||||
memset(&groupchats[groupnum], 0, sizeof(GroupChat));
|
||||
|
||||
int i;
|
||||
@ -186,6 +170,12 @@ void close_groupchat(ToxWindow *self, Tox *m, uint32_t groupnum)
|
||||
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 */
|
||||
void redraw_groupchat_win(ToxWindow *self)
|
||||
{
|
||||
@ -292,104 +282,102 @@ static void groupchat_onGroupTitleChange(ToxWindow *self, Tox *m, uint32_t group
|
||||
write_to_log(tmp_event, nick, ctx->log, true);
|
||||
}
|
||||
|
||||
/* Puts two copies of peerlist/lengths in chat instance */
|
||||
static void copy_peernames(Tox *m, uint32_t gnum, size_t npeers)
|
||||
static void group_update_name_list(uint32_t groupnum)
|
||||
{
|
||||
/* Assumes these are initiated in init_groupchat_win */
|
||||
free(groupchats[gnum].peer_names);
|
||||
free(groupchats[gnum].oldpeer_names);
|
||||
free(groupchats[gnum].peer_name_lengths);
|
||||
free(groupchats[gnum].oldpeer_name_lengths);
|
||||
GroupChat *chat = &groupchats[groupnum];
|
||||
|
||||
int N = TOX_MAX_NAME_LENGTH;
|
||||
|
||||
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);
|
||||
if (!chat) {
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
qsort(chat->name_list, count, TOX_MAX_NAME_LENGTH, qsort_strcasecmp_hlpr);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
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) {
|
||||
memcpy(&groupchats[gnum].peer_names[i * N], UNKNOWN_NAME, u_len);
|
||||
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;
|
||||
continue;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&Winthread.lock);
|
||||
peer->active = true;
|
||||
peer->name_length = length;
|
||||
peer->peernumber = i;
|
||||
}
|
||||
|
||||
const char *event = "has joined the room";
|
||||
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);
|
||||
group_update_name_list(groupnum);
|
||||
}
|
||||
|
||||
static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, uint32_t groupnum, uint32_t peernum,
|
||||
TOX_CONFERENCE_STATE_CHANGE change)
|
||||
static void groupchat_onGroupNameListChange(ToxWindow *self, Tox *m, uint32_t groupnum)
|
||||
{
|
||||
if (self->num != groupnum)
|
||||
return;
|
||||
@ -397,107 +385,57 @@ static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, uint32_t gr
|
||||
if (groupnum > max_groupchat_index)
|
||||
return;
|
||||
|
||||
GroupChat *chat = &groupchats[groupnum];
|
||||
TOX_ERR_CONFERENCE_PEER_QUERY 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) {
|
||||
groupchats[groupnum].num_peers = num_peers;
|
||||
chat->num_peers = num_peers;
|
||||
} else {
|
||||
num_peers = groupchats[groupnum].num_peers;
|
||||
num_peers = old_num;
|
||||
}
|
||||
|
||||
if (peernum > num_peers)
|
||||
chat->max_idx = num_peers;
|
||||
update_peer_list(m, groupnum, num_peers);
|
||||
}
|
||||
|
||||
static void groupchat_onGroupPeerNameChange(ToxWindow *self, Tox *m, uint32_t groupnum, uint32_t peernum,
|
||||
const char *name, size_t length)
|
||||
{
|
||||
if (self->num != groupnum) {
|
||||
return;
|
||||
|
||||
/* get old peer name before updating name list */
|
||||
uint8_t oldpeername[TOX_MAX_NAME_LENGTH];
|
||||
|
||||
if (change != TOX_CONFERENCE_STATE_CHANGE_PEER_JOIN) {
|
||||
memcpy(oldpeername, &groupchats[groupnum].oldpeer_names[peernum * TOX_MAX_NAME_LENGTH], sizeof(oldpeername));
|
||||
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);
|
||||
GroupChat *chat = &groupchats[groupnum];
|
||||
|
||||
/* 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';
|
||||
if (!chat) {
|
||||
return;
|
||||
}
|
||||
|
||||
qsort(groupchats[groupnum].peer_names, groupchats[groupnum].num_peers, TOX_MAX_NAME_LENGTH, qsort_strcasecmp_hlpr);
|
||||
size_t i;
|
||||
|
||||
ChatContext *ctx = self->chatwin;
|
||||
for (i = 0; i < chat->max_idx; ++i) {
|
||||
GroupPeer *peer = &chat->peer_list[i];
|
||||
|
||||
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);
|
||||
// Test against default tox name to prevent nick change spam on initial join (TODO: this is disgusting)
|
||||
if (peer->active && peer->peernumber == peernum && strcmp(peer->name, "Tox User")) {
|
||||
ChatContext *ctx = self->chatwin;
|
||||
char timefrmt[TIME_STR_SIZE];
|
||||
get_time_str(timefrmt, sizeof(timefrmt));
|
||||
|
||||
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);
|
||||
snprintf(tmp_event, sizeof(tmp_event), "is now known as %s", (char *) name);
|
||||
|
||||
write_to_log(tmp_event, peer->name, ctx->log, true);
|
||||
line_info_add(self, timefrmt, peer->name, (char *) name, NAME_CHANGE, 0, 0, " is now known as ");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sound_notify(self, silent, NT_WNDALERT_2, NULL);
|
||||
groupchat_onGroupNameListChange(self, m, groupnum);
|
||||
}
|
||||
|
||||
static void send_group_action(ToxWindow *self, ChatContext *ctx, Tox *m, char *action)
|
||||
@ -550,7 +488,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
|
||||
/* TODO: make this not suck */
|
||||
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);
|
||||
} else if (wcsncmp(ctx->line, L"/avatar \"", wcslen(L"/avatar \"")) == 0) {
|
||||
diff = dir_match(self, m, ctx->line, L"/avatar");
|
||||
@ -601,7 +539,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
|
||||
if (line[0] == '/') {
|
||||
if (strcmp(line, "/close") == 0) {
|
||||
close_groupchat(self, m, self->num);
|
||||
delete_groupchat(self, m, self->num);
|
||||
return;
|
||||
} else if (strncmp(line, "/me ", strlen("/me ")) == 0) {
|
||||
send_group_action(self, ctx, m, line + strlen("/me "));
|
||||
@ -678,7 +616,7 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m)
|
||||
int maxlen = SIDEBAR_WIDTH - 2;
|
||||
|
||||
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);
|
||||
|
||||
tmpnck[maxlen] = '\0';
|
||||
@ -747,7 +685,8 @@ ToxWindow new_group_chat(Tox *m, uint32_t groupnum)
|
||||
ret.onDraw = &groupchat_onDraw;
|
||||
ret.onInit = &groupchat_onInit;
|
||||
ret.onGroupMessage = &groupchat_onGroupMessage;
|
||||
ret.onGroupNamelistChange = &groupchat_onGroupNamelistChange;
|
||||
ret.onGroupNameListChange = &groupchat_onGroupNameListChange;
|
||||
ret.onGroupPeerNameChange = &groupchat_onGroupPeerNameChange;
|
||||
ret.onGroupTitleChange = &groupchat_onGroupTitleChange;
|
||||
|
||||
snprintf(ret.name, sizeof(ret.name), "Group %d", groupnum);
|
||||
|
@ -31,20 +31,31 @@
|
||||
#define MAX_GROUPCHAT_NUM MAX_WINDOWS_NUM - 2
|
||||
#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 {
|
||||
int chatwin;
|
||||
bool active;
|
||||
uint8_t type;
|
||||
uint32_t num_peers;
|
||||
int side_pos; /* current position of the sidebar - used for scrolling up and down */
|
||||
time_t start_time;
|
||||
uint8_t *peer_names;
|
||||
uint8_t *oldpeer_names;
|
||||
uint16_t *peer_name_lengths;
|
||||
uint16_t *oldpeer_name_lengths;
|
||||
|
||||
GroupPeer *peer_list;
|
||||
size_t max_idx;
|
||||
|
||||
char *name_list;
|
||||
size_t num_peers;
|
||||
|
||||
} 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);
|
||||
|
||||
/* destroys and re-creates groupchat window with or without the peerlist */
|
||||
|
@ -31,7 +31,7 @@
|
||||
#define MAX_LINE_INFO_QUEUE 1024
|
||||
#define MAX_LINE_INFO_MSG_SIZE MAX_STR_SIZE + TOXIC_MAX_NAME_LENGTH + 32 /* needs extra room for log loading */
|
||||
|
||||
enum {
|
||||
typedef enum {
|
||||
SYS_MSG,
|
||||
IN_MSG,
|
||||
OUT_MSG,
|
||||
|
@ -30,7 +30,7 @@ struct chatlog {
|
||||
bool log_on; /* specific to current chat window */
|
||||
};
|
||||
|
||||
enum {
|
||||
typedef enum {
|
||||
LOG_GROUP,
|
||||
LOG_PROMPT,
|
||||
LOG_CHAT,
|
||||
|
@ -26,10 +26,8 @@
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include <dirent.h>
|
||||
#if SYSTEM == BSD
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#endif /* BSD! */
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
@ -163,6 +163,13 @@ void prompt_update_status(ToxWindow *prompt, TOX_USER_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.
|
||||
Returns request number on success, -1 if queue is full. */
|
||||
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 */
|
||||
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 */
|
||||
|
@ -23,7 +23,6 @@
|
||||
#ifdef PYTHON
|
||||
#include <Python.h>
|
||||
#include "api.h"
|
||||
#endif /* PYTHON */
|
||||
|
||||
#include "execute.h"
|
||||
|
||||
@ -67,7 +66,7 @@ static PyObject *python_api_get_nick(PyObject *self, PyObject *args)
|
||||
|
||||
static PyObject *python_api_get_status(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *ret;
|
||||
PyObject *ret = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
@ -345,3 +344,4 @@ void python_draw_handler_help(WINDOW *win)
|
||||
wprintw(win, " %-29s: %.50s\n", cur->name, cur->help);
|
||||
}
|
||||
}
|
||||
#endif /* PYTHON */
|
||||
|
@ -88,7 +88,7 @@ struct user_settings {
|
||||
#endif
|
||||
};
|
||||
|
||||
enum {
|
||||
enum settings_values {
|
||||
AUTOLOG_OFF = 0,
|
||||
AUTOLOG_ON = 1,
|
||||
|
||||
@ -114,7 +114,7 @@ enum {
|
||||
|
||||
MPLEX_OFF = 0,
|
||||
MPLEX_ON = 1,
|
||||
} settings_values;
|
||||
};
|
||||
|
||||
#define LINE_JOIN "-->"
|
||||
#define LINE_QUIT "<--"
|
||||
|
97
src/toxic.c
97
src/toxic.c
@ -52,6 +52,7 @@
|
||||
#include "friendlist.h"
|
||||
#include "prompt.h"
|
||||
#include "misc_tools.h"
|
||||
#include "groupchat.h"
|
||||
#include "file_transfers.h"
|
||||
#include "line_info.h"
|
||||
#include "settings.h"
|
||||
@ -305,12 +306,46 @@ static void load_friendlist(Tox *m)
|
||||
size_t i;
|
||||
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);
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
if (num_chats) {
|
||||
tox_conference_get_chatlist(m, chatlist);
|
||||
}
|
||||
|
||||
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 */
|
||||
static int password_prompt(char *buf, int size)
|
||||
{
|
||||
@ -551,7 +586,8 @@ static void init_tox_callbacks(Tox *m)
|
||||
tox_callback_friend_read_receipt(m, on_read_receipt);
|
||||
tox_callback_conference_invite(m, on_groupinvite);
|
||||
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_file_recv(m, on_file_recv);
|
||||
tox_callback_file_chunk_request(m, on_file_chunk_request);
|
||||
@ -563,30 +599,30 @@ static void init_tox_options(struct Tox_Options *tox_opts)
|
||||
{
|
||||
tox_options_default(tox_opts);
|
||||
|
||||
tox_opts->ipv6_enabled = !arg_opts.use_ipv4;
|
||||
tox_opts->udp_enabled = !arg_opts.force_tcp;
|
||||
tox_opts->proxy_type = arg_opts.proxy_type;
|
||||
tox_opts->tcp_port = arg_opts.tcp_port;
|
||||
tox_options_set_ipv6_enabled(tox_opts, !arg_opts.use_ipv4);
|
||||
tox_options_set_udp_enabled(tox_opts, !arg_opts.force_tcp);
|
||||
tox_options_set_proxy_type(tox_opts, arg_opts.proxy_type);
|
||||
tox_options_set_tcp_port(tox_opts, arg_opts.tcp_port);
|
||||
|
||||
if (!tox_opts->ipv6_enabled)
|
||||
if (!tox_options_get_ipv6_enabled(tox_opts))
|
||||
queue_init_message("Forcing IPv4 connection");
|
||||
|
||||
if (tox_opts->tcp_port)
|
||||
queue_init_message("TCP relaying enabled on port %d", tox_opts->tcp_port);
|
||||
if (tox_options_get_tcp_port(tox_opts))
|
||||
queue_init_message("TCP relaying enabled on port %d", tox_options_get_tcp_port(tox_opts));
|
||||
|
||||
if (tox_opts->proxy_type != TOX_PROXY_TYPE_NONE) {
|
||||
tox_opts->proxy_port = arg_opts.proxy_port;
|
||||
tox_opts->proxy_host = arg_opts.proxy_address;
|
||||
const char *ps = tox_opts->proxy_type == TOX_PROXY_TYPE_SOCKS5 ? "SOCKS5" : "HTTP";
|
||||
if (tox_options_get_proxy_type(tox_opts) != TOX_PROXY_TYPE_NONE) {
|
||||
tox_options_set_proxy_port(tox_opts, arg_opts.proxy_port);
|
||||
tox_options_set_proxy_host(tox_opts, arg_opts.proxy_address);
|
||||
const char *ps = tox_options_get_proxy_type(tox_opts) == TOX_PROXY_TYPE_SOCKS5 ? "SOCKS5" : "HTTP";
|
||||
|
||||
char tmp[sizeof(arg_opts.proxy_address) + MAX_STR_SIZE];
|
||||
snprintf(tmp, sizeof(tmp), "Using %s proxy %s : %d", ps, arg_opts.proxy_address, arg_opts.proxy_port);
|
||||
queue_init_message("%s", tmp);
|
||||
}
|
||||
|
||||
if (!tox_opts->udp_enabled) {
|
||||
if (!tox_options_get_udp_enabled(tox_opts)) {
|
||||
queue_init_message("UDP disabled");
|
||||
} else if (tox_opts->proxy_type != TOX_PROXY_TYPE_NONE) {
|
||||
} else if (tox_options_get_proxy_type(tox_opts) != TOX_PROXY_TYPE_NONE) {
|
||||
const char *msg = "WARNING: Using a proxy without disabling UDP may leak your real IP address.";
|
||||
queue_init_message("%s", msg);
|
||||
msg = "Use the -t option to disable UDP.";
|
||||
@ -675,9 +711,8 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, TOX_ERR_NEW
|
||||
(uint8_t *) plain, &pwerr);
|
||||
|
||||
if (pwerr == TOX_ERR_DECRYPTION_OK) {
|
||||
tox_opts->savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE;
|
||||
tox_opts->savedata_data = (uint8_t *) plain;
|
||||
tox_opts->savedata_length = plain_len;
|
||||
tox_options_set_savedata_type(tox_opts, TOX_SAVEDATA_TYPE_TOX_SAVE);
|
||||
tox_options_set_savedata_data(tox_opts, (uint8_t *) plain, plain_len);
|
||||
|
||||
m = tox_new(tox_opts, new_err);
|
||||
|
||||
@ -698,9 +733,8 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, TOX_ERR_NEW
|
||||
}
|
||||
}
|
||||
} else { /* data is not encrypted */
|
||||
tox_opts->savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE;
|
||||
tox_opts->savedata_data = (uint8_t *) data;
|
||||
tox_opts->savedata_length = len;
|
||||
tox_options_set_savedata_type(tox_opts, TOX_SAVEDATA_TYPE_TOX_SAVE);
|
||||
tox_options_set_savedata_data(tox_opts, (uint8_t *) data, len);
|
||||
|
||||
m = tox_new(tox_opts, new_err);
|
||||
|
||||
@ -715,7 +749,7 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, TOX_ERR_NEW
|
||||
if (file_exists(data_path))
|
||||
exit_toxic_err("failed in load_tox", FATALERR_FILEOP);
|
||||
|
||||
tox_opts->savedata_type = TOX_SAVEDATA_TYPE_NONE;
|
||||
tox_options_set_savedata_type(tox_opts, TOX_SAVEDATA_TYPE_NONE);
|
||||
|
||||
m = tox_new(tox_opts, new_err);
|
||||
|
||||
@ -731,16 +765,19 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, TOX_ERR_NEW
|
||||
|
||||
static Tox *load_toxic(char *data_path)
|
||||
{
|
||||
struct Tox_Options tox_opts;
|
||||
init_tox_options(&tox_opts);
|
||||
TOX_ERR_OPTIONS_NEW options_new_err;
|
||||
struct Tox_Options *tox_opts = tox_options_new(&options_new_err);
|
||||
if (!tox_opts)
|
||||
exit_toxic_err("tox_options_new returned fatal error", options_new_err);
|
||||
init_tox_options(tox_opts);
|
||||
|
||||
TOX_ERR_NEW new_err;
|
||||
Tox *m = load_tox(data_path, &tox_opts, &new_err);
|
||||
Tox *m = load_tox(data_path, tox_opts, &new_err);
|
||||
|
||||
if (new_err == TOX_ERR_NEW_PORT_ALLOC && tox_opts.ipv6_enabled) {
|
||||
if (new_err == TOX_ERR_NEW_PORT_ALLOC && tox_options_get_ipv6_enabled(tox_opts)) {
|
||||
queue_init_message("Falling back to ipv4");
|
||||
tox_opts.ipv6_enabled = false;
|
||||
m = load_tox(data_path, &tox_opts, &new_err);
|
||||
tox_options_set_ipv6_enabled(tox_opts, false);
|
||||
m = load_tox(data_path, tox_opts, &new_err);
|
||||
}
|
||||
|
||||
if (!m)
|
||||
@ -756,6 +793,7 @@ static Tox *load_toxic(char *data_path)
|
||||
if (tox_self_get_name_size(m) == 0)
|
||||
tox_self_set_name(m, (uint8_t *) "Toxic User", strlen("Toxic User"), NULL);
|
||||
|
||||
tox_options_free(tox_opts);
|
||||
return m;
|
||||
}
|
||||
|
||||
@ -814,7 +852,7 @@ void *thread_cqueue(void *data)
|
||||
ToxWindow *toxwin = get_window_ptr(i);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1196,6 +1234,7 @@ int main(int argc, char **argv)
|
||||
|
||||
prompt = init_windows(m);
|
||||
prompt_init_statusbar(prompt, m);
|
||||
load_groups(prompt, m);
|
||||
|
||||
/* thread for ncurses stuff */
|
||||
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);
|
||||
void on_groupinvite(Tox *m, uint32_t friendnumber, TOX_CONFERENCE_TYPE type, const uint8_t *group_pub_key,
|
||||
size_t length, void *userdata);
|
||||
void on_group_namelistchange(Tox *m, uint32_t groupnumber, uint32_t peernumber, TOX_CONFERENCE_STATE_CHANGE change,
|
||||
void *userdata);
|
||||
void on_group_namelistchange(Tox *m, uint32_t groupnumber, 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 *userdata);
|
||||
void on_file_chunk_request(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length,
|
||||
|
@ -45,8 +45,7 @@ void receive_video_frame_cb( ToxAV *av, uint32_t friend_number,
|
||||
int32_t ystride, int32_t ustride, int32_t vstride,
|
||||
void *user_data );
|
||||
|
||||
void video_bit_rate_status_cb( ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate,
|
||||
uint32_t video_bit_rate, void *user_data);
|
||||
void video_bit_rate_status_cb( ToxAV *av, uint32_t friend_number, uint32_t video_bit_rate, void *user_data);
|
||||
|
||||
static void print_err (ToxWindow *self, const char *error_str)
|
||||
{
|
||||
@ -74,7 +73,7 @@ ToxAV *init_video(ToxWindow *self, Tox *tox)
|
||||
}
|
||||
|
||||
toxav_callback_video_receive_frame(CallControl.av, receive_video_frame_cb, &CallControl);
|
||||
toxav_callback_bit_rate_status(CallControl.av, video_bit_rate_status_cb, &CallControl);
|
||||
toxav_callback_video_bit_rate(CallControl.av, video_bit_rate_status_cb, &CallControl);
|
||||
|
||||
return CallControl.av;
|
||||
}
|
||||
@ -83,7 +82,7 @@ void terminate_video()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CALLS; ++i) {
|
||||
for (i = 0; i < CallControl.max_calls; ++i) {
|
||||
Call *this_call = &CallControl.calls[i];
|
||||
|
||||
stop_video_transmission(this_call, i);
|
||||
@ -135,7 +134,7 @@ int start_video_transmission(ToxWindow *self, ToxAV *av, Call *call)
|
||||
|
||||
CallControl.video_bit_rate = default_video_bit_rate;
|
||||
|
||||
if ( toxav_bit_rate_set(CallControl.av, self->num, -1, CallControl.video_bit_rate, NULL) == false ) {
|
||||
if ( toxav_video_set_bit_rate(CallControl.av, self->num, CallControl.video_bit_rate, NULL) == false ) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set video bit rate");
|
||||
return -1;
|
||||
}
|
||||
@ -156,7 +155,7 @@ int start_video_transmission(ToxWindow *self, ToxAV *av, Call *call)
|
||||
int stop_video_transmission(Call *call, int friend_number)
|
||||
{
|
||||
CallControl.video_bit_rate = 0;
|
||||
toxav_bit_rate_set(CallControl.av, friend_number, -1, CallControl.video_bit_rate, NULL);
|
||||
toxav_video_set_bit_rate(CallControl.av, friend_number, CallControl.video_bit_rate, NULL);
|
||||
|
||||
if ( call->vin_idx != -1 ) {
|
||||
close_video_device(vdt_input, call->vin_idx);
|
||||
@ -185,11 +184,10 @@ void receive_video_frame_cb(ToxAV *av, uint32_t friend_number,
|
||||
write_video_device_callback(friend_number, width, height, y, u, v, ystride, ustride, vstride, user_data);
|
||||
}
|
||||
|
||||
void video_bit_rate_status_cb(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate,
|
||||
uint32_t video_bit_rate, void *user_data)
|
||||
void video_bit_rate_status_cb(ToxAV *av, uint32_t friend_number, uint32_t video_bit_rate, void *user_data)
|
||||
{
|
||||
CallControl.video_bit_rate = video_bit_rate;
|
||||
toxav_bit_rate_set(CallControl.av, friend_number, -1, CallControl.video_bit_rate, NULL);
|
||||
toxav_video_set_bit_rate(CallControl.av, friend_number, CallControl.video_bit_rate, NULL);
|
||||
}
|
||||
|
||||
void callback_recv_video_starting(uint32_t friend_number)
|
||||
|
@ -69,7 +69,7 @@ typedef struct VideoDevice {
|
||||
void *cb_data; /* Data to be passed to callback */
|
||||
int32_t friend_number; /* ToxAV friend number */
|
||||
|
||||
#if defined(__linux__) || SYSTEM == BSD
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
int fd; /* File descriptor of video device selected/opened */
|
||||
struct v4l2_format fmt;
|
||||
struct VideoBuffer *buffers;
|
||||
@ -136,7 +136,7 @@ static void yuv420tobgr(uint16_t width, uint16_t height, const uint8_t *y,
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__linux__) || SYSTEM == BSD
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
static void yuv422to420(uint8_t *plane_y, uint8_t *plane_u, uint8_t *plane_v,
|
||||
uint8_t *input, uint16_t width, uint16_t height)
|
||||
{
|
||||
@ -724,14 +724,14 @@ void *video_thread_poll (void *arg) // TODO: maybe use thread for every input so
|
||||
XFlush(device->x_display);
|
||||
free(img_data);
|
||||
|
||||
#if defined(__linux__) || SYSTEM == BSD
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
|
||||
if ( -1 == xioctl(device->fd, VIDIOC_QBUF, &buf) ) {
|
||||
unlock;
|
||||
continue;
|
||||
}
|
||||
|
||||
#endif /* __linux__ / BSD */
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@ -787,7 +787,7 @@ VideoDeviceError close_video_device(VideoDeviceType type, uint32_t device_idx)
|
||||
XCloseDisplay(device->x_display);
|
||||
pthread_mutex_destroy(device->mutex);
|
||||
|
||||
#if defined(__linux__) || SYSTEM == BSD
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
free(device->buffers);
|
||||
#endif /* __linux__ / BSD */
|
||||
|
||||
|
@ -176,14 +176,28 @@ 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 *userdata)
|
||||
void on_group_namelistchange(Tox *m, uint32_t groupnumber, void *userdata)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
if (windows[i].onGroupNamelistChange != NULL)
|
||||
windows[i].onGroupNamelistChange(&windows[i], m, groupnumber, peernumber, change);
|
||||
if (windows[i].onGroupNameListChange != NULL)
|
||||
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)
|
||||
{
|
||||
char nick[TOXIC_MAX_NAME_LENGTH + 1];
|
||||
length = copy_tox_str(nick, sizeof(nick), (const char *) name, length);
|
||||
filter_str(nick, length);
|
||||
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
if (windows[i].onGroupPeerNameChange != NULL)
|
||||
windows[i].onGroupPeerNameChange(&windows[i], m, groupnumber, peernumber, nick, length);
|
||||
}
|
||||
}
|
||||
|
||||
@ -608,10 +622,11 @@ void kill_all_windows(Tox *m)
|
||||
size_t 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);
|
||||
else if (windows[i].is_groupchat)
|
||||
close_groupchat(&windows[i], m, windows[i].num);
|
||||
} else if (windows[i].is_groupchat) {
|
||||
free_groupchat(&windows[i], m, windows[i].num);
|
||||
}
|
||||
}
|
||||
|
||||
kill_prompt_window(prompt);
|
||||
|
@ -42,7 +42,7 @@
|
||||
#define CHATBOX_HEIGHT 2
|
||||
|
||||
/* Curses foreground colours (background is black) */
|
||||
enum {
|
||||
typedef enum {
|
||||
WHITE,
|
||||
GREEN,
|
||||
CYAN,
|
||||
@ -123,7 +123,8 @@ struct ToxWindow {
|
||||
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(*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(*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);
|
||||
|
Reference in New Issue
Block a user