1
0
mirror of https://github.com/Tha14/toxic.git synced 2024-06-29 14:17:46 +02:00

Merge remote-tracking branch 'origin/master' into keybinds

This commit is contained in:
matt 2014-07-28 14:06:54 +01:00
commit a0cde4ae8c
27 changed files with 303 additions and 132 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -78,7 +78,7 @@ struct _ASettings {
ToxAv *av;
ToxAvCodecSettings cs;
ToxAvCSettings cs;
Call calls[MAX_CALLS];
} ASettins;
@ -173,8 +173,11 @@ void read_device_callback (const int16_t* captured, uint32_t size, void* data)
void write_device_callback(ToxAv* av, int32_t call_index, int16_t* data, int size)
{
if (ASettins.calls[call_index].ttas)
write_out(ASettins.calls[call_index].out_idx, data, size, 1);
if (call_index >= 0 && ASettins.calls[call_index].ttas) {
ToxAvCSettings csettings = ASettins.cs;
toxav_get_peer_csettings(av, call_index, 0, &csettings);
write_out(ASettins.calls[call_index].out_idx, data, size, csettings.audio_channels);
}
}
int start_transmission(ToxWindow *self)
@ -182,7 +185,7 @@ int start_transmission(ToxWindow *self)
if ( !ASettins.av || self->call_idx == -1 ) return -1;
/* Don't provide support for video */
if ( 0 != toxav_prepare_transmission(ASettins.av, self->call_idx, &ASettins.cs, 0) ) {
if ( 0 != toxav_prepare_transmission(ASettins.av, self->call_idx, av_jbufdc * 2, av_VADd, 0) ) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Could not prepare transmission");
}
@ -192,8 +195,11 @@ int start_transmission(ToxWindow *self)
set_call(&ASettins.calls[self->call_idx], _True);
if ( open_primary_device(input, &ASettins.calls[self->call_idx].in_idx,
av_DefaultSettings.audio_sample_rate, av_DefaultSettings.audio_frame_duration) != de_None )
ToxAvCSettings csettings;
toxav_get_peer_csettings(ASettins.av, self->call_idx, 0, &csettings);
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,
@ -202,7 +208,7 @@ int start_transmission(ToxWindow *self)
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to register input handler!");
if ( open_primary_device(output, &ASettins.calls[self->call_idx].out_idx,
av_DefaultSettings.audio_sample_rate, av_DefaultSettings.audio_frame_duration) != de_None ) {
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 output device!");
ASettins.calls[self->call_idx].has_output = 0;
}
@ -345,7 +351,7 @@ void cmd_call(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
goto on_error;
}
ToxAvError error = toxav_call(ASettins.av, &self->call_idx, self->num, TypeAudio, 30);
ToxAvError error = toxav_call(ASettins.av, &self->call_idx, self->num, &ASettins.cs, 30);
if ( error != ErrorNone ) {
if ( error == ErrorAlreadyInCall ) error_str = "Already in a call!";
@ -376,7 +382,7 @@ void cmd_answer(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
goto on_error;
}
ToxAvError error = toxav_answer(ASettins.av, self->call_idx, TypeAudio);
ToxAvError error = toxav_answer(ASettins.av, self->call_idx, &ASettins.cs);
if ( error != ErrorNone ) {
if ( error == ErrorInvalidState ) error_str = "Cannot answer in invalid state!";
@ -615,19 +621,23 @@ void cmd_ccur_device(WINDOW * window, ToxWindow * self, Tox *m, int argc, char (
if ( self->call_idx > -1) {
Call* this_call = &ASettins.calls[self->call_idx];
if (this_call->ttas) {
ToxAvCSettings csettings;
toxav_get_peer_csettings(ASettins.av, self->call_idx, 0, &csettings);
if (type == output) {
pthread_mutex_lock(&this_call->mutex);
close_device(output, this_call->out_idx);
this_call->has_output = open_device(output, selection, &this_call->out_idx,
av_DefaultSettings.audio_sample_rate, av_DefaultSettings.audio_frame_duration)
csettings.audio_sample_rate, csettings.audio_frame_duration, csettings.audio_channels)
== de_None ? 1 : 0;
pthread_mutex_unlock(&this_call->mutex);
}
else {
/* TODO: check for failure */
close_device(input, this_call->in_idx);
open_device(input, selection, &this_call->in_idx,
av_DefaultSettings.audio_sample_rate, av_DefaultSettings.audio_frame_duration);
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);
}

View File

@ -202,7 +202,7 @@ int complete_line(ToxWindow *self, const void *list, int n_items, int size)
}
/* transforms a sendfile tab complete contaning the shorthand "~/" into the full home directory.*/
static void complt_home_dir(ToxWindow *self, char *path)
static void complt_home_dir(ToxWindow *self, char *path, int pathsize)
{
ChatContext *ctx = self->chatwin;
@ -210,8 +210,8 @@ static void complt_home_dir(ToxWindow *self, char *path)
get_home_dir(homedir, sizeof(homedir));
char newline[MAX_STR_SIZE];
const char *isqt = !strchr(path, '\"') ? "\"" : "";
snprintf(newline, sizeof(newline), "/sendfile %s%s/", isqt, homedir);
snprintf(newline, sizeof(newline), "/sendfile \"%s%s", homedir, path + 1);
snprintf(path, pathsize, "%s", &newline[11]);
wchar_t wline[MAX_STR_SIZE];
@ -231,22 +231,20 @@ static void complt_home_dir(ToxWindow *self, char *path)
/* attempts to match /sendfile "<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
*/
#define MAX_DIRS 256
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, wchar_t *line)
int dir_match(ToxWindow *self, Tox *m, const wchar_t *line)
{
char b_path[MAX_STR_SIZE];
char b_name[MAX_STR_SIZE];
const wchar_t *tmpline = &line[11]; /* start after "/sendfile \"" */
if (wcs_to_mbs_buf(b_path, line, sizeof(b_path)) == -1)
if (wcs_to_mbs_buf(b_path, tmpline, sizeof(b_path)) == -1)
return -1;
if (!strncmp(b_path, "\"~/", 3) || !strncmp(b_path, "~/", 2)) {
complt_home_dir(self, b_path);
return -1;
}
if (!strncmp(b_path, "~/", 2))
complt_home_dir(self, b_path, sizeof(b_path));
int si = char_rfind(b_path, '/', strlen(b_path));

View File

@ -33,11 +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);
/* matches /sendfile "<incomplete-dir>" line to matching directories.
/* attempts to match /sendfile "<incomplete-dir>" line to matching directories.
if only one match, auto-complete line.
return diff between old len and new len of ctx->line, or -1 if no matches
*/
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);
#endif /* #define _autocomplete_h */

View File

@ -423,7 +423,7 @@ static void chat_onFileData(ToxWindow *self, Tox *m, int32_t num, uint8_t filenu
if (!remain || timed_out(friends[num].file_receiver.last_progress[filenum], curtime, 1)) {
friends[num].file_receiver.last_progress[filenum] = curtime;
uint64_t size = friends[num].file_receiver.size[filenum];
double pct_remain = remain ? (1 - (remain / size)) * 100 : 100;
double pct_remain = remain > 0 ? (1 - (remain / size)) * 100 : 100;
print_progress_bar(self, filenum, num, pct_remain);
friends[num].file_receiver.bps[filenum] = 0;
}
@ -756,10 +756,9 @@ 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;
int sf_len = 11;
if (wcsncmp(ctx->line, L"/sendfile \"", sf_len) == 0) {
diff = dir_match(self, m, &ctx->line[sf_len]);
if (wcsncmp(ctx->line, L"/sendfile \"", wcslen(L"/sendfile \"")) == 0) {
diff = dir_match(self, m, ctx->line);
} else {
diff = complete_line(self, chat_cmd_list, AC_NUM_CHAT_COMMANDS, MAX_CMDNAME_SIZE);
}
@ -770,7 +769,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
ctx->start = wlen < x2 ? 0 : wlen - x2 + 1;
}
} else {
beep();
notify(self, error, 0);
}
} else if (key == '\n') {

View File

@ -37,6 +37,7 @@ extern ToxicFriend friends[MAX_FRIENDS_NUM];
extern FileSender file_senders[MAX_FILES];
extern uint8_t max_file_senders_index;
extern uint8_t num_active_file_senders;
void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{
@ -209,6 +210,7 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
for (i = 0; i < MAX_FILES; ++i) {
if (!file_senders[i].active) {
file_senders[i].queue_pos = num_active_file_senders;
memcpy(file_senders[i].pathname, path, path_len + 1);
file_senders[i].active = true;
file_senders[i].toxwin = self;
@ -223,6 +225,8 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
const char *msg = "Sending file: '%s'";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, msg, path);
++num_active_file_senders;
if (i == max_file_senders_index)
++max_file_senders_index;

View File

@ -63,6 +63,7 @@ typedef struct _Device {
pthread_mutex_t mutex[1];
uint32_t sample_rate;
uint32_t frame_duration;
int32_t sound_mode;
#ifdef _AUDIO
float VAD_treshold; /* 40 is usually recommended value */
#endif
@ -194,19 +195,21 @@ DeviceError set_primary_device(DeviceType type, int32_t selection)
return de_None;
}
DeviceError open_primary_device(DeviceType type, uint32_t* device_idx, uint32_t sample_rate, uint32_t frame_duration)
DeviceError open_primary_device(DeviceType type, uint32_t* device_idx, uint32_t sample_rate, uint32_t frame_duration, uint8_t channels)
{
return open_device(type, primary_device[type], device_idx, sample_rate, frame_duration);
return open_device(type, primary_device[type], device_idx, sample_rate, frame_duration, channels);
}
// TODO: generate buffers separately
DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx, uint32_t sample_rate, uint32_t frame_duration)
DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx, uint32_t sample_rate, uint32_t frame_duration, uint8_t channels)
{
if (size[type] <= selection || selection < 0) return de_InvalidSelection;
if (channels != 1 && channels != 2) return de_UnsupportedMode;
lock;
const uint32_t frame_size = (sample_rate * frame_duration / 1000);
uint32_t i;
@ -220,6 +223,7 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx
device->sample_rate = sample_rate;
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 ) {
@ -238,7 +242,7 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx
if (type == input) {
device->dhndl = alcCaptureOpenDevice(devices_names[type][selection],
sample_rate, AL_FORMAT_MONO16, frame_size * 2);
sample_rate, device->sound_mode, frame_size * 2);
#ifdef _AUDIO
device->VAD_treshold = user_settings_->VAD_treshold;
#endif
@ -263,7 +267,7 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx
memset(zeros, 0, frame_size*2);
for ( i =0; i < OPENAL_BUFS; ++i) {
alBufferData(device->buffers[i], AL_FORMAT_MONO16, zeros, frame_size*2, sample_rate);
alBufferData(device->buffers[i], device->sound_mode, zeros, frame_size*2, sample_rate);
}
alSourceQueueBuffers(device->source, OPENAL_BUFS, device->buffers);
@ -372,7 +376,7 @@ inline__ DeviceError write_out(uint32_t device_idx, int16_t* data, uint32_t leng
}
alBufferData(bufid, AL_FORMAT_MONO16, data, lenght * 2 * channels, device->sample_rate);
alBufferData(bufid, device->sound_mode, data, lenght * 2 * channels, device->sample_rate);
alSourceQueueBuffers(device->source, 1, &bufid);
ALint state;
@ -415,7 +419,7 @@ void* thread_poll (void* arg) // TODO: maybe use thread for every input source
}
Device* device = running[input][i];
int16_t frame[4096];
int16_t frame[16000];
alcCaptureSamples(device->dhndl, frame, f_size);
if ( device->muted

View File

@ -50,7 +50,8 @@ typedef enum DeviceError {
de_AllDevicesBusy = -5,
de_DeviceNotActive = -6,
de_BufferError = -7,
de_AlError = -8,
de_UnsupportedMode = -8,
de_AlError = -9,
} DeviceError;
typedef void (*DataHandleCallback) (const int16_t*, uint32_t size, void* data);
@ -76,9 +77,9 @@ DeviceError device_set_VAD_treshold(uint32_t device_idx, float value);
#endif
DeviceError set_primary_device(DeviceType type, int32_t selection);
DeviceError open_primary_device(DeviceType type, uint32_t* device_idx, uint32_t sample_rate, uint32_t frame_duration);
DeviceError open_primary_device(DeviceType type, uint32_t* device_idx, uint32_t sample_rate, uint32_t frame_duration, uint8_t channels);
/* Start device */
DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx, uint32_t sample_rate, uint32_t frame_duration);
DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx, uint32_t sample_rate, uint32_t frame_duration, uint8_t channels);
/* Stop device */
DeviceError close_device(DeviceType type, uint32_t device_idx);

View File

@ -35,13 +35,15 @@
FileSender file_senders[MAX_FILES];
uint8_t max_file_senders_index;
uint8_t num_active_file_senders;
extern ToxicFriend friends[MAX_FRIENDS_NUM];
#define KiB 1024
#define MiB 1048576 /* 1024 ^ 2 */
#define GiB 1073741824 /* 1024 ^ 3 */
/* creates initial progress line that will be updated during file transfer. */
/* creates initial progress line that will be updated during file transfer.
Assumes progline is of size MAX_STR_SIZE */
void prep_prog_line(char *progline)
{
strcpy(progline, "0.0 B/s [");
@ -127,6 +129,7 @@ static void close_file_sender(ToxWindow *self, Tox *m, int i, char *msg, int CTR
fclose(file_senders[i].file);
memset(&file_senders[i], 0, sizeof(FileSender));
set_max_file_senders_index();
--num_active_file_senders;
}
void close_all_file_senders(Tox *m)
@ -145,6 +148,41 @@ void close_all_file_senders(Tox *m)
}
}
static void send_file_data(ToxWindow *self, Tox *m, int i, int32_t friendnum, int filenum, const char *pathname)
{
char msg[MAX_STR_SIZE];
FILE *fp = file_senders[i].file;
while (true) {
if (tox_file_send_data(m, friendnum, filenum, (uint8_t *) file_senders[i].nextpiece,
file_senders[i].piecelen) == -1)
return;
uint64_t curtime = get_unix_time();
file_senders[i].timestamp = curtime;
file_senders[i].bps += file_senders[i].piecelen;
file_senders[i].piecelen = fread(file_senders[i].nextpiece, 1,
tox_file_data_size(m, friendnum), fp);
double remain = (double) tox_file_data_remaining(m, friendnum, filenum, 0);
/* refresh line with percentage complete and transfer speed (must be called once per second) */
if ((self->chatwin != NULL && timed_out(file_senders[i].last_progress, curtime, 1)) || !remain) {
file_senders[i].last_progress = curtime;
double pct_remain = remain > 0 ? (1 - (remain / file_senders[i].size)) * 100 : 100;
print_progress_bar(self, i, -1, pct_remain);
file_senders[i].bps = 0;
}
if (file_senders[i].piecelen == 0) {
snprintf(msg, sizeof(msg), "File '%s' successfuly sent.", pathname);
close_file_sender(self, m, i, msg, TOX_FILECONTROL_FINISHED, filenum, friendnum);
notify(self, transfer_completed, NT_NOFOCUS | NT_WNDALERT_2);
return;
}
}
}
void do_file_senders(Tox *m)
{
char msg[MAX_STR_SIZE];
@ -154,11 +192,15 @@ void do_file_senders(Tox *m)
if (!file_senders[i].active)
continue;
if (file_senders[i].queue_pos > 0) {
--file_senders[i].queue_pos;
continue;
}
ToxWindow *self = file_senders[i].toxwin;
char *pathname = file_senders[i].pathname;
int filenum = file_senders[i].filenum;
int32_t friendnum = file_senders[i].friendnum;
FILE *fp = file_senders[i].file;
/* If file transfer has timed out kill transfer and send kill control */
if (timed_out(file_senders[i].timestamp, get_unix_time(), TIMEOUT_FILESENDER)) {
@ -168,33 +210,7 @@ void do_file_senders(Tox *m)
continue;
}
while (true) {
if (tox_file_send_data(m, friendnum, filenum, (uint8_t *) file_senders[i].nextpiece,
file_senders[i].piecelen) == -1)
break;
uint64_t curtime = get_unix_time();
file_senders[i].timestamp = curtime;
file_senders[i].bps += file_senders[i].piecelen;
file_senders[i].piecelen = fread(file_senders[i].nextpiece, 1,
tox_file_data_size(m, friendnum), fp);
double remain = (double) tox_file_data_remaining(m, friendnum, filenum, 0);
/* refresh line with percentage complete and transfer speed (must be called once per second) */
if ((self->chatwin != NULL && timed_out(file_senders[i].last_progress, curtime, 1)) || !remain) {
file_senders[i].last_progress = curtime;
double pct_remain = remain ? (1 - (remain / file_senders[i].size)) * 100 : 100;
print_progress_bar(self, i, -1, pct_remain);
file_senders[i].bps = 0;
}
if (file_senders[i].piecelen == 0) {
snprintf(msg, sizeof(msg), "File '%s' successfuly sent.", pathname);
close_file_sender(self, m, i, msg, TOX_FILECONTROL_FINISHED, filenum, friendnum);
notify(self, transfer_completed, NT_NOFOCUS | NT_WNDALERT_2);
break;
}
}
file_senders[i].queue_pos = num_active_file_senders - 1;
send_file_data(self, m, i, friendnum, filenum, pathname);
}
}

