1
0
mirror of https://github.com/Tha14/toxic.git synced 2025-06-27 02:06:45 +02:00

Compare commits

...

41 Commits

Author SHA1 Message Date
97a8ecd115 small fix and bump version to 0.5.2 2014-09-29 13:56:17 -04:00
64d782569a add asciidoc and libnotify-dev to install script 2014-09-29 01:54:53 -04:00
6248baf98b fix segfault 2014-09-29 01:30:22 -04:00
33cfca7ecc bug fixes and code cleanup 2014-09-28 17:49:48 -04:00
a01cc35368 Merge branch 'master' of github.com:Tox/toxic 2014-09-28 16:48:09 +02:00
b10eebd77e This should fix audio problem 2014-09-28 16:47:31 +02:00
05661ca9b6 core API update and refactor group invites a bit 2014-09-27 22:50:20 -04:00
784883f773 What if, like, photosynthesis is a lie?! 2014-09-28 00:13:45 +02:00
a9e5723ca4 a couple fixes 2014-09-27 03:08:19 -04:00
95dfea8d29 keep chatlog names consistent with friend name changes 2014-09-27 02:28:11 -04:00
e574af7d68 fix CPU usage issue regarding audio drivers, courtesy of mannol 2014-09-26 20:32:48 -04:00
2918ca45a2 Merge pull request #255 from Ansa89/trivial-fix
Fix "error: unknown type name 'off_t'"
2014-09-26 13:01:44 -04:00
6ad744f770 Add stdlib.h header to allow off_t type 2014-09-26 10:50:42 +02:00
5b394e6f35 notify.c: better headers order 2014-09-26 10:46:14 +02:00
940af2c711 a few fixes, update example config file 2014-09-26 03:39:36 -04:00
544c402f78 implement avatars (setting only) and generalize path tab-complete 2014-09-26 03:10:44 -04:00
cee9e624b8 more UI changes 2014-09-25 15:23:50 -04:00
2e65ee3609 a few UI changes 2014-09-25 04:31:45 -04:00
3a176e1cab move to page end after pressing return 2014-09-25 00:42:08 -04:00
00cccad22c a few general fixes 2014-09-24 15:20:15 -04:00
a432d733d7 use 64-bit off_t for file sizes 2014-09-24 14:23:08 -04:00
893e88294b more succinct way to get file sizes 2014-09-24 00:06:02 -04:00
b071a9e992 more thorough error checking 2014-09-23 22:51:56 -04:00
48cf4ebf02 fix for issue #254 2014-09-23 21:32:05 -04:00
773a75b948 update makefile checks 2014-09-22 21:51:55 -04:00
133c0e8d63 rename reserved identifiers per C standard 2014-09-22 21:24:45 -04:00
bf54cb36ef set signal handlers at more appropriate places 2014-09-22 20:00:36 -04:00
032853b5c9 Merge branch 'Pyrohh-master' 2014-09-22 19:41:23 -04:00
650c13ca7a There's no need for rm -rf, just rm -f 2014-09-22 18:45:45 -04:00
9d5fe03285 small fix 2014-09-22 18:38:46 -04:00
c3f68b60d3 bigger log identifiers to reduce chance of collision 2014-09-22 17:34:30 -04:00
1c16467eb9 don't share chatlogs across data files (changes log naming convention) 2014-09-22 17:09:39 -04:00
3c74385f5c use proper variable type for sig handler flags 2014-09-22 14:27:33 -04:00
c07c0028bb increase line_info msg buffer size so won't cut off long log lines 2014-09-22 13:49:09 -04:00
dc3b2e04ab load chatlog history when opening a chatwindow 2014-09-22 04:29:28 -04:00
7fd3aa9164 Merge pull request #246 from urras/patch-2
Update screenshot
2014-09-21 13:17:13 -04:00
4c60312e2d Update screenshot 2014-09-21 12:42:04 -04:00
16e29aa4e0 Merge pull request #243 from Ansa89/trivial-fix
Makefile: use single quotes also for PACKAGE_DATADIR
2014-09-19 12:28:32 -04:00
bd7b073155 Makefile: fix typo 2014-09-19 10:47:25 +02:00
f25cf870e6 Makefile: use single quotes also for PACKAGE_DATADIR 2014-09-19 10:45:27 +02:00
13291d0365 bump version to 0.5.1 2014-09-19 01:24:39 -04:00
55 changed files with 1005 additions and 550 deletions

View File

@ -5,7 +5,7 @@ compiler:
before_script:
# Installing yasm (needed for compiling vpx) and openal
- sudo apt-get -yq install yasm libopenal-dev libconfig-dev libalut-dev
- sudo apt-get -yq install yasm libopenal-dev libconfig-dev libalut-dev libnotify-dev asciidoc
# Installing libsodium, needed for toxcore
- git clone https://github.com/jedisct1/libsodium.git libsodium
- cd libsodium

View File

