mirror of
https://github.com/Tha14/toxic.git
synced 2025-06-27 21:06:46 +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
|
-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 = -std=gnu99 -pthread -Wall -g -fstack-protector-all
|
||||||
CFLAGS += '-DTOXICVER="$(VERSION)"' -DHAVE_WIDECHAR -D_XOPEN_SOURCE_EXTENDED -D_FILE_OFFSET_BITS=64
|
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"/>
|
src="https://scan.coverity.com/projects/4975/badge.svg"/>
|
||||||
</a>
|
</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)
|
[](https://i.imgur.com/san99Z2.png)
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
[Use our repositories](https://wiki.tox.chat/binaries#other_linux)<br />
|
[See the install instructions](/INSTALL.md)
|
||||||
[Compile it yourself](/INSTALL.md)
|
|
||||||
|
|
||||||
## Settings
|
## 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.
|
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
|
# Variables for audio call support
|
||||||
AUDIO_LIBS = libtoxav openal
|
AUDIO_LIBS = openal
|
||||||
AUDIO_CFLAGS = -DAUDIO
|
AUDIO_CFLAGS = -DAUDIO
|
||||||
ifneq (, $(findstring audio_device.o, $(OBJ)))
|
ifneq (, $(findstring audio_device.o, $(OBJ)))
|
||||||
AUDIO_OBJ = audio_call.o
|
AUDIO_OBJ = audio_call.o
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Variables for video call support
|
# Variables for video call support
|
||||||
VIDEO_LIBS = libtoxav vpx x11
|
VIDEO_LIBS = vpx x11
|
||||||
VIDEO_CFLAGS = -DVIDEO
|
VIDEO_CFLAGS = -DVIDEO
|
||||||
ifneq (, $(findstring video_device.o, $(OBJ)))
|
ifneq (, $(findstring video_device.o, $(OBJ)))
|
||||||
VIDEO_OBJ = video_call.o
|
VIDEO_OBJ = video_call.o
|
||||||
|
@ -36,7 +36,6 @@
|
|||||||
|
|
||||||
#ifdef PYTHON
|
#ifdef PYTHON
|
||||||
#include "python_api.h"
|
#include "python_api.h"
|
||||||
#endif /* PYTHON */
|
|
||||||
|
|
||||||
Tox *user_tox;
|
Tox *user_tox;
|
||||||
static WINDOW *cur_window;
|
static WINDOW *cur_window;
|
||||||
@ -208,3 +207,4 @@ void invoke_autoruns(WINDOW *window, ToxWindow *self)
|
|||||||
|
|
||||||
closedir(d);
|
closedir(d);
|
||||||
}
|
}
|
||||||
|
#endif /* PYTHON */
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern FriendsList Friends;
|
extern FriendsList Friends;
|
||||||
|
struct CallControl CallControl;
|
||||||
|
|
||||||
#define cbend pthread_exit(NULL)
|
#define cbend pthread_exit(NULL)
|
||||||
|
|
||||||
@ -133,8 +134,6 @@ ToxAV *init_audio(ToxWindow *self, Tox *tox)
|
|||||||
CallControl.video_frame_duration = 0;
|
CallControl.video_frame_duration = 0;
|
||||||
#endif /* VIDEO */
|
#endif /* VIDEO */
|
||||||
|
|
||||||
memset(CallControl.calls, 0, sizeof(CallControl.calls));
|
|
||||||
|
|
||||||
if ( !CallControl.av ) {
|
if ( !CallControl.av ) {
|
||||||
CallControl.audio_errors |= ae_StartingCoreAudio;
|
CallControl.audio_errors |= ae_StartingCoreAudio;
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to init ToxAV");
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to init ToxAV");
|
||||||
@ -160,7 +159,7 @@ void terminate_audio()
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < MAX_CALLS; ++i)
|
for (i = 0; i < CallControl.max_calls; ++i)
|
||||||
stop_transmission(&CallControl.calls[i], i);
|
stop_transmission(&CallControl.calls[i], i);
|
||||||
|
|
||||||
if ( CallControl.av )
|
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);
|
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,
|
void audio_bit_rate_status_cb(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, void *user_data)
|
||||||
uint32_t video_bit_rate, void *user_data)
|
|
||||||
{
|
{
|
||||||
CallControl.audio_bit_rate = audio_bit_rate;
|
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)
|
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);
|
const uint32_t bitrate = strtol(argv[1], NULL, 10);
|
||||||
|
|
||||||
TOXAV_ERR_BIT_RATE_SET error;
|
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) {
|
if (error != TOXAV_ERR_BIT_RATE_SET_OK) {
|
||||||
switch (error) {
|
switch (error) {
|
||||||
@ -863,8 +861,8 @@ void cmd_bitrate(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)
|
|||||||
error_str = "Syncronization error occured";
|
error_str = "Syncronization error occured";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOXAV_ERR_BIT_RATE_SET_INVALID_AUDIO_BIT_RATE:
|
case TOXAV_ERR_BIT_RATE_SET_INVALID_BIT_RATE:
|
||||||
error_str = "Invalid audio bit rate value (valid is 6-510)";
|
error_str = "Invalid AV bit rate value (valid is 6-510)";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_FOUND:
|
case TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_FOUND:
|
||||||
@ -900,3 +898,47 @@ void stop_current_call(ToxWindow *self)
|
|||||||
|
|
||||||
CallControl.pending_call = false;
|
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"
|
#include "audio_device.h"
|
||||||
|
|
||||||
#define MAX_CALLS 10
|
|
||||||
|
|
||||||
typedef enum _AudioError {
|
typedef enum _AudioError {
|
||||||
ae_None = 0,
|
ae_None = 0,
|
||||||
ae_StartingCaptureDevice = 1 << 0,
|
ae_StartingCaptureDevice = 1 << 0,
|
||||||
@ -65,7 +63,9 @@ struct CallControl {
|
|||||||
ToxAV *av;
|
ToxAV *av;
|
||||||
ToxWindow *prompt;
|
ToxWindow *prompt;
|
||||||
|
|
||||||
Call calls[MAX_CALLS];
|
Call *calls;
|
||||||
|
uint32_t max_calls;
|
||||||
|
|
||||||
uint32_t call_state;
|
uint32_t call_state;
|
||||||
bool pending_call;
|
bool pending_call;
|
||||||
bool audio_enabled;
|
bool audio_enabled;
|
||||||
@ -79,9 +79,9 @@ struct CallControl {
|
|||||||
uint32_t video_bit_rate;
|
uint32_t video_bit_rate;
|
||||||
int32_t video_frame_duration;
|
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 */
|
/* You will have to pass pointer to first member of 'windows' declared in windows.c */
|
||||||
ToxAV *init_audio(ToxWindow *self, Tox *tox);
|
ToxAV *init_audio(ToxWindow *self, Tox *tox);
|
||||||
@ -89,5 +89,7 @@ void terminate_audio();
|
|||||||
int start_transmission(ToxWindow *self, Call *call);
|
int start_transmission(ToxWindow *self, Call *call);
|
||||||
int stop_transmission(Call *call, uint32_t friend_number);
|
int stop_transmission(Call *call, uint32_t friend_number);
|
||||||
void stop_current_call(ToxWindow *self);
|
void stop_current_call(ToxWindow *self);
|
||||||
|
void init_friend_AV(uint32_t index);
|
||||||
|
void del_friend_AV(uint32_t index);
|
||||||
|
|
||||||
#endif /* AUDIO_CALL_H */
|
#endif /* AUDIO_CALL_H */
|
||||||
|
@ -38,16 +38,18 @@
|
|||||||
#include "execute.h"
|
#include "execute.h"
|
||||||
#include "configdir.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);
|
execute(self->chatwin->history, self, m, "/clear", GLOBAL_COMMAND_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
const char *L = (char *) list;
|
const char *L = (char *) list;
|
||||||
int i;
|
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, "%s", &L[i * size]);
|
||||||
|
}
|
||||||
|
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, ""); /* formatting */
|
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.
|
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 */
|
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;
|
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 s_len = strlen(sub);
|
||||||
int n_matches = 0;
|
size_t n_matches = 0;
|
||||||
char matches[n_items][MAX_STR_SIZE];
|
char matches[n_items][MAX_STR_SIZE];
|
||||||
int i = 0;
|
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)
|
if (dp == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
char dirnames[MAX_DIRS][NAME_MAX + 1];
|
char dirnames[MAX_DIRS][NAME_MAX+1];
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
int dircount = 0;
|
int dircount = 0;
|
||||||
|
|
||||||
@ -305,9 +307,9 @@ int dir_match(ToxWindow *self, Tox *m, const wchar_t *line, const wchar_t *cmd)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (dircount > 1) {
|
if (dircount > 1) {
|
||||||
qsort(dirnames, dircount, NAME_MAX, qsort_strcasecmp_hlpr);
|
qsort(dirnames, dircount, NAME_MAX + 1, qsort_strcasecmp_hlpr);
|
||||||
print_matches(self, m, dirnames, dircount, NAME_MAX);
|
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.
|
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 */
|
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.
|
/* attempts to match /command "<incomplete-dir>" line to matching directories.
|
||||||
|
|
||||||
|
@ -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;
|
||||||
@ -108,7 +109,10 @@ static struct DHT_Nodes {
|
|||||||
/* Determine if a node is offline by comparing the age of the nodeslist
|
/* Determine if a node is offline by comparing the age of the nodeslist
|
||||||
* to the last time the node was successfully pinged.
|
* 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.
|
/* 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,
|
* 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);
|
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;
|
return -3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -577,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);
|
||||||
|
@ -466,6 +466,10 @@ void friendlist_onFriendAdded(ToxWindow *self, Tox *m, uint32_t num, bool sort)
|
|||||||
if (sort)
|
if (sort)
|
||||||
sort_friendlist_index();
|
sort_friendlist_index();
|
||||||
|
|
||||||
|
#ifdef AUDIO
|
||||||
|
init_friend_AV(i);
|
||||||
|
#endif
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -605,6 +609,10 @@ static void delete_friend(Tox *m, uint32_t f_num)
|
|||||||
Friends.max_idx = i;
|
Friends.max_idx = i;
|
||||||
realloc_friends(i);
|
realloc_friends(i);
|
||||||
|
|
||||||
|
#ifdef AUDIO
|
||||||
|
del_friend_AV(i);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* make sure num_selected stays within Friends.num_friends range */
|
/* make sure num_selected stays within Friends.num_friends range */
|
||||||
if (Friends.num_friends && Friends.num_selected == Friends.num_friends)
|
if (Friends.num_friends && Friends.num_selected == Friends.num_friends)
|
||||||
--Friends.num_selected;
|
--Friends.num_selected;
|
||||||
@ -1155,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);
|
||||||
|
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].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,12 @@ 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 +282,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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
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 +385,57 @@ 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;
|
||||||
|
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;
|
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 */
|
GroupChat *chat = &groupchats[groupnum];
|
||||||
copy_peernames(m, groupnum, num_peers);
|
|
||||||
|
|
||||||
/* get current peername then sort namelist */
|
if (!chat) {
|
||||||
uint8_t peername[TOX_MAX_NAME_LENGTH];
|
return;
|
||||||
|
|
||||||
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);
|
size_t i;
|
||||||
|
|
||||||
ChatContext *ctx = self->chatwin;
|
for (i = 0; i < chat->max_idx; ++i) {
|
||||||
|
GroupPeer *peer = &chat->peer_list[i];
|
||||||
|
|
||||||
const char *event;
|
// Test against default tox name to prevent nick change spam on initial join (TODO: this is disgusting)
|
||||||
char timefrmt[TIME_STR_SIZE];
|
if (peer->active && peer->peernumber == peernum && strcmp(peer->name, "Tox User")) {
|
||||||
get_time_str(timefrmt, sizeof(timefrmt));
|
ChatContext *ctx = self->chatwin;
|
||||||
|
char timefrmt[TIME_STR_SIZE];
|
||||||
switch (change) {
|
get_time_str(timefrmt, sizeof(timefrmt));
|
||||||
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];
|
char tmp_event[TOXIC_MAX_NAME_LENGTH * 2 + 32];
|
||||||
snprintf(tmp_event, sizeof(tmp_event), "is now known as %s", (char *) peername);
|
snprintf(tmp_event, sizeof(tmp_event), "is now known as %s", (char *) name);
|
||||||
write_to_log(tmp_event, (char *) oldpeername, ctx->log, true);
|
|
||||||
|
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;
|
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)
|
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 */
|
/* 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 +539,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 +616,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 +685,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 */
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
#define MAX_LINE_INFO_QUEUE 1024
|
#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 */
|
#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,
|
SYS_MSG,
|
||||||
IN_MSG,
|
IN_MSG,
|
||||||
OUT_MSG,
|
OUT_MSG,
|
||||||
|
@ -30,7 +30,7 @@ struct chatlog {
|
|||||||
bool log_on; /* specific to current chat window */
|
bool log_on; /* specific to current chat window */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
typedef enum {
|
||||||
LOG_GROUP,
|
LOG_GROUP,
|
||||||
LOG_PROMPT,
|
LOG_PROMPT,
|
||||||
LOG_CHAT,
|
LOG_CHAT,
|
||||||
|
@ -26,10 +26,8 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#if SYSTEM == BSD
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#endif /* BSD! */
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
#ifdef PYTHON
|
#ifdef PYTHON
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
#include "api.h"
|
#include "api.h"
|
||||||
#endif /* PYTHON */
|
|
||||||
|
|
||||||
#include "execute.h"
|
#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)
|
static PyObject *python_api_get_status(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *ret;
|
PyObject *ret = NULL;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, ""))
|
if (!PyArg_ParseTuple(args, ""))
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -345,3 +344,4 @@ void python_draw_handler_help(WINDOW *win)
|
|||||||
wprintw(win, " %-29s: %.50s\n", cur->name, cur->help);
|
wprintw(win, " %-29s: %.50s\n", cur->name, cur->help);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* PYTHON */
|
||||||
|
@ -88,7 +88,7 @@ struct user_settings {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum settings_values {
|
||||||
AUTOLOG_OFF = 0,
|
AUTOLOG_OFF = 0,
|
||||||
AUTOLOG_ON = 1,
|
AUTOLOG_ON = 1,
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ enum {
|
|||||||
|
|
||||||
MPLEX_OFF = 0,
|
MPLEX_OFF = 0,
|
||||||
MPLEX_ON = 1,
|
MPLEX_ON = 1,
|
||||||
} settings_values;
|
};
|
||||||
|
|
||||||
#define LINE_JOIN "-->"
|
#define LINE_JOIN "-->"
|
||||||
#define LINE_QUIT "<--"
|
#define LINE_QUIT "<--"
|
||||||
|
97
src/toxic.c
97
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,46 @@ 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];
|
||||||
|
|
||||||
|
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 */
|
/* 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 +586,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);
|
||||||
@ -563,30 +599,30 @@ static void init_tox_options(struct Tox_Options *tox_opts)
|
|||||||
{
|
{
|
||||||
tox_options_default(tox_opts);
|
tox_options_default(tox_opts);
|
||||||
|
|
||||||
tox_opts->ipv6_enabled = !arg_opts.use_ipv4;
|
tox_options_set_ipv6_enabled(tox_opts, !arg_opts.use_ipv4);
|
||||||
tox_opts->udp_enabled = !arg_opts.force_tcp;
|
tox_options_set_udp_enabled(tox_opts, !arg_opts.force_tcp);
|
||||||
tox_opts->proxy_type = arg_opts.proxy_type;
|
tox_options_set_proxy_type(tox_opts, arg_opts.proxy_type);
|
||||||
tox_opts->tcp_port = arg_opts.tcp_port;
|
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");
|
queue_init_message("Forcing IPv4 connection");
|
||||||
|
|
||||||
if (tox_opts->tcp_port)
|
if (tox_options_get_tcp_port(tox_opts))
|
||||||
queue_init_message("TCP relaying enabled on port %d", tox_opts->tcp_port);
|
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) {
|
if (tox_options_get_proxy_type(tox_opts) != TOX_PROXY_TYPE_NONE) {
|
||||||
tox_opts->proxy_port = arg_opts.proxy_port;
|
tox_options_set_proxy_port(tox_opts, arg_opts.proxy_port);
|
||||||
tox_opts->proxy_host = arg_opts.proxy_address;
|
tox_options_set_proxy_host(tox_opts, arg_opts.proxy_address);
|
||||||
const char *ps = tox_opts->proxy_type == TOX_PROXY_TYPE_SOCKS5 ? "SOCKS5" : "HTTP";
|
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];
|
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);
|
snprintf(tmp, sizeof(tmp), "Using %s proxy %s : %d", ps, arg_opts.proxy_address, arg_opts.proxy_port);
|
||||||
queue_init_message("%s", tmp);
|
queue_init_message("%s", tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tox_opts->udp_enabled) {
|
if (!tox_options_get_udp_enabled(tox_opts)) {
|
||||||
queue_init_message("UDP disabled");
|
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.";
|
const char *msg = "WARNING: Using a proxy without disabling UDP may leak your real IP address.";
|
||||||
queue_init_message("%s", msg);
|
queue_init_message("%s", msg);
|
||||||
msg = "Use the -t option to disable UDP.";
|
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);
|
(uint8_t *) plain, &pwerr);
|
||||||
|
|
||||||
if (pwerr == TOX_ERR_DECRYPTION_OK) {
|
if (pwerr == TOX_ERR_DECRYPTION_OK) {
|
||||||
tox_opts->savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE;
|
tox_options_set_savedata_type(tox_opts, TOX_SAVEDATA_TYPE_TOX_SAVE);
|
||||||
tox_opts->savedata_data = (uint8_t *) plain;
|
tox_options_set_savedata_data(tox_opts, (uint8_t *) plain, plain_len);
|
||||||
tox_opts->savedata_length = plain_len;
|
|
||||||
|
|
||||||
m = tox_new(tox_opts, new_err);
|
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 */
|
} else { /* data is not encrypted */
|
||||||
tox_opts->savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE;
|
tox_options_set_savedata_type(tox_opts, TOX_SAVEDATA_TYPE_TOX_SAVE);
|
||||||
tox_opts->savedata_data = (uint8_t *) data;
|
tox_options_set_savedata_data(tox_opts, (uint8_t *) data, len);
|
||||||
tox_opts->savedata_length = len;
|
|
||||||
|
|
||||||
m = tox_new(tox_opts, new_err);
|
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))
|
if (file_exists(data_path))
|
||||||
exit_toxic_err("failed in load_tox", FATALERR_FILEOP);
|
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);
|
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)
|
static Tox *load_toxic(char *data_path)
|
||||||
{
|
{
|
||||||
struct Tox_Options tox_opts;
|
TOX_ERR_OPTIONS_NEW options_new_err;
|
||||||
init_tox_options(&tox_opts);
|
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_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");
|
queue_init_message("Falling back to ipv4");
|
||||||
tox_opts.ipv6_enabled = false;
|
tox_options_set_ipv6_enabled(tox_opts, false);
|
||||||
m = load_tox(data_path, &tox_opts, &new_err);
|
m = load_tox(data_path, tox_opts, &new_err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m)
|
if (!m)
|
||||||
@ -756,6 +793,7 @@ static Tox *load_toxic(char *data_path)
|
|||||||
if (tox_self_get_name_size(m) == 0)
|
if (tox_self_get_name_size(m) == 0)
|
||||||
tox_self_set_name(m, (uint8_t *) "Toxic User", strlen("Toxic User"), NULL);
|
tox_self_set_name(m, (uint8_t *) "Toxic User", strlen("Toxic User"), NULL);
|
||||||
|
|
||||||
|
tox_options_free(tox_opts);
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -814,7 +852,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1196,6 +1234,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,
|
||||||
|
@ -45,8 +45,7 @@ void receive_video_frame_cb( ToxAV *av, uint32_t friend_number,
|
|||||||
int32_t ystride, int32_t ustride, int32_t vstride,
|
int32_t ystride, int32_t ustride, int32_t vstride,
|
||||||
void *user_data );
|
void *user_data );
|
||||||
|
|
||||||
void video_bit_rate_status_cb( ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate,
|
void video_bit_rate_status_cb( ToxAV *av, uint32_t friend_number, uint32_t video_bit_rate, void *user_data);
|
||||||
uint32_t video_bit_rate, void *user_data);
|
|
||||||
|
|
||||||
static void print_err (ToxWindow *self, const char *error_str)
|
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_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;
|
return CallControl.av;
|
||||||
}
|
}
|
||||||
@ -83,7 +82,7 @@ void terminate_video()
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < MAX_CALLS; ++i) {
|
for (i = 0; i < CallControl.max_calls; ++i) {
|
||||||
Call *this_call = &CallControl.calls[i];
|
Call *this_call = &CallControl.calls[i];
|
||||||
|
|
||||||
stop_video_transmission(this_call, 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;
|
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");
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set video bit rate");
|
||||||
return -1;
|
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)
|
int stop_video_transmission(Call *call, int friend_number)
|
||||||
{
|
{
|
||||||
CallControl.video_bit_rate = 0;
|
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 ) {
|
if ( call->vin_idx != -1 ) {
|
||||||
close_video_device(vdt_input, call->vin_idx);
|
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);
|
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,
|
void video_bit_rate_status_cb(ToxAV *av, uint32_t friend_number, uint32_t video_bit_rate, void *user_data)
|
||||||
uint32_t video_bit_rate, void *user_data)
|
|
||||||
{
|
{
|
||||||
CallControl.video_bit_rate = video_bit_rate;
|
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)
|
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 */
|
void *cb_data; /* Data to be passed to callback */
|
||||||
int32_t friend_number; /* ToxAV friend number */
|
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 */
|
int fd; /* File descriptor of video device selected/opened */
|
||||||
struct v4l2_format fmt;
|
struct v4l2_format fmt;
|
||||||
struct VideoBuffer *buffers;
|
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,
|
static void yuv422to420(uint8_t *plane_y, uint8_t *plane_u, uint8_t *plane_v,
|
||||||
uint8_t *input, uint16_t width, uint16_t height)
|
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);
|
XFlush(device->x_display);
|
||||||
free(img_data);
|
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) ) {
|
if ( -1 == xioctl(device->fd, VIDIOC_QBUF, &buf) ) {
|
||||||
unlock;
|
unlock;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __linux__ / BSD */
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -787,7 +787,7 @@ VideoDeviceError close_video_device(VideoDeviceType type, uint32_t device_idx)
|
|||||||
XCloseDisplay(device->x_display);
|
XCloseDisplay(device->x_display);
|
||||||
pthread_mutex_destroy(device->mutex);
|
pthread_mutex_destroy(device->mutex);
|
||||||
|
|
||||||
#if defined(__linux__) || SYSTEM == BSD
|
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||||
free(device->buffers);
|
free(device->buffers);
|
||||||
#endif /* __linux__ / BSD */
|
#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 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)
|
||||||
|
{
|
||||||
|
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;
|
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);
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
#define CHATBOX_HEIGHT 2
|
#define CHATBOX_HEIGHT 2
|
||||||
|
|
||||||
/* Curses foreground colours (background is black) */
|
/* Curses foreground colours (background is black) */
|
||||||
enum {
|
typedef enum {
|
||||||
WHITE,
|
WHITE,
|
||||||
GREEN,
|
GREEN,
|
||||||
CYAN,
|
CYAN,
|
||||||
@ -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);
|
||||||
|
Reference in New Issue
Block a user