View File

@ -45,9 +45,11 @@ typedef struct {
double bps;
uint64_t size;
uint32_t line_id;
uint8_t queue_pos;
} FileSender;
/* creates progress line that will be updated during file transfer. */
/* creates initial progress line that will be updated during file transfer.
Assumes progline is of size MAX_STR_SIZE */
void prep_prog_line(char *progline);
/* prints a progress bar for file transfers.

View File

@ -363,10 +363,10 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
ctx->start = wlen < x2 ? 0 : wlen - x2 + 1;
}
} else {
beep();
notify(self, error, 0);
}
} else {
beep();
notify(self, error, 0);
}
} else if (key == user_settings_->key_peer_list_down) { /* Scroll peerlist up and down one position */
int L = y2 - CHATBOX_HEIGHT - SDBAR_OFST;

View File

@ -31,6 +31,7 @@
#include "misc_tools.h"
#include "toxic_strings.h"
#include "line_info.h"
#include "notify.h"
/* add a char to input field and buffer */
void input_new_char(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_y)
@ -41,12 +42,12 @@ void input_new_char(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_
/* this is the only place we need to do this check */
if (cur_len == -1) {
beep();
notify(self, error, 0);
return;
}
if (add_char_to_buf(ctx, key) == -1) {
beep();
notify(self, error, 0);
return;
}
@ -62,7 +63,7 @@ static void input_backspace(ToxWindow *self, int x, int mx_x)
ChatContext *ctx = self->chatwin;
if (del_char_buf_bck(ctx) == -1) {
beep();
notify(self, error, 0);
return;
}
@ -79,21 +80,21 @@ static void input_backspace(ToxWindow *self, int x, int mx_x)
static void input_delete(ToxWindow *self)
{
if (del_char_buf_frnt(self->chatwin) == -1)
beep();
notify(self, error, 0);
}
/* deletes entire line before cursor from input field and buffer */
static void input_discard(ToxWindow *self)
{
if (discard_buf(self->chatwin) == -1)
beep();
notify(self, error, 0);
}
/* deletes entire line after cursor from input field and buffer */
static void input_kill(ChatContext *ctx)
{
if (kill_buf(ctx) == -1)
beep();
notify(NULL, error, NT_ALWAYS);
}
static void input_yank(ToxWindow *self, int x, int mx_x)
@ -101,7 +102,7 @@ static void input_yank(ToxWindow *self, int x, int mx_x)
ChatContext *ctx = self->chatwin;
if (yank_buf(ctx) == -1) {
beep();
notify(self, error, 0);
return;
}

View File

@ -30,6 +30,7 @@
#include "line_info.h"
#include "groupchat.h"
#include "settings.h"
#include "notify.h"
extern struct user_settings *user_settings_;
@ -420,14 +421,14 @@ static void line_info_scroll_up(struct history *hst)
{
if (hst->line_start->prev)
hst->line_start = hst->line_start->prev;
else beep();
else notify(NULL, error, NT_ALWAYS);
}
static void line_info_scroll_down(struct history *hst)
{
if (hst->line_start->next)
hst->line_start = hst->line_start->next;
else beep();
else notify(NULL, error, NT_ALWAYS);
}
static void line_info_page_up(ToxWindow *self, struct history *hst)

View File

@ -28,34 +28,43 @@
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdarg.h>
#include <time.h>
#include <assert.h>
#include <sys/stat.h>
#ifdef __APPLE__
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#ifdef _SOUND_NOTIFY
#include <OpenAL/alut.h> /* Is this good? */
#ifdef _AUDIO
#ifdef __APPLE__
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#ifdef _SOUND_NOTIFY
#include <OpenAL/alut.h> /* Is this good? */
#endif
#else
#include <AL/al.h>
#include <AL/alc.h>
#ifdef _SOUND_NOTIFY
#include <AL/alut.h> /* freealut packet */
#endif
#endif
#else
#include <AL/al.h>
#include <AL/alc.h>
#ifdef _SOUND_NOTIFY
#include <AL/alut.h> /* freealut packet */
#endif
#endif
#endif /* _AUDIO */
#ifdef _X11
#include <X11/Xlib.h>
#endif /* _X11 */
#ifdef _BOX_NOTIFY
#include <libnotify/notify.h>
#endif
#define SOUNDS_SIZE 10
#define ACTIVE_SOUNDS_MAX 50
#define ACTIVE_NOTIFS_MAX 50
extern struct user_settings *user_settings_;
struct _Control {
time_t cooldown;
time_t notif_timeout;
unsigned long this_window;
#ifdef _X11
Display *display;
@ -69,14 +78,22 @@ struct _Control {
#endif /* _SOUND_NOTIFY */
} Control = {0};
struct _ActiveNotifications {
#ifdef _SOUND_NOTIFY
struct _ActiveSounds {
uint32_t source;
uint32_t buffer;
_Bool active;
_Bool looping;
} actives[ACTIVE_SOUNDS_MAX] = {{0}};
#endif
#ifdef _BOX_NOTIFY
NotifyNotification* box;
char messages[128][128];
char title[24];
size_t size;
time_t timeout;
#endif
} actives[ACTIVE_NOTIFS_MAX] = {{0}};
/**********************************************************************************/
/**********************************************************************************/
/**********************************************************************************/
@ -112,20 +129,27 @@ void graceful_clear()
int i;
pthread_mutex_lock(Control.poll_mutex);
while (1) {
for (i = 0; i < ACTIVE_SOUNDS_MAX; i ++) {
for (i = 0; i < ACTIVE_NOTIFS_MAX; i ++) {
if (actives[i].active) {
#ifdef _BOX_NOTIFY
if (actives[i].box) {
notify_notification_close(actives[i].box, NULL);
memset(&actives[i], 0, sizeof(struct _ActiveNotifications));
}
#endif
if ( actives[i].looping ) {
stop_sound(i);
} else {
if (!is_playing(actives[i].source))
memset(&actives[i], 0, sizeof(struct _ActiveSounds));
memset(&actives[i], 0, sizeof(struct _ActiveNotifications));
else break;
}
}
}
if (i == ACTIVE_SOUNDS_MAX) {
if (i == ACTIVE_NOTIFS_MAX) {
pthread_mutex_unlock(Control.poll_mutex);
return;
}
@ -140,17 +164,36 @@ void* do_playing(void* _p)
int i;
while(Control.poll_active) {
pthread_mutex_lock(Control.poll_mutex);
for (i = 0; i < ACTIVE_SOUNDS_MAX; i ++) {
if (actives[i].active && !actives[i].looping) {
for (i = 0; i < ACTIVE_NOTIFS_MAX; i ++) {
if (actives[i].active && !actives[i].looping
#ifdef _BOX_NOTIFY
&& !actives[i].box
#endif
) {
if (!is_playing(actives[i].source)) {
/* Close */
alSourceStop(actives[i].source);
alDeleteSources(1, &actives[i].source);
alDeleteBuffers(1,&actives[i].buffer);
memset(&actives[i], 0, sizeof(struct _ActiveSounds));
memset(&actives[i], 0, sizeof(struct _ActiveNotifications));
}
}
#ifdef _BOX_NOTIFY
else if (actives[i].box && !actives[i].looping &&
time(NULL) >= actives[i].timeout && !is_playing(actives[i].source))
{
alSourceStop(actives[i].source);
alDeleteSources(1, &actives[i].source);
alDeleteBuffers(1,&actives[i].buffer);
memset(&actives[i], 0, sizeof(struct _ActiveNotifications));
GError* ignore;
notify_notification_close(actives[i].box, &ignore);
memset(&actives[i], 0, sizeof(struct _ActiveNotifications));
assert(0);
}
#endif
}
pthread_mutex_unlock(Control.poll_mutex);
usleep(10000);
@ -163,8 +206,8 @@ int play_source(uint32_t source, uint32_t buffer, _Bool looping)
{
pthread_mutex_lock(Control.poll_mutex);
int i = 0;
for (; i < ACTIVE_SOUNDS_MAX && actives[i].active; i ++);
if ( i == ACTIVE_SOUNDS_MAX ) {
for (; i < ACTIVE_NOTIFS_MAX && actives[i].active; i ++);
if ( i == ACTIVE_NOTIFS_MAX ) {
pthread_mutex_unlock(Control.poll_mutex);
return -1; /* Full */
}
@ -189,11 +232,11 @@ int play_source(uint32_t source, uint32_t buffer, _Bool looping)
/* Opens primary device */
int init_notify(int login_cooldown)
int init_notify(int login_cooldown, int notification_timeout)
{
#ifdef _SOUND_NOTIFY
alutInitWithoutContext(NULL, NULL);
if (open_primary_device(output, &Control.device_idx, 48000, 20) != de_None)
if (open_primary_device(output, &Control.device_idx, 48000, 20, 1) != de_None)
return -1;
pthread_mutex_init(Control.poll_mutex, NULL);
@ -214,6 +257,10 @@ int init_notify(int login_cooldown)
#endif /* _X11 */
#ifdef _BOX_NOTIFY
notify_init("toxic");
#endif
Control.notif_timeout = notification_timeout;
return 1;
}
@ -230,6 +277,11 @@ void terminate_notify()
close_device(output, Control.device_idx);
alutExit();
#endif /* _SOUND_NOTIFY */
#ifdef _BOX_NOTIFY
notify_uninit();
#endif
}
#ifdef _SOUND_NOTIFY
@ -271,7 +323,7 @@ int play_sound_internal(Notification what, _Bool loop)
int play_notify_sound(Notification notif, uint64_t flags)
{
int rc = 0;
int rc = -1;
if (flags & NT_BEEP) beep();
else if (notif != silent) {
@ -287,12 +339,12 @@ int play_notify_sound(Notification notif, uint64_t flags)
void stop_sound(int sound)
{
if (sound >= 0 && sound < ACTIVE_SOUNDS_MAX && actives[sound].looping && actives[sound].active) {
if (sound >= 0 && sound < ACTIVE_NOTIFS_MAX && actives[sound].looping && actives[sound].active ) {
alSourcei(actives[sound].source, AL_LOOPING, false);
alSourceStop(actives[sound].source);
alDeleteSources(1, &actives[sound].source);
alDeleteBuffers(1,&actives[sound].buffer);
memset(&actives[sound], 0, sizeof(struct _ActiveSounds));
memset(&actives[sound], 0, sizeof(struct _ActiveNotifications));
}
}
#endif
@ -330,9 +382,97 @@ int notify(ToxWindow* self, Notification notif, uint64_t flags)
else if (flags & NT_ALWAYS)
rc = m_play_sound(notif, flags);
if (flags & NT_NOTIFWND) {
/* TODO: pop notify window */
}
return rc;
}
int box_notify(ToxWindow* self, Notification notif, uint64_t flags, char* title, char* format, ...)
{
#ifdef _BOX_NOTIFY
int id = notify(self, notif, flags);
pthread_mutex_lock(Control.poll_mutex);
if (id == -1 && !(flags & NT_NOFOCUS && Control.this_window == get_focused_window_id())) { /* Could not play */
for (id = 0; id < ACTIVE_NOTIFS_MAX && actives[id].active; id ++);
if ( id == ACTIVE_NOTIFS_MAX ) {
pthread_mutex_unlock(Control.poll_mutex);
return -1; /* Full */
}
actives[id].active = 1;
}
strncpy(actives[id].title, title, 24);
if (strlen(title) > 23) strcpy(actives[id].title + 20, "...");
va_list __ARGS__; va_start (__ARGS__, format);
snprintf (actives[id].messages[0], 127, format, __ARGS__);
va_end (__ARGS__);
if (strlen(actives[id].messages[0]) > 124)
strcpy(actives[id].messages[0] + 124, "...");
actives[id].box = notify_notification_new(actives[id].title, actives[id].messages[0], NULL);
actives[id].size ++;
actives[id].timeout = time(NULL) + Control.notif_timeout;
notify_notification_set_timeout(actives[id].box, Control.notif_timeout);
notify_notification_show(actives[id].box, NULL);
pthread_mutex_unlock(Control.poll_mutex);
return id;
#else
return notify(self, notif, flags);
#endif
}
int box_notify_append(ToxWindow* self, Notification notif, uint64_t flags, int id, char* format, ...)
{
#ifdef _BOX_NOTIFY
if (id < 0 || id >= ACTIVE_NOTIFS_MAX || !actives[id].box || actives[id].size >= 128 ) return -1;
/* Consider colored notify as primary */
if (self && self->alert == WINDOW_ALERT_NONE) {
if (flags & NT_WNDALERT_0) self->alert = WINDOW_ALERT_0;
else if (flags & NT_WNDALERT_1) self->alert = WINDOW_ALERT_1;
else if (flags & NT_WNDALERT_2) self->alert = WINDOW_ALERT_2;
}
if (flags & NT_NOFOCUS && Control.this_window == get_focused_window_id())
return -1;
pthread_mutex_lock(Control.poll_mutex);
/* Play the sound again */
alSourcePlay(actives[id].source);
va_list __ARGS__; va_start (__ARGS__, format);
snprintf (actives[id].messages[actives[id].size], 127, format, __ARGS__);
va_end (__ARGS__);
if (strlen(actives[id].messages[actives[id].size]) > 124)
strcpy(actives[id].messages[actives[id].size] + 124, "...");
actives[id].size ++;
actives[id].timeout = time(NULL) + Control.notif_timeout;
char formated[128 * 129] = {'\0'};
int i = 0;
for (; i <actives[id].size; i ++) {
strcat(formated, actives[id].messages[i]);
strcat(formated, "\n");
}
formated[strlen(formated) - 1] = '\0';
notify_notification_update(actives[id].box, actives[id].title, formated, NULL);
notify_notification_show(actives[id].box, NULL);
pthread_mutex_unlock(Control.poll_mutex);
return id;
#else
return notify(self, notif, flags);
#endif
}

View File

@ -60,11 +60,14 @@ typedef enum _Flags {
NT_ALWAYS = 1 << 8, /* Force sound to play */
} Flags;
int init_notify(int login_cooldown);
int init_notify(int login_cooldown, int notification_timeout);
void terminate_notify();
int notify(ToxWindow* self, Notification notif, uint64_t flags);
int box_notify(ToxWindow* self, Notification notif, uint64_t flags, char* title, char* format, ...);
int box_notify_append(ToxWindow* self, Notification notif, uint64_t flags, int id, char* format, ...);
#ifdef _SOUND_NOTIFY
int set_sound(Notification sound, const char* value);
void stop_sound(int sound);

View File

@ -185,10 +185,10 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
ctx->start = wlen < x2 ? 0 : wlen - x2 + 1;
}
} else {
beep();
notify(self, error, 0);
}
} else {
beep();
notify(self, error, 0);
}
} else if (key == '\n') {
rm_trailing_spaces_buf(ctx);
@ -309,21 +309,13 @@ static void prompt_onConnectionChange(ToxWindow *self, Tox *m, int32_t friendnum
line_info_add(self, timefrmt, nick, NULL, CONNECTION, 0, GREEN, msg);
write_to_log(msg, nick, ctx->log, true);
#ifdef _SOUND_NOTIFY
notify(self, user_log_in, NT_WNDALERT_2 | NT_NOTIFWND | NT_RESTOL);
#else
notify(self, silent, NT_WNDALERT_2 | NT_NOTIFWND | NT_RESTOL);
#endif /* _SOUND_NOTIFY */
} else {
msg = "has gone offline";
line_info_add(self, timefrmt, nick, NULL, CONNECTION, 0, RED, msg);
write_to_log(msg, nick, ctx->log, true);
#ifdef _SOUND_NOTIFY
notify(self, user_log_out, NT_WNDALERT_2 | NT_NOTIFWND | NT_RESTOL);
#else
notify(self, silent, NT_WNDALERT_2 | NT_NOTIFWND | NT_RESTOL);
#endif /* _SOUND_NOTIFY */
}
}

View File

@ -635,12 +635,12 @@ int main(int argc, char *argv[])
#endif /* _AUDIO */
init_notify(60);
init_notify(60, 3000);
#ifdef _SOUND_NOTIFY
notify(prompt, self_log_in, 0);
#endif /* _SOUND_NOTIFY */
const char *msg;
if (config_err) {

View File

@ -28,6 +28,7 @@
#include "windows.h"
#include "misc_tools.h"
#include "toxic_strings.h"
#include "notify.h"
/* Adds char to line at pos. Return 0 on success, -1 if line buffer is full */
int add_char_to_buf(ChatContext *ctx, wint_t ch)
@ -191,7 +192,7 @@ void fetch_hist_item(ChatContext *ctx, int key_dir)
if (key_dir == KEY_UP) {
if (--ctx->hst_pos < 0) {
ctx->hst_pos = 0;
beep();
notify(NULL, error, NT_ALWAYS);
}
} else {
if (++ctx->hst_pos >= ctx->hst_tot) {