@ -1,7 +1,7 @@
# Toxic [![Build Status](https://travis-ci.org/Tox/toxic.png?branch=master)](https://travis-ci.org/Tox/toxic)
Toxic is a [Tox](https://tox.im)-based instant messenging client which formerly resided in the [Tox core repository](https://github.com/irungentoo/toxcore), and is now available as a standalone application.
![Toxic Screenshot](https://i.imgur.com/ryaEmQZ.png "Home Screen")
![Toxic Screenshot](https://i.imgur.com/san99Z2.png "Home Screen")
## Installation

View File

@ -6,8 +6,8 @@ CFG_DIR = $(BASE_DIR)/cfg
LIBS = libtoxcore ncursesw libconfig
CFLAGS = -std=gnu99 -pthread -Wall -g
CFLAGS += '-DTOXICVER="$(VERSION)"' -DHAVE_WIDECHAR -D_XOPEN_SOURCE_EXTENDED
CFLAGS += -DPACKAGE_DATADIR="\"$(abspath $(DATADIR))\""
CFLAGS += '-DTOXICVER="$(VERSION)"' -DHAVE_WIDECHAR -D_XOPEN_SOURCE_EXTENDED -D_FILE_OFFSET_BITS=64
CFLAGS += '-DPACKAGE_DATADIR="$(abspath $(DATADIR))"'
CFLAGS += $(USER_CFLAGS)
LDFLAGS = $(USER_LDFLAGS)
@ -58,7 +58,7 @@ toxic: $(OBJ)
@$(CC) -MM $(CFLAGS) $(SRC_DIR)/$*.c > $*.d
clean:
rm -rf *.d *.o toxic
rm -f *.d *.o toxic
-include $(OBJ:.o=.d)

View File

@ -1,6 +1,6 @@
# Variables for audio call support
AUDIO_LIBS = libtoxav openal
AUDIO_CFLAGS = -D_AUDIO
AUDIO_CFLAGS = -DAUDIO
ifneq (, $(findstring device.o, $(OBJ)))
AUDIO_OBJ = audio_call.o
else

View File

@ -1,6 +1,6 @@
# Variables for desktop notifications support
DESK_NOTIFY_LIBS = libnotify
DESK_NOTIFY_CFLAGS = -D_BOX_NOTIFY
DESK_NOTIFY_CFLAGS = -DBOX_NOTIFY
# Check if we can build desktop notifications support
CHECK_DESK_NOTIFY_LIBS = $(shell pkg-config --exists $(DESK_NOTIFY_LIBS) || echo -n "error")

View File

@ -1,6 +1,6 @@
# Variables for sound notifications support
SND_NOTIFY_LIBS = openal freealut
SND_NOTIFY_CFLAGS = -D_SOUND_NOTIFY
SND_NOTIFY_CFLAGS = -DSOUND_NOTIFY
ifneq (, $(findstring device.o, $(OBJ)))
SND_NOTIFY_OBJ =
else

View File

@ -1,6 +1,6 @@
# Variables for X11 support
X11_LIBS = x11
X11_CFLAGS = -D_X11
X11_CFLAGS = -DX11
# Check if we can build X11 support
CHECK_X11_LIBS = $(shell pkg-config --exists $(X11_LIBS) || echo -n "error")

View File

@ -1,5 +1,5 @@
# Version
TOXIC_VERSION = 0.5.0
TOXIC_VERSION = 0.5.2
REV = $(shell git rev-list HEAD --count)
VERSION = $(TOXIC_VERSION)_r$(REV)

View File

@ -2,12 +2,12 @@
.\" Title: toxic.conf
.\" Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
.\" Date: 2014-08-26
.\" Date: 2014-09-19
.\" Manual: Toxic Manual
.\" Source: toxic __VERSION__
.\" Language: English
.\"
.TH "TOXIC\&.CONF" "5" "2014\-08\-26" "toxic __VERSION__" "Toxic Manual"
.TH "TOXIC\&.CONF" "5" "2014\-09\-19" "toxic __VERSION__" "Toxic Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@ -138,6 +138,11 @@ Configuration related to paths\&.
Default path for downloads\&. String value\&. Absolute path for downloaded files\&.
.RE
.PP
\fBavatar_path\fR
.RS 4
Path for your avatar (file must be a \&.png and cannot exceed 16\&.3 KiB)
.RE
.PP
\fBchatlogs_path\fR
.RS 4
Default path for chatlogs\&. String value\&. Absolute path for chatlog files\&.

View File

@ -87,6 +87,9 @@ OPTIONS
Default path for downloads. String value. Absolute path for downloaded
files.
*avatar_path*;;
Path for your avatar (file must be a .png and cannot exceed 16.3 KiB)
*chatlogs_path*;;
Default path for chatlogs. String value. Absolute path for chatlog files.

View File

@ -45,6 +45,9 @@ tox = {
// Path for downloaded files
// download_path="/home/USERNAME/Downloads/";
// Path for your avatar (file must be a .png and cannot exceed 16.3 KiB)
// avatar_path="/home/USERNAME/Pictures/youravatar.png";
// Path for chatlogs
// chatlogs_path="/home/USERNAME/toxic_chatlogs/";
};

View File

@ -29,6 +29,7 @@
#include "line_info.h"
#include "notify.h"
#include <stdbool.h>
#include <curses.h>
#include <string.h>
#include <pthread.h>
@ -48,36 +49,41 @@
#endif
#endif
#define _cbend pthread_exit(NULL)
#define cbend pthread_exit(NULL)
#define MAX_CALLS 10
#define frame_size (av_DefaultSettings.audio_sample_rate * av_DefaultSettings.audio_frame_duration / 1000)
typedef struct _Call {
typedef struct Call {
pthread_t ttid; /* Transmission thread id */
_Bool ttas, has_output; /* Transmission thread active status (0 - stopped, 1- running) */
bool ttas, has_output; /* Transmission thread active status (0 - stopped, 1- running) */
uint32_t in_idx, out_idx;
pthread_mutex_t mutex;
} Call;
void set_call(Call* call, _Bool start)
static int set_call(Call* call, bool start)
{
call->in_idx = -1;
call->out_idx = -1;
if ( start ) {
call->ttas = _True;
pthread_mutex_init(&call->mutex, NULL);
call->ttas = true;
if (pthread_mutex_init(&call->mutex, NULL) != 0)
return -1;
}
else {
call->ttid = 0;
pthread_mutex_destroy(&call->mutex);
if (pthread_mutex_destroy(&call->mutex) != 0)
return -1;
}
return 0;
}
struct _ASettings {
struct ASettings {
AudioError errors;
ToxAv *av;
@ -198,7 +204,8 @@ int start_transmission(ToxWindow *self)
!toxav_capability_supported(ASettins.av, self->call_idx, AudioEncoding) )
return -1;
set_call(&ASettins.calls[self->call_idx], _True);
if (set_call(&ASettins.calls[self->call_idx], true) == -1)
return -1;
ToxAvCSettings csettings;
toxav_get_peer_csettings(ASettins.av, self->call_idx, 0, &csettings);
@ -206,9 +213,9 @@ int start_transmission(ToxWindow *self)
if ( open_primary_device(input, &ASettins.calls[self->call_idx].in_idx,
csettings.audio_sample_rate, csettings.audio_frame_duration, csettings.audio_channels) != de_None )
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to open input device!");
if ( register_device_callback(self->call_idx, ASettins.calls[self->call_idx].in_idx,
read_device_callback, &self->call_idx, _True) != de_None)
read_device_callback, &self->call_idx, true) != de_None)
/* Set VAD as true for all; TODO: Make it more dynamic */
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to register input handler!");
@ -225,7 +232,7 @@ int stop_transmission(int call_index)
{
if ( ASettins.calls[call_index].ttas ) {
toxav_kill_transmission(ASettins.av, call_index);
ASettins.calls[call_index].ttas = _False;
ASettins.calls[call_index].ttas = false;
if ( ASettins.calls[call_index].in_idx != -1 )
close_device(input, ASettins.calls[call_index].in_idx);
@ -233,7 +240,9 @@ int stop_transmission(int call_index)
if ( ASettins.calls[call_index].out_idx != -1 )
close_device(output, ASettins.calls[call_index].out_idx);
set_call(&ASettins.calls[call_index], _False);
if (set_call(&ASettins.calls[call_index], false) == -1)
return -1;
return 0;
}
@ -452,7 +461,7 @@ void cmd_hangup(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
if (toxav_get_call_state(ASettins.av, self->call_idx) == av_CallInviting) {
error = toxav_cancel(ASettins.av, self->call_idx, self->num,
"Only those who appreciate small things know the beauty that is life");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
#endif
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call canceled!");
@ -610,7 +619,7 @@ void cmd_ccur_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*a
open_device(input, selection, &this_call->in_idx, csettings.audio_sample_rate,
csettings.audio_frame_duration, csettings.audio_channels);
/* Set VAD as true for all; TODO: Make it more dynamic */
register_device_callback(self->call_idx, this_call->in_idx, read_device_callback, &self->call_idx, _True);
register_device_callback(self->call_idx, this_call->in_idx, read_device_callback, &self->call_idx, true);
}
}
}

View File

@ -20,8 +20,8 @@
*
*/
#ifndef _audio_h
#define _audio_h
#ifndef AUDIO_H
#define AUDIO_H
#include <tox/toxav.h>
@ -42,4 +42,4 @@ void terminate_audio();
void stop_current_call(ToxWindow *self);
#endif /* _audio_h */
#endif /* AUDIO_H */

View File

@ -104,7 +104,9 @@ int complete_line(ToxWindow *self, const void *list, int n_items, int size)
if (wcs_to_mbs_buf(ubuf, ctx->line, sizeof(ubuf)) == -1)
return -1;
bool dir_search = strncmp(ubuf, "/sendfile", strlen("/sendfile")) == 0;
/* TODO: generalize this */
bool dir_search = !strncmp(ubuf, "/sendfile", strlen("/sendfile"))
|| !strncmp(ubuf, "/avatar", strlen("/avatar"));
/* isolate substring from space behind pos to pos */
char tmp[MAX_STR_SIZE];
@ -202,8 +204,8 @@ int complete_line(ToxWindow *self, const void *list, int n_items, int size)
return diff;
}
/* transforms a sendfile tab complete contaning the shorthand "~/" into the full home directory.*/
static void complt_home_dir(ToxWindow *self, char *path, int pathsize)
/* transforms a tab complete starting with the shorthand "~" into the full home directory.*/
static void complt_home_dir(ToxWindow *self, char *path, int pathsize, const char *cmd, int cmdlen)
{
ChatContext *ctx = self->chatwin;
@ -211,8 +213,8 @@ static void complt_home_dir(ToxWindow *self, char *path, int pathsize)
get_home_dir(homedir, sizeof(homedir));
char newline[MAX_STR_SIZE];
snprintf(newline, sizeof(newline), "/sendfile \"%s%s", homedir, path + 1);
snprintf(path, pathsize, "%s", &newline[11]);
snprintf(newline, sizeof(newline), "%s \"%s%s", cmd, homedir, path + 1);
snprintf(path, pathsize, "%s", &newline[cmdlen]);
wchar_t wline[MAX_STR_SIZE];
@ -229,23 +231,27 @@ static void complt_home_dir(ToxWindow *self, char *path, int pathsize)
ctx->len = ctx->pos;
}
/* attempts to match /sendfile "<incomplete-dir>" line to matching directories.
/* attempts to match /command "<incomplete-dir>" line to matching directories.
if only one match, auto-complete line.
return diff between old len and new len of ctx->line, -1 if no matches or > 1 match */
#define MAX_DIRS 512
int dir_match(ToxWindow *self, Tox *m, const wchar_t *line)
int dir_match(ToxWindow *self, Tox *m, const wchar_t *line, const wchar_t *cmd)
{
char b_path[MAX_STR_SIZE];
char b_name[MAX_STR_SIZE];
const wchar_t *tmpline = &line[11]; /* start after "/sendfile \"" */
char b_cmd[MAX_STR_SIZE];
const wchar_t *tmpline = &line[wcslen(cmd) + 2]; /* start after "/command \"" */
if (wcs_to_mbs_buf(b_path, tmpline, sizeof(b_path)) == -1)
return -1;
if (wcs_to_mbs_buf(b_cmd, cmd, sizeof(b_cmd)) == -1)
return -1;
if (b_path[0] == '~')
complt_home_dir(self, b_path, sizeof(b_path));
complt_home_dir(self, b_path, sizeof(b_path), b_cmd, strlen(b_cmd) + 2);
int si = char_rfind(b_path, '/', strlen(b_path));
@ -261,7 +267,6 @@ int dir_match(ToxWindow *self, Tox *m, const wchar_t *line)
strcpy(b_name, &b_path[si + 1]);
b_path[si + 1] = '\0';
int b_name_len = strlen(b_name);
DIR *dp = opendir(b_path);
if (dp == NULL)

View File

@ -20,8 +20,8 @@
*
*/
#ifndef _autocomplete_h
#define _autocomplete_h
#ifndef AUTOCOMPLETE_H
#define AUTOCOMPLETE_H
/* looks for all instances in list that begin with the last entered word in line according to pos,
then fills line with the complete word. e.g. "Hello jo" would complete the line
@ -33,10 +33,10 @@
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);
/* attempts to match /sendfile "<incomplete-dir>" line to matching directories.
/* attempts to match /command "<incomplete-dir>" line to matching directories.
if only one match, auto-complete line.
return diff between old len and new len of ctx->line, -1 if no matches or > 1 match */
int dir_match(ToxWindow *self, Tox *m, const wchar_t *line);
int dir_match(ToxWindow *self, Tox *m, const wchar_t *line, const wchar_t *cmd);
#endif /* #define _autocomplete_h */
#endif /* #define AUTOCOMPLETE_H */

View File

@ -45,34 +45,35 @@
#include "notify.h"
#include "message_queue.h"
#ifdef _AUDIO
#ifdef AUDIO
#include "audio_call.h"
#endif /* _AUDIO */
#endif /* AUDIO */
extern char *DATA_FILE;
extern FileSender file_senders[MAX_FILES];
extern _Friends Friends;
extern FriendsList Friends;
extern struct _Winthread Winthread;
extern struct user_settings *user_settings_;
extern struct Winthread Winthread;
extern struct user_settings *user_settings;
#ifdef _AUDIO
#ifdef AUDIO
static void init_infobox(ToxWindow *self);
static void kill_infobox(ToxWindow *self);
#endif /* _AUDIO */
#endif /* AUDIO */
#ifdef _AUDIO
#define AC_NUM_CHAT_COMMANDS 26
#ifdef AUDIO
#define AC_NUM_CHAT_COMMANDS 27
#else
#define AC_NUM_CHAT_COMMANDS 19
#endif /* _AUDIO */
#define AC_NUM_CHAT_COMMANDS 20
#endif /* AUDIO */
/* Array of chat command names used for tab completion. */
static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = {
{ "/accept" },
{ "/add" },
{ "/avatar" },
{ "/cancel" },
{ "/clear" },
{ "/close" },
@ -91,7 +92,7 @@ static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = {
{ "/sendfile" },
{ "/status" },
#ifdef _AUDIO
#ifdef AUDIO
{ "/call" },
{ "/answer" },
@ -101,12 +102,12 @@ static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = {
{ "/mute" },
{ "/sense" },
#endif /* _AUDIO */
#endif /* AUDIO */
};
static void set_self_typingstatus(ToxWindow *self, Tox *m, uint8_t is_typing)
{
if (user_settings_->show_typing_self == SHOW_TYPING_OFF)
if (user_settings->show_typing_self == SHOW_TYPING_OFF)
return;
ChatContext *ctx = self->chatwin;
@ -137,7 +138,7 @@ void kill_chat_window(ToxWindow *self, Tox *m)
line_info_cleanup(ctx->hst);
cqueue_cleanup(ctx->cqueue);
#ifdef _AUDIO
#ifdef AUDIO
stop_current_call(self);
#endif
@ -197,8 +198,8 @@ static void chat_onConnectionChange(ToxWindow *self, Tox *m, int32_t num, uint8_
if (status == 1) { /* Friend goes online */
statusbar->is_online = true;
Friends.list[num].is_typing = user_settings_->show_typing_other == SHOW_TYPING_ON
? tox_get_is_typing(m, num) : 0;
Friends.list[num].is_typing = user_settings->show_typing_other == SHOW_TYPING_ON
? tox_get_is_typing(m, num) : 0;
chat_resume_file_transfers(m, num);
msg = "has come online";
@ -317,9 +318,9 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t
}
/* use specified path in config if possible */
if (user_settings_->download_path[0]) {
snprintf(filename_path, sizeof(filename_path), "%s%s", user_settings_->download_path, filename_nopath);
len += strlen(user_settings_->download_path);
if (user_settings->download_path[0]) {
snprintf(filename_path, sizeof(filename_path), "%s%s", user_settings->download_path, filename_nopath);
len += strlen(user_settings->download_path);
}
if (len >= sizeof(Friends.list[num].file_receiver[filenum].filename)) {
@ -528,7 +529,12 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t rec
uint64_t datapos;
memcpy(&datapos, tmp, sizeof(uint64_t));
fseek(fp, datapos, SEEK_SET);
if (fseek(fp, datapos, SEEK_SET) == -1) {
snprintf(msg, sizeof(msg), "File transfer for '%s' failed.", filename);
close_file_sender(self, m, send_idx, NULL, TOX_FILECONTROL_FINISHED, filenum, num);
break;
}
tox_file_send_control(m, num, 0, filenum, TOX_FILECONTROL_ACCEPT, 0, 0);
file_senders[send_idx].noconnection = false;
break;
@ -557,32 +563,40 @@ static void chat_onFileData(ToxWindow *self, Tox *m, int32_t num, uint8_t filenu
Friends.list[num].file_receiver[filenum].bytes_recv += length;
}
static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, const char *group_pub_key)
static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, const char *group_pub_key, uint16_t length)
{
if (self->num != friendnumber)
return;
if (Friends.list[friendnumber].group_invite.key != NULL)
free(Friends.list[friendnumber].group_invite.key);
char *k = malloc(length);
if (k == NULL)
exit_toxic_err("Failed in chat_onGroupInvite", FATALERR_MEMORY);
memcpy(k, group_pub_key, length);
Friends.list[friendnumber].group_invite.key = k;
Friends.list[friendnumber].group_invite.pending = true;
Friends.list[friendnumber].group_invite.length = length;
char name[TOX_MAX_NAME_LENGTH];
get_nick_truncate(m, name, friendnumber);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s has invited you to a group chat.", name);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type \"/join\" to join the chat.");
memcpy(Friends.list[friendnumber].groupchat_key, group_pub_key,
sizeof(Friends.list[friendnumber].groupchat_key));
Friends.list[friendnumber].groupchat_pending = true;
sound_notify(self, generic_message, NT_WNDALERT_2, NULL);
if (self->active_box != -1)
box_silent_notify2(self, NT_WNDALERT_2 | NT_NOFOCUS, self->active_box, "invites you to join group chat");
else
box_silent_notify(self, NT_WNDALERT_2 | NT_NOFOCUS, &self->active_box, name, "invites you to join group chat");
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s has invited you to a group chat.", name);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type \"/join\" to join the chat.");
}
/* Av Stuff */
#ifdef _AUDIO
#ifdef AUDIO
void chat_onInvite (ToxWindow *self, ToxAv *av, int call_index)
{
@ -611,10 +625,10 @@ void chat_onRinging (ToxWindow *self, ToxAv *av, int call_index)
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ringing...type \"/hangup\" to cancel it.");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
if (self->ringing_sound == -1)
sound_notify(self, call_outgoing, NT_LOOP, &self->ringing_sound);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
void chat_onStarting (ToxWindow *self, ToxAv *av, int call_index)
@ -626,9 +640,9 @@ void chat_onStarting (ToxWindow *self, ToxAv *av, int call_index)
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call started! Type: \"/hangup\" to end it.");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
void chat_onEnding (ToxWindow *self, ToxAv *av, int call_index)
@ -640,9 +654,9 @@ void chat_onEnding (ToxWindow *self, ToxAv *av, int call_index)
self->call_idx = -1;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call ended!");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
void chat_onError (ToxWindow *self, ToxAv *av, int call_index)
@ -653,9 +667,9 @@ void chat_onError (ToxWindow *self, ToxAv *av, int call_index)
self->call_idx = -1;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error!");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
void chat_onStart (ToxWindow *self, ToxAv *av, int call_index)
@ -667,9 +681,9 @@ void chat_onStart (ToxWindow *self, ToxAv *av, int call_index)
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call started! Type: \"/hangup\" to end it.");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
void chat_onCancel (ToxWindow *self, ToxAv *av, int call_index)
@ -681,9 +695,9 @@ void chat_onCancel (ToxWindow *self, ToxAv *av, int call_index)
self->call_idx = -1;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call canceled!");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
void chat_onReject (ToxWindow *self, ToxAv *av, int call_index)
@ -694,9 +708,9 @@ void chat_onReject (ToxWindow *self, ToxAv *av, int call_index)
self->call_idx = -1;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Rejected!");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
void chat_onEnd (ToxWindow *self, ToxAv *av, int call_index)
@ -708,9 +722,9 @@ void chat_onEnd (ToxWindow *self, ToxAv *av, int call_index)
self->call_idx = -1;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call ended!");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
void chat_onRequestTimeout (ToxWindow *self, ToxAv *av, int call_index)
@ -721,9 +735,9 @@ void chat_onRequestTimeout (ToxWindow *self, ToxAv *av, int call_index)
self->call_idx = -1;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No answer!");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
void chat_onPeerTimeout (ToxWindow *self, ToxAv *av, int call_index)
@ -735,9 +749,9 @@ void chat_onPeerTimeout (ToxWindow *self, ToxAv *av, int call_index)
self->call_idx = -1;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer disconnected; call ended!");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
static void init_infobox(ToxWindow *self)
@ -752,7 +766,7 @@ static void init_infobox(ToxWindow *self)
ctx->infobox.win = newwin(INFOBOX_HEIGHT, INFOBOX_WIDTH + 1, 1, x2 - INFOBOX_WIDTH);
ctx->infobox.starttime = get_unix_time();
ctx->infobox.vad_lvl = user_settings_->VAD_treshold;
ctx->infobox.vad_lvl = user_settings->VAD_treshold;
ctx->infobox.active = true;
strcpy(ctx->infobox.timestr, "00");
}
@ -822,7 +836,7 @@ static void draw_infobox(ToxWindow *self)
wrefresh(infobox->win);
}
#endif /* _AUDIO */
#endif /* AUDIO */
static void send_action(ToxWindow *self, ChatContext *ctx, Tox *m, char *action)
{
@ -874,8 +888,11 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
if (key == '\t' && ctx->len > 1 && ctx->line[0] == '/') { /* TAB key: auto-complete */
int diff = -1;
/* TODO: make this not suck */
if (wcsncmp(ctx->line, L"/sendfile \"", wcslen(L"/sendfile \"")) == 0) {
diff = dir_match(self, m, ctx->line);
diff = dir_match(self, m, ctx->line, L"/sendfile");
} else if (wcsncmp(ctx->line, L"/avatar \"", wcslen(L"/avatar \"")) == 0) {
diff = dir_match(self, m, ctx->line, L"/avatar");
} else {
diff = complete_line(self, chat_cmd_list, AC_NUM_CHAT_COMMANDS, MAX_CMDNAME_SIZE);
}
@ -1017,7 +1034,7 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
}
if (statusbar->statusmsg[0])
wprintw(statusbar->topline, "- %s ", statusbar->statusmsg);
wprintw(statusbar->topline, ": %s ", statusbar->statusmsg);
wclrtoeol(statusbar->topline);
wmove(statusbar->topline, 0, x2 - (KEY_IDENT_DIGITS * 2) - 3);
@ -1040,7 +1057,7 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
wrefresh(self->window);
#ifdef _AUDIO
#ifdef AUDIO
if (ctx->infobox.active) {
draw_infobox(self);
wrefresh(self->window);
@ -1091,8 +1108,14 @@ static void chat_onInit(ToxWindow *self, Tox *m)
line_info_init(ctx->hst);
if (Friends.list[self->num].logging_on)
log_enable(nick, Friends.list[self->num].pub_key, ctx->log);
char myid[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(m, (uint8_t *) myid);
log_enable(nick, myid, Friends.list[self->num].pub_key, ctx->log, LOG_CHAT);
load_chat_history(self, ctx->log);
if (!Friends.list[self->num].logging_on)
log_disable(ctx->log);
execute(ctx->history, self, m, "/log", GLOBAL_COMMAND_MODE);
@ -1124,7 +1147,7 @@ ToxWindow new_chat(Tox *m, int32_t friendnum)
ret.onFileData = &chat_onFileData;
ret.onReadReceipt = &chat_onReadReceipt;
#ifdef _AUDIO
#ifdef AUDIO
ret.onInvite = &chat_onInvite;
ret.onRinging = &chat_onRinging;
ret.onStarting = &chat_onStarting;
@ -1140,7 +1163,7 @@ ToxWindow new_chat(Tox *m, int32_t friendnum)
ret.call_idx = -1;
ret.device_selection[0] = ret.device_selection[1] = -1;
ret.ringing_sound = -1;
#endif /* _AUDIO */
#endif /* AUDIO */
ret.active_box = -1;

View File

@ -20,8 +20,8 @@
*
*/
#ifndef CHAT_H_6489PZ13
#define CHAT_H_6489PZ13
#ifndef CHAT_H
#define CHAT_H
#include "windows.h"
#include "toxic.h"
@ -32,4 +32,4 @@ void chat_close_file_receiver(Tox *m, int filenum, int friendnum, int CTRL);
void kill_chat_window(ToxWindow *self, Tox *m);
ToxWindow new_chat(Tox *m, int32_t friendnum);
#endif /* end of include guard: CHAT_H_6489PZ13 */
#endif /* end of include guard: CHAT_H */

View File

@ -34,7 +34,7 @@
#include "file_senders.h"
extern ToxWindow *prompt;
extern _Friends Friends;
extern FriendsList Friends;
extern FileSender file_senders[MAX_FILES];
extern uint8_t max_file_senders_index;
@ -123,14 +123,15 @@ void cmd_join_group(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar
return;
}
const char *groupkey = Friends.list[self->num].groupchat_key;
const char *groupkey = Friends.list[self->num].group_invite.key;
uint16_t length = Friends.list[self->num].group_invite.length;
if (!Friends.list[self->num].groupchat_pending) {
if (!Friends.list[self->num].group_invite.pending) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending group chat invite.");
return;
}
int groupnum = tox_join_groupchat(m, self->num, (uint8_t *) groupkey);
int groupnum = tox_join_groupchat(m, self->num, (uint8_t *) groupkey, length);
if (groupnum == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize.");
@ -224,9 +225,13 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
return;
}
fseek(file_to_send, 0, SEEK_END);
uint64_t filesize = ftell(file_to_send);
fseek(file_to_send, 0, SEEK_SET);
off_t filesize = file_size(path);
if (filesize == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File corrupt.");
fclose(file_to_send);
return;
}
char filename[MAX_STR_SIZE] = {0};
get_file_name(filename, sizeof(filename), path);
@ -235,6 +240,7 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
if (filenum == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error sending file.");
fclose(file_to_send);
return;
}

View File

@ -20,8 +20,8 @@
*
*/
#ifndef _chat_commands_h
#define _chat_commands_h
#ifndef CHAT_COMMANDS_H
#define CHAT_COMMANDS_H
#include "windows.h"
#include "toxic.h"
@ -32,7 +32,7 @@ void cmd_join_group(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR
void cmd_savefile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_sendfile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
#ifdef _AUDIO
#ifdef AUDIO
void cmd_call(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_answer(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_reject(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
@ -41,6 +41,6 @@ void cmd_cancel(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZ
void cmd_ccur_device(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_mute(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_sense(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
#endif /* _AUDIO */
#endif /* AUDIO */
#endif /* #define _chat_commands_h */
#endif /* #define CHAT_COMMANDS_H */

View File

@ -20,8 +20,8 @@
*
*/
#ifndef _configdir_h
#define _configdir_h
#ifndef CONFIGDIR_H
#define CONFIGDIR_H
#ifndef NSS_BUFLEN_PASSWD
#define NSS_BUFLEN_PASSWD 4096
@ -38,4 +38,4 @@ char *get_user_config_dir(void);
void get_home_dir(char *home, int size);
int create_user_config_dirs(char *path);
#endif /* #define _configdir_h */
#endif /* #define CONFIGDIR_H */

View File

@ -22,7 +22,7 @@
#include "device.h"
#ifdef _AUDIO
#ifdef AUDIO
#include "audio_call.h"
#endif
@ -41,6 +41,7 @@
#endif
#endif
#include <stdbool.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
@ -50,9 +51,9 @@
#define OPENAL_BUFS 5
#define inline__ inline __attribute__((always_inline))
extern struct user_settings *user_settings_;
extern struct user_settings *user_settings;
typedef struct _Device {
typedef struct Device {
ALCdevice *dhndl; /* Handle of device selected/opened */
ALCcontext *ctx; /* Device context */
DataHandleCallback cb; /* Use this to handle data from input device usually */
@ -60,15 +61,15 @@ typedef struct _Device {
int32_t call_idx; /* ToxAv call index */
uint32_t source, buffers[OPENAL_BUFS]; /* Playback source/buffers */
size_t ref_count;
uint32_t ref_count;
int32_t selection;
_Bool enable_VAD;
_Bool muted;
bool enable_VAD;
bool muted;
pthread_mutex_t mutex[1];
uint32_t sample_rate;
uint32_t frame_duration;
int32_t sound_mode;
#ifdef _AUDIO
#ifdef AUDIO
float VAD_treshold; /* 40 is usually recommended value */
#endif
} Device;
@ -76,12 +77,12 @@ typedef struct _Device {
const char *ddevice_names[2]; /* Default device */
const char *devices_names[2][MAX_DEVICES]; /* Container of available devices */
static int size[2]; /* Size of above containers */
Device *running[2][MAX_DEVICES]; /* Running devices */
Device *running[2][MAX_DEVICES] = {{NULL}}; /* Running devices */
uint32_t primary_device[2]; /* Primary device */
#ifdef _AUDIO
#ifdef AUDIO
static ToxAv* av = NULL;
#endif /* _AUDIO */
#endif /* AUDIO */
/* q_mutex */
#define lock pthread_mutex_lock(&mutex)
@ -89,21 +90,19 @@ static ToxAv* av = NULL;
pthread_mutex_t mutex;
_Bool thread_running = _True,
thread_paused = _True; /* Thread control */
bool thread_running = true,
thread_paused = true; /* Thread control */
void* thread_poll(void*);
/* Meet devices */
#ifdef _AUDIO
#ifdef AUDIO
DeviceError init_devices(ToxAv* av_)
#else
DeviceError init_devices()
#endif /* _AUDIO */
#endif /* AUDIO */
{
const char *stringed_device_list;
size[input] = 0;
if ( (stringed_device_list = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER)) ) {
ddevice_names[input] = alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
@ -114,8 +113,6 @@ DeviceError init_devices()
}
}
size[output] = 0;
if ( (stringed_device_list = alcGetString(NULL, ALC_DEVICE_SPECIFIER)) ) {
ddevice_names[output] = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
@ -125,18 +122,18 @@ DeviceError init_devices()
stringed_device_list += strlen( stringed_device_list ) + 1;
}
}
// Start poll thread
pthread_mutex_init(&mutex, NULL);
if (pthread_mutex_init(&mutex, NULL) != 0)
return de_InternalError;
pthread_t thread_id;
if ( pthread_create(&thread_id, NULL, thread_poll, NULL) != 0 || pthread_detach(thread_id) != 0)
return de_InternalError;
#ifdef _AUDIO
#ifdef AUDIO
av = av_;
#endif /* _AUDIO */
#endif /* AUDIO */
return (DeviceError) de_None;
}
@ -147,7 +144,8 @@ DeviceError terminate_devices()
thread_running = false;
usleep(20000);
pthread_mutex_destroy(&mutex);
if (pthread_mutex_destroy(&mutex) != 0)
return (DeviceError) de_InternalError;
return (DeviceError) de_None;
}
@ -170,7 +168,7 @@ DeviceError device_mute(DeviceType type, uint32_t device_idx)
return de_None;
}
#ifdef _AUDIO
#ifdef AUDIO
DeviceError device_set_VAD_treshold(uint32_t device_idx, float value)
{
if (device_idx >= MAX_DEVICES) return de_InvalidSelection;
@ -222,6 +220,18 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx
if (i == MAX_DEVICES) { unlock; return de_AllDevicesBusy; }
else *device_idx = i;
for (i = 0; i < MAX_DEVICES; i ++) { /* Check if any device has the same selection */
if ( running[type][i] && running[type][i]->selection == selection ) {
// printf("a%d-%d:%p ", selection, i, running[type][i]->dhndl);
running[type][*device_idx] = running[type][i];
running[type][i]->ref_count ++;
unlock;
return de_None;
}
}
Device* device = running[type][*device_idx] = calloc(1, sizeof(Device));
device->selection = selection;
@ -229,26 +239,17 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx
device->frame_duration = frame_duration;
device->sound_mode = channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
for (i = 0; i < *device_idx; i ++) { /* Check if any previous has the same selection */
if ( running[type][i]->selection == selection ) {
device->dhndl = running[type][i]->dhndl;
if (type == output) {
device->ctx = running[type][i]->ctx;
memcpy(device->buffers, running[type][i]->buffers, sizeof(running[type][i]->buffers));
device->source = running[type][i]->source;
}
device->ref_count++;
pthread_mutex_init(device->mutex, NULL);
unlock;
return de_None;
}
if (pthread_mutex_init(device->mutex, NULL) != 0) {
free(device);
unlock;
return de_InternalError;
}
if (type == input) {
device->dhndl = alcCaptureOpenDevice(devices_names[type][selection],
sample_rate, device->sound_mode, frame_size * 2);
#ifdef _AUDIO
device->VAD_treshold = user_settings_->VAD_treshold;
#ifdef AUDIO
device->VAD_treshold = user_settings->VAD_treshold;
#endif
}
else {
@ -287,10 +288,9 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx
if (type == input) {
alcCaptureStart(device->dhndl);
thread_paused = _False;
thread_paused = false;
}
pthread_mutex_init(device->mutex, NULL);
unlock;
return de_None;
}
@ -301,17 +301,18 @@ DeviceError close_device(DeviceType type, uint32_t device_idx)
lock;
Device* device = running[type][device_idx];
DeviceError rc = de_None;
if (!device) {
unlock;
return de_DeviceNotActive;
}
if ( !(device->ref_count--) ) {
running[type][device_idx] = NULL;
unlock;
running[type][device_idx] = NULL;
if ( !device->ref_count ) {
DeviceError rc = de_None;
// printf("Closed device ");
if (type == input) {
if ( !alcCaptureCloseDevice(device->dhndl) ) rc = de_AlError;
@ -328,16 +329,15 @@ DeviceError close_device(DeviceType type, uint32_t device_idx)
}
free(device);
return rc;
}
else device->ref_count--;
unlock;
return de_None;
return rc;
}
DeviceError register_device_callback( int32_t call_idx, uint32_t device_idx, DataHandleCallback callback, void* data, _Bool enable_VAD)
{
DeviceError register_device_callback( int32_t call_idx, uint32_t device_idx, DataHandleCallback callback, void* data, bool enable_VAD)
{
if (size[input] <= device_idx || !running[input][device_idx] || running[input][device_idx]->dhndl == NULL)
return de_InvalidSelection;
@ -427,9 +427,9 @@ void* thread_poll (void* arg) // TODO: maybe use thread for every input source
alcCaptureSamples(device->dhndl, frame, f_size);
if ( device->muted
#ifdef _AUDIO
#ifdef AUDIO
|| (device->enable_VAD && !toxav_has_activity(av, device->call_idx, frame, f_size, device->VAD_treshold))
#endif /* _AUDIO */
#endif /* AUDIO */
)
{ unlock; continue; } /* Skip if no voice activity */
@ -464,4 +464,4 @@ void* get_device_callback_data(uint32_t device_idx)
return NULL;
return running[input][device_idx]->cb_data;
}
}

View File

@ -26,16 +26,13 @@
* Read from running input device(s) via select()/callback combo.
*/
#ifndef _device_h
#define _device_h
#ifndef DEVICE_H
#define DEVICE_H
#define MAX_DEVICES 32
#include <inttypes.h>
#include "windows.h"
#define _True 1
#define _False 0
typedef enum DeviceType {
input,
output,
@ -57,22 +54,22 @@ typedef enum DeviceError {
typedef void (*DataHandleCallback) (const int16_t*, uint32_t size, void* data);
#ifdef _AUDIO
#ifdef AUDIO
DeviceError init_devices(ToxAv* av);
#else
DeviceError init_devices();
#endif /* _AUDIO */
#endif /* AUDIO */
DeviceError terminate_devices();
/* Callback handles ready data from INPUT device */
DeviceError register_device_callback(int32_t call_idx, uint32_t device_idx, DataHandleCallback callback, void* data, _Bool enable_VAD);
DeviceError register_device_callback(int32_t call_idx, uint32_t device_idx, DataHandleCallback callback, void* data, bool enable_VAD);
void* get_device_callback_data(uint32_t device_idx);
/* toggle device mute */
DeviceError device_mute(DeviceType type, uint32_t device_idx);
#ifdef _AUDIO
#ifdef AUDIO
DeviceError device_set_VAD_treshold(uint32_t device_idx, float value);
#endif
@ -89,4 +86,4 @@ DeviceError write_out(uint32_t device_idx, int16_t* data, uint32_t lenght, uint8
void print_devices(ToxWindow* self, DeviceType type);
DeviceError selection_valid(DeviceType type, int32_t selection);
#endif /* _device_h */
#endif /* DEVICE_H */

View File

@ -46,7 +46,7 @@
#define MAX_DNS_REQST_SIZE 255
#define TOX_DNS3_TXT_PREFIX "v=tox3;id="
extern struct _Winthread Winthread;
extern struct Winthread Winthread;
extern struct _dns3_servers dns3_servers;
extern struct arg_opts arg_opts;

View File

@ -23,10 +23,10 @@
/* Does DNS lookup for addr and puts resulting tox id in id_bin.
Return 0 on success, -1 on failure. */
#ifndef _dns_h
#define _dns_h
#ifndef DNS_H
#define DNS_H
/* creates new thread for dns3 lookup. Only allows one lookup at a time. */
void dns3_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr, const char *msg);
#endif /* #define _dns_h */
#endif /* #define DNS_H */

View File

@ -41,6 +41,7 @@ struct cmd_func {
static struct cmd_func global_commands[] = {
{ "/accept", cmd_accept },
{ "/add", cmd_add },
{ "/avatar", cmd_avatar },
{ "/clear", cmd_clear },
{ "/connect", cmd_connect },
{ "/decline", cmd_decline },
@ -55,10 +56,10 @@ static struct cmd_func global_commands[] = {
{ "/quit", cmd_quit },
{ "/requests", cmd_requests },
{ "/status", cmd_status },
#ifdef _AUDIO
#ifdef AUDIO
{ "/lsdev", cmd_list_devices },
{ "/sdev", cmd_change_device },
#endif /* _AUDIO */
#endif /* AUDIO */
{ NULL, NULL },
};
@ -68,7 +69,7 @@ static struct cmd_func chat_commands[] = {
{ "/join", cmd_join_group },
{ "/savefile", cmd_savefile },
{ "/sendfile", cmd_sendfile },
#ifdef _AUDIO
#ifdef AUDIO
{ "/call", cmd_call },
{ "/answer", cmd_answer },
{ "/reject", cmd_reject },
@ -76,7 +77,7 @@ static struct cmd_func chat_commands[] = {
{ "/sdev", cmd_ccur_device },
{ "/mute", cmd_mute },
{ "/sense", cmd_sense },
#endif /* _AUDIO */
#endif /* AUDIO */
{ NULL, NULL },
};

View File

@ -20,8 +20,8 @@
*
*/
#ifndef _execute_h
#define _execute_h
#ifndef EXECUTE_H
#define EXECUTE_H
#include "toxic.h"
#include "windows.h"
@ -36,4 +36,4 @@ enum {
void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode);
#endif /* #define _execute_h */
#endif /* #define EXECUTE_H */

View File

@ -36,7 +36,7 @@
FileSender file_senders[MAX_FILES];
uint8_t max_file_senders_index;
uint8_t num_active_file_senders;
extern _Friends Friends;
extern FriendsList Friends;
/* creates initial progress line that will be updated during file transfer.
Assumes progline is of size MAX_STR_SIZE */
@ -229,7 +229,7 @@ static void send_file_data(ToxWindow *self, Tox *m, int i, int32_t friendnum, in
snprintf(msg, sizeof(msg), "File transfer for '%s' failed: Read error.", file_senders[i].filename);
close_file_sender(self, m, i, msg, TOX_FILECONTROL_KILL, filenum, friendnum);
sound_notify(self, error, NT_NOFOCUS | NT_WNDALERT_2, NULL);
if (self->active_box != -1)
box_notify2(self, error, NT_NOFOCUS | NT_WNDALERT_2, self->active_box, "%s", msg);
else

View File

@ -20,8 +20,8 @@
*
*/
#ifndef _filesenders_h
#define _filesenders_h
#ifndef FILESENDERS_H
#define FILESENDERS_H
#include "toxic.h"
#include "windows.h"
@ -72,4 +72,4 @@ void reset_file_sender_queue(void);
void close_all_file_senders(Tox *m);
void do_file_senders(Tox *m);
#endif /* #define _filesenders_h */
#endif /* #define FILESENDERS_H */

View File

@ -37,8 +37,9 @@
#include "settings.h"
#include "notify.h"
#include "help.h"
#include "log.h"
#ifdef _AUDIO
#ifdef AUDIO
#include "audio_call.h"
#endif
@ -46,15 +47,15 @@
extern char *DATA_FILE;
extern char *BLOCK_FILE;
extern ToxWindow *prompt;
extern struct _Winthread Winthread;
extern struct user_settings *user_settings_;
extern struct Winthread Winthread;
extern struct user_settings *user_settings;
extern struct arg_opts arg_opts;
static uint8_t blocklist_view = 0; /* 0 if we're in friendlist view, 1 if we're in blocklist view */
_Friends Friends;
FriendsList Friends;
static struct _Blocked {
static struct Blocked {
int num_selected;
int max_idx;
int num_blocked;
@ -63,7 +64,7 @@ static struct _Blocked {
BlockedFriend *list;
} Blocked;
static struct _pendingDel {
static struct pendingDel {
int num;
bool active;
WINDOW *popup;
@ -111,6 +112,13 @@ static void realloc_blocklist(int n)
void kill_friendlist(void)
{
int i;
for (i = 0; i < Friends.max_idx; ++i) {
if (Friends.list[i].active && Friends.list[i].group_invite.key != NULL)
free(Friends.list[i].group_invite.key);
}
realloc_blocklist(0);
realloc_friends(0);
}
@ -163,6 +171,8 @@ static int save_blocklist(char *path)
ret = 0;
fclose(fp);
return ret;
on_error:
free(data);
return ret;
@ -180,9 +190,12 @@ int load_blocklist(char *path)
if (fp == NULL)
return -1;
fseek(fp, 0, SEEK_END);
int len = ftell(fp);
fseek(fp, 0, SEEK_SET);
off_t len = file_size(path);
if (len == -1) {
fclose(fp);
return -1;
}
char *data = malloc(len);
@ -285,7 +298,7 @@ static void update_friend_last_online(int32_t num, uint64_t timestamp)
Friends.list[num].last_online.tm = *localtime((const time_t*)&timestamp);
/* if the format changes make sure TIME_STR_SIZE is the correct size */
const char *t = user_settings_->time == TIME_12 ? "%I:%M %p" : "%H:%M";
const char *t = user_settings->time == TIME_12 ? "%I:%M %p" : "%H:%M";
strftime(Friends.list[num].last_online.hour_min_str, TIME_STR_SIZE, t,
&Friends.list[num].last_online.tm);
}
@ -330,12 +343,27 @@ static void friendlist_onNickChange(ToxWindow *self, Tox *m, int32_t num, const
if (len > TOX_MAX_NAME_LENGTH || num >= Friends.max_idx)
return;
/* save old name for log renaming */
char oldname[TOXIC_MAX_NAME_LENGTH];
snprintf(oldname, sizeof(oldname), "%s", Friends.list[num].name);
/* update name */
char tempname[TOX_MAX_NAME_LENGTH];
strcpy(tempname, nick);
len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1);
tempname[len] = '\0';
snprintf(Friends.list[num].name, sizeof(Friends.list[num].name), "%s", tempname);
Friends.list[num].namelength = len;
/* get data for chatlog renaming */
char newnamecpy[TOXIC_MAX_NAME_LENGTH];
char myid[TOX_FRIEND_ADDRESS_SIZE];
strcpy(newnamecpy, tempname);
tox_get_address(m, (uint8_t *) myid);
if (strcmp(oldname, newnamecpy) != 0)
rename_logfile(oldname, newnamecpy, myid, Friends.list[num].pub_key, Friends.list[num].chatwin);
sort_friendlist_index();
}
@ -377,7 +405,7 @@ void friendlist_onFriendAdded(ToxWindow *self, Tox *m, int32_t num, bool sort)
Friends.list[i].chatwin = -1;
Friends.list[i].online = false;
Friends.list[i].status = TOX_USERSTATUS_NONE;
Friends.list[i].logging_on = (bool) user_settings_->autolog == AUTOLOG_ON;
Friends.list[i].logging_on = (bool) user_settings->autolog == AUTOLOG_ON;
tox_get_client_id(m, num, (uint8_t *) Friends.list[i].pub_key);
update_friend_last_online(i, tox_get_last_online(m, i));
@ -419,7 +447,7 @@ static void friendlist_add_blocked(Tox *m, int32_t fnum, int32_t bnum)
Friends.list[i].active = true;
Friends.list[i].chatwin = -1;
Friends.list[i].status = TOX_USERSTATUS_NONE;
Friends.list[i].logging_on = (bool) user_settings_->autolog == AUTOLOG_ON;
Friends.list[i].logging_on = (bool) user_settings->autolog == AUTOLOG_ON;
Friends.list[i].namelength = Blocked.list[bnum].namelength;
update_friend_last_online(i, Blocked.list[bnum].last_on);
memcpy(Friends.list[i].name, Blocked.list[bnum].name, Friends.list[i].namelength + 1);
@ -458,7 +486,7 @@ static void friendlist_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, u
}
}
static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, const char *group_pub_key)
static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, const char *group_pub_key, uint16_t length)
{
if (num >= Friends.max_idx)
return;
@ -501,6 +529,9 @@ static void delete_friend(Tox *m, int32_t f_num)
}
}
if (Friends.list[f_num].group_invite.key != NULL)
free(Friends.list[f_num].group_invite.key);
tox_del_friend(m, f_num);
memset(&Friends.list[f_num], 0, sizeof(ToxicFriend));
@ -994,7 +1025,7 @@ void disable_chatwin(int32_t f_num)
Friends.list[f_num].chatwin = -1;
}
#ifdef _AUDIO
#ifdef AUDIO
static void friendlist_onAv(ToxWindow *self, ToxAv *av, int call_index)
{
int id = toxav_get_peer_id(av, call_index, 0);
@ -1021,7 +1052,7 @@ static void friendlist_onAv(ToxWindow *self, ToxAv *av, int call_index)
}
}
}
#endif /* _AUDIO */
#endif /* AUDIO */
ToxWindow new_friendlist(void)
{
@ -1043,7 +1074,7 @@ ToxWindow new_friendlist(void)
ret.onFileSendRequest = &friendlist_onFileSendRequest;
ret.onGroupInvite = &friendlist_onGroupInvite;
#ifdef _AUDIO
#ifdef AUDIO
ret.onInvite = &friendlist_onAv;
ret.onRinging = &friendlist_onAv;
ret.onStarting = &friendlist_onAv;
@ -1058,7 +1089,7 @@ ToxWindow new_friendlist(void)
ret.call_idx = -1;
ret.device_selection[0] = ret.device_selection[1] = -1;
#endif /* _AUDIO */
#endif /* AUDIO */
ret.active_box = -1;

View File

@ -20,8 +20,8 @@
*
*/
#ifndef FRIENDLIST_H_53I41IM
#define FRIENDLIST_H_53I41IM
#ifndef FRIENDLIST_H
#define FRIENDLIST_H
#include <time.h>
@ -48,13 +48,17 @@ struct LastOnline {
char hour_min_str[TIME_STR_SIZE]; /* holds 12/24-hour time string e.g. "10:43 PM" */
};
struct GroupChatInvite {
char *key;
uint16_t length;
bool pending;
};
typedef struct {
char name[TOXIC_MAX_NAME_LENGTH];
int namelength;
char statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH];
uint16_t statusmsg_len;
char groupchat_key[TOX_CLIENT_ID_SIZE];
bool groupchat_pending;
char pub_key[TOX_CLIENT_ID_SIZE];
int32_t num;
int chatwin;
@ -65,6 +69,7 @@ typedef struct {
uint8_t status;
struct LastOnline last_online;
struct FileReceiver file_receiver[MAX_FILES];
struct GroupChatInvite group_invite;
uint8_t active_file_receivers;
} ToxicFriend;
@ -83,7 +88,7 @@ typedef struct {
int num_friends;
int *index;
ToxicFriend *list;
} _Friends;
} FriendsList;
ToxWindow new_friendlist(void);
void disable_chatwin(int32_t f_num);
@ -95,4 +100,4 @@ void friendlist_onFriendAdded(ToxWindow *self, Tox *m, int32_t num, bool sort);
/* sorts friendlist_index first by connection status then alphabetically */
void sort_friendlist_index(void);
#endif /* end of include guard: FRIENDLIST_H_53I41IM */
#endif /* end of include guard: FRIENDLIST_H */

View File

@ -37,8 +37,8 @@
extern char *DATA_FILE;
extern ToxWindow *prompt;
extern _Friends Friends;
extern _FriendRequests FriendRequests;
extern FriendsList Friends;
extern FriendRequests FrndRequests;
/* command functions */
void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
@ -55,13 +55,13 @@ void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
return;
}
if (!FriendRequests.request[req].active) {
if (!FrndRequests.request[req].active) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending friend request with that ID.");
return;
}
const char *msg;
int32_t friendnum = tox_add_friend_norequest(m, FriendRequests.request[req].key);
int32_t friendnum = tox_add_friend_norequest(m, FrndRequests.request[req].key);
if (friendnum == -1)
msg = "Failed to add friend.";
@ -70,17 +70,17 @@ void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
on_friendadded(m, friendnum, true);
}
memset(&FriendRequests.request[req], 0, sizeof(struct _friend_request));
memset(&FrndRequests.request[req], 0, sizeof(struct friend_request));
int i;
for (i = FriendRequests.max_idx; i > 0; --i) {
if (FriendRequests.request[i - 1].active)
for (i = FrndRequests.max_idx; i > 0; --i) {
if (FrndRequests.request[i - 1].active)
break;
}
FriendRequests.max_idx = i;
--FriendRequests.num_requests;
FrndRequests.max_idx = i;
--FrndRequests.num_requests;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", msg);
}
@ -184,6 +184,81 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
}
}
void cmd_avatar(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{
if (argc < 2) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: No file path supplied.");
return;
}
/* turns the avatar off */
if (strlen(argv[1]) < 3) {
tox_unset_avatar(m);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No avatar set.");
return;
}
if (argv[1][0] != '\"') {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Path must be enclosed in quotes.");
return;
}
/* remove opening and closing quotes */
char path[MAX_STR_SIZE];
snprintf(path, sizeof(path), "%s", &argv[1][1]);
int len = strlen(path) - 1;
path[len] = '\0';
off_t sz = file_size(path);
if (sz <= 8) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Invalid file.");
return;
}
if (sz > TOX_AVATAR_MAX_DATA_LENGTH) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: File is too large.");
return;
}
FILE *fp = fopen(path, "rb");
if (fp == NULL) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Could not open file.");
return;
}
char PNG_signature[8] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
if (check_file_signature(PNG_signature, sizeof(PNG_signature), fp) != 0) {
fclose(fp);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: File type not supported.");
return;
}
char *avatar = malloc(sz);
if (avatar == NULL)
exit_toxic_err("Failed in set_avatar", FATALERR_MEMORY);
if (fread(avatar, sz, 1, fp) != 1) {
fclose(fp);
free(avatar);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Read fail.");
return;
}
if (tox_set_avatar(m, TOX_AVATAR_FORMAT_PNG, (const uint8_t *) avatar, (uint32_t) sz) == -1)
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Core error.");
char filename[MAX_STR_SIZE];
get_file_name(filename, sizeof(filename), path);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Avatar set to '%s'", filename);
fclose(fp);
free(avatar);
}
void cmd_clear(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{
line_info_clear(self->chatwin->hst);
@ -227,22 +302,22 @@ void cmd_decline(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)
return;
}
if (!FriendRequests.request[req].active) {
if (!FrndRequests.request[req].active) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending friend request with that ID.");
return;
}
memset(&FriendRequests.request[req], 0, sizeof(struct _friend_request));
memset(&FrndRequests.request[req], 0, sizeof(struct friend_request));
int i;
for (i = FriendRequests.max_idx; i > 0; --i) {
if (FriendRequests.request[i - 1].active)
for (i = FrndRequests.max_idx; i > 0; --i) {
if (FrndRequests.request[i - 1].active)
break;
}
FriendRequests.max_idx = i;
--FriendRequests.num_requests;
FrndRequests.max_idx = i;
--FrndRequests.num_requests;
}
void cmd_groupchat(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
@ -286,16 +361,16 @@ void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
const char *swch = argv[1];
if (!strcmp(swch, "1") || !strcmp(swch, "on")) {
char myid[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(m, (uint8_t *) myid);
if (self->is_chat) {
Friends.list[self->num].logging_on = true;
log_enable(self->name, Friends.list[self->num].pub_key, log);
log_enable(self->name, myid, Friends.list[self->num].pub_key, log, LOG_CHAT);
} else if (self->is_prompt) {
char myid[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(m, (uint8_t *) myid);
log_enable(self->name, myid, log);
log_enable(self->name, myid, NULL, log, LOG_PROMPT);
} else if (self->is_groupchat) {
log_enable(self->name, NULL, log);
log_enable(self->name, myid, NULL, log, LOG_GROUP);
}
msg = "Logging enabled";
@ -399,7 +474,7 @@ void cmd_quit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
void cmd_requests(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{
if (FriendRequests.num_requests == 0) {
if (FrndRequests.num_requests == 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending friend requests.");
return;
}
@ -407,22 +482,22 @@ void cmd_requests(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
int i, j;
int count = 0;
for (i = 0; i < FriendRequests.max_idx; ++i) {
if (!FriendRequests.request[i].active)
for (i = 0; i < FrndRequests.max_idx; ++i) {
if (!FrndRequests.request[i].active)
continue;
char id[TOX_CLIENT_ID_SIZE * 2 + 1] = {0};
for (j = 0; j < TOX_CLIENT_ID_SIZE; ++j) {
char d[3];
snprintf(d, sizeof(d), "%02X", FriendRequests.request[i].key[j] & 0xff);
snprintf(d, sizeof(d), "%02X", FrndRequests.request[i].key[j] & 0xff);
strcat(id, d);
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%d : %s", i, id);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", FriendRequests.request[i].msg);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", FrndRequests.request[i].msg);
if (++count < FriendRequests.num_requests)
if (++count < FrndRequests.num_requests)
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "");
}
}

View File

@ -20,14 +20,15 @@
*
*/
#ifndef _global_commands_h
#define _global_commands_h
#ifndef GLOBAL_COMMANDS_H
#define GLOBAL_COMMANDS_H
#include "windows.h"
#include "toxic.h"
void cmd_accept(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_add(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_avatar(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_clear(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_connect(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_decline(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
@ -43,9 +44,9 @@ void cmd_status(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZ
void cmd_add_helper(ToxWindow *self, Tox *m, char *id_bin, char *msg);
#ifdef _AUDIO
#ifdef AUDIO
void cmd_list_devices(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_change_device(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
#endif /* _AUDIO */
#endif /* AUDIO */
#endif /* #define _global_commands_h */
#endif /* #define GLOBAL_COMMANDS_H */

View File

@ -50,7 +50,7 @@ extern char *DATA_FILE;
static GroupChat groupchats[MAX_GROUPCHAT_NUM];
static int max_groupchat_index = 0;
extern struct user_settings *user_settings_;
extern struct user_settings *user_settings;
/* temporary until group chats have unique commands */
extern const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE];
@ -67,11 +67,16 @@ int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum)
groupchats[i].chatwin = add_window(m, new_group_chat(m, groupnum));
groupchats[i].active = true;
groupchats[i].num_peers = 0;
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);
@ -302,7 +307,7 @@ static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnu
case TOX_CHAT_CHANGE_PEER_DEL:
event = "has left the room";
line_info_add(self, timefrmt, (char *) oldpeername, NULL, CONNECTION, 0, 0, event);
line_info_add(self, timefrmt, (char *) oldpeername, NULL, CONNECTION, 0, RED, event);
if (groupchats[self->num].side_pos > 0)
--groupchats[self->num].side_pos;
@ -367,11 +372,15 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
if (ctx->len > 0) {
int diff;
if ((ctx->line[0] != '/') || (ctx->line[1] == 'm' && ctx->line[2] == 'e'))
diff = complete_line(self, groupchats[self->num].peer_names,
groupchats[self->num].num_peers, TOX_MAX_NAME_LENGTH);
else
/* 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,
TOX_MAX_NAME_LENGTH);
} else if (wcsncmp(ctx->line, L"/avatar \"", wcslen(L"/avatar \"")) == 0) {
diff = dir_match(self, m, ctx->line, L"/avatar");
} else {
diff = complete_line(self, glob_cmd_list, AC_NUM_GLOB_COMMANDS, MAX_CMDNAME_SIZE);
}
if (diff != -1) {
if (x + diff > x2 - 1) {
@ -384,12 +393,12 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
} else {
sound_notify(self, error, 0, NULL);
}
} else if (key == user_settings_->key_peer_list_down) { /* Scroll peerlist up and down one position */
} else if (key == user_settings->key_peer_list_down) { /* Scroll peerlist up and down one position */
int L = y2 - CHATBOX_HEIGHT - SDBAR_OFST;
if (groupchats[self->num].side_pos < groupchats[self->num].num_peers - L)
++groupchats[self->num].side_pos;
} else if (key == user_settings_->key_peer_list_up) {
} else if (key == user_settings->key_peer_list_up) {
if (groupchats[self->num].side_pos > 0)
--groupchats[self->num].side_pos;
} else if (key == '\n') {
@ -503,8 +512,11 @@ static void groupchat_onInit(ToxWindow *self, Tox *m)
line_info_init(ctx->hst);
if (user_settings_->autolog == AUTOLOG_ON)
log_enable(self->name, NULL, ctx->log);
if (user_settings->autolog == AUTOLOG_ON) {
char myid[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(m, (uint8_t *) myid);
log_enable(self->name, myid, NULL, ctx->log, LOG_GROUP);
}
execute(ctx->history, self, m, "/log", GLOBAL_COMMAND_MODE);

View File

@ -20,8 +20,8 @@
*
*/
#ifndef _groupchat_h
#define _groupchat_h
#ifndef GROUPCHAT_H
#define GROUPCHAT_H
#include "toxic.h"
#include "windows.h"
@ -45,4 +45,4 @@ void kill_groupchat_window(ToxWindow *self);
int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum);
ToxWindow new_group_chat(Tox *m, int groupnum);
#endif /* #define _groupchat_h */
#endif /* #define GROUPCHAT_H */

View File

@ -138,6 +138,7 @@ static void help_draw_global(ToxWindow *self)
wprintw(win, " /add <addr> <msg> : Add contact with optional message\n");
wprintw(win, " /accept <id> : Accept friend request\n");
wprintw(win, " /avatar <path> : Set a personal avatar\n");
wprintw(win, " /decline <id> : Decline friend request\n");
wprintw(win, " /requests : List pending friend requests\n");
wprintw(win, " /connect <ip> <port> <key> : Manually connect to a DHT node\n");
@ -151,14 +152,14 @@ static void help_draw_global(ToxWindow *self)
wprintw(win, " /close : Close the current chat window\n");
wprintw(win, " /quit or /exit : Exit Toxic\n");
#ifdef _AUDIO
#ifdef AUDIO
wattron(win, A_BOLD);
wprintw(win, "\n Audio:\n");
wattroff(win, A_BOLD);
wprintw(win, " /lsdev <type> : List devices where type: in|out\n");
wprintw(win, " /sdev <type> <id> : Set active device\n");
#endif /* _AUDIO */
#endif /* AUDIO */
help_draw_bottom_menu(win);
@ -182,7 +183,7 @@ static void help_draw_chat(ToxWindow *self)
wprintw(win, " /savefile <id> : Receive a file\n");
wprintw(win, " /cancel <type> <id> : Cancel file transfer where type: in|out\n");
#ifdef _AUDIO
#ifdef AUDIO
wattron(win, A_BOLD);
wprintw(win, "\n Audio:\n");
wattroff(win, A_BOLD);
@ -194,7 +195,7 @@ static void help_draw_chat(ToxWindow *self)
wprintw(win, " /sdev <type> <id> : Change active device\n");
wprintw(win, " /mute <type> : Mute active device if in call\n");
wprintw(win, " /sense <n> : VAD sensitivity treshold\n");
#endif /* _AUDIO */
#endif /* AUDIO */
help_draw_bottom_menu(win);
@ -256,7 +257,7 @@ void help_onKey(ToxWindow *self, wint_t key)
break;
case 'c':
#ifdef _AUDIO
#ifdef AUDIO
help_init_window(self, 19, 80);
#else
help_init_window(self, 9, 80);
@ -265,10 +266,10 @@ void help_onKey(ToxWindow *self, wint_t key)
break;
case 'g':
#ifdef _AUDIO
help_init_window(self, 23, 80);
#ifdef AUDIO
help_init_window(self, 24, 80);
#else
help_init_window(self, 19, 80);
help_init_window(self, 20, 80);
#endif
self->help->type = HELP_GLOBAL;
break;

View File

@ -20,8 +20,8 @@
*
*/
#ifndef _help_h
#define _help_h
#ifndef HELP_H
#define HELP_H
#include "toxic.h"
#include "windows.h"
@ -39,4 +39,4 @@ void help_onDraw(ToxWindow *self);
void help_init_menu(ToxWindow *self);
void help_onKey(ToxWindow *self, wint_t key);
#endif /* #define _help_h */
#endif /* #define HELP_H */

View File

@ -20,8 +20,8 @@
*
*/
#ifndef _input_h
#define _input_h
#ifndef INPUT_H
#define INPUT_H
/* add a char to input field and buffer for given chatcontext */
void input_new_char(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_y);
@ -30,4 +30,4 @@ void input_new_char(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_
return true if key matches a function, false otherwise */
bool input_handle(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_y);
#endif /* #define _input_h */
#endif /* #define INPUT_H */

View File

@ -34,7 +34,7 @@
#include "message_queue.h"
#include "misc_tools.h"
extern struct user_settings *user_settings_;
extern struct user_settings *user_settings;
void line_info_init(struct history *hst)
{
@ -48,8 +48,8 @@ void line_info_init(struct history *hst)
hst->queue_sz = 0;
}
/* resets line_start (page end) */
static void line_info_reset_start(ToxWindow *self, struct history *hst)
/* resets line_start (moves to end of chat history) */
void line_info_reset_start(ToxWindow *self, struct history *hst)
{
struct line_info *line = hst->line_end;
@ -111,13 +111,13 @@ static void line_info_root_fwd(struct history *hst)
hst->line_root = tmp;
}
/* returns ptr to queue item 0 and removes it from queue */
/* returns ptr to queue item 0 and removes it from queue. Returns NULL if queue is empty. */
static struct line_info *line_info_ret_queue(struct history *hst)
{
if (hst->queue_sz <= 0)
return NULL;
struct line_info *ret = hst->queue[0];
struct line_info *line = hst->queue[0];
int i;
@ -126,7 +126,7 @@ static struct line_info *line_info_ret_queue(struct history *hst)
--hst->queue_sz;
return ret;
return line;
}
/* creates new line_info line and puts it in the queue. */
@ -135,7 +135,7 @@ void line_info_add(ToxWindow *self, char *timestr, char *name1, char *name2, uin
{
struct history *hst = self->chatwin->hst;
if (hst->queue_sz >= MAX_QUEUE)
if (hst->queue_sz >= MAX_LINE_INFO_QUEUE)
return;
struct line_info *new_line = calloc(1, sizeof(struct line_info));
@ -143,7 +143,7 @@ void line_info_add(ToxWindow *self, char *timestr, char *name1, char *name2, uin
if (new_line == NULL)
exit_toxic_err("failed in line_info_add", FATALERR_MEMORY);
char frmt_msg[MAX_STR_SIZE] = {0};
char frmt_msg[MAX_LINE_INFO_MSG_SIZE] = {0};
va_list args;
va_start(args, msg);
@ -156,21 +156,25 @@ void line_info_add(ToxWindow *self, char *timestr, char *name1, char *name2, uin
switch (type) {
case IN_ACTION:
case OUT_ACTION:
len += 3;
len += 5;
break;
case IN_MSG:
case OUT_MSG:
len += 2;
len += 6;
break;
case CONNECTION:
len += 3;
len += 5;
break;
case SYS_MSG:
break;
case NAME_CHANGE:
len += 4;
break;
case PROMPT:
++len;
break;
@ -226,7 +230,7 @@ static void line_info_check_queue(ToxWindow *self)
if (line == NULL)
return;
if (hst->start_id > user_settings_->history_size)
if (hst->start_id > user_settings->history_size)
line_info_root_fwd(hst);
line->id = hst->line_end->id + 1;
@ -254,6 +258,10 @@ static void line_info_check_queue(ToxWindow *self)
++hst->start_id;
}
}
/* force move to bottom of history when we print an outgoing message */
if (line->type == OUT_MSG)
line_info_reset_start(self, hst);
}
#define NOREAD_FLAG_TIMEOUT 5 /* seconds before a sent message with no read receipt is flagged as unread */
@ -305,7 +313,7 @@ void line_info_print(ToxWindow *self)
nameclr = CYAN;
wattron(win, COLOR_PAIR(nameclr));
wprintw(win, "%s: ", line->name1);
wprintw(win, "--- %s: ", line->name1);
wattroff(win, COLOR_PAIR(nameclr));
if (line->msg[0] == '>')
@ -338,7 +346,7 @@ void line_info_print(ToxWindow *self)
wattroff(win, COLOR_PAIR(BLUE));
wattron(win, COLOR_PAIR(YELLOW));
wprintw(win, "* %s %s", line->name1, line->msg);
wprintw(win, "-*- %s %s", line->name1, line->msg);
wattroff(win, COLOR_PAIR(YELLOW));
if (type == OUT_ACTION && timed_out(line->timestamp, get_unix_time(), NOREAD_FLAG_TIMEOUT)) {
@ -395,9 +403,12 @@ void line_info_print(ToxWindow *self)
wattroff(win, COLOR_PAIR(BLUE));
wattron(win, COLOR_PAIR(line->colour));
wprintw(win, "%s ", line->colour == RED ? "<--" : "-->");
wattron(win, A_BOLD);
wprintw(win, "* %s ", line->name1);
wprintw(win, "%s ", line->name1);
wattroff(win, A_BOLD);
wprintw(win, "%s\n", line->msg);
wattroff(win, COLOR_PAIR(line->colour));
@ -409,8 +420,9 @@ void line_info_print(ToxWindow *self)
wattroff(win, COLOR_PAIR(BLUE));
wattron(win, COLOR_PAIR(MAGENTA));
wprintw(win, "-!- ");
wattron(win, A_BOLD);
wprintw(win, "* %s", line->name1);
wprintw(win, "%s", line->name1);
wattroff(win, A_BOLD);
wprintw(win, "%s", line->msg);
@ -494,19 +506,19 @@ bool line_info_onKey(ToxWindow *self, wint_t key)
struct history *hst = self->chatwin->hst;
bool match = true;
if (key == user_settings_->key_half_page_up) {
if (key == user_settings->key_half_page_up) {
line_info_page_up(self, hst);
}
else if (key == user_settings_->key_half_page_down) {
else if (key == user_settings->key_half_page_down) {
line_info_page_down(self, hst);
}
else if (key == user_settings_->key_scroll_line_up) {
else if (key == user_settings->key_scroll_line_up) {
line_info_scroll_up(hst);
}
else if (key == user_settings_->key_scroll_line_down) {
else if (key == user_settings->key_scroll_line_down) {
line_info_scroll_down(hst);
}
else if (key == user_settings_->key_page_bottom) {
else if (key == user_settings->key_page_bottom) {
line_info_reset_start(self, hst);
}
else {

View File

@ -20,15 +20,16 @@
*
*/
#ifndef _line_info_h
#define _line_info_h
#ifndef LINE_INFO_H
#define LINE_INFO_H
#include "windows.h"
#include "toxic.h"
#define MAX_HISTORY 100000
#define MIN_HISTORY 40
#define MAX_QUEUE 128
#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 {
SYS_MSG,
@ -47,7 +48,7 @@ struct line_info {
char timestr[TIME_STR_SIZE];
char name1[TOXIC_MAX_NAME_LENGTH];
char name2[TOXIC_MAX_NAME_LENGTH];
char msg[TOX_MAX_MESSAGE_LENGTH];
char msg[MAX_LINE_INFO_MSG_SIZE];
uint64_t timestamp;
uint8_t type;
uint8_t bold;
@ -68,7 +69,7 @@ struct history {
struct line_info *line_end;
uint32_t start_id; /* keeps track of where line_start should be when at bottom of history */
struct line_info *queue[MAX_QUEUE];
struct line_info *queue[MAX_LINE_INFO_QUEUE];
int queue_sz;
};
@ -88,7 +89,10 @@ void line_info_clear(struct history *hst);
/* puts msg in specified line_info msg buffer */
void line_info_set(ToxWindow *self, uint32_t id, char *msg);
/* resets line_start (moves to end of chat history) */
void line_info_reset_start(ToxWindow *self, struct history *hst);
void line_info_init(struct history *hst);
bool line_info_onKey(ToxWindow *self, wint_t key); /* returns true if key is a match */
#endif /* #define _line_info_h */
#endif /* #define LINE_INFO_H */

212
src/log.c
View File

@ -23,6 +23,7 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include "configdir.h"
#include "toxic.h"
@ -30,60 +31,88 @@
#include "misc_tools.h"
#include "log.h"
#include "settings.h"
#include "line_info.h"
extern struct user_settings *user_settings_;
extern struct user_settings *user_settings;
/* Creates/fetches log file by appending to the config dir the name and a pseudo-unique identity */
void init_logging_session(char *name, const char *key, struct chatlog *log)
/* There are three types of logs: chat logs, groupchat logs, and prompt logs (see LOG_TYPE in log.h)
A prompt log is in the format: LOGDIR/selfkey-home.log
A chat log is in the format: LOGDIR/selfkey-friendname-otherkey.log
A groupchat log is in the format: LOGDIR/selfkey-groupname-date[time].log
Only the first (KEY_IDENT_DIGITS * 2) numbers of the key are used.
Returns 0 on success, -1 if the path is too long */
static int get_log_path(char *dest, int destsize, char *name, const char *selfkey, const char *otherkey, int logtype)
{
if (!log->log_on)
return;
if (!valid_nick(name))
name = UNKNOWN_NAME;
const char *set_path = user_settings_->chatlogs_path;
const char *namedash = logtype == LOG_PROMPT ? "" : "-";
const char *set_path = user_settings->chatlogs_path;
char *user_config_dir = get_user_config_dir();
int path_len = strlen(set_path) + strlen(name) ? *set_path
: strlen(user_config_dir) + strlen(LOGDIR) + strlen(name);
int path_len = strlen(name) + strlen(".log") + strlen("-") + strlen(namedash);
path_len += strlen(set_path) ? *set_path : strlen(user_config_dir) + strlen(LOGDIR);
/* use first 4 digits of key as log ident. If no key use a timestamp */
char ident[32];
/* first 6 digits of selfkey */
char self_id[32];
path_len += KEY_IDENT_DIGITS * 2;
sprintf(&self_id[0], "%02X", selfkey[0] & 0xff);
sprintf(&self_id[2], "%02X", selfkey[1] & 0xff);
sprintf(&self_id[4], "%02X", selfkey[2] & 0xff);
self_id[KEY_IDENT_DIGITS * 2] = '\0';
if (key != NULL) {
path_len += (KEY_IDENT_DIGITS * 2 + 5);
sprintf(&ident[0], "%02X", key[0] & 0xff);
sprintf(&ident[2], "%02X", key[1] & 0xff);
ident[KEY_IDENT_DIGITS * 2 + 1] = '\0';
} else {
strftime(ident, sizeof(ident), "%Y-%m-%d[%H:%M:%S]", get_time());
path_len += strlen(ident) + 1;
char other_id[32] = {0};
switch (logtype) {
case LOG_CHAT:
path_len += KEY_IDENT_DIGITS * 2;
sprintf(&other_id[0], "%02X", otherkey[0] & 0xff);
sprintf(&other_id[2], "%02X", otherkey[1] & 0xff);
sprintf(&other_id[4], "%02X", otherkey[2] & 0xff);
other_id[KEY_IDENT_DIGITS * 2] = '\0';
break;
case LOG_GROUP:
strftime(other_id, sizeof(other_id), "%Y-%m-%d[%H:%M:%S]", get_time());
path_len += strlen(other_id);
break;
}
if (path_len >= MAX_STR_SIZE) {
log->log_on = false;
if (path_len >= destsize) {
free(user_config_dir);
return;
return -1;
}
char log_path[MAX_STR_SIZE];
if (*set_path)
snprintf(log_path, sizeof(log_path), "%s%s-%s.log", set_path, name, ident);
if (!string_is_empty(set_path))
snprintf(dest, destsize, "%s%s-%s%s%s.log", set_path, self_id, name, namedash, other_id);
else
snprintf(log_path, sizeof(log_path), "%s%s%s-%s.log", user_config_dir, LOGDIR, name, ident);
snprintf(dest, destsize, "%s%s%s-%s%s%s.log", user_config_dir, LOGDIR, self_id, name, namedash, other_id);
free(user_config_dir);
log->file = fopen(log_path, "a");
return 0;
}
if (log->file == NULL) {
log->log_on = false;
return;
}
/* Opens log file or creates a new one */
static int init_logging_session(char *name, const char *selfkey, const char *otherkey, struct chatlog *log, int logtype)
{
if (selfkey == NULL || (logtype == LOG_CHAT && otherkey == NULL))
return -1;
fprintf(log->file, "\n*** NEW SESSION ***\n\n");
char log_path[MAX_STR_SIZE];
if (get_log_path(log_path, sizeof(log_path), name, selfkey, otherkey, logtype) == -1)
return -1;
log->file = fopen(log_path, "a+");
snprintf(log->path, sizeof(log->path), "%s", log_path);
if (log->file == NULL)
return -1;
return 0;
}
#define LOG_FLUSH_LIMIT 1 /* limits calls to fflush to a max of one per LOG_FLUSH_LIMIT seconds */
@ -105,7 +134,7 @@ void write_to_log(const char *msg, const char *name, struct chatlog *log, bool e
else
snprintf(name_frmt, sizeof(name_frmt), "%s:", name);
const char *t = user_settings_->time == TIME_12 ? "%Y/%m/%d [%I:%M:%S %p]" : "%Y/%m/%d [%H:%M:%S]";
const char *t = user_settings->time == TIME_12 ? "%Y/%m/%d [%I:%M:%S %p]" : "%Y/%m/%d [%H:%M:%S]";
char s[MAX_STR_SIZE];
strftime(s, MAX_STR_SIZE, t, get_time());
fprintf(log->file, "%s %s %s\n", s, name_frmt, msg);
@ -118,20 +147,119 @@ void write_to_log(const char *msg, const char *name, struct chatlog *log, bool e
}
}
void log_enable(char *name, const char *key, struct chatlog *log)
void log_disable(struct chatlog *log)
{
if (log->file != NULL)
fclose(log->file);
memset(log, 0, sizeof(struct chatlog));
}
void log_enable(char *name, const char *selfkey, const char *otherkey, struct chatlog *log, int logtype)
{
log->log_on = true;
if (log->file == NULL)
init_logging_session(name, key, log);
if (log->file != NULL)
return;
if (init_logging_session(name, selfkey, otherkey, log, logtype) == -1)
log_disable(log);
}
void log_disable(struct chatlog *log)
/* Loads previous history from chat log */
void load_chat_history(ToxWindow *self, struct chatlog *log)
{
log->log_on = false;
if (log->file == NULL)
return;
if (log->file != NULL) {
fclose(log->file);
log->file = NULL;
off_t sz = file_size(log->path);
if (sz <= 0)
return;
char *hstbuf = malloc(sz);
if (hstbuf == NULL)
exit_toxic_err("failed in load_chat_history", FATALERR_MEMORY);
if (fseek(log->file, 0L, SEEK_SET) == -1) {
free(hstbuf);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Failed to read log file");
return;
}
if (fread(hstbuf, sz, 1, log->file) != 1) {
free(hstbuf);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Failed to read log file");
return;
}
/* Number of history lines to load: must not be larger than MAX_LINE_INFO_QUEUE - 2 */
int L = MIN(MAX_LINE_INFO_QUEUE - 2, user_settings->history_size);
int start, count = 0;
/* start at end and backtrace L lines or to the beginning of buffer */
for (start = sz - 1; start >= 0 && count < L; --start) {
if (hstbuf[start] == '\n')
++count;
}
const char *line = strtok(&hstbuf[start + 1], "\n");
if (line == NULL) {
free(hstbuf);
return;
}
while (line != NULL && count--) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", line);
line = strtok(NULL, "\n");
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "");
free(hstbuf);
}
/* renames chatlog file replacing src with dest.
Returns 0 on success or if no log exists, -1 on failure. */
int rename_logfile(char *src, char *dest, const char *selfkey, const char *otherkey, int winnum)
{
ToxWindow *toxwin = get_window_ptr(winnum);
struct chatlog *log = NULL;
bool log_on = false;
/* disable log if necessary and save its state */
if (toxwin != NULL) {
log = toxwin->chatwin->log;
log_on = log->log_on;
}
if (log_on)
log_disable(log);
char newpath[MAX_STR_SIZE];
char oldpath[MAX_STR_SIZE];
if (get_log_path(oldpath, sizeof(oldpath), src, selfkey, otherkey, LOG_CHAT) == -1)
goto on_error;
if (!file_exists(oldpath))
return 0;
if (get_log_path(newpath, sizeof(newpath), dest, selfkey, otherkey, LOG_CHAT) == -1)
goto on_error;
if (rename(oldpath, newpath) != 0)
goto on_error;
if (log_on)
log_enable(dest, selfkey, otherkey, log, LOG_CHAT);
return 0;
on_error:
if (log_on)
log_enable(src, selfkey, otherkey, log, LOG_CHAT);
return -1;
}

View File

@ -20,25 +20,36 @@
*
*/
#ifndef _log_h
#define _log_h
#ifndef LOG_H
#define LOG_H
struct chatlog {
FILE *file;
uint64_t lastwrite;
char path[MAX_STR_SIZE];
bool log_on; /* specific to current chat window */
};
/* Creates/fetches log file by appending to the config dir the name and a pseudo-unique identity */
void init_logging_session(char *name, const char *key, struct chatlog *log);
enum {
LOG_GROUP,
LOG_PROMPT,
LOG_CHAT,
} LOG_TYPE;
/* formats/writes line to log file */
void write_to_log(const char *msg, const char *name, struct chatlog *log, bool event);
/* enables logging for specified log and creates/fetches file if necessary */
void log_enable(char *name, const char *key, struct chatlog *log);
void log_enable(char *name, const char *selfkey, const char *otherkey, struct chatlog *log, int logtype);
/* disables logging for specified log and closes file */
void log_disable(struct chatlog *log);
#endif /* #define _log_h */
/* Loads previous history from chat log */
void load_chat_history(ToxWindow *self, struct chatlog *log);
/* renames chatlog file replacing src with dest.
Returns 0 on success or if no log exists, -1 on failure. */
int rename_logfile(char *src, char *dest, const char *selfkey, const char *otherkey, int winnum);
#endif /* #define LOG_H */

View File

@ -20,6 +20,9 @@
*
*/
#ifndef MESSAGE_QUEUE_H
#define MESSAGE_QUEUE_H
struct cqueue_msg {
char message[MAX_STR_SIZE];
int len;
@ -44,3 +47,5 @@ void cqueue_try_send(ToxWindow *self, Tox *m);
/* removes message with matching receipt from queue, writes to log and updates line to show the message was received. */
void cqueue_remove(ToxWindow *self, Tox *m, uint32_t receipt);
#endif /* #define MESSAGE_QUEUE_H */

View File

@ -35,7 +35,7 @@
#include "file_senders.h"
extern ToxWindow *prompt;
extern struct user_settings *user_settings_;
extern struct user_settings *user_settings;
static uint64_t current_unix_time;
@ -82,12 +82,12 @@ struct tm *get_time(void)
/*Puts the current time in buf in the format of [HH:mm:ss] */
void get_time_str(char *buf, int bufsize)
{
if (user_settings_->timestamps == TIMESTAMPS_OFF) {
if (user_settings->timestamps == TIMESTAMPS_OFF) {
buf[0] = '\0';
return;
}
const char *t = user_settings_->time == TIME_12 ? "[%-I:%M:%S] " : "[%H:%M:%S] ";
const char *t = user_settings->time == TIME_12 ? "%I:%M:%S " : "%H:%M:%S ";
strftime(buf, bufsize, t, get_time());
}
@ -311,3 +311,33 @@ bool file_exists(const char *path)
struct stat s;
return stat(path, &s) == 0;
}
/* returns file size or -1 on error */
off_t file_size(const char *path)
{
struct stat st;
if (stat(path, &st) == -1)
return -1;
return st.st_size;
}
/* compares the first size bytes of fp to signature.
Returns 0 if they are the same, 1 if they differ, and -1 on error.
On success this function will seek back to the beginning of fp */
int check_file_signature(const char *signature, size_t size, FILE *fp)
{
char buf[size];
if (fread(buf, size, 1, fp) != 1)
return -1;
int ret = memcmp(signature, buf, size);
if (fseek(fp, 0L, SEEK_SET) == -1)
return -1;
return ret == 0 ? 0 : 1;
}

View File

@ -19,8 +19,10 @@
* along with Toxic. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _misc_tools_h
#define _misc_tools_h
#ifndef MISC_TOOLS_H
#define MISC_TOOLS_H
#include <sys/stat.h>
#include "windows.h"
#include "toxic.h"
@ -112,4 +114,13 @@ void bytes_convert_str(char *buf, int size, uint64_t bytes);
/* checks if a file exists. Returns true or false */
bool file_exists(const char *path);
#endif /* #define _misc_tools_h */
/* returns file size or -1 on error */
off_t file_size(const char *path);
/* compares the first size bytes of fp and signature.
Returns 0 if they are the same, 1 if they differ, and -1 on error.
On success this function will seek back to the beginning of fp */
int check_file_signature(const char *signature, size_t size, FILE *fp);
#endif /* #define MISC_TOOLS_H */

View File

@ -20,12 +20,6 @@
*
*/
#include "notify.h"
#include "device.h"
#include "settings.h"
#include "line_info.h"
#include "misc_tools.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@ -36,7 +30,13 @@
#include <assert.h>
#include <sys/stat.h>
#if defined(_AUDIO) || defined(_SOUND_NOTIFY)
#include "notify.h"
#include "device.h"
#include "settings.h"
#include "line_info.h"
#include "misc_tools.h"
#if defined(AUDIO) || defined(SOUND_NOTIFY)
#ifdef __APPLE__
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
@ -48,16 +48,16 @@
#include <AL/alext.h>
#endif
#endif
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
#include <AL/alut.h> /* freealut packet */
#endif
#endif /* _AUDIO */
#endif /* AUDIO */
#ifdef _X11
#ifdef X11
#include <X11/Xlib.h>
#endif /* _X11 */
#endif /* X11 */
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
#include <libnotify/notify.h>
#endif
@ -65,36 +65,36 @@
#define SOUNDS_SIZE 10
#define ACTIVE_NOTIFS_MAX 50
extern struct user_settings *user_settings_;
extern struct user_settings *user_settings;
struct _Control {
struct Control {
time_t cooldown;
time_t notif_timeout;
#ifdef _X11
#ifdef X11
Display *display;
unsigned long this_window;
#endif /* _X11 */
#endif /* X11 */
#if defined(_SOUND_NOTIFY) || defined(_BOX_NOTIFY)
#if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY)
pthread_mutex_t poll_mutex[1];
bool poll_active;
#endif
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
uint32_t device_idx; /* index of output device */
char* sounds[SOUNDS_SIZE];
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
} Control = {0};
struct _ActiveNotifications {
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
uint32_t source;
uint32_t buffer;
bool looping;
#endif
bool active;
int *id_indicator;
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
NotifyNotification* box;
char messages[MAX_BOX_MSG_LEN + 1][MAX_BOX_MSG_LEN + 1];
char title[24];
@ -122,7 +122,7 @@ static void tab_notify(ToxWindow *self, uint64_t flags)
self->alert = WINDOW_ALERT_2;
}
#ifdef _X11
#ifdef X11
long unsigned int get_focused_window_id()
{
if (!Control.display) return 0;
@ -132,12 +132,12 @@ long unsigned int get_focused_window_id()
XGetInputFocus(Control.display, &focus, &revert);
return focus;
}
#endif /* _X11 */
#endif /* X11 */
static bool notifications_are_disabled(uint64_t flags)
{
bool res = flags & NT_RESTOL && Control.cooldown > get_unix_time();
#ifdef _X11
#ifdef X11
return res || (flags & NT_NOFOCUS && Control.this_window == get_focused_window_id());
#else
return res;
@ -146,19 +146,19 @@ static bool notifications_are_disabled(uint64_t flags)
static void control_lock()
{
#if defined(_SOUND_NOTIFY) || defined(_BOX_NOTIFY)
#if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY)
pthread_mutex_lock(Control.poll_mutex);
#endif
}
static void control_unlock()
{
#if defined(_SOUND_NOTIFY) || defined(_BOX_NOTIFY)
#if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY)
pthread_mutex_unlock(Control.poll_mutex);
#endif
}
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
bool is_playing(int source)
{
int ready;
@ -166,6 +166,33 @@ bool is_playing(int source)
return ready == AL_PLAYING;
}
/* TODO maybe find better way to do this */
/* cooldown is in seconds */
#define DEVICE_COOLDOWN 5 /* TODO perhaps load this from config? */
static bool device_opened = false;
time_t last_opened_update = 0;
bool m_open_device()
{
last_opened_update = time(NULL);
if (device_opened) return true;
/* Blah error check */
open_primary_device(output, &Control.device_idx, 48000, 20, 1);
return (device_opened = true);
}
bool m_close_device()
{
if (!device_opened) return true;
close_device(output, Control.device_idx);
return !(device_opened = false);
}
/* Terminate all sounds but wait for them to finish first */
void graceful_clear()
{
@ -174,7 +201,7 @@ void graceful_clear()
while (1) {
for (i = 0; i < ACTIVE_NOTIFS_MAX; i ++) {
if (actives[i].active) {
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
if (actives[i].box) {
GError* ignore;
notify_notification_close(actives[i].box, &ignore);
@ -195,6 +222,7 @@ void graceful_clear()
}
if (i == ACTIVE_NOTIFS_MAX) {
m_close_device(); /* In case it's opened */
control_unlock();
return;
}
@ -207,11 +235,19 @@ void* do_playing(void* _p)
{
(void)_p;
int i;
bool has_looping = false;
while(Control.poll_active) {
control_lock();
for (i = 0; i < ACTIVE_NOTIFS_MAX; i ++) {
if (actives[i].looping) has_looping = true;
if (actives[i].active && !actives[i].looping
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
&& !actives[i].box
#endif
) {
@ -223,7 +259,7 @@ void* do_playing(void* _p)
memset(&actives[i], 0, sizeof(struct _ActiveNotifications));
}
}
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
else if (actives[i].box && time(NULL) >= actives[i].n_timeout)
{
GError* ignore;
@ -242,6 +278,14 @@ void* do_playing(void* _p)
}
#endif
}
/* device is opened and no activity in under DEVICE_COOLDOWN time, close device*/
if (device_opened && !has_looping &&
(time(NULL) - last_opened_update) > DEVICE_COOLDOWN) {
m_close_device();
}
has_looping = false;
control_unlock();
usleep(10000);
}
@ -266,7 +310,7 @@ int play_source(uint32_t source, uint32_t buffer, bool looping)
return i;
}
#elif _BOX_NOTIFY
#elif BOX_NOTIFY
void* do_playing(void* _p)
{
(void)_p;
@ -321,15 +365,16 @@ void graceful_clear()
/* Opens primary device */
int init_notify(int login_cooldown, int notification_timeout)
{
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
alutInitWithoutContext(NULL, NULL);
if (open_primary_device(output, &Control.device_idx, 48000, 20, 1) != de_None)
return -1;
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
#if defined(_SOUND_NOTIFY) || defined(_BOX_NOTIFY)
pthread_mutex_init(Control.poll_mutex, NULL);
#if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY)
if (pthread_mutex_init(Control.poll_mutex, NULL) != 0)
return -1;
pthread_t thread;
if (pthread_create(&thread, NULL, do_playing, NULL) != 0 || pthread_detach(thread) != 0 ) {
pthread_mutex_destroy(Control.poll_mutex);
return -1;
@ -338,13 +383,13 @@ int init_notify(int login_cooldown, int notification_timeout)
#endif
Control.cooldown = time(NULL) + login_cooldown;
#ifdef _X11
#ifdef X11
Control.display = XOpenDisplay(NULL);
Control.this_window = get_focused_window_id();
#endif /* _X11 */
#endif /* X11 */
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
notify_init("toxic");
#endif
Control.notif_timeout = notification_timeout;
@ -353,26 +398,25 @@ int init_notify(int login_cooldown, int notification_timeout)
void terminate_notify()
{
#if defined(_SOUND_NOTIFY) || defined(_BOX_NOTIFY)
#if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY)
if ( !Control.poll_active ) return;
Control.poll_active = 0;
graceful_clear();
#endif
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
int i = 0;
for (; i < SOUNDS_SIZE; i ++) free(Control.sounds[i]);
close_device(output, Control.device_idx);
alutExit();
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
notify_uninit();
#endif
}
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
int set_sound(Notification sound, const char* value)
{
if (sound == silent) return 0;
@ -392,6 +436,8 @@ int play_sound_internal(Notification what, bool loop)
uint32_t source;
uint32_t buffer;
m_open_device();
alGenSources(1, &source);
alGenBuffers(1, &buffer);
buffer = alutCreateBufferFromFile(Control.sounds[what]);
@ -428,7 +474,7 @@ int play_notify_sound(Notification notif, uint64_t flags)
void stop_sound(int id)
{
if (id >= 0 && id < ACTIVE_NOTIFS_MAX && actives[id].looping && actives[id].active ) {
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
if (actives[id].box) {
GError* ignore;
notify_notification_close(actives[id].box, &ignore);
@ -446,17 +492,17 @@ void stop_sound(int id)
static int m_play_sound(Notification notif, uint64_t flags)
{
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
return play_notify_sound(notif, flags);
#else
if (notif != silent)
beep();
return -1;
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
void m_notify_action(NotifyNotification *box, char *action, void* data)
{
}
@ -472,13 +518,13 @@ int sound_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_in
int id = -1;
control_lock();
if (self && (!self->stb || self->stb->status != TOX_USERSTATUS_BUSY) && user_settings_->alerts == ALERTS_ENABLED)
if (self && (!self->stb || self->stb->status != TOX_USERSTATUS_BUSY) && user_settings->alerts == ALERTS_ENABLED)
id = m_play_sound(notif, flags);
else if (flags & NT_ALWAYS)
id = m_play_sound(notif, flags);
#if defined(_BOX_NOTIFY) && !defined(_SOUND_NOTIFY)
#if defined(BOX_NOTIFY) && !defined(SOUND_NOTIFY)
if (id == -1) {
for (id = 0; id < ACTIVE_NOTIFS_MAX && actives[id].box; id ++);
@ -508,7 +554,7 @@ int sound_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id)
return -1;
if (id < 0 || id >= ACTIVE_NOTIFS_MAX) return -1;
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
control_lock();
if (!actives[id].active || !Control.sounds[notif]) {
@ -516,6 +562,8 @@ int sound_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id)
return -1;
}
m_open_device();
alSourceStop(actives[id].source);
alDeleteSources(1, &actives[id].source);
alDeleteBuffers(1,&actives[id].buffer);
@ -537,7 +585,7 @@ int sound_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id)
beep();
return 0;
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indicator, char* title, const char* format, ...)
@ -547,13 +595,13 @@ int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indi
return -1;
}
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
int id = sound_notify(self, notif, flags, id_indicator);
control_lock();
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
if (id == -1) { /* Could not play */
for (id = 0; id < ACTIVE_NOTIFS_MAX && actives[id].active; id ++);
@ -601,7 +649,7 @@ int box_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id, con
return -1;
}
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
if (sound_notify2(self, notif, flags, id) == -1)
return -1;
@ -651,7 +699,7 @@ int box_silent_notify(ToxWindow* self, uint64_t flags, int* id_indicator, const
if (notifications_are_disabled(flags))
return -1;
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
control_lock();
@ -701,7 +749,7 @@ int box_silent_notify2(ToxWindow* self, uint64_t flags, int id, const char* form
if (notifications_are_disabled(flags))
return -1;
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
control_lock();
if (id < 0 || id >= ACTIVE_NOTIFS_MAX || !actives[id].box || actives[id].size >= MAX_BOX_MSG_LEN + 1 ) {

View File

@ -20,8 +20,8 @@
*
*/
#ifndef _notify_h
#define _notify_h
#ifndef NOTIFY_H
#define NOTIFY_H
#include <inttypes.h>
#include "windows.h"
@ -73,8 +73,8 @@ int box_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id, con
int box_silent_notify(ToxWindow* self, uint64_t flags, int* id_indicator, const char* title, const char* format, ...);
int box_silent_notify2(ToxWindow* self, uint64_t flags, int id, const char* format, ...);
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
int set_sound(Notification sound, const char* value);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
#endif /* _notify_h */
#endif /* NOTIFY_H */

View File

@ -43,15 +43,16 @@
#include "autocomplete.h"
extern ToxWindow *prompt;
extern struct user_settings *user_settings_;
extern struct _Winthread Winthread;
extern struct user_settings *user_settings;
extern struct Winthread Winthread;
_FriendRequests FriendRequests;
FriendRequests FrndRequests;
/* Array of global command names used for tab completion. */
const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = {
{ "/accept" },
{ "/add" },
{ "/avatar" },
{ "/clear" },
{ "/close" }, /* rm /close when groupchats gets its own list */
{ "/connect" },
@ -67,12 +68,12 @@ const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = {
{ "/requests" },
{ "/status" },
#ifdef _AUDIO
#ifdef AUDIO
{ "/lsdev" },
{ "/sdev" },
#endif /* _AUDIO */
#endif /* AUDIO */
};
void kill_prompt_window(ToxWindow *self)
@ -131,21 +132,21 @@ void prompt_update_connectionstatus(ToxWindow *prompt, bool is_connected)
Returns request number on success, -1 if queue is full. */
static int add_friend_request(const char *public_key, const char *data)
{
if (FriendRequests.max_idx >= MAX_FRIEND_REQUESTS)
if (FrndRequests.max_idx >= MAX_FRIEND_REQUESTS)
return -1;
int i;
for (i = 0; i <= FriendRequests.max_idx; ++i) {
if (!FriendRequests.request[i].active) {
FriendRequests.request[i].active = true;
memcpy(FriendRequests.request[i].key, public_key, TOX_CLIENT_ID_SIZE);
snprintf(FriendRequests.request[i].msg, sizeof(FriendRequests.request[i].msg), "%s", data);
for (i = 0; i <= FrndRequests.max_idx; ++i) {
if (!FrndRequests.request[i].active) {
FrndRequests.request[i].active = true;
memcpy(FrndRequests.request[i].key, public_key, TOX_CLIENT_ID_SIZE);
snprintf(FrndRequests.request[i].msg, sizeof(FrndRequests.request[i].msg), "%s", data);
if (i == FriendRequests.max_idx)
++FriendRequests.max_idx;
if (i == FrndRequests.max_idx)
++FrndRequests.max_idx;
++FriendRequests.num_requests;
++FrndRequests.num_requests;
return i;
}
@ -183,7 +184,12 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
if (key == '\t') { /* TAB key: auto-completes command */
if (ctx->len > 1 && ctx->line[0] == '/') {
int diff = complete_line(self, glob_cmd_list, AC_NUM_GLOB_COMMANDS, MAX_CMDNAME_SIZE);
int diff = -1;
if (wcsncmp(ctx->line, L"/avatar \"", wcslen(L"/avatar \"")) == 0)
diff = dir_match(self, m, ctx->line, L"/avatar");
else
diff = complete_line(self, glob_cmd_list, AC_NUM_GLOB_COMMANDS, MAX_CMDNAME_SIZE);
if (diff != -1) {
if (x + diff > x2 - 1) {
@ -271,7 +277,7 @@ static void prompt_onDraw(ToxWindow *self, Tox *m)
} else {
wprintw(statusbar->topline, " [Offline]");
wattron(statusbar->topline, A_BOLD);
wprintw(statusbar->topline, " %s ", statusbar->nick);
wprintw(statusbar->topline, " %s", statusbar->nick);
wattroff(statusbar->topline, A_BOLD);
}
@ -299,7 +305,7 @@ static void prompt_onDraw(ToxWindow *self, Tox *m)
}
if (statusbar->statusmsg[0])
wprintw(statusbar->topline, " - %s", statusbar->statusmsg);
wprintw(statusbar->topline, " : %s", statusbar->statusmsg);
mvwhline(self->window, y2 - CHATBOX_HEIGHT, 0, ACS_HLINE, x2);
@ -455,16 +461,16 @@ static void prompt_onInit(ToxWindow *self, Tox *m)
line_info_init(ctx->hst);
if (user_settings_->autolog == AUTOLOG_ON) {
if (user_settings->autolog == AUTOLOG_ON) {
char myid[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(m, (uint8_t *) myid);
log_enable(self->name, myid, ctx->log);
log_enable(self->name, myid, NULL, ctx->log, LOG_PROMPT);
}
scrollok(ctx->history, 0);
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
if (user_settings_->show_welcome_msg == SHOW_WELCOME_MSG_ON)
if (user_settings->show_welcome_msg == SHOW_WELCOME_MSG_ON)
print_welcome_msg(self);
}

View File

@ -20,21 +20,21 @@
*
*/
#ifndef PROMPT_H_UZYGWFFL
#define PROMPT_H_UZYGWFFL
#ifndef PROMPT_H
#define PROMPT_H
#include "toxic.h"
#include "windows.h"
#ifdef _AUDIO
#define AC_NUM_GLOB_COMMANDS 18
#ifdef AUDIO
#define AC_NUM_GLOB_COMMANDS 19
#else
#define AC_NUM_GLOB_COMMANDS 16
#endif /* _AUDIO */
#define AC_NUM_GLOB_COMMANDS 17
#endif /* AUDIO */
#define MAX_FRIEND_REQUESTS 32
struct _friend_request {
struct friend_request {
bool active;
char msg[MAX_STR_SIZE];
uint8_t key[TOX_CLIENT_ID_SIZE];
@ -43,8 +43,8 @@ struct _friend_request {
typedef struct {
int max_idx;
int num_requests;
struct _friend_request request[MAX_FRIEND_REQUESTS];
} _FriendRequests;
struct friend_request request[MAX_FRIEND_REQUESTS];
} FriendRequests;
ToxWindow new_prompt(void);
void prep_prompt_win(void);
@ -55,4 +55,4 @@ void prompt_update_status(ToxWindow *prompt, uint8_t status);
void prompt_update_connectionstatus(ToxWindow *prompt, bool is_connected);
void kill_prompt_window(ToxWindow *self);
#endif /* end of include guard: PROMPT_H_UZYGWFFL */
#endif /* end of include guard: PROMPT_H */

View File

@ -31,9 +31,9 @@
#include "notify.h"
#include "misc_tools.h"
#ifdef _AUDIO
#ifdef AUDIO
#include "device.h"
#endif /* _AUDIO */
#endif /* AUDIO */
#include "settings.h"
#include "line_info.h"
@ -44,7 +44,7 @@
#define NO_SOUND "silent"
static struct _ui_strings {
static struct ui_strings {
const char* self;
const char* timestamps;
const char* alerts;
@ -81,7 +81,7 @@ static void ui_defaults(struct user_settings* settings)
settings->show_welcome_msg = SHOW_WELCOME_MSG_ON;
}
static const struct _keys_strings {
static const struct keys_strings {
const char* self;
const char* next_tab;
const char* prev_tab;
@ -119,24 +119,27 @@ static void key_defaults(struct user_settings* settings)
settings->key_peer_list_down = T_KEY_C_RB;
}
static const struct _tox_strings {
static const struct tox_strings {
const char* self;
const char* download_path;
const char* chatlogs_path;
const char* avatar_path;
} tox_strings = {
"tox",
"download_path",
"chatlogs_path",
"avatar_path",
};
static void tox_defaults(struct user_settings* settings)
{
strcpy(settings->download_path, "");
strcpy(settings->chatlogs_path, "");
strcpy(settings->avatar_path, "");
}
#ifdef _AUDIO
static const struct _audio_strings {
#ifdef AUDIO
static const struct audio_strings {
const char* self;
const char* input_device;
const char* output_device;
@ -156,8 +159,8 @@ static void audio_defaults(struct user_settings* settings)
}
#endif
#ifdef _SOUND_NOTIFY
static const struct _sound_strings {
#ifdef SOUND_NOTIFY
static const struct sound_strings {
const char* self;
const char* error;
const char* self_log_in;
@ -212,7 +215,7 @@ int settings_load(struct user_settings *s, const char *patharg)
tox_defaults(s);
key_defaults(s);
#ifdef _AUDIO
#ifdef AUDIO
audio_defaults(s);
#endif
@ -280,6 +283,14 @@ int settings_load(struct user_settings *s, const char *patharg)
else if (s->chatlogs_path[len - 1] != '/')
strcat(&s->chatlogs_path[len - 1], "/");
}
if ( config_setting_lookup_string(setting, tox_strings.avatar_path, &str) ) {
snprintf(s->avatar_path, sizeof(s->avatar_path), "%s", str);
int len = strlen(s->avatar_path);
if (len >= sizeof(s->avatar_path))
s->avatar_path[0] = '\0';
}
}
/* keys */
@ -296,7 +307,7 @@ int settings_load(struct user_settings *s, const char *patharg)
if (config_setting_lookup_string(setting, key_strings.peer_list_down, &tmp)) s->key_peer_list_down = key_parse(&tmp);
}
#ifdef _AUDIO
#ifdef AUDIO
if ((setting = config_lookup(cfg, audio_strings.self)) != NULL) {
config_setting_lookup_int(setting, audio_strings.input_device, &s->audio_in_dev);
s->audio_in_dev = s->audio_in_dev < 0 || s->audio_in_dev > MAX_DEVICES ? 0 : s->audio_in_dev;
@ -308,7 +319,7 @@ int settings_load(struct user_settings *s, const char *patharg)
}
#endif
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
if ((setting = config_lookup(cfg, sound_strings.self)) != NULL) {
if ( (config_setting_lookup_string(setting, sound_strings.error, &str) != CONFIG_TRUE) ||
!set_sound(error, str) ) {

View File

@ -20,8 +20,8 @@
*
*/
#ifndef _settings_h
#define _settings_h
#ifndef SETTINGS_H
#define SETTINGS_H
#include <limits.h>
@ -39,9 +39,10 @@ struct user_settings {
char download_path[PATH_MAX];
char chatlogs_path[PATH_MAX];
char avatar_path[PATH_MAX];
int key_next_tab; /* character code */
int key_prev_tab; /* character code */
int key_next_tab;
int key_prev_tab;
int key_scroll_line_up;
int key_scroll_line_down;
int key_half_page_up;
@ -49,7 +50,8 @@ struct user_settings {
int key_page_bottom;
int key_peer_list_up;
int key_peer_list_down;
#ifdef _AUDIO
#ifdef AUDIO
int audio_in_dev;
int audio_out_dev;
double VAD_treshold;
@ -82,4 +84,4 @@ enum {
} settings_values;
int settings_load(struct user_settings *s, const char *patharg);
#endif /* #define _settings_h */
#endif /* #define SETTINGS_H */

View File

@ -56,18 +56,19 @@
#include "notify.h"
#include "device.h"
#include "message_queue.h"
#include "execute.h"
#ifdef _AUDIO
#ifdef AUDIO
#include "audio_call.h"
#endif /* _AUDIO */
#endif /* AUDIO */
#ifndef PACKAGE_DATADIR
#define PACKAGE_DATADIR "."
#endif
#ifdef _AUDIO
#ifdef AUDIO
ToxAv *av;
#endif /* _AUDIO */
#endif /* AUDIO */
/* Export for use in Callbacks */
char *DATA_FILE = NULL;
@ -76,15 +77,15 @@ ToxWindow *prompt = NULL;
#define AUTOSAVE_FREQ 60
struct _Winthread Winthread;
struct _cqueue_thread cqueue_thread;
struct Winthread Winthread;
struct cqueue_thread cqueue_thread;
struct arg_opts arg_opts;
struct user_settings *user_settings_ = NULL;
struct user_settings *user_settings = NULL;
#define MIN_PASSWORD_LEN 6
#define MAX_PASSWORD_LEN 64
static struct _user_password {
static struct user_password {
bool data_is_encrypted;
char pass[MAX_PASSWORD_LEN + 1];
int len;
@ -92,7 +93,7 @@ static struct _user_password {
static void catch_SIGINT(int sig)
{
Winthread.sig_exit_toxic = true;
Winthread.sig_exit_toxic = 1;
}
static void catch_SIGSEGV(int sig)
@ -105,7 +106,7 @@ static void catch_SIGSEGV(int sig)
static void flag_window_resize(int sig)
{
Winthread.flag_resize = true;
Winthread.flag_resize = 1;
}
static void init_signal_catchers(void)
@ -118,21 +119,21 @@ static void init_signal_catchers(void)
void exit_toxic_success(Tox *m)
{
store_data(m, DATA_FILE);
memset(&user_password, 0, sizeof(struct _user_password));
memset(&user_password, 0, sizeof(struct user_password));
close_all_file_senders(m);
kill_all_windows(m);
free(DATA_FILE);
free(BLOCK_FILE);
free(user_settings_);
free(user_settings);
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
// sound_notify(NULL, self_log_out, NT_ALWAYS, NULL);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
terminate_notify();
#ifdef _AUDIO
#ifdef AUDIO
terminate_audio();
#endif /* _AUDIO */
#endif /* AUDIO */
tox_kill(m);
endwin();
exit(EXIT_SUCCESS);
@ -171,7 +172,7 @@ static void init_term(void)
short bg_color = COLOR_BLACK;
start_color();
if (user_settings_->colour_theme == NATIVE_COLS) {
if (user_settings->colour_theme == NATIVE_COLS) {
if (assume_default_colors(-1, -1) == OK)
bg_color = -1;
}
@ -222,7 +223,7 @@ static void queue_init_message(const char *msg, ...)
init_messages.msgs = new_msgs;
}
/* called after messages have been printed to console and are no longer needed */
/* called after messages have been printed to prompt and are no longer needed */
static void cleanup_init_messages(void)
{
if (init_messages.num <= 0)
@ -324,7 +325,7 @@ static Tox *init_tox(void)
#define MAXNODES 50
#define NODELEN (MAX_NODE_LINE - TOX_CLIENT_ID_SIZE - 7)
static struct _toxNodes {
static struct toxNodes {
int lines;
char nodes[MAXNODES][NODELEN];
uint16_t ports[MAXNODES];
@ -629,9 +630,12 @@ static void load_data(Tox *m, char *path)
FILE *fd;
if ((fd = fopen(path, "rb")) != NULL) {
fseek(fd, 0, SEEK_END);
int len = ftell(fd);
fseek(fd, 0, SEEK_SET);
off_t len = file_size(path);
if (len == -1) {
fclose(fd);
exit_toxic_err("failed in load_data", FATALERR_FILEOP);
}
char *buf = malloc(len);
@ -643,7 +647,7 @@ static void load_data(Tox *m, char *path)
if (fread(buf, len, 1, fd) != 1) {
free(buf);
fclose(fd);
exit_toxic_err("failed in load_data", FATALERR_FREAD);
exit_toxic_err("failed in load_data", FATALERR_FILEOP);
}
bool is_encrypted = tox_is_data_encrypted((uint8_t *) buf);
@ -720,6 +724,7 @@ void *thread_winref(void *data)
{
Tox *m = (Tox *) data;
uint8_t draw_count = 0;
init_signal_catchers();
while (true) {
draw_active_window(m);
@ -727,7 +732,7 @@ void *thread_winref(void *data)
if (Winthread.flag_resize) {
on_window_resize();
Winthread.flag_resize = false;
Winthread.flag_resize = 0;
} else if (draw_count >= INACTIVE_WIN_REFRESH_RATE) {
refresh_inactive_windows();
draw_count = 0;
@ -963,7 +968,6 @@ static useconds_t optimal_msleepval(uint64_t *looptimer, uint64_t *loopcount, ui
int main(int argc, char *argv[])
{
init_signal_catchers();
parse_args(argc, argv);
if (arg_opts.encrypt_data && arg_opts.unencrypt_data) {
@ -990,18 +994,18 @@ int main(int argc, char *argv[])
}
/* init user_settings struct and load settings from conf file */
user_settings_ = calloc(1, sizeof(struct user_settings));
user_settings = calloc(1, sizeof(struct user_settings));
if (user_settings_ == NULL)
if (user_settings == NULL)
exit_toxic_err("failed in main", FATALERR_MEMORY);
const char *p = arg_opts.config_path[0] ? arg_opts.config_path : NULL;
int settings_err = settings_load(user_settings_, p);
int settings_err = settings_load(user_settings, p);
Tox *m = init_tox();
if (m == NULL)
exit_toxic_err("failed in main", FATALERR_NETWORKINIT);
exit_toxic_err("failed in main", FATALERR_NETWORKINIT);
if (!arg_opts.ignore_data_file) {
if (arg_opts.encrypt_data && !datafile_exists)
@ -1026,24 +1030,24 @@ int main(int argc, char *argv[])
if (pthread_create(&cqueue_thread.tid, NULL, thread_cqueue, (void *) m) != 0)
exit_toxic_err("failed in main", FATALERR_THREAD_CREATE);
#ifdef _AUDIO
#ifdef AUDIO
av = init_audio(prompt, m);
set_primary_device(input, user_settings_->audio_in_dev);
set_primary_device(output, user_settings_->audio_out_dev);
set_primary_device(input, user_settings->audio_in_dev);
set_primary_device(output, user_settings->audio_out_dev);
#elif _SOUND_NOTIFY
#elif SOUND_NOTIFY
if ( init_devices() == de_InternalError )
queue_init_message("Failed to init audio devices");
#endif /* _AUDIO */
#endif /* AUDIO */
init_notify(60, 3000);
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
// sound_notify(prompt, self_log_in, 0, NULL);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
const char *msg;
@ -1058,6 +1062,11 @@ int main(int argc, char *argv[])
print_init_messages(prompt);
cleanup_init_messages();
/* set user avatar from config file. if no path is supplied tox_unset_avatar is called */
char avatarstr[MAX_STR_SIZE];
snprintf(avatarstr, sizeof(avatarstr), "/avatar \"%s\"", user_settings->avatar_path);
execute(prompt->chatwin->history, prompt, m, avatarstr, GLOBAL_COMMAND_MODE);
uint64_t last_save = (uint64_t) time(NULL);
uint64_t looptimer = last_save;
useconds_t msleepval = 40000;

View File

@ -20,8 +20,8 @@
*
*/
#ifndef _toxic_h
#define _toxic_h
#ifndef TOXIC_H
#define TOXIC_H
#ifndef TOXICVER
#define TOXICVER "NOVER_" /* Use the -D flag to set this */
@ -45,7 +45,7 @@
#define MAX_STR_SIZE TOX_MAX_MESSAGE_LENGTH
#define MAX_CMDNAME_SIZE 64
#define TOXIC_MAX_NAME_LENGTH 32 /* Must be <= TOX_MAX_NAME_LENGTH */
#define KEY_IDENT_DIGITS 2 /* number of hex digits to display for the pub-key based identifier */
#define KEY_IDENT_DIGITS 3 /* number of hex digits to display for the pub-key based identifier */
#define TIME_STR_SIZE 16
/* ASCII key codes */
@ -69,9 +69,9 @@
typedef enum _FATAL_ERRS {
FATALERR_MEMORY = -1, /* heap memory allocation failed */
FATALERR_FREAD = -2, /* fread() failed on critical read */
FATALERR_THREAD_CREATE = -3, /* thread creation failed */
FATALERR_MUTEX_INIT = -4, /* mutex init failed */
FATALERR_FILEOP = -2, /* critical file operation failed */
FATALERR_THREAD_CREATE = -3, /* thread creation failed for critical thread */
FATALERR_MUTEX_INIT = -4, /* mutex init for critical thread failed */
FATALERR_THREAD_ATTR = -5, /* thread attr object init failed */
FATALERR_LOCALE_SET = -6, /* system locale not set */
FATALERR_STORE_DATA = -7, /* store_data failed in critical section */
@ -101,7 +101,7 @@ void on_statusmessagechange(Tox *m, int32_t friendnumber, const uint8_t *string,
void on_friendadded(Tox *m, int32_t friendnumber, bool sort);
void on_groupmessage(Tox *m, int groupnumber, int peernumber, const uint8_t *message, uint16_t length, void *userdata);
void on_groupaction(Tox *m, int groupnumber, int peernumber, const uint8_t *action, uint16_t length, void *userdata);
void on_groupinvite(Tox *m, int32_t friendnumber, const uint8_t *group_pub_key, void *userdata);
void on_groupinvite(Tox *m, int32_t friendnumber, const uint8_t *group_pub_key, uint16_t length, void *userdata);
void on_group_namelistchange(Tox *m, int groupnumber, int peernumber, uint8_t change, void *userdata);
void on_file_sendrequest(Tox *m, int32_t friendnumber, uint8_t filenumber, uint64_t filesize, const uint8_t *pathname,
uint16_t pathname_length, void *userdata);
@ -111,4 +111,4 @@ void on_file_data(Tox *m, int32_t friendnumber, uint8_t filenumber, const uint8_
void on_typing_change(Tox *m, int32_t friendnumber, uint8_t is_typing, void *userdata);
void on_read_receipt(Tox *m, int32_t, uint32_t, void *userdata);
#endif /* #define _toxic_h */
#endif /* #define TOXIC_H */

View File

@ -20,8 +20,8 @@
*
*/
#ifndef _toxic_strings_h
#define _toxic_strings_h
#ifndef TOXIC_STRINGS_H
#define TOXIC_STRINGS_H
#include "windows.h"
@ -61,4 +61,4 @@ void add_line_to_hist(ChatContext *ctx);
resets line if at end of history */
void fetch_hist_item(ChatContext *ctx, int key_dir);
#endif /* #define _toxic_strings_h */
#endif /* #define TOXIC_STRINGS_H */

View File

@ -35,12 +35,12 @@
#include "settings.h"
extern char *DATA_FILE;
extern struct _Winthread Winthread;
extern struct Winthread Winthread;
static ToxWindow windows[MAX_WINDOWS_NUM];
static ToxWindow *active_window;
extern ToxWindow *prompt;
extern struct user_settings *user_settings_;
extern struct user_settings *user_settings;
static int num_active_windows;
@ -67,7 +67,7 @@ void on_connectionchange(Tox *m, int32_t friendnumber, uint8_t status, void *use
void on_typing_change(Tox *m, int32_t friendnumber, uint8_t is_typing, void *userdata)
{
if (user_settings_->show_typing_other == SHOW_TYPING_OFF)
if (user_settings->show_typing_other == SHOW_TYPING_OFF)
return;
int i;
@ -164,13 +164,13 @@ void on_groupaction(Tox *m, int groupnumber, int peernumber, const uint8_t *acti
}
}
void on_groupinvite(Tox *m, int32_t friendnumber, const uint8_t *group_pub_key, void *userdata)
void on_groupinvite(Tox *m, int32_t friendnumber, const uint8_t *group_pub_key, uint16_t length, void *userdata)
{
int i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onGroupInvite != NULL)
windows[i].onGroupInvite(&windows[i], m, friendnumber, (const char *) group_pub_key);
windows[i].onGroupInvite(&windows[i], m, friendnumber, (const char *) group_pub_key, length);
}
}
@ -278,7 +278,7 @@ void set_next_window(int ch)
ToxWindow *inf = active_window;
while (true) {
if (ch == user_settings_->key_next_tab) {
if (ch == user_settings->key_next_tab) {
if (++active_window > end)
active_window = windows;
} else if (--active_window < windows)
@ -366,12 +366,12 @@ void on_window_resize(void)
w->stb->topline = subwin(w->window, 2, x2, 0, 0);
}
#ifdef _AUDIO
#ifdef AUDIO
if (w->chatwin->infobox.active) {
delwin(w->chatwin->infobox.win);
w->chatwin->infobox.win = newwin(INFOBOX_HEIGHT, INFOBOX_WIDTH + 1, 1, x2 - INFOBOX_WIDTH);
}
#endif /* _AUDIO */
#endif /* AUDIO */
scrollok(w->chatwin->history, 0);
}
@ -462,7 +462,7 @@ void draw_active_window(Tox *m)
ltr = isprint(ch);
#endif /* HAVE_WIDECHAR */
if (!ltr && (ch == user_settings_->key_next_tab || ch == user_settings_->key_prev_tab)) {
if (!ltr && (ch == user_settings->key_next_tab || ch == user_settings->key_prev_tab)) {
set_next_window((int) ch);
} else {
pthread_mutex_lock(&Winthread.lock);

View File

@ -20,18 +20,19 @@
*
*/
#ifndef _windows_h
#define _windows_h
#ifndef WINDOWS_H
#define WINDOWS_H
#include <pthread.h>
#include <wctype.h>
#include <wchar.h>
#include <signal.h>
#include <tox/tox.h>
#ifdef _AUDIO
#ifdef AUDIO
#include <tox/toxav.h>
#endif /* _AUDIO */
#endif /* AUDIO */
#include "toxic.h"
@ -64,14 +65,14 @@ typedef enum {
Uncomment if necessary */
/* #define URXVT_FIX */
struct _Winthread {
struct Winthread {
pthread_t tid;
pthread_mutex_t lock;
bool sig_exit_toxic;
bool flag_resize;
volatile sig_atomic_t sig_exit_toxic;
volatile sig_atomic_t flag_resize;
};
struct _cqueue_thread {
struct cqueue_thread {
pthread_t tid;
};
@ -114,7 +115,7 @@ struct ToxWindow {
void(*onAction)(ToxWindow *, Tox *, int32_t, const char *, uint16_t);
void(*onGroupMessage)(ToxWindow *, Tox *, int, int, const char *, uint16_t);
void(*onGroupAction)(ToxWindow *, Tox *, int, int, const char *, uint16_t);
void(*onGroupInvite)(ToxWindow *, Tox *, int32_t, const char *);
void(*onGroupInvite)(ToxWindow *, Tox *, int32_t, const char *, uint16_t);
void(*onGroupNamelistChange)(ToxWindow *, Tox *, int, int, uint8_t);
void(*onFileSendRequest)(ToxWindow *, Tox *, int32_t, uint8_t, uint64_t, const char *, uint16_t);
void(*onFileControl)(ToxWindow *, Tox *, int32_t, uint8_t, uint8_t, uint8_t, const char *, uint16_t);
@ -122,7 +123,7 @@ struct ToxWindow {
void(*onTypingChange)(ToxWindow *, Tox *, int32_t, uint8_t);
void(*onReadReceipt)(ToxWindow *, Tox *, int32_t, uint32_t);
#ifdef _AUDIO
#ifdef AUDIO
void(*onInvite)(ToxWindow *, ToxAv *, int);
void(*onRinging)(ToxWindow *, ToxAv *, int);
@ -141,7 +142,7 @@ struct ToxWindow {
int device_selection[2]; /* -1 if not set, if set uses these selections instead of primary device */
int ringing_sound;
#endif /* _AUDIO */
#endif /* AUDIO */
int active_box; /* For box notify */
@ -175,7 +176,7 @@ struct StatusBar {
bool is_online;
};
#ifdef _AUDIO
#ifdef AUDIO
#define INFOBOX_HEIGHT 7
@ -194,7 +195,7 @@ struct infobox {
WINDOW *win;
};
#endif /* _AUDIO */
#endif /* AUDIO */
#define MAX_LINE_HIST 128
@ -216,7 +217,7 @@ struct ChatContext {
struct chatlog *log;
struct chat_queue *cqueue;
#ifdef _AUDIO
#ifdef AUDIO
struct infobox infobox;
#endif
@ -247,4 +248,4 @@ ToxWindow *get_window_ptr(int i);
call at least once per second */
void refresh_inactive_windows(void);
#endif /* #define _windows_h */
#endif /* #define WINDOWS_H */