mirror of
https://github.com/Tha14/toxic.git
synced 2025-06-27 14:36:45 +02:00
Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
600e013adc | |||
1d71e2eb18 | |||
f858714edd | |||
4df44a7274 | |||
a26ed9d28f | |||
2bd5083b8f | |||
8805f694b9 | |||
71040355fd | |||
6bc5d8c543 | |||
abb39ea6b5 | |||
15846d2b50 | |||
958df9f2e8 | |||
2fd43aebee | |||
34c29745cc | |||
da6fe41d75 | |||
e17fa89d8f | |||
f056f13329 |
@ -29,8 +29,8 @@
|
||||
Using [Homebrew](http://brew.sh):
|
||||
```
|
||||
brew install openal-soft freealut libconfig
|
||||
brew install https://raw.githubusercontent.com/Tox/homebrew-tox/master/Formula/libtoxcore.rb
|
||||
brew install https://raw.githubusercontent.com/Homebrew/homebrew-x11/master/libnotify.rb
|
||||
brew install --HEAD https://raw.githubusercontent.com/Tox/homebrew-tox/master/Formula/libtoxcore.rb
|
||||
brew install libnotify
|
||||
```
|
||||
|
||||
You can omit `libnotify` if you intend to build without desktop notifications enabled.
|
||||
|
11
astylerc
Normal file
11
astylerc
Normal file
@ -0,0 +1,11 @@
|
||||
--style=kr
|
||||
--pad-header
|
||||
--max-code-length=120
|
||||
--convert-tabs
|
||||
--indent-switches
|
||||
--pad-oper
|
||||
--align-pointer=name
|
||||
--align-reference=name
|
||||
--preserve-date
|
||||
--lineend=linux
|
||||
--break-blocks
|
@ -34,6 +34,12 @@ ifneq ($(DESK_NOTIFY), disabled)
|
||||
-include $(CHECKS_DIR)/desktop_notifications.mk
|
||||
endif
|
||||
|
||||
# Check if we want build QR exported as PNG support
|
||||
QR_PNG = $(shell if [ -z "$(DISABLE_QRPNG)" ] || [ "$(DISABLE_QRPNG)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
|
||||
ifneq ($(QR_PNG), disabled)
|
||||
-include $(CHECKS_DIR)/qr_png.mk
|
||||
endif
|
||||
|
||||
# Check if we can build Toxic
|
||||
CHECK_LIBS = $(shell $(PKG_CONFIG) --exists $(LIBS) || echo -n "error")
|
||||
ifneq ($(CHECK_LIBS), error)
|
||||
|
15
cfg/checks/qr_png.mk
Normal file
15
cfg/checks/qr_png.mk
Normal file
@ -0,0 +1,15 @@
|
||||
# Variables for QR exported as PNG support
|
||||
PNG_LIBS = libpng
|
||||
PNG_CFLAGS = -DQRPNG
|
||||
|
||||
# Check if we can build QR exported as PNG support
|
||||
CHECK_PNG_LIBS = $(shell pkg-config --exists $(PNG_LIBS) || echo -n "error")
|
||||
ifneq ($(CHECK_PNG_LIBS), error)
|
||||
LIBS += $(PNG_LIBS)
|
||||
CFLAGS += $(PNG_CFLAGS)
|
||||
else ifneq ($(MAKECMDGOALS), clean)
|
||||
MISSING_PNG_LIBS = $(shell for lib in $(PNG_LIBS) ; do if ! $(PKG_CONFIG) --exists $$lib ; then echo $$lib ; fi ; done)
|
||||
$(warning WARNING -- Toxic will be compiled without QR exported as PNG support)
|
||||
$(warning WARNING -- You need these libraries for QR exported as PNG support)
|
||||
$(warning WARNING -- $(MISSING_PNG_LIBS))
|
||||
endif
|
@ -8,13 +8,13 @@ else
|
||||
endif
|
||||
|
||||
# Check if we can build video support
|
||||
CHECK_VIDEO_LIBS = $(shell pkg-config --exists $(VIDEO_LIBS) || echo -n "error")
|
||||
CHECK_VIDEO_LIBS = $(shell $(PKG_CONFIG) --exists $(VIDEO_LIBS) || echo -n "error")
|
||||
ifneq ($(CHECK_VIDEO_LIBS), error)
|
||||
LIBS += $(VIDEO_LIBS)
|
||||
CFLAGS += $(VIDEO_CFLAGS)
|
||||
OBJ += $(VIDEO_OBJ)
|
||||
else ifneq ($(MAKECMDGOALS), clean)
|
||||
MISSING_VIDEO_LIBS = $(shell for lib in $(VIDEO_LIBS) ; do if ! pkg-config --exists $$lib ; then echo $$lib ; fi ; done)
|
||||
MISSING_VIDEO_LIBS = $(shell for lib in $(VIDEO_LIBS) ; do if ! $(PKG_CONFIG) --exists $$lib ; then echo $$lib ; fi ; done)
|
||||
$(warning WARNING -- Toxic will be compiled without video support)
|
||||
$(warning WARNING -- You will need these libraries for video support)
|
||||
$(warning WARNING -- $(MISSING_VIDEO_LIBS))
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Version
|
||||
TOXIC_VERSION = 0.7.1
|
||||
TOXIC_VERSION = 0.7.2
|
||||
REV = $(shell git rev-list HEAD --count 2>/dev/null || echo -n "error")
|
||||
ifneq (, $(findstring error, $(REV)))
|
||||
VERSION = $(TOXIC_VERSION)
|
||||
|
@ -14,6 +14,7 @@ help:
|
||||
@echo " DISABLE_AV: Set to \"1\" to force building without audio call support"
|
||||
@echo " DISABLE_SOUND_NOTIFY: Set to \"1\" to force building without sound notification support"
|
||||
@echo " DISABLE_DESKTOP_NOTIFY: Set to \"1\" to force building without desktop notifications support"
|
||||
@echo " DISABLE_QRPNG: Set to \"1\" to force building without QR exported as PNG support"
|
||||
@echo " USER_CFLAGS: Add custom flags to default CFLAGS"
|
||||
@echo " USER_LDFLAGS: Add custom flags to default LDFLAGS"
|
||||
@echo " PREFIX: Specify a prefix directory for binaries, data files,... (default is \"$(abspath $(PREFIX))\")"
|
||||
|
@ -75,9 +75,9 @@ static int set_call(Call* call, bool start)
|
||||
|
||||
if ( pthread_mutex_init(&call->mutex, NULL) != 0 )
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
call->ttid = 0;
|
||||
|
||||
if ( pthread_mutex_destroy(&call->mutex) != 0 )
|
||||
return -1;
|
||||
}
|
||||
@ -85,7 +85,8 @@ static int set_call(Call* call, bool start)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void call_cb ( ToxAV *av, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *user_data );
|
||||
void call_cb ( ToxAV *av, uint32_t friend_number, bool audio_enabled, bool video_enabled,
|
||||
void *user_data );
|
||||
void callstate_cb ( ToxAV *av, uint32_t friend_number, uint32_t state, void *user_data );
|
||||
void receive_audio_frame_cb ( ToxAV *av, uint32_t friend_number, int16_t const *pcm, size_t sample_count,
|
||||
uint8_t channels, uint32_t sampling_rate, void *user_data );
|
||||
@ -158,6 +159,7 @@ ToxAV *init_audio(ToxWindow *self, Tox *tox)
|
||||
void terminate_audio()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CALLS; ++i)
|
||||
stop_transmission(&CallControl.calls[i], i);
|
||||
|
||||
@ -177,8 +179,8 @@ void read_device_callback(const int16_t* captured, uint32_t size, void* data)
|
||||
if ( sample_count <= 0 || toxav_audio_send_frame(CallControl.av, friend_number,
|
||||
captured, sample_count,
|
||||
CallControl.audio_channels,
|
||||
CallControl.audio_sample_rate, &error) == false )
|
||||
{}
|
||||
CallControl.audio_sample_rate, &error) == false ) {
|
||||
}
|
||||
}
|
||||
|
||||
void write_device_callback(uint32_t friend_number, const int16_t *PCM, uint16_t sample_count, uint8_t channels,
|
||||
@ -287,6 +289,7 @@ void callstate_cb(ToxAV *av, uint32_t friend_number, uint32_t state, void *user_
|
||||
CallControl.pending_call = false;
|
||||
|
||||
break;
|
||||
|
||||
case ( TOXAV_FRIEND_CALL_STATE_FINISHED ):
|
||||
if ( CallControl.pending_call )
|
||||
callback_call_rejected(friend_number);
|
||||
@ -305,6 +308,7 @@ void callstate_cb(ToxAV *av, uint32_t friend_number, uint32_t state, void *user_
|
||||
CallControl.pending_call = false;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( CallControl.pending_call ) {
|
||||
/* Start answered call */
|
||||
@ -313,6 +317,7 @@ void callstate_cb(ToxAV *av, uint32_t friend_number, uint32_t state, void *user_
|
||||
|
||||
} else {
|
||||
#ifdef VIDEO
|
||||
|
||||
/* Handle receiving client video call states */
|
||||
if ( state & TOXAV_FRIEND_CALL_STATE_SENDING_V )
|
||||
callback_recv_video_starting(friend_number);
|
||||
@ -376,9 +381,11 @@ void callback_recv_starting(uint32_t friend_number)
|
||||
ToxWindow *windows = CallControl.prompt;
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
if ( windows[i].onStarting != NULL && windows[i].num == friend_number ) {
|
||||
windows[i].onStarting(&windows[i], CallControl.av, friend_number, CallControl.call_state);
|
||||
|
||||
if ( 0 != start_transmission(&windows[i], &CallControl.calls[friend_number]) ) /* YEAH! */
|
||||
line_info_add(&windows[i], NULL, NULL, NULL, SYS_MSG, 0, 0 , "Error starting transmission!");
|
||||
|
||||
@ -402,9 +409,11 @@ void callback_call_started(uint32_t friend_number)
|
||||
ToxWindow *windows = CallControl.prompt;
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i)
|
||||
if ( windows[i].onStart != NULL && windows[i].num == friend_number ) {
|
||||
windows[i].onStart(&windows[i], CallControl.av, friend_number, CallControl.call_state);
|
||||
|
||||
if ( 0 != start_transmission(&windows[i], &CallControl.calls[friend_number]) ) {/* YEAH! */
|
||||
line_info_add(&windows[i], NULL, NULL, NULL, SYS_MSG, 0, 0, "Error starting transmission!");
|
||||
return;
|
||||
@ -479,6 +488,7 @@ void cmd_call(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
|
||||
}
|
||||
|
||||
toxav_call(CallControl.av, self->num, CallControl.audio_bit_rate, CallControl.video_bit_rate, &error);
|
||||
|
||||
if ( error != TOXAV_ERR_CALL_OK ) {
|
||||
if ( error == TOXAV_ERR_CALL_FRIEND_ALREADY_IN_CALL ) error_str = "Already in a call!";
|
||||
else if ( error == TOXAV_ERR_CALL_MALLOC ) error_str = "Memory allocation issue";
|
||||
@ -518,6 +528,7 @@ void cmd_answer(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
|
||||
}
|
||||
|
||||
toxav_answer(CallControl.av, self->num, CallControl.audio_bit_rate, CallControl.video_bit_rate, &error);
|
||||
|
||||
if ( error != TOXAV_ERR_ANSWER_OK ) {
|
||||
if ( error == TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING ) error_str = "No incoming call!";
|
||||
else if ( error == TOXAV_ERR_ANSWER_CODEC_INITIALIZATION ) error_str = "Failed to initialize codecs!";
|
||||
@ -715,6 +726,7 @@ void cmd_ccur_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*a
|
||||
/* If call is active, change device */
|
||||
if ( self->is_call ) {
|
||||
Call *this_call = &CallControl.calls[self->num];
|
||||
|
||||
if ( this_call->ttas ) {
|
||||
|
||||
|
||||
@ -725,8 +737,7 @@ void cmd_ccur_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*a
|
||||
CallControl.audio_sample_rate, CallControl.audio_frame_duration, CallControl.audio_channels)
|
||||
== de_None ? 1 : 0;
|
||||
pthread_mutex_unlock(&this_call->mutex);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* TODO: check for failure */
|
||||
close_device(input, this_call->in_idx);
|
||||
open_device(input, selection, &this_call->in_idx, CallControl.audio_sample_rate,
|
||||
@ -774,6 +785,7 @@ void cmd_mute(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
|
||||
Call *this_call = &CallControl.calls[self->num];
|
||||
|
||||
pthread_mutex_lock(&this_call->mutex);
|
||||
|
||||
if ( type == input ) {
|
||||
device_mute(type, this_call->in_idx);
|
||||
self->chatwin->infobox.in_is_muted ^= 1;
|
||||
@ -781,6 +793,7 @@ void cmd_mute(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
|
||||
device_mute(type, this_call->out_idx);
|
||||
self->chatwin->infobox.out_is_muted ^= 1;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&this_call->mutex);
|
||||
}
|
||||
|
||||
|
@ -103,6 +103,7 @@ DeviceError init_devices()
|
||||
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);
|
||||
|
||||
@ -113,10 +114,12 @@ DeviceError init_devices()
|
||||
}
|
||||
|
||||
size[output] = 0;
|
||||
|
||||
if (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE)
|
||||
stringed_device_list = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
|
||||
else
|
||||
stringed_device_list = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
|
||||
|
||||
if (stringed_device_list) {
|
||||
ddevice_names[output] = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
|
||||
|
||||
@ -131,6 +134,7 @@ DeviceError init_devices()
|
||||
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;
|
||||
|
||||
@ -159,6 +163,7 @@ DeviceError terminate_devices()
|
||||
DeviceError device_mute(DeviceType type, uint32_t device_idx)
|
||||
{
|
||||
if (device_idx >= MAX_DEVICES) return de_InvalidSelection;
|
||||
|
||||
lock;
|
||||
|
||||
Device *device = running[type][device_idx];
|
||||
@ -178,6 +183,7 @@ DeviceError device_mute(DeviceType type, uint32_t device_idx)
|
||||
DeviceError device_set_VAD_treshold(uint32_t device_idx, float value)
|
||||
{
|
||||
if (device_idx >= MAX_DEVICES) return de_InvalidSelection;
|
||||
|
||||
lock;
|
||||
|
||||
Device *device = running[input][device_idx];
|
||||
@ -198,12 +204,14 @@ DeviceError device_set_VAD_treshold(uint32_t device_idx, float value)
|
||||
DeviceError set_primary_device(DeviceType type, int32_t selection)
|
||||
{
|
||||
if (size[type] <= selection || selection < 0) return de_InvalidSelection;
|
||||
|
||||
primary_device[type] = selection;
|
||||
|
||||
return de_None;
|
||||
}
|
||||
|
||||
DeviceError open_primary_device(DeviceType type, uint32_t* device_idx, uint32_t sample_rate, uint32_t frame_duration, uint8_t channels)
|
||||
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, channels);
|
||||
}
|
||||
@ -214,7 +222,8 @@ void get_primary_device_name(DeviceType type, char *buf, int size)
|
||||
}
|
||||
|
||||
// TODO: generate buffers separately
|
||||
DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx, uint32_t sample_rate, uint32_t frame_duration, uint8_t channels)
|
||||
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;
|
||||
|
||||
@ -225,10 +234,13 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx
|
||||
const uint32_t frame_size = (sample_rate * frame_duration / 1000);
|
||||
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < MAX_DEVICES && running[type][i] != NULL; ++i);
|
||||
|
||||
if (i == MAX_DEVICES) { unlock; return de_AllDevicesBusy; }
|
||||
else *device_idx = i;
|
||||
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 ) {
|
||||
@ -261,9 +273,9 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx
|
||||
#ifdef AUDIO
|
||||
device->VAD_treshold = user_settings->VAD_treshold;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
device->dhndl = alcOpenDevice(devices_names[type][selection]);
|
||||
|
||||
if ( !device->dhndl ) {
|
||||
free(device);
|
||||
running[type][*device_idx] = NULL;
|
||||
@ -323,27 +335,28 @@ DeviceError close_device(DeviceType type, uint32_t device_idx)
|
||||
if ( !device->ref_count ) {
|
||||
if (type == input) {
|
||||
if ( !alcCaptureCloseDevice(device->dhndl) ) rc = de_AlError;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (alcGetCurrentContext() != device->ctx) alcMakeContextCurrent(device->ctx);
|
||||
|
||||
alDeleteSources(1, &device->source);
|
||||
alDeleteBuffers(OPENAL_BUFS, device->buffers);
|
||||
|
||||
alcMakeContextCurrent(NULL);
|
||||
|
||||
if ( device->ctx ) alcDestroyContext(device->ctx);
|
||||
|
||||
if ( !alcCloseDevice(device->dhndl) ) rc = de_AlError;
|
||||
}
|
||||
|
||||
free(device);
|
||||
}
|
||||
else device->ref_count--;
|
||||
} else device->ref_count--;
|
||||
|
||||
unlock;
|
||||
return rc;
|
||||
}
|
||||
|
||||
DeviceError register_device_callback( int32_t friend_number, uint32_t device_idx, DataHandleCallback callback, void* data, bool enable_VAD)
|
||||
DeviceError register_device_callback( int32_t friend_number, 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;
|
||||
@ -380,15 +393,15 @@ inline__ DeviceError write_out(uint32_t device_idx, const int16_t* data, uint32_
|
||||
alSourceUnqueueBuffers(device->source, processed, bufids);
|
||||
alDeleteBuffers(processed - 1, bufids + 1);
|
||||
bufid = bufids[0];
|
||||
}
|
||||
else if(queued < 16) alGenBuffers(1, &bufid);
|
||||
} else if (queued < 16) alGenBuffers(1, &bufid);
|
||||
else {
|
||||
pthread_mutex_unlock(device->mutex);
|
||||
return de_Busy;
|
||||
}
|
||||
|
||||
|
||||
alBufferData(bufid, channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, data, sample_count * 2 * channels, sample_rate);
|
||||
alBufferData(bufid, channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, data, sample_count * 2 * channels,
|
||||
sample_rate);
|
||||
alSourceQueueBuffers(device->source, 1, &bufid);
|
||||
|
||||
ALint state;
|
||||
@ -411,9 +424,9 @@ void* thread_poll (void* arg) // TODO: maybe use thread for every input source
|
||||
int32_t sample = 0;
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
while (1) {
|
||||
lock;
|
||||
|
||||
if (!thread_running) {
|
||||
unlock;
|
||||
break;
|
||||
@ -430,6 +443,7 @@ void* thread_poll (void* arg) // TODO: maybe use thread for every input source
|
||||
else {
|
||||
for (i = 0; i < size[input]; ++i) {
|
||||
lock;
|
||||
|
||||
if (running[input][i] != NULL) {
|
||||
alcGetIntegerv(running[input][i]->dhndl, ALC_CAPTURE_SAMPLES, sizeof(int32_t), &sample);
|
||||
|
||||
@ -439,6 +453,7 @@ void* thread_poll (void* arg) // TODO: maybe use thread for every input source
|
||||
unlock;
|
||||
continue;
|
||||
}
|
||||
|
||||
Device *device = running[input][i];
|
||||
|
||||
int16_t frame[16000];
|
||||
@ -451,8 +466,10 @@ void* thread_poll (void* arg) // TODO: maybe use thread for every input source
|
||||
|
||||
if ( device->cb ) device->cb(frame, f_size, device->cb_data);
|
||||
}
|
||||
|
||||
unlock;
|
||||
}
|
||||
|
||||
usleep(5000);
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,8 @@ DeviceError init_devices();
|
||||
DeviceError terminate_devices();
|
||||
|
||||
/* Callback handles ready data from INPUT device */
|
||||
DeviceError register_device_callback(int32_t friend_number, uint32_t device_idx, DataHandleCallback callback, void* data, bool enable_VAD);
|
||||
DeviceError register_device_callback(int32_t friend_number, uint32_t device_idx, DataHandleCallback callback,
|
||||
void *data, bool enable_VAD);
|
||||
void *get_device_callback_data(uint32_t device_idx);
|
||||
|
||||
/* toggle device mute */
|
||||
@ -75,14 +76,17 @@ 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, uint8_t channels);
|
||||
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, uint8_t channels);
|
||||
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);
|
||||
|
||||
/* Write data to device */
|
||||
DeviceError write_out(uint32_t device_idx, const int16_t* data, uint32_t length, uint8_t channels, uint32_t sample_rate);
|
||||
DeviceError write_out(uint32_t device_idx, const int16_t *data, uint32_t length, uint8_t channels,
|
||||
uint32_t sample_rate);
|
||||
|
||||
void print_devices(ToxWindow *self, DeviceType type);
|
||||
void get_primary_device_name(DeviceType type, char *buf, int size);
|
||||
|
@ -185,6 +185,7 @@ int complete_line(ToxWindow *self, const void *list, int n_items, int size)
|
||||
int n_endchrs = strlen(endchrs);
|
||||
int strt = ctx->pos - s_len;
|
||||
int diff = match_len - s_len + n_endchrs;
|
||||
|
||||
if (ctx->len + diff >= MAX_STR_SIZE)
|
||||
return -1;
|
||||
|
||||
|
@ -55,6 +55,7 @@ int avatar_send(Tox *m, uint32_t friendnum)
|
||||
TOX_ERR_FILE_SEND err;
|
||||
uint32_t filenum = tox_file_send(m, friendnum, TOX_FILE_KIND_AVATAR, (size_t) Avatar.size,
|
||||
NULL, (uint8_t *) Avatar.name, Avatar.name_len, &err);
|
||||
|
||||
if (Avatar.size == 0)
|
||||
return 0;
|
||||
|
||||
@ -150,6 +151,7 @@ void on_avatar_file_control(Tox *m, struct FileTransfer *ft, TOX_FILE_CONTROL co
|
||||
} else if (ft->state == FILE_TRANSFER_PAUSED) {
|
||||
ft->state = FILE_TRANSFER_STARTED;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TOX_FILE_CONTROL_PAUSE:
|
||||
|
@ -251,6 +251,7 @@ static int update_DHT_nodeslist(const char *nodes_path)
|
||||
}
|
||||
|
||||
struct Recv_Curl_Data recv_data;
|
||||
|
||||
memset(&recv_data, 0, sizeof(struct Recv_Curl_Data));
|
||||
|
||||
if (curl_fetch_nodes_JSON(&recv_data) == -1) {
|
||||
@ -476,7 +477,7 @@ void *load_nodeslist_thread(void *data)
|
||||
/* If nodeslist does not contain any valid entries we set the last_scan value
|
||||
* to 0 so that it will fetch a new list the next time this function is called.
|
||||
*/
|
||||
if (idx == 0) {
|
||||
if (Nodes.count == 0) {
|
||||
const char *s = "{\"last_scan\":0}";
|
||||
rewind(fp);
|
||||
fwrite(s, strlen(s), 1, fp); // Not much we can do if it fails
|
||||
@ -523,6 +524,7 @@ int load_DHT_nodeslist(void)
|
||||
}
|
||||
|
||||
thread_data.active = true;
|
||||
|
||||
if (pthread_create(&thread_data.tid, &thread_data.attr, load_nodeslist_thread, NULL) != 0) {
|
||||
thread_data.active = false;
|
||||
return -5;
|
||||
|
11
src/chat.c
11
src/chat.c
@ -466,10 +466,12 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, uint32_t friendnum, uint
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case TOX_FILE_CONTROL_PAUSE: {
|
||||
ft->state = FILE_TRANSFER_PAUSED;
|
||||
break;
|
||||
}
|
||||
|
||||
case TOX_FILE_CONTROL_CANCEL: {
|
||||
snprintf(msg, sizeof(msg), "File transfer for '%s' was aborted.", ft->file_name);
|
||||
close_file_transfer(self, m, ft, -1, msg, notif_error);
|
||||
@ -671,8 +673,10 @@ void chat_onRinging (ToxWindow *self, ToxAV *av, uint32_t friend_number, int sta
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ringing...type \"/hangup\" to cancel it.");
|
||||
|
||||
#ifdef SOUND_NOTIFY
|
||||
|
||||
if (self->ringing_sound == -1)
|
||||
sound_notify(self, call_outgoing, NT_LOOP, &self->ringing_sound);
|
||||
|
||||
#endif /* SOUND_NOTIFY */
|
||||
}
|
||||
|
||||
@ -950,8 +954,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
} else if (key == '\r') {
|
||||
rm_trailing_spaces_buf(ctx);
|
||||
|
||||
if (!wstring_is_empty(ctx->line))
|
||||
{
|
||||
if (!wstring_is_empty(ctx->line)) {
|
||||
add_line_to_hist(ctx);
|
||||
|
||||
wstrsubst(ctx->line, L'¶', L'\n');
|
||||
@ -1029,9 +1032,11 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
|
||||
case TOX_USER_STATUS_NONE:
|
||||
colour = GREEN;
|
||||
break;
|
||||
|
||||
case TOX_USER_STATUS_AWAY:
|
||||
colour = YELLOW;
|
||||
break;
|
||||
|
||||
case TOX_USER_STATUS_BUSY:
|
||||
colour = RED;
|
||||
break;
|
||||
@ -1107,9 +1112,11 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
|
||||
wnoutrefresh(self->window);
|
||||
|
||||
#ifdef AUDIO
|
||||
|
||||
if (ctx->infobox.active) {
|
||||
draw_infobox(self);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (self->help->active)
|
||||
|
@ -92,8 +92,10 @@ void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*a
|
||||
return;
|
||||
}
|
||||
|
||||
if (tox_invite_friend(m, self->num, groupnum) == -1) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to invite contact to group.");
|
||||
TOX_ERR_CONFERENCE_INVITE err;
|
||||
|
||||
if (!tox_conference_invite(m, self->num, groupnum, &err)) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to invite contact to group (error %d)", err);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -116,24 +118,23 @@ void cmd_join_group(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar
|
||||
return;
|
||||
}
|
||||
|
||||
int groupnum = -1;
|
||||
if (type != TOX_CONFERENCE_TYPE_TEXT) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Toxic does not support audio groups.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == TOX_GROUPCHAT_TYPE_TEXT)
|
||||
groupnum = tox_join_groupchat(m, self->num, (uint8_t *) groupkey, length);
|
||||
/*#ifdef AUDIO
|
||||
else
|
||||
groupnum = toxav_join_av_groupchat(m, self->num, (uint8_t *) groupkey, length,
|
||||
NULL, NULL);
|
||||
#endif*/
|
||||
TOX_ERR_CONFERENCE_JOIN err;
|
||||
|
||||
if (groupnum == -1) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize.");
|
||||
uint32_t groupnum = tox_conference_join(m, self->num, (uint8_t *) groupkey, length, &err);
|
||||
|
||||
if (err != TOX_ERR_CONFERENCE_JOIN_OK) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize (error %d)", err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (init_groupchat_win(prompt, m, groupnum, type) == -1) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize.");
|
||||
tox_del_groupchat(m, groupnum);
|
||||
tox_conference_delete(m, groupnum, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -190,6 +191,7 @@ void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
|
||||
return;
|
||||
|
||||
on_recv_error:
|
||||
|
||||
switch (err) {
|
||||
case TOX_ERR_FILE_CONTROL_FRIEND_NOT_FOUND:
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: Friend not found.");
|
||||
@ -282,6 +284,7 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
|
||||
return;
|
||||
|
||||
on_send_error:
|
||||
|
||||
switch (err) {
|
||||
case TOX_ERR_FILE_SEND_FRIEND_NOT_FOUND:
|
||||
errmsg = "File transfer failed: Invalid friend.";
|
||||
|
@ -186,6 +186,7 @@ void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode)
|
||||
case GROUPCHAT_COMMAND_MODE:
|
||||
if (do_command(w, self, m, num_args, group_commands, args) == 0)
|
||||
return;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -560,6 +560,7 @@ static void select_friend(ToxWindow *self, wint_t key, int *selected, int num)
|
||||
static void delete_friend(Tox *m, uint32_t f_num)
|
||||
{
|
||||
TOX_ERR_FRIEND_DELETE err;
|
||||
|
||||
if (tox_friend_delete(m, f_num, &err) != true) {
|
||||
fprintf(stderr, "tox_friend_delete failed with error %d\n", err);
|
||||
return;
|
||||
@ -645,10 +646,12 @@ static void draw_del_popup(void)
|
||||
wattron(PendingDelete.popup, A_BOLD);
|
||||
|
||||
pthread_mutex_lock(&Winthread.lock);
|
||||
|
||||
if (blocklist_view == 0)
|
||||
wprintw(PendingDelete.popup, "%s", Friends.list[PendingDelete.num].name);
|
||||
else
|
||||
wprintw(PendingDelete.popup, "%s", Blocked.list[PendingDelete.num].name);
|
||||
|
||||
pthread_mutex_unlock(&Winthread.lock);
|
||||
|
||||
wattroff(PendingDelete.popup, A_BOLD);
|
||||
@ -799,6 +802,7 @@ static void friendlist_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
block_friend(m, f);
|
||||
else
|
||||
unblock_friend(m, f);
|
||||
|
||||
break;
|
||||
|
||||
case KEY_RIGHT:
|
||||
@ -811,6 +815,7 @@ static void friendlist_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
select_friend(self, key, &Friends.num_selected, Friends.num_friends);
|
||||
else
|
||||
select_friend(self, key, &Blocked.num_selected, Blocked.num_blocked);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -970,9 +975,11 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m)
|
||||
case TOX_USER_STATUS_NONE:
|
||||
colour = GREEN;
|
||||
break;
|
||||
|
||||
case TOX_USER_STATUS_AWAY:
|
||||
colour = YELLOW;
|
||||
break;
|
||||
|
||||
case TOX_USER_STATUS_BUSY:
|
||||
colour = RED;
|
||||
break;
|
||||
@ -1112,6 +1119,7 @@ void disable_chatwin(uint32_t f_num)
|
||||
static void friendlist_onAV(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state)
|
||||
{
|
||||
assert(0);
|
||||
|
||||
if ( friend_number >= Friends.max_idx)
|
||||
return;
|
||||
|
||||
|
@ -130,6 +130,7 @@ void cmd_add_helper(ToxWindow *self, Tox *m, const char *id_bin, const char *msg
|
||||
break;
|
||||
|
||||
case TOX_ERR_FRIEND_ADD_NULL:
|
||||
|
||||
/* fallthrough */
|
||||
default:
|
||||
errmsg = "Faile to add friend: Unknown error.";
|
||||
@ -260,6 +261,7 @@ void cmd_connect(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)
|
||||
}
|
||||
|
||||
char key_binary[TOX_PUBLIC_KEY_SIZE * 2 + 1];
|
||||
|
||||
if (hex_string_to_bin(ascii_key, strlen(ascii_key), key_binary, TOX_PUBLIC_KEY_SIZE) == -1) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid key.");
|
||||
return;
|
||||
@ -281,6 +283,7 @@ void cmd_connect(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)
|
||||
case TOX_ERR_BOOTSTRAP_NULL:
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Bootstrap failed.");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -333,31 +336,31 @@ void cmd_groupchat(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg
|
||||
uint8_t type;
|
||||
|
||||
if (!strcasecmp(argv[1], "audio"))
|
||||
type = TOX_GROUPCHAT_TYPE_AV;
|
||||
type = TOX_CONFERENCE_TYPE_AV;
|
||||
else if (!strcasecmp(argv[1], "text"))
|
||||
type = TOX_GROUPCHAT_TYPE_TEXT;
|
||||
type = TOX_CONFERENCE_TYPE_TEXT;
|
||||
else {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Valid group types are: text | audio");
|
||||
return;
|
||||
}
|
||||
|
||||
int groupnum = -1;
|
||||
if (type != TOX_CONFERENCE_TYPE_TEXT) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Toxic does not support audio groups.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == TOX_GROUPCHAT_TYPE_TEXT)
|
||||
groupnum = tox_add_groupchat(m);
|
||||
/*#ifdef AUDIO
|
||||
else
|
||||
groupnum = toxav_add_av_groupchat(m, NULL, NULL);
|
||||
#endif*/
|
||||
TOX_ERR_CONFERENCE_NEW err;
|
||||
|
||||
if (groupnum == -1) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize.");
|
||||
uint32_t groupnum = tox_conference_new(m, &err);
|
||||
|
||||
if (err != TOX_ERR_CONFERENCE_NEW_OK) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize (error %d)", err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (init_groupchat_win(prompt, m, groupnum, type) == -1) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize.");
|
||||
tox_del_groupchat(m, groupnum);
|
||||
tox_conference_delete(m, groupnum, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -448,25 +451,42 @@ void cmd_myqr(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
|
||||
char dir[data_file_len + 1];
|
||||
size_t dir_len = get_base_dir(DATA_FILE, data_file_len, dir);
|
||||
|
||||
#ifdef QRPNG
|
||||
|
||||
if (argc == 0) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Required 'txt' or 'png'");
|
||||
return;
|
||||
} else if (!strcmp(argv[1], "txt")) {
|
||||
|
||||
#endif /* QRPNG */
|
||||
char qr_path[dir_len + nick_len + strlen(QRCODE_FILENAME_EXT) + 1];
|
||||
snprintf(qr_path, sizeof(qr_path), "%s%s%s", dir, nick, QRCODE_FILENAME_EXT);
|
||||
|
||||
FILE *output = fopen(qr_path, "wb");
|
||||
|
||||
if (output == NULL) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ID_to_QRcode(id_string, output) == -1) {
|
||||
fclose(output);
|
||||
if (ID_to_QRcode_txt(id_string, qr_path) == -1) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code.");
|
||||
return;
|
||||
}
|
||||
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "QR code has been printed to the file '%s'", qr_path);
|
||||
|
||||
fclose(output);
|
||||
#ifdef QRPNG
|
||||
} else if (!strcmp(argv[1], "png")) {
|
||||
char qr_path[dir_len + nick_len + strlen(QRCODE_FILENAME_EXT_PNG) + 1];
|
||||
snprintf(qr_path, sizeof(qr_path), "%s%s%s", dir, nick, QRCODE_FILENAME_EXT_PNG);
|
||||
|
||||
if (ID_to_QRcode_png(id_string, qr_path) == -1) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code.");
|
||||
return;
|
||||
}
|
||||
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "QR code has been printed to the file '%s'", qr_path);
|
||||
|
||||
} else {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Unknown option '%s' -- Required 'txt' or 'png'", argv[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* QRPNG */
|
||||
}
|
||||
|
||||
void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
@ -543,8 +563,10 @@ void cmd_nospam(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Your new Tox ID is:");
|
||||
cmd_myid(window, self, m, 0, NULL);
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "");
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Any services that relied on your old ID will need to be updated manually.");
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "If you ever want your old Tox ID back, type '/nospam %X'", old_nospam);
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,
|
||||
"Any services that relied on your old ID will need to be updated manually.");
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "If you ever want your old Tox ID back, type '/nospam %X'",
|
||||
old_nospam);
|
||||
}
|
||||
|
||||
void cmd_prompt_help(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
|
@ -30,17 +30,24 @@
|
||||
|
||||
void cmd_set_title(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
TOX_ERR_CONFERENCE_TITLE err;
|
||||
char title[MAX_STR_SIZE];
|
||||
|
||||
if (argc < 1) {
|
||||
int tlen = tox_group_get_title(m, self->num, (uint8_t *) title, TOX_MAX_NAME_LENGTH);
|
||||
size_t tlen = tox_conference_get_title_size(m, self->num, &err);
|
||||
|
||||
if (err != TOX_ERR_CONFERENCE_TITLE_OK) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Title is not set");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tox_conference_get_title(m, self->num, (uint8_t *) title, &err)) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Title is not set");
|
||||
return;
|
||||
}
|
||||
|
||||
if (tlen != -1) {
|
||||
title[tlen] = '\0';
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Title is set to: %s", title);
|
||||
} else {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Title is not set");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@ -55,8 +62,8 @@ void cmd_set_title(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg
|
||||
int len = strlen(title) - 1;
|
||||
title[len] = '\0';
|
||||
|
||||
if (tox_group_set_title(m, self->num, (uint8_t *) title, len) != 0) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set title.");
|
||||
if (!tox_conference_set_title(m, self->num, (uint8_t *) title, len, &err)) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set title (error %d)", err);
|
||||
return;
|
||||
}
|
||||
|
||||
|
291
src/groupchat.c
291
src/groupchat.c
@ -97,26 +97,13 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = {
|
||||
{ "/requests" },
|
||||
{ "/status" },
|
||||
{ "/title" },
|
||||
|
||||
#ifdef AUDIO
|
||||
|
||||
{ "/lsdev" },
|
||||
{ "/sdev" },
|
||||
{ "/mute" },
|
||||
{ "/sense" },
|
||||
|
||||
#endif /* AUDIO */
|
||||
};
|
||||
|
||||
#ifdef AUDIO
|
||||
static int group_audio_open_out_device(int groupnum);
|
||||
static int group_audio_close_out_device(int groupnum);
|
||||
#endif /* AUDIO */
|
||||
|
||||
int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum, uint8_t type)
|
||||
int init_groupchat_win(ToxWindow *prompt, Tox *m, uint32_t groupnum, uint8_t type)
|
||||
{
|
||||
if (groupnum > MAX_GROUPCHAT_NUM)
|
||||
if (groupnum > MAX_GROUPCHAT_NUM) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ToxWindow self = new_group_chat(m, groupnum);
|
||||
int i;
|
||||
@ -141,12 +128,6 @@ int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum, uint8_t type)
|
||||
memcpy(&groupchats[i].oldpeer_names[0], UNKNOWN_NAME, sizeof(UNKNOWN_NAME));
|
||||
groupchats[i].oldpeer_name_lengths[0] = (uint16_t) strlen(UNKNOWN_NAME);
|
||||
|
||||
#ifdef AUDIO
|
||||
if (type == TOX_GROUPCHAT_TYPE_AV)
|
||||
if (group_audio_open_out_device(i) == -1)
|
||||
fprintf(stderr, "Group Audio failed to init\n");
|
||||
#endif /* AUDIO */
|
||||
|
||||
set_active_window(groupchats[i].chatwin);
|
||||
|
||||
if (i == max_groupchat_index)
|
||||
@ -174,12 +155,9 @@ static void kill_groupchat_window(ToxWindow *self)
|
||||
del_window(self);
|
||||
}
|
||||
|
||||
void close_groupchat(ToxWindow *self, Tox *m, int groupnum)
|
||||
void close_groupchat(ToxWindow *self, Tox *m, uint32_t groupnum)
|
||||
{
|
||||
tox_del_groupchat(m, groupnum);
|
||||
#ifdef AUDIO
|
||||
group_audio_close_out_device(groupnum);
|
||||
#endif
|
||||
tox_conference_delete(m, groupnum, NULL);
|
||||
|
||||
free(groupchats[groupnum].peer_names);
|
||||
free(groupchats[groupnum].oldpeer_names);
|
||||
@ -237,8 +215,8 @@ void redraw_groupchat_win(ToxWindow *self)
|
||||
|
||||
}
|
||||
|
||||
static void groupchat_onGroupMessage(ToxWindow *self, Tox *m, int groupnum, int peernum,
|
||||
const char *msg, uint16_t len)
|
||||
static void groupchat_onGroupMessage(ToxWindow *self, Tox *m, uint32_t groupnum, uint32_t peernum,
|
||||
TOX_MESSAGE_TYPE type, const char *msg, size_t len)
|
||||
{
|
||||
if (self->num != groupnum)
|
||||
return;
|
||||
@ -266,56 +244,19 @@ static void groupchat_onGroupMessage(ToxWindow *self, Tox *m, int groupnum, int
|
||||
box_silent_notify(self, NT_NOFOCUS, &self->active_box, self->name, "%s %s", nick, msg);
|
||||
|
||||
nick_clr = RED;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
sound_notify(self, silent, NT_WNDALERT_1, NULL);
|
||||
}
|
||||
|
||||
char timefrmt[TIME_STR_SIZE];
|
||||
get_time_str(timefrmt, sizeof(timefrmt));
|
||||
|
||||
line_info_add(self, timefrmt, nick, NULL, IN_MSG, 0, nick_clr, "%s", msg);
|
||||
line_info_add(self, timefrmt, nick, NULL, type == TOX_MESSAGE_TYPE_NORMAL ? IN_MSG : IN_ACTION, 0, nick_clr, "%s", msg);
|
||||
write_to_log(msg, nick, ctx->log, false);
|
||||
}
|
||||
|
||||
static void groupchat_onGroupAction(ToxWindow *self, Tox *m, int groupnum, int peernum, const char *action,
|
||||
uint16_t len)
|
||||
{
|
||||
if (self->num != groupnum)
|
||||
return;
|
||||
|
||||
ChatContext *ctx = self->chatwin;
|
||||
|
||||
char nick[TOX_MAX_NAME_LENGTH];
|
||||
get_group_nick_truncate(m, nick, peernum, groupnum);
|
||||
|
||||
char selfnick[TOX_MAX_NAME_LENGTH];
|
||||
tox_self_get_name(m, (uint8_t *) selfnick);
|
||||
|
||||
size_t n_len = tox_self_get_name_size(m);
|
||||
selfnick[n_len] = '\0';
|
||||
|
||||
if (strcasestr(action, selfnick)) {
|
||||
sound_notify(self, generic_message, NT_WNDALERT_0 | user_settings->bell_on_message, NULL);
|
||||
|
||||
if (self->active_box != -1)
|
||||
box_silent_notify2(self, NT_NOFOCUS, self->active_box, "* %s %s", nick, action );
|
||||
else
|
||||
box_silent_notify(self, NT_NOFOCUS, &self->active_box, self->name, "* %s %s", nick, action);
|
||||
}
|
||||
else {
|
||||
sound_notify(self, silent, NT_WNDALERT_1, NULL);
|
||||
}
|
||||
|
||||
char timefrmt[TIME_STR_SIZE];
|
||||
get_time_str(timefrmt, sizeof(timefrmt));
|
||||
|
||||
line_info_add(self, timefrmt, nick, NULL, IN_ACTION, 0, 0, "%s", action);
|
||||
write_to_log(action, nick, ctx->log, true);
|
||||
}
|
||||
|
||||
static void groupchat_onGroupTitleChange(ToxWindow *self, Tox *m, int groupnum, int peernum, const char *title,
|
||||
uint8_t length)
|
||||
static void groupchat_onGroupTitleChange(ToxWindow *self, Tox *m, uint32_t groupnum, uint32_t peernum, const char *title,
|
||||
size_t length)
|
||||
{
|
||||
ChatContext *ctx = self->chatwin;
|
||||
|
||||
@ -341,7 +282,7 @@ static void groupchat_onGroupTitleChange(ToxWindow *self, Tox *m, int groupnum,
|
||||
}
|
||||
|
||||
/* Puts two copies of peerlist/lengths in chat instance */
|
||||
static void copy_peernames(int gnum, uint8_t peerlist[][TOX_MAX_NAME_LENGTH], uint16_t lengths[], int npeers)
|
||||
static void copy_peernames(Tox *m, uint32_t gnum, size_t npeers)
|
||||
{
|
||||
/* Assumes these are initiated in init_groupchat_win */
|
||||
free(groupchats[gnum].peer_names);
|
||||
@ -351,27 +292,34 @@ static void copy_peernames(int gnum, uint8_t peerlist[][TOX_MAX_NAME_LENGTH], ui
|
||||
|
||||
int N = TOX_MAX_NAME_LENGTH;
|
||||
|
||||
groupchats[gnum].peer_names = malloc(sizeof(uint8_t) * npeers * N);
|
||||
groupchats[gnum].oldpeer_names = malloc(sizeof(uint8_t) * npeers * N);
|
||||
groupchats[gnum].peer_name_lengths = malloc(sizeof(uint16_t) * npeers);
|
||||
groupchats[gnum].oldpeer_name_lengths = malloc(sizeof(uint16_t) * npeers);
|
||||
groupchats[gnum].peer_names = calloc(1, sizeof(uint8_t) * npeers * N);
|
||||
groupchats[gnum].oldpeer_names = calloc(1, sizeof(uint8_t) * npeers * N);
|
||||
groupchats[gnum].peer_name_lengths = calloc(1, sizeof(uint16_t) * npeers);
|
||||
groupchats[gnum].oldpeer_name_lengths = calloc(1, sizeof(uint16_t) * npeers);
|
||||
|
||||
if (groupchats[gnum].peer_names == NULL || groupchats[gnum].oldpeer_names == NULL
|
||||
|| groupchats[gnum].peer_name_lengths == NULL || groupchats[gnum].oldpeer_name_lengths == NULL) {
|
||||
exit_toxic_err("failed in copy_peernames", FATALERR_MEMORY);
|
||||
exit_toxic_err("failed in copy_peernames()", FATALERR_MEMORY);
|
||||
}
|
||||
|
||||
uint16_t u_len = strlen(UNKNOWN_NAME);
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < npeers; ++i) {
|
||||
if (!lengths[i]) {
|
||||
uint8_t name[TOX_MAX_NAME_LENGTH];
|
||||
TOX_ERR_CONFERENCE_PEER_QUERY err;
|
||||
|
||||
size_t n_len = tox_conference_peer_get_name_size(m, gnum, i, &err);
|
||||
|
||||
if (err != TOX_ERR_CONFERENCE_PEER_QUERY_OK) {
|
||||
memcpy(&groupchats[gnum].peer_names[i * N], UNKNOWN_NAME, u_len);
|
||||
groupchats[gnum].peer_names[i * N + u_len] = '\0';
|
||||
groupchats[gnum].peer_name_lengths[i] = u_len;
|
||||
} else {
|
||||
uint16_t n_len = MIN(lengths[i], TOXIC_MAX_NAME_LENGTH - 1);
|
||||
memcpy(&groupchats[gnum].peer_names[i * N], peerlist[i], n_len);
|
||||
tox_conference_peer_get_name(m, gnum, i, name, NULL);
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH - 1);
|
||||
memcpy(&groupchats[gnum].peer_names[i * N], name, n_len);
|
||||
groupchats[gnum].peer_names[i * N + n_len] = '\0';
|
||||
groupchats[gnum].peer_name_lengths[i] = n_len;
|
||||
filter_str((char *) &groupchats[gnum].peer_names[i * N], n_len);
|
||||
@ -385,8 +333,8 @@ static void copy_peernames(int gnum, uint8_t peerlist[][TOX_MAX_NAME_LENGTH], ui
|
||||
struct group_add_thrd {
|
||||
Tox *m;
|
||||
ToxWindow *self;
|
||||
int peernum;
|
||||
int groupnum;
|
||||
uint32_t peernum;
|
||||
uint32_t groupnum;
|
||||
time_t timestamp;
|
||||
pthread_t tid;
|
||||
pthread_attr_t attr;
|
||||
@ -429,7 +377,8 @@ void *group_add_wait(void *data)
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnum, int peernum, uint8_t change)
|
||||
static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, uint32_t groupnum, uint32_t peernum,
|
||||
TOX_CONFERENCE_STATE_CHANGE change)
|
||||
{
|
||||
if (self->num != groupnum)
|
||||
return;
|
||||
@ -437,8 +386,15 @@ static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnu
|
||||
if (groupnum > max_groupchat_index)
|
||||
return;
|
||||
|
||||
groupchats[groupnum].num_peers = tox_group_number_peers(m, groupnum);
|
||||
int num_peers = groupchats[groupnum].num_peers;
|
||||
TOX_ERR_CONFERENCE_PEER_QUERY err;
|
||||
|
||||
uint32_t num_peers = tox_conference_peer_count(m, groupnum, &err);
|
||||
|
||||
if (err == TOX_ERR_CONFERENCE_PEER_QUERY_OK) {
|
||||
groupchats[groupnum].num_peers = num_peers;
|
||||
} else {
|
||||
num_peers = groupchats[groupnum].num_peers;
|
||||
}
|
||||
|
||||
if (peernum > num_peers)
|
||||
return;
|
||||
@ -446,28 +402,19 @@ static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnu
|
||||
/* get old peer name before updating name list */
|
||||
uint8_t oldpeername[TOX_MAX_NAME_LENGTH];
|
||||
|
||||
if (change != TOX_CHAT_CHANGE_PEER_ADD) {
|
||||
memcpy(oldpeername, &groupchats[groupnum].oldpeer_names[peernum * TOX_MAX_NAME_LENGTH],
|
||||
sizeof(oldpeername));
|
||||
if (change != TOX_CONFERENCE_STATE_CHANGE_PEER_JOIN) {
|
||||
memcpy(oldpeername, &groupchats[groupnum].oldpeer_names[peernum * TOX_MAX_NAME_LENGTH], sizeof(oldpeername));
|
||||
uint16_t old_n_len = groupchats[groupnum].oldpeer_name_lengths[peernum];
|
||||
oldpeername[old_n_len] = '\0';
|
||||
}
|
||||
|
||||
/* Update name/len lists */
|
||||
uint8_t tmp_peerlist[num_peers][TOX_MAX_NAME_LENGTH];
|
||||
uint16_t tmp_peerlens[num_peers];
|
||||
|
||||
if (tox_group_get_names(m, groupnum, tmp_peerlist, tmp_peerlens, num_peers) == -1) {
|
||||
memset(tmp_peerlist, 0, sizeof(tmp_peerlist));
|
||||
memset(tmp_peerlens, 0, sizeof(tmp_peerlens));
|
||||
}
|
||||
|
||||
copy_peernames(groupnum, tmp_peerlist, tmp_peerlens, num_peers);
|
||||
copy_peernames(m, groupnum, num_peers);
|
||||
|
||||
/* get current peername then sort namelist */
|
||||
uint8_t peername[TOX_MAX_NAME_LENGTH];
|
||||
|
||||
if (change != TOX_CHAT_CHANGE_PEER_DEL) {
|
||||
if (change != TOX_CONFERENCE_STATE_CHANGE_PEER_EXIT) {
|
||||
uint16_t n_len = groupchats[groupnum].peer_name_lengths[peernum];
|
||||
memcpy(peername, &groupchats[groupnum].peer_names[peernum * TOX_MAX_NAME_LENGTH], sizeof(peername));
|
||||
peername[n_len] = '\0';
|
||||
@ -482,7 +429,7 @@ static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnu
|
||||
get_time_str(timefrmt, sizeof(timefrmt));
|
||||
|
||||
switch (change) {
|
||||
case TOX_CHAT_CHANGE_PEER_ADD:
|
||||
case TOX_CONFERENCE_STATE_CHANGE_PEER_JOIN:
|
||||
if (!timed_out(groupchats[groupnum].start_time, GROUP_EVENT_WAIT))
|
||||
break;
|
||||
|
||||
@ -512,7 +459,7 @@ static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnu
|
||||
|
||||
break;
|
||||
|
||||
case TOX_CHAT_CHANGE_PEER_DEL:
|
||||
case TOX_CONFERENCE_STATE_CHANGE_PEER_EXIT:
|
||||
event = "has left the room";
|
||||
line_info_add(self, timefrmt, (char *) oldpeername, NULL, DISCONNECTION, 0, RED, event);
|
||||
|
||||
@ -522,7 +469,7 @@ static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnu
|
||||
write_to_log(event, (char *) oldpeername, ctx->log, true);
|
||||
break;
|
||||
|
||||
case TOX_CHAT_CHANGE_PEER_NAME:
|
||||
case TOX_CONFERENCE_STATE_CHANGE_PEER_NAME_CHANGE:
|
||||
if (!timed_out(groupchats[self->num].start_time, GROUP_EVENT_WAIT))
|
||||
return;
|
||||
|
||||
@ -549,9 +496,10 @@ static void send_group_action(ToxWindow *self, ChatContext *ctx, Tox *m, char *a
|
||||
return;
|
||||
}
|
||||
|
||||
if (tox_group_action_send(m, self->num, (uint8_t *) action, strlen(action)) == -1) {
|
||||
const char *errmsg = " * Failed to send action.";
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, errmsg);
|
||||
TOX_ERR_CONFERENCE_SEND_MESSAGE err;
|
||||
|
||||
if (!tox_conference_send_message(m, self->num, TOX_MESSAGE_TYPE_ACTION, (uint8_t *) action, strlen(action), &err)) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Failed to send action (error %d)", err);
|
||||
}
|
||||
}
|
||||
|
||||
@ -621,8 +569,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
} else if (key == '\r') {
|
||||
rm_trailing_spaces_buf(ctx);
|
||||
|
||||
if (!wstring_is_empty(ctx->line))
|
||||
{
|
||||
if (!wstring_is_empty(ctx->line)) {
|
||||
add_line_to_hist(ctx);
|
||||
|
||||
wstrsubst(ctx->line, L'¶', L'\n');
|
||||
@ -642,9 +589,10 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
execute(ctx->history, self, m, line, GROUPCHAT_COMMAND_MODE);
|
||||
}
|
||||
} else {
|
||||
if (tox_group_message_send(m, self->num, (uint8_t *) line, strlen(line)) == -1) {
|
||||
const char *errmsg = " * Failed to send message.";
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, errmsg);
|
||||
TOX_ERR_CONFERENCE_SEND_MESSAGE err;
|
||||
|
||||
if (!tox_conference_send_message(m, self->num, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) line, strlen(line), &err)) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Failed to send message (error %d)", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -702,7 +650,7 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m)
|
||||
wmove(ctx->sidebar, i + 2, 1);
|
||||
|
||||
pthread_mutex_lock(&Winthread.lock);
|
||||
int peer = i + groupchats[self->num].side_pos;
|
||||
uint32_t peer = i + groupchats[self->num].side_pos;
|
||||
pthread_mutex_unlock(&Winthread.lock);
|
||||
|
||||
/* truncate nick to fit in side panel without modifying list */
|
||||
@ -767,125 +715,7 @@ static void groupchat_onInit(ToxWindow *self, Tox *m)
|
||||
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
|
||||
}
|
||||
|
||||
|
||||
#ifdef AUDIO
|
||||
static int group_audio_open_out_device(int groupnum)
|
||||
{
|
||||
char dname[MAX_STR_SIZE];
|
||||
get_primary_device_name(output, dname, sizeof(dname));
|
||||
dname[MAX_STR_SIZE - 1] = '\0';
|
||||
|
||||
groupchats[groupnum].audio.dvhandle = alcOpenDevice(dname);
|
||||
|
||||
if (groupchats[groupnum].audio.dvhandle == NULL)
|
||||
return -1;
|
||||
|
||||
groupchats[groupnum].audio.dvctx = alcCreateContext(groupchats[groupnum].audio.dvhandle, NULL);
|
||||
alcMakeContextCurrent(groupchats[groupnum].audio.dvctx);
|
||||
alGenBuffers(OPENAL_BUFS, groupchats[groupnum].audio.buffers);
|
||||
alGenSources((uint32_t) 1, &groupchats[groupnum].audio.source);
|
||||
alSourcei(groupchats[groupnum].audio.source, AL_LOOPING, AL_FALSE);
|
||||
|
||||
if (alcGetError(groupchats[groupnum].audio.dvhandle) != AL_NO_ERROR) {
|
||||
group_audio_close_out_device(groupnum);
|
||||
groupchats[groupnum].audio.dvhandle = NULL;
|
||||
groupchats[groupnum].audio.dvctx = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
alSourceQueueBuffers(groupchats[groupnum].audio.source, OPENAL_BUFS, groupchats[groupnum].audio.buffers);
|
||||
alSourcePlay(groupchats[groupnum].audio.source);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int group_audio_close_out_device(int groupnum)
|
||||
{
|
||||
if (!groupchats[groupnum].audio.dvhandle)
|
||||
return -1;
|
||||
|
||||
if (!groupchats[groupnum].audio.dvctx)
|
||||
return -1;
|
||||
|
||||
if (alcGetCurrentContext() != groupchats[groupnum].audio.dvctx)
|
||||
alcMakeContextCurrent(groupchats[groupnum].audio.dvctx);
|
||||
|
||||
alDeleteSources((uint32_t) 1, &groupchats[groupnum].audio.source);
|
||||
alDeleteBuffers(OPENAL_BUFS, groupchats[groupnum].audio.buffers);
|
||||
|
||||
alcMakeContextCurrent(NULL);
|
||||
alcDestroyContext(groupchats[groupnum].audio.dvctx);
|
||||
|
||||
if (!alcCloseDevice(groupchats[groupnum].audio.dvhandle))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// static int group_audio_write(int peernum, int groupnum, const int16_t *pcm, unsigned int samples, uint8_t channels,
|
||||
// unsigned int sample_rate)
|
||||
// {
|
||||
// if (!pcm)
|
||||
// return -1;
|
||||
|
||||
// if (channels == 0 || channels > 2)
|
||||
// return -2;
|
||||
|
||||
// ALuint bufid;
|
||||
// ALint processed = 0, queued = 0;
|
||||
|
||||
// alGetSourcei(groupchats[groupnum].audio.source, AL_BUFFERS_PROCESSED, &processed);
|
||||
// alGetSourcei(groupchats[groupnum].audio.source, AL_BUFFERS_QUEUED, &queued);
|
||||
// fprintf(stderr, "source: %d, queued: %d, processed: %d\n", groupchats[groupnum].audio.source, queued, processed);
|
||||
|
||||
// if (processed) {
|
||||
// ALuint bufids[processed];
|
||||
// alSourceUnqueueBuffers(groupchats[groupnum].audio.source, processed, bufids);
|
||||
// alDeleteBuffers(processed - 1, bufids + 1);
|
||||
// bufid = bufids[0];
|
||||
// } else if (queued < 16) {
|
||||
// alGenBuffers(1, &bufid);
|
||||
// } else {
|
||||
// return -3;
|
||||
// }
|
||||
|
||||
// int length = samples * channels * sizeof(int16_t);
|
||||
|
||||
// alBufferData(bufid, (channels == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, pcm, length, sample_rate);
|
||||
// alSourceQueueBuffers(groupchats[groupnum].audio.source, 1, &bufid);
|
||||
|
||||
// ALint state;
|
||||
// alGetSourcei(groupchats[groupnum].audio.source, AL_SOURCE_STATE, &state);
|
||||
|
||||
// if (state != AL_PLAYING)
|
||||
// alSourcePlay(groupchats[groupnum].audio.source);
|
||||
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
static void groupchat_onWriteDevice(ToxWindow *self, Tox *m, uint32_t groupnum, int peernum, const int16_t *pcm,
|
||||
unsigned int samples, uint8_t channels, unsigned int sample_rate)
|
||||
{
|
||||
return;
|
||||
|
||||
// if (groupnum != self->num)
|
||||
// return;
|
||||
|
||||
// if (peernum < 0)
|
||||
// return;
|
||||
|
||||
// if (groupchats[groupnum].audio.dvhandle == NULL)
|
||||
// fprintf(stderr, "dvhandle is null)\n");
|
||||
|
||||
// if (groupchats[groupnum].audio.dvctx == NULL)
|
||||
// fprintf(stderr, "ctx is null\n");
|
||||
|
||||
// int ret = group_audio_write(peernum, groupnum, pcm, samples, channels, sample_rate);
|
||||
// fprintf(stderr, "write: %d\n", ret);
|
||||
}
|
||||
#endif /* AUDIO */
|
||||
|
||||
ToxWindow new_group_chat(Tox *m, int groupnum)
|
||||
ToxWindow new_group_chat(Tox *m, uint32_t groupnum)
|
||||
{
|
||||
ToxWindow ret;
|
||||
memset(&ret, 0, sizeof(ret));
|
||||
@ -898,13 +728,8 @@ ToxWindow new_group_chat(Tox *m, int groupnum)
|
||||
ret.onInit = &groupchat_onInit;
|
||||
ret.onGroupMessage = &groupchat_onGroupMessage;
|
||||
ret.onGroupNamelistChange = &groupchat_onGroupNamelistChange;
|
||||
ret.onGroupAction = &groupchat_onGroupAction;
|
||||
ret.onGroupTitleChange = &groupchat_onGroupTitleChange;
|
||||
|
||||
#ifdef AUDIO
|
||||
ret.onWriteDevice = &groupchat_onWriteDevice;
|
||||
#endif
|
||||
|
||||
snprintf(ret.name, sizeof(ret.name), "Group %d", groupnum);
|
||||
|
||||
ChatContext *chatwin = calloc(1, sizeof(ChatContext));
|
||||
|
@ -26,61 +26,30 @@
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
|
||||
#ifdef AUDIO
|
||||
#include "audio_call.h"
|
||||
#endif
|
||||
|
||||
#ifdef AUDIO
|
||||
#ifdef __APPLE__
|
||||
#include <OpenAL/al.h>
|
||||
#include <OpenAL/alc.h>
|
||||
#else
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
/* compatibility with older versions of OpenAL */
|
||||
#ifndef ALC_ALL_DEVICES_SPECIFIER
|
||||
#include <AL/alext.h>
|
||||
#endif /* ALC_ALL_DEVICES_SPECIFIER */
|
||||
#endif /* __APPLE__ */
|
||||
#endif /* AUDIO */
|
||||
|
||||
#define SIDEBAR_WIDTH 16
|
||||
#define SDBAR_OFST 2 /* Offset for the peer number box at the top of the statusbar */
|
||||
#define MAX_GROUPCHAT_NUM MAX_WINDOWS_NUM - 2
|
||||
#define GROUP_EVENT_WAIT 3
|
||||
|
||||
#ifdef AUDIO
|
||||
struct GAudio {
|
||||
ALCdevice *dvhandle; /* Handle of device selected/opened */
|
||||
ALCcontext *dvctx;
|
||||
ALuint source;
|
||||
ALuint buffers[OPENAL_BUFS];
|
||||
};
|
||||
#endif /* AUDIO */
|
||||
|
||||
typedef struct {
|
||||
int chatwin;
|
||||
bool active;
|
||||
uint8_t type;
|
||||
int num_peers;
|
||||
uint32_t num_peers;
|
||||
int side_pos; /* current position of the sidebar - used for scrolling up and down */
|
||||
time_t start_time;
|
||||
uint8_t *peer_names;
|
||||
uint8_t *oldpeer_names;
|
||||
uint16_t *peer_name_lengths;
|
||||
uint16_t *oldpeer_name_lengths;
|
||||
|
||||
#ifdef AUDIO
|
||||
struct GAudio audio;
|
||||
#endif
|
||||
} GroupChat;
|
||||
|
||||
void close_groupchat(ToxWindow *self, Tox *m, int groupnum);
|
||||
int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum, uint8_t type);
|
||||
void close_groupchat(ToxWindow *self, Tox *m, uint32_t groupnum);
|
||||
int init_groupchat_win(ToxWindow *prompt, Tox *m, uint32_t groupnum, uint8_t type);
|
||||
|
||||
/* destroys and re-creates groupchat window with or without the peerlist */
|
||||
void redraw_groupchat_win(ToxWindow *self);
|
||||
|
||||
ToxWindow new_group_chat(Tox *m, int groupnum);
|
||||
ToxWindow new_group_chat(Tox *m, uint32_t groupnum);
|
||||
|
||||
#endif /* #define GROUPCHAT_H */
|
||||
|
@ -158,7 +158,11 @@ static void help_draw_global(ToxWindow *self)
|
||||
wprintw(win, " /log <on> or <off> : Enable/disable logging\n");
|
||||
wprintw(win, " /group <type> : Create a group chat where type: text | audio\n");
|
||||
wprintw(win, " /myid : Print your Tox ID\n");
|
||||
#ifdef QRPNG
|
||||
wprintw(win, " /myqr <txt> or <png> : Print your Tox ID's QR code to a file.\n");
|
||||
#else
|
||||
wprintw(win, " /myqr : Print your Tox ID's QR code to a file.\n");
|
||||
#endif /* QRPNG */
|
||||
wprintw(win, " /clear : Clear window history\n");
|
||||
wprintw(win, " /close : Close the current chat window\n");
|
||||
wprintw(win, " /quit or /exit : Exit Toxic\n");
|
||||
|
@ -275,9 +275,9 @@ bool input_handle(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_y)
|
||||
self->show_peerlist ^= 1;
|
||||
redraw_groupchat_win(self);
|
||||
}
|
||||
|
||||
match = true;
|
||||
}
|
||||
else if (key == user_settings->key_toggle_pastemode) {
|
||||
} else if (key == user_settings->key_toggle_pastemode) {
|
||||
self->chatwin->pastemode ^= 1;
|
||||
match = true;
|
||||
}
|
||||
|
@ -158,12 +158,14 @@ void line_info_add(ToxWindow *self, const char *timestr, const char *name1, cons
|
||||
/* for type-specific formatting in print function */
|
||||
switch (type) {
|
||||
case IN_ACTION:
|
||||
|
||||
/* fallthrough */
|
||||
case OUT_ACTION:
|
||||
len += strlen(user_settings->line_normal) + 2;
|
||||
break;
|
||||
|
||||
case IN_MSG:
|
||||
|
||||
/* fallthrough */
|
||||
case OUT_MSG:
|
||||
len += strlen(user_settings->line_normal) + 3;
|
||||
@ -304,8 +306,10 @@ void line_info_print(ToxWindow *self)
|
||||
|
||||
switch (type) {
|
||||
case OUT_MSG:
|
||||
|
||||
/* fallthrough */
|
||||
case OUT_MSG_READ:
|
||||
|
||||
/* fallthrough */
|
||||
case IN_MSG:
|
||||
wattron(win, COLOR_PAIR(BLUE));
|
||||
@ -324,8 +328,8 @@ void line_info_print(ToxWindow *self)
|
||||
wattroff(win, COLOR_PAIR(nameclr));
|
||||
|
||||
char *msg = line->msg;
|
||||
while (msg)
|
||||
{
|
||||
|
||||
while (msg) {
|
||||
char *line = strsep(&msg, "\n");
|
||||
|
||||
if (line[0] == '>')
|
||||
@ -360,8 +364,10 @@ void line_info_print(ToxWindow *self)
|
||||
break;
|
||||
|
||||
case OUT_ACTION_READ:
|
||||
|
||||
/* fallthrough */
|
||||
case OUT_ACTION:
|
||||
|
||||
/* fallthrough */
|
||||
case IN_ACTION:
|
||||
wattron(win, COLOR_PAIR(BLUE));
|
||||
@ -548,20 +554,15 @@ bool line_info_onKey(ToxWindow *self, wint_t key)
|
||||
|
||||
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 {
|
||||
} else {
|
||||
match = false;
|
||||
}
|
||||
|
||||
|
@ -262,6 +262,7 @@ int rename_logfile(char *src, char *dest, const char *selfkey, const char *other
|
||||
return 0;
|
||||
|
||||
on_error:
|
||||
|
||||
if (log_on)
|
||||
log_enable(src, selfkey, otherkey, log, LOG_CHAT);
|
||||
|
||||
|
@ -26,9 +26,13 @@
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#if defined(__FreeBSD__)
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
@ -319,35 +323,53 @@ void str_to_lower(char *str)
|
||||
Returns nick len */
|
||||
size_t get_nick_truncate(Tox *m, char *buf, uint32_t friendnum)
|
||||
{
|
||||
size_t len = tox_friend_get_name_size(m, friendnum, NULL);
|
||||
TOX_ERR_FRIEND_QUERY err;
|
||||
size_t len = tox_friend_get_name_size(m, friendnum, &err);
|
||||
|
||||
if (len == 0) {
|
||||
strcpy(buf, UNKNOWN_NAME);
|
||||
len = strlen(UNKNOWN_NAME);
|
||||
if (err != TOX_ERR_FRIEND_QUERY_OK) {
|
||||
goto on_error;
|
||||
} else {
|
||||
tox_friend_get_name(m, friendnum, (uint8_t *) buf, NULL);
|
||||
if (!tox_friend_get_name(m, friendnum, (uint8_t *) buf, NULL)) {
|
||||
goto on_error;
|
||||
}
|
||||
}
|
||||
|
||||
len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1);
|
||||
buf[len] = '\0';
|
||||
filter_str(buf, len);
|
||||
return len;
|
||||
|
||||
on_error:
|
||||
strcpy(buf, UNKNOWN_NAME);
|
||||
len = strlen(UNKNOWN_NAME);
|
||||
buf[len] = '\0';
|
||||
return len;
|
||||
}
|
||||
|
||||
/* same as get_nick_truncate but for groupchats */
|
||||
int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum)
|
||||
int get_group_nick_truncate(Tox *m, char *buf, uint32_t peernum, uint32_t groupnum)
|
||||
{
|
||||
int len = tox_group_peername(m, groupnum, peernum, (uint8_t *) buf);
|
||||
TOX_ERR_CONFERENCE_PEER_QUERY err;
|
||||
size_t len = tox_conference_peer_get_name_size(m, groupnum, peernum, &err);
|
||||
|
||||
if (len == -1) {
|
||||
strcpy(buf, UNKNOWN_NAME);
|
||||
len = strlen(UNKNOWN_NAME);
|
||||
if (err != TOX_ERR_CONFERENCE_PEER_QUERY_OK) {
|
||||
goto on_error;
|
||||
} else {
|
||||
if (!tox_conference_peer_get_name(m, groupnum, peernum, (uint8_t *) buf, NULL)) {
|
||||
goto on_error;
|
||||
}
|
||||
}
|
||||
|
||||
len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1);
|
||||
buf[len] = '\0';
|
||||
filter_str(buf, len);
|
||||
return len;
|
||||
|
||||
on_error:
|
||||
strcpy(buf, UNKNOWN_NAME);
|
||||
len = strlen(UNKNOWN_NAME);
|
||||
buf[len] = '\0';
|
||||
return len;
|
||||
}
|
||||
|
||||
/* copies data to msg buffer.
|
||||
|
@ -126,7 +126,7 @@ void str_to_lower(char *str);
|
||||
size_t get_nick_truncate(Tox *m, char *buf, uint32_t friendnum);
|
||||
|
||||
/* same as get_nick_truncate but for groupchats */
|
||||
int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum);
|
||||
int get_group_nick_truncate(Tox *m, char *buf, uint32_t peernum, uint32_t groupnum);
|
||||
|
||||
/* copies data to msg buffer.
|
||||
returns length of msg, which will be no larger than size-1 */
|
||||
|
@ -249,21 +249,29 @@ void *lookup_thread_func(void *data)
|
||||
}
|
||||
|
||||
struct Recv_Curl_Data recv_data;
|
||||
|
||||
memset(&recv_data, 0, sizeof(struct Recv_Curl_Data));
|
||||
|
||||
char post_data[MAX_STR_SIZE];
|
||||
|
||||
snprintf(post_data, sizeof(post_data), "{\"action\": 3, \"name\": \"%s\"}", name);
|
||||
|
||||
struct curl_slist *headers = NULL;
|
||||
|
||||
headers = curl_slist_append(headers, "Content-Type: application/json");
|
||||
|
||||
headers = curl_slist_append(headers, "charsets: utf-8");
|
||||
|
||||
curl_easy_setopt(c_handle, CURLOPT_HTTPHEADER, headers);
|
||||
|
||||
curl_easy_setopt(c_handle, CURLOPT_URL, real_domain);
|
||||
|
||||
curl_easy_setopt(c_handle, CURLOPT_WRITEFUNCTION, curl_cb_write_data);
|
||||
|
||||
curl_easy_setopt(c_handle, CURLOPT_WRITEDATA, &recv_data);
|
||||
|
||||
curl_easy_setopt(c_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
|
||||
|
||||
curl_easy_setopt(c_handle, CURLOPT_POSTFIELDS, post_data);
|
||||
|
||||
int proxy_ret = set_curl_proxy(c_handle, arg_opts.proxy_address, arg_opts.proxy_port, arg_opts.proxy_type);
|
||||
|
60
src/notify.c
60
src/notify.c
@ -189,11 +189,13 @@ void graceful_clear()
|
||||
for (i = 0; i < ACTIVE_NOTIFS_MAX; i ++) {
|
||||
if (actives[i].active) {
|
||||
#ifdef BOX_NOTIFY
|
||||
|
||||
if (actives[i].box) {
|
||||
GError *ignore;
|
||||
notify_notification_close(actives[i].box, &ignore);
|
||||
actives[i].box = NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (actives[i].id_indicator)
|
||||
@ -240,10 +242,12 @@ void* do_playing(void* _p)
|
||||
for (i = 0; i < ACTIVE_NOTIFS_MAX; i ++) {
|
||||
|
||||
if (actives[i].looping) has_looping = true;
|
||||
|
||||
test_active_notify = actives[i].active && !actives[i].looping;
|
||||
#ifdef BOX_NOTIFY
|
||||
test_active_notify = test_active_notify && !actives[i].box;
|
||||
#endif
|
||||
|
||||
if (test_active_notify) {
|
||||
if (actives[i].id_indicator)
|
||||
*actives[i].id_indicator = -1; /* reset indicator value */
|
||||
@ -256,12 +260,13 @@ void* do_playing(void* _p)
|
||||
memset(&actives[i], 0, sizeof(struct _ActiveNotifications));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BOX_NOTIFY
|
||||
else if (actives[i].box && time(NULL) >= actives[i].n_timeout)
|
||||
{
|
||||
else if (actives[i].box && time(NULL) >= actives[i].n_timeout) {
|
||||
GError *ignore;
|
||||
notify_notification_close(actives[i].box, &ignore);
|
||||
actives[i].box = NULL;
|
||||
|
||||
if (actives[i].id_indicator)
|
||||
*actives[i].id_indicator = -1; /* reset indicator value */
|
||||
|
||||
@ -273,6 +278,7 @@ void* do_playing(void* _p)
|
||||
memset(&actives[i], 0, sizeof(struct _ActiveNotifications));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -281,18 +287,22 @@ void* do_playing(void* _p)
|
||||
(time(NULL) - last_opened_update) > DEVICE_COOLDOWN) {
|
||||
m_close_device();
|
||||
}
|
||||
|
||||
has_looping = false;
|
||||
|
||||
control_unlock();
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
int play_source(uint32_t source, uint32_t buffer, bool looping)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (; i < ACTIVE_NOTIFS_MAX && actives[i].active; i ++);
|
||||
|
||||
if ( i == ACTIVE_NOTIFS_MAX ) {
|
||||
return -1; /* Full */
|
||||
}
|
||||
@ -323,20 +333,22 @@ void* do_playing(void* _p)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ACTIVE_NOTIFS_MAX; i ++) {
|
||||
if (actives[i].box && time(NULL) >= actives[i].n_timeout)
|
||||
{
|
||||
if (actives[i].box && time(NULL) >= actives[i].n_timeout) {
|
||||
GError *ignore;
|
||||
notify_notification_close(actives[i].box, &ignore);
|
||||
actives[i].box = NULL;
|
||||
|
||||
if (actives[i].id_indicator)
|
||||
*actives[i].id_indicator = -1; /* reset indicator value */
|
||||
|
||||
memset(&actives[i], 0, sizeof(struct _ActiveNotifications));
|
||||
}
|
||||
}
|
||||
|
||||
control_unlock();
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
@ -378,6 +390,7 @@ int init_notify(int login_cooldown, int notification_timeout)
|
||||
#endif /* SOUND_NOTIFY */
|
||||
|
||||
#if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY)
|
||||
|
||||
if (pthread_mutex_init(Control.poll_mutex, NULL) != 0)
|
||||
return -1;
|
||||
|
||||
@ -419,7 +432,9 @@ void terminate_notify()
|
||||
|
||||
#ifdef SOUND_NOTIFY
|
||||
int i = 0;
|
||||
|
||||
for (; i < SOUNDS_SIZE; i ++) free(Control.sounds[i]);
|
||||
|
||||
alutExit();
|
||||
#endif /* SOUND_NOTIFY */
|
||||
|
||||
@ -457,6 +472,7 @@ int play_sound_internal(Notification what, bool loop)
|
||||
alSourcei(source, AL_LOOPING, loop);
|
||||
|
||||
int rc = play_source(source, buffer, loop);
|
||||
|
||||
if (rc < 0) {
|
||||
alSourceStop(source);
|
||||
alDeleteSources(1, &source);
|
||||
@ -472,6 +488,7 @@ int play_notify_sound(Notification notif, uint64_t flags)
|
||||
int rc = -1;
|
||||
|
||||
if (flags & NT_BEEP) beep();
|
||||
|
||||
if (notif != silent) {
|
||||
if ( !Control.poll_active || !Control.sounds[notif] )
|
||||
return -1;
|
||||
@ -487,13 +504,17 @@ void stop_sound(int id)
|
||||
{
|
||||
if (id >= 0 && id < ACTIVE_NOTIFS_MAX && actives[id].looping && actives[id].active ) {
|
||||
#ifdef BOX_NOTIFY
|
||||
|
||||
if (actives[id].box) {
|
||||
GError *ignore;
|
||||
notify_notification_close(actives[id].box, &ignore);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (actives[id].id_indicator)
|
||||
*actives[id].id_indicator = -1;
|
||||
|
||||
// alSourcei(actives[id].source, AL_LOOPING, false);
|
||||
alSourceStop(actives[id].source);
|
||||
alDeleteSources(1, &actives[id].source);
|
||||
@ -508,6 +529,7 @@ static int m_play_sound(Notification notif, uint64_t flags)
|
||||
#ifdef SOUND_NOTIFY
|
||||
return play_notify_sound(notif, flags);
|
||||
#else
|
||||
|
||||
if (notif != silent)
|
||||
beep();
|
||||
|
||||
@ -540,6 +562,7 @@ int sound_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_in
|
||||
|
||||
if (id == -1) {
|
||||
for (id = 0; id < ACTIVE_NOTIFS_MAX && actives[id].box; id++);
|
||||
|
||||
if ( id == ACTIVE_NOTIFS_MAX ) {
|
||||
control_unlock();
|
||||
return -1; /* Full */
|
||||
@ -566,6 +589,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
|
||||
control_lock();
|
||||
|
||||
@ -592,6 +616,7 @@ int sound_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id)
|
||||
|
||||
return id;
|
||||
#else
|
||||
|
||||
if (notif != silent)
|
||||
beep();
|
||||
|
||||
@ -599,7 +624,8 @@ int sound_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id)
|
||||
#endif /* SOUND_NOTIFY */
|
||||
}
|
||||
|
||||
int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indicator, const char* title, const char* format, ...)
|
||||
int box_notify(ToxWindow *self, Notification notif, uint64_t flags, int *id_indicator, const char *title,
|
||||
const char *format, ...)
|
||||
{
|
||||
if (notifications_are_disabled(flags)) {
|
||||
tab_notify(self, flags);
|
||||
@ -613,9 +639,11 @@ int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indi
|
||||
control_lock();
|
||||
|
||||
#ifdef SOUND_NOTIFY
|
||||
|
||||
if (id == -1) { /* Could not play */
|
||||
|
||||
for (id = 0; id < ACTIVE_NOTIFS_MAX && actives[id].active; id ++);
|
||||
|
||||
if ( id == ACTIVE_NOTIFS_MAX ) {
|
||||
control_unlock();
|
||||
return -1; /* Full */
|
||||
@ -623,17 +651,23 @@ int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indi
|
||||
|
||||
actives[id].active = 1;
|
||||
actives[id].id_indicator = id_indicator;
|
||||
|
||||
if (id_indicator) *id_indicator = id;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
if (id == -1)
|
||||
return -1;
|
||||
|
||||
#endif /* SOUND_NOTIFY */
|
||||
|
||||
snprintf(actives[id].title, sizeof(actives[id].title), "%s", title);
|
||||
|
||||
if (strlen(title) > 23) strcpy(actives[id].title + 20, "...");
|
||||
|
||||
va_list __ARGS__; va_start (__ARGS__, format);
|
||||
va_list __ARGS__;
|
||||
va_start (__ARGS__, format);
|
||||
vsnprintf (actives[id].messages[0], MAX_BOX_MSG_LEN, format, __ARGS__);
|
||||
va_end (__ARGS__);
|
||||
|
||||
@ -675,7 +709,8 @@ int box_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id, con
|
||||
return -1;
|
||||
}
|
||||
|
||||
va_list __ARGS__; va_start (__ARGS__, format);
|
||||
va_list __ARGS__;
|
||||
va_start (__ARGS__, format);
|
||||
vsnprintf (actives[id].messages[actives[id].size], MAX_BOX_MSG_LEN, format, __ARGS__);
|
||||
va_end (__ARGS__);
|
||||
|
||||
@ -688,6 +723,7 @@ int box_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id, con
|
||||
char formated[128 * 129] = {'\0'};
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (; i < actives[id].size; i ++) {
|
||||
strcat(formated, actives[id].messages[i]);
|
||||
strcat(formated, "\n");
|
||||
@ -718,7 +754,9 @@ int box_silent_notify(ToxWindow* self, uint64_t flags, int* id_indicator, const
|
||||
control_lock();
|
||||
|
||||
int id;
|
||||
|
||||
for (id = 0; id < ACTIVE_NOTIFS_MAX && actives[id].active; id ++);
|
||||
|
||||
if ( id == ACTIVE_NOTIFS_MAX ) {
|
||||
control_unlock();
|
||||
return -1; /* Full */
|
||||
@ -730,9 +768,11 @@ int box_silent_notify(ToxWindow* self, uint64_t flags, int* id_indicator, const
|
||||
}
|
||||
|
||||
snprintf(actives[id].title, sizeof(actives[id].title), "%s", title);
|
||||
|
||||
if (strlen(title) > 23) strcpy(actives[id].title + 20, "...");
|
||||
|
||||
va_list __ARGS__; va_start (__ARGS__, format);
|
||||
va_list __ARGS__;
|
||||
va_start (__ARGS__, format);
|
||||
vsnprintf (actives[id].messages[0], MAX_BOX_MSG_LEN, format, __ARGS__);
|
||||
va_end (__ARGS__);
|
||||
|
||||
@ -772,7 +812,8 @@ int box_silent_notify2(ToxWindow* self, uint64_t flags, int id, const char* form
|
||||
}
|
||||
|
||||
|
||||
va_list __ARGS__; va_start (__ARGS__, format);
|
||||
va_list __ARGS__;
|
||||
va_start (__ARGS__, format);
|
||||
vsnprintf (actives[id].messages[actives[id].size], MAX_BOX_MSG_LEN, format, __ARGS__);
|
||||
va_end (__ARGS__);
|
||||
|
||||
@ -785,6 +826,7 @@ int box_silent_notify2(ToxWindow* self, uint64_t flags, int id, const char* form
|
||||
char formated[128 * 129] = {'\0'};
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (; i < actives[id].size; i ++) {
|
||||
strcat(formated, actives[id].messages[i]);
|
||||
strcat(formated, "\n");
|
||||
|
@ -26,8 +26,7 @@
|
||||
#include <inttypes.h>
|
||||
#include "windows.h"
|
||||
|
||||
typedef enum _Notification
|
||||
{
|
||||
typedef enum _Notification {
|
||||
silent = -1,
|
||||
notif_error,
|
||||
self_log_in,
|
||||
@ -68,7 +67,8 @@ int sound_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id);
|
||||
|
||||
void stop_sound(int id);
|
||||
|
||||
int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indicator, const char* title, const char* format, ...);
|
||||
int box_notify(ToxWindow *self, Notification notif, uint64_t flags, int *id_indicator, const char *title,
|
||||
const char *format, ...);
|
||||
int box_notify2(ToxWindow *self, Notification notif, uint64_t flags, int id, const char *format, ...);
|
||||
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, ...);
|
||||
|
@ -36,8 +36,11 @@
|
||||
void bgrtoyuv420(uint8_t *plane_y, uint8_t *plane_u, uint8_t *plane_v, uint8_t *rgb, uint16_t width, uint16_t height);
|
||||
|
||||
#ifdef __OBJC__
|
||||
@interface OSXVideo : NSObject <AVCaptureVideoDataOutputSampleBufferDelegate>
|
||||
- (instancetype)initWithDeviceNames:(char **)device_names AmtDevices:(int *)size;
|
||||
@interface OSXVideo :
|
||||
NSObject <AVCaptureVideoDataOutputSampleBufferDelegate>
|
||||
- (instancetype)initWithDeviceNames:
|
||||
(char **)device_names AmtDevices:
|
||||
(int *)size;
|
||||
@end
|
||||
#endif /* __OBJC__ */
|
||||
|
||||
|
@ -67,6 +67,7 @@ void bgrxtoyuv420(uint8_t *plane_y, uint8_t *plane_u, uint8_t *plane_v, uint8_t
|
||||
|
||||
for (y = 0; y != height; y += 2) {
|
||||
p = rgb;
|
||||
|
||||
for (x = 0; x != width; x++) {
|
||||
b = *rgb++;
|
||||
g = *rgb++;
|
||||
@ -91,9 +92,12 @@ void bgrxtoyuv420(uint8_t *plane_y, uint8_t *plane_u, uint8_t *plane_v, uint8_t
|
||||
|
||||
*plane_y++ = rgb_to_y(r, g, b);
|
||||
|
||||
b = ((int)b + (int)*(rgb - 8) + (int)*p + (int)*(p + 4) + 2) / 4; p++;
|
||||
g = ((int)g + (int)*(rgb - 7) + (int)*p + (int)*(p + 4) + 2) / 4; p++;
|
||||
r = ((int)r + (int)*(rgb - 6) + (int)*p + (int)*(p + 4) + 2) / 4; p++;
|
||||
b = ((int)b + (int) * (rgb - 8) + (int) * p + (int) * (p + 4) + 2) / 4;
|
||||
p++;
|
||||
g = ((int)g + (int) * (rgb - 7) + (int) * p + (int) * (p + 4) + 2) / 4;
|
||||
p++;
|
||||
r = ((int)r + (int) * (rgb - 6) + (int) * p + (int) * (p + 4) + 2) / 4;
|
||||
p++;
|
||||
p++;
|
||||
|
||||
*plane_u++ = rgb_to_u(r, g, b);
|
||||
@ -122,11 +126,15 @@ void bgrxtoyuv420(uint8_t *plane_y, uint8_t *plane_u, uint8_t *plane_v, uint8_t
|
||||
BOOL _shouldMangleDimensions;
|
||||
}
|
||||
|
||||
- (instancetype)initWithDeviceNames: (char **)device_names AmtDevices: (int *)size {
|
||||
- (instancetype)initWithDeviceNames:
|
||||
(char **)device_names AmtDevices:
|
||||
(int *)size
|
||||
{
|
||||
_session = [[AVCaptureSession alloc] init];
|
||||
|
||||
NSArray *devices = [AVCaptureDevice devicesWithMediaType: AVMediaTypeVideo];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < [devices count]; ++i) {
|
||||
AVCaptureDevice *device = [devices objectAtIndex: i];
|
||||
char *video_input_name;
|
||||
@ -138,12 +146,14 @@ void bgrxtoyuv420(uint8_t *plane_y, uint8_t *plane_u, uint8_t *plane_v, uint8_t
|
||||
|
||||
if ( i <= 0 )
|
||||
return nil;
|
||||
|
||||
*size = i;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
- (void)dealloc
|
||||
{
|
||||
pthread_mutex_destroy(&_frameLock);
|
||||
[_session release];
|
||||
[_linkerVideo release];
|
||||
@ -151,7 +161,11 @@ void bgrxtoyuv420(uint8_t *plane_y, uint8_t *plane_u, uint8_t *plane_v, uint8_t
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (int)openVideoDeviceIndex: (uint32_t)device_idx Width: (uint16_t *)width Height: (uint16_t *)height {
|
||||
- (int)openVideoDeviceIndex:
|
||||
(uint32_t)device_idx Width:
|
||||
(uint16_t *)width Height:
|
||||
(uint16_t *)height
|
||||
{
|
||||
pthread_mutex_init(&_frameLock, NULL);
|
||||
pthread_mutex_lock(&_frameLock);
|
||||
_processingQueue = dispatch_queue_create("Toxic processing queue", DISPATCH_QUEUE_SERIAL);
|
||||
@ -178,6 +192,7 @@ void bgrxtoyuv420(uint8_t *plane_y, uint8_t *plane_u, uint8_t *plane_v, uint8_t
|
||||
/* Obtain device resolution */
|
||||
AVCaptureInputPort *port = [input.ports objectAtIndex: 0];
|
||||
CMFormatDescriptionRef format_description = port.formatDescription;
|
||||
|
||||
if ( format_description ) {
|
||||
CMVideoDimensions dimensions = CMVideoFormatDescriptionGetDimensions(format_description);
|
||||
*width = dimensions.width;
|
||||
@ -189,14 +204,18 @@ void bgrxtoyuv420(uint8_t *plane_y, uint8_t *plane_u, uint8_t *plane_v, uint8_t
|
||||
|
||||
_linkerVideo = [[AVCaptureVideoDataOutput alloc] init];
|
||||
[_linkerVideo setSampleBufferDelegate: self queue: _processingQueue];
|
||||
|
||||
// TODO possibly get a better pixel format
|
||||
if (_shouldMangleDimensions) {
|
||||
[_linkerVideo setVideoSettings:@{(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA),
|
||||
[_linkerVideo setVideoSettings: @ {
|
||||
(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA),
|
||||
(id)kCVPixelBufferWidthKey: @640,
|
||||
(id)kCVPixelBufferHeightKey: @480}];
|
||||
(id)kCVPixelBufferHeightKey: @480
|
||||
}];
|
||||
} else {
|
||||
[_linkerVideo setVideoSettings: @ {(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA)}];
|
||||
}
|
||||
|
||||
[_session addOutput: _linkerVideo];
|
||||
[_session startRunning];
|
||||
|
||||
@ -204,7 +223,9 @@ void bgrxtoyuv420(uint8_t *plane_y, uint8_t *plane_u, uint8_t *plane_v, uint8_t
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (void)closeVideoDeviceIndex: (uint32_t)device_idx {
|
||||
- (void)closeVideoDeviceIndex:
|
||||
(uint32_t)device_idx
|
||||
{
|
||||
NSArray *devices = [AVCaptureDevice devicesWithMediaType: AVMediaTypeVideo];
|
||||
AVCaptureDevice *device = [devices objectAtIndex: device_idx];
|
||||
NSError *error = NULL;
|
||||
@ -215,9 +236,14 @@ void bgrxtoyuv420(uint8_t *plane_y, uint8_t *plane_u, uint8_t *plane_v, uint8_t
|
||||
[_linkerVideo release];
|
||||
}
|
||||
|
||||
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
|
||||
- (void)captureOutput:
|
||||
(AVCaptureOutput *)captureOutput didOutputSampleBuffer:
|
||||
(CMSampleBufferRef)sampleBuffer fromConnection:
|
||||
(AVCaptureConnection *)connection
|
||||
{
|
||||
pthread_mutex_lock(&_frameLock);
|
||||
CVImageBufferRef img = CMSampleBufferGetImageBuffer(sampleBuffer);
|
||||
|
||||
if (!img) {
|
||||
NSLog(@"Toxic WARNING: Bad sampleBuffer from AVfoundation!");
|
||||
} else {
|
||||
@ -228,10 +254,17 @@ void bgrxtoyuv420(uint8_t *plane_y, uint8_t *plane_u, uint8_t *plane_v, uint8_t
|
||||
// we're not going to do anything to it, so it's safe to lock it always
|
||||
CVPixelBufferLockBaseAddress(_currentFrame, kCVPixelBufferLock_ReadOnly);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&_frameLock);
|
||||
}
|
||||
|
||||
- (int)getVideoFrameY: (uint8_t *)y U: (uint8_t *)u V: (uint8_t *)v Width: (uint16_t *)width Height: (uint16_t *)height {
|
||||
- (int)getVideoFrameY:
|
||||
(uint8_t *)y U:
|
||||
(uint8_t *)u V:
|
||||
(uint8_t *)v Width:
|
||||
(uint16_t *)width Height:
|
||||
(uint16_t *)height
|
||||
{
|
||||
if (!_currentFrame) {
|
||||
return -1;
|
||||
}
|
||||
@ -240,6 +273,7 @@ void bgrxtoyuv420(uint8_t *plane_y, uint8_t *plane_u, uint8_t *plane_v, uint8_t
|
||||
CFRetain(_currentFrame);
|
||||
|
||||
CFTypeID imageType = CFGetTypeID(_currentFrame);
|
||||
|
||||
if (imageType == CVPixelBufferGetTypeID()) {
|
||||
// TODO maybe handle other formats
|
||||
bgrxtoyuv420(y, u, v, CVPixelBufferGetBaseAddress(_currentFrame), *width, *height);
|
||||
|
@ -238,8 +238,7 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
} else if (key == '\r') {
|
||||
rm_trailing_spaces_buf(ctx);
|
||||
|
||||
if (!wstring_is_empty(ctx->line))
|
||||
{
|
||||
if (!wstring_is_empty(ctx->line)) {
|
||||
add_line_to_hist(ctx);
|
||||
wstrsubst(ctx->line, L'¶', L'\n');
|
||||
|
||||
@ -301,10 +300,12 @@ static void prompt_onDraw(ToxWindow *self, Tox *m)
|
||||
status_text = "Online";
|
||||
colour = GREEN;
|
||||
break;
|
||||
|
||||
case TOX_USER_STATUS_AWAY:
|
||||
status_text = "Away";
|
||||
colour = YELLOW;
|
||||
break;
|
||||
|
||||
case TOX_USER_STATUS_BUSY:
|
||||
status_text = "Busy";
|
||||
colour = RED;
|
||||
@ -404,8 +405,7 @@ static void prompt_onConnectionChange(ToxWindow *self, Tox *m, uint32_t friendnu
|
||||
else
|
||||
box_notify(self, user_log_in, NT_WNDALERT_2 | NT_NOTIFWND | NT_RESTOL, &self->active_box,
|
||||
"Toxic", "%s has come online", nick );
|
||||
}
|
||||
else if (connection_status == TOX_CONNECTION_NONE) {
|
||||
} else if (connection_status == TOX_CONNECTION_NONE) {
|
||||
msg = "has gone offline";
|
||||
line_info_add(self, timefrmt, nick, NULL, DISCONNECTION, 0, RED, msg);
|
||||
write_to_log(msg, nick, ctx->log, true);
|
||||
|
127
src/qr_code.c
127
src/qr_code.c
@ -23,30 +23,42 @@
|
||||
#include <stdlib.h>
|
||||
#include <qrencode.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
#include "qr_code.h"
|
||||
|
||||
#ifdef QRPNG
|
||||
#include <png.h>
|
||||
#define INCHES_PER_METER (100.0/2.54)
|
||||
#define DPI 72
|
||||
#define SQUARE_SIZE 5
|
||||
#endif /* QRPNG */
|
||||
|
||||
#define BORDER_LEN 1
|
||||
#define CHAR_1 "\342\226\210"
|
||||
#define CHAR_2 "\342\226\204"
|
||||
#define CHAR_3 "\342\226\200"
|
||||
|
||||
/* Converts a tox ID string into a QRcode and prints it to the given file stream.
|
||||
/* Converts a tox ID string into a QRcode and prints it into the given filename.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
* Returns -1 on failure.
|
||||
*/
|
||||
int ID_to_QRcode(const char *tox_id, FILE *fp)
|
||||
int ID_to_QRcode_txt(const char *tox_id, const char *outfile)
|
||||
{
|
||||
FILE *fp = fopen(outfile, "wb");
|
||||
|
||||
if (fp == NULL)
|
||||
return -1;
|
||||
|
||||
QRcode *qr_obj = QRcode_encodeString(tox_id, 0, QR_ECLEVEL_L, QR_MODE_8, 0);
|
||||
|
||||
if (qr_obj == NULL)
|
||||
if (qr_obj == NULL) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t width = qr_obj->width;
|
||||
size_t i, j;
|
||||
@ -83,7 +95,116 @@ int ID_to_QRcode(const char *tox_id, FILE *fp)
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
QRcode_free(qr_obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef QRPNG
|
||||
/* Converts a tox ID string into a QRcode and prints it into the given filename as png.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
* Returns -1 on failure.
|
||||
*/
|
||||
int ID_to_QRcode_png(const char *tox_id, const char *outfile)
|
||||
{
|
||||
static FILE *fp;
|
||||
unsigned char *p;
|
||||
unsigned char black[4] = {0, 0, 0, 255};
|
||||
size_t x, y, xx, yy, real_width;
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
|
||||
fp = fopen(outfile, "wb");
|
||||
|
||||
if (fp == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
QRcode *qr_obj = QRcode_encodeString(tox_id, 0, QR_ECLEVEL_L, QR_MODE_8, 0);
|
||||
|
||||
if (qr_obj == NULL) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
real_width = (qr_obj->width + BORDER_LEN * 2) * SQUARE_SIZE;
|
||||
size_t row_size = real_width * 4;
|
||||
unsigned char row[row_size];
|
||||
|
||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
|
||||
if (png_ptr == NULL) {
|
||||
fclose(fp);
|
||||
QRcode_free(qr_obj);
|
||||
return -1;
|
||||
}
|
||||
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
|
||||
if (info_ptr == NULL) {
|
||||
fclose(fp);
|
||||
QRcode_free(qr_obj);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
fclose(fp);
|
||||
QRcode_free(qr_obj);
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
png_init_io(png_ptr, fp);
|
||||
png_set_IHDR(png_ptr, info_ptr, real_width, real_width, 8,
|
||||
PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||
png_set_pHYs(png_ptr, info_ptr, DPI * INCHES_PER_METER,
|
||||
DPI * INCHES_PER_METER, PNG_RESOLUTION_METER);
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
|
||||
/* top margin */
|
||||
memset(row, 0xff, row_size);
|
||||
|
||||
for (y = 0; y < BORDER_LEN * SQUARE_SIZE; y++) {
|
||||
png_write_row(png_ptr, row);
|
||||
}
|
||||
|
||||
/* data */
|
||||
p = qr_obj->data;
|
||||
|
||||
for (y = 0; y < qr_obj->width; y++) {
|
||||
memset(row, 0xff, row_size);
|
||||
|
||||
for (x = 0; x < qr_obj->width; x++) {
|
||||
for (xx = 0; xx < SQUARE_SIZE; xx++) {
|
||||
if (*p & 1) {
|
||||
memcpy(&row[((BORDER_LEN + x) * SQUARE_SIZE + xx) * 4], black, 4);
|
||||
}
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
|
||||
for (yy = 0; yy < SQUARE_SIZE; yy++) {
|
||||
png_write_row(png_ptr, row);
|
||||
}
|
||||
}
|
||||
|
||||
/* bottom margin */
|
||||
memset(row, 0xff, row_size);
|
||||
|
||||
for (y = 0; y < BORDER_LEN * SQUARE_SIZE; y++) {
|
||||
png_write_row(png_ptr, row);
|
||||
}
|
||||
|
||||
png_write_end(png_ptr, info_ptr);
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
|
||||
fclose(fp);
|
||||
QRcode_free(qr_obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* QRPNG */
|
||||
|
@ -25,11 +25,21 @@
|
||||
|
||||
#define QRCODE_FILENAME_EXT ".QRcode"
|
||||
|
||||
/* Converts a tox ID string into a QRcode and prints it to the given file stream.
|
||||
/* Converts a tox ID string into a QRcode and prints it into the given filename.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
* Returns -1 on failure.
|
||||
*/
|
||||
int ID_to_QRcode(const char *tox_id, FILE *fp);
|
||||
int ID_to_QRcode_txt(const char *tox_id, const char *outfile);
|
||||
|
||||
#ifdef QRPNG
|
||||
#define QRCODE_FILENAME_EXT_PNG ".QRcode.png"
|
||||
/* Converts a tox ID string into a QRcode and prints it into the given filename as png.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
* Returns -1 on failure.
|
||||
*/
|
||||
int ID_to_QRcode_png(const char *tox_id, const char *outfile);
|
||||
#endif /* QRPNG */
|
||||
|
||||
#endif /* QR_CODE */
|
||||
|
@ -245,7 +245,8 @@ static const struct sound_strings {
|
||||
};
|
||||
#endif
|
||||
|
||||
static int key_parse(const char **bind) {
|
||||
static int key_parse(const char **bind)
|
||||
{
|
||||
int len = strlen(*bind);
|
||||
|
||||
if (len > 5) {
|
||||
@ -262,7 +263,8 @@ static int key_parse(const char **bind) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void set_key_binding(int *key, const char **bind) {
|
||||
static void set_key_binding(int *key, const char **bind)
|
||||
{
|
||||
int code = key_parse(bind);
|
||||
|
||||
if (code != -1) {
|
||||
@ -318,6 +320,7 @@ int settings_load(struct user_settings *s, const char *patharg)
|
||||
config_setting_lookup_bool(setting, ui_strings.timestamps, &s->timestamps);
|
||||
|
||||
int time = 24;
|
||||
|
||||
if ( config_setting_lookup_int(setting, ui_strings.time_format, &time) ) {
|
||||
if (time == 12) {
|
||||
snprintf(s->timestamp_format, sizeof(s->timestamp_format), "%s", "%I:%M:%S %p");
|
||||
@ -338,12 +341,15 @@ int settings_load(struct user_settings *s, const char *patharg)
|
||||
if (config_setting_lookup_bool(setting, ui_strings.bell_on_message, &s->bell_on_message)) {
|
||||
s->bell_on_message = s->bell_on_message ? NT_BEEP : 0;
|
||||
}
|
||||
|
||||
if (config_setting_lookup_bool(setting, ui_strings.bell_on_filetrans, &s->bell_on_filetrans)) {
|
||||
s->bell_on_filetrans = s->bell_on_filetrans ? NT_BEEP : 0;
|
||||
}
|
||||
|
||||
if (config_setting_lookup_bool(setting, ui_strings.bell_on_filetrans_accept, &s->bell_on_filetrans_accept)) {
|
||||
s->bell_on_filetrans_accept = s->bell_on_filetrans_accept ? NT_BEEP : 0;
|
||||
}
|
||||
|
||||
if (config_setting_lookup_bool(setting, ui_strings.bell_on_invite, &s->bell_on_invite)) {
|
||||
s->bell_on_invite = s->bell_on_invite ? NT_BEEP : 0;
|
||||
}
|
||||
@ -361,12 +367,15 @@ int settings_load(struct user_settings *s, const char *patharg)
|
||||
if ( config_setting_lookup_string(setting, ui_strings.line_join, &str) ) {
|
||||
snprintf(s->line_join, sizeof(s->line_join), "%s", str);
|
||||
}
|
||||
|
||||
if ( config_setting_lookup_string(setting, ui_strings.line_quit, &str) ) {
|
||||
snprintf(s->line_quit, sizeof(s->line_quit), "%s", str);
|
||||
}
|
||||
|
||||
if ( config_setting_lookup_string(setting, ui_strings.line_alert, &str) ) {
|
||||
snprintf(s->line_alert, sizeof(s->line_alert), "%s", str);
|
||||
}
|
||||
|
||||
if ( config_setting_lookup_string(setting, ui_strings.line_normal, &str) ) {
|
||||
snprintf(s->line_normal, sizeof(s->line_normal), "%s", str);
|
||||
}
|
||||
@ -421,31 +430,43 @@ int settings_load(struct user_settings *s, const char *patharg)
|
||||
/* keys */
|
||||
if ((setting = config_lookup(cfg, key_strings.self)) != NULL) {
|
||||
const char *tmp = NULL;
|
||||
|
||||
if (config_setting_lookup_string(setting, key_strings.next_tab, &tmp))
|
||||
set_key_binding(&s->key_next_tab, &tmp);
|
||||
|
||||
if (config_setting_lookup_string(setting, key_strings.prev_tab, &tmp))
|
||||
set_key_binding(&s->key_prev_tab, &tmp);
|
||||
|
||||
if (config_setting_lookup_string(setting, key_strings.scroll_line_up, &tmp))
|
||||
set_key_binding(&s->key_scroll_line_up, &tmp);
|
||||
|
||||
if (config_setting_lookup_string(setting, key_strings.scroll_line_down, &tmp))
|
||||
set_key_binding(&s->key_scroll_line_down, &tmp);
|
||||
|
||||
if (config_setting_lookup_string(setting, key_strings.half_page_up, &tmp))
|
||||
set_key_binding(&s->key_half_page_up, &tmp);
|
||||
|
||||
if (config_setting_lookup_string(setting, key_strings.half_page_down, &tmp))
|
||||
set_key_binding(&s->key_half_page_down, &tmp);
|
||||
|
||||
if (config_setting_lookup_string(setting, key_strings.page_bottom, &tmp))
|
||||
set_key_binding(&s->key_page_bottom, &tmp);
|
||||
|
||||
if (config_setting_lookup_string(setting, key_strings.peer_list_up, &tmp))
|
||||
set_key_binding(&s->key_peer_list_up, &tmp);
|
||||
|
||||
if (config_setting_lookup_string(setting, key_strings.peer_list_down, &tmp))
|
||||
set_key_binding(&s->key_peer_list_down, &tmp);
|
||||
|
||||
if (config_setting_lookup_string(setting, key_strings.toggle_peerlist, &tmp))
|
||||
set_key_binding(&s->key_toggle_peerlist, &tmp);
|
||||
|
||||
if (config_setting_lookup_string(setting, key_strings.toggle_pastemode, &tmp))
|
||||
set_key_binding(&s->key_toggle_pastemode, &tmp);
|
||||
}
|
||||
|
||||
#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;
|
||||
@ -455,9 +476,11 @@ int settings_load(struct user_settings *s, const char *patharg)
|
||||
|
||||
config_setting_lookup_float(setting, audio_strings.VAD_treshold, &s->VAD_treshold);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef SOUND_NOTIFY
|
||||
|
||||
if ((setting = config_lookup(cfg, sound_strings.self)) != NULL) {
|
||||
if ( (config_setting_lookup_string(setting, sound_strings.notif_error, &str) != CONFIG_TRUE) ||
|
||||
!set_sound(notif_error, str) ) {
|
||||
@ -506,8 +529,7 @@ int settings_load(struct user_settings *s, const char *patharg)
|
||||
if (str && strcasecmp(str, NO_SOUND) != 0)
|
||||
set_sound(transfer_completed, PACKAGE_DATADIR "/sounds/ToxicTransferComplete.wav");
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
set_sound(notif_error, PACKAGE_DATADIR "/sounds/ToxicError.wav");
|
||||
set_sound(user_log_in, PACKAGE_DATADIR "/sounds/ToxicContactOnline.wav");
|
||||
set_sound(user_log_out, PACKAGE_DATADIR "/sounds/ToxicContactOffline.wav");
|
||||
@ -517,6 +539,7 @@ int settings_load(struct user_settings *s, const char *patharg)
|
||||
set_sound(transfer_pending, PACKAGE_DATADIR "/sounds/ToxicTransferStart.wav");
|
||||
set_sound(transfer_completed, PACKAGE_DATADIR "/sounds/ToxicTransferComplete.wav");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
config_destroy(cfg);
|
||||
|
@ -52,8 +52,7 @@ extern struct Winthread Winthread;
|
||||
#define PATH_SEP_S "/"
|
||||
#define PATH_SEP_C '/'
|
||||
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
MPLEX_NONE,
|
||||
MPLEX_SCREEN,
|
||||
MPLEX_TMUX,
|
||||
@ -97,13 +96,14 @@ static char *read_into_dyn_buffer (FILE *stream)
|
||||
char *dyn_buffer = NULL;
|
||||
int dyn_buffer_size = 1; /* account for the \0 */
|
||||
|
||||
while ((input_ptr = fgets (buffer, BUFFER_SIZE, stream)) != NULL)
|
||||
{
|
||||
while ((input_ptr = fgets (buffer, BUFFER_SIZE, stream)) != NULL) {
|
||||
int length = dyn_buffer_size + strlen (input_ptr);
|
||||
|
||||
if (dyn_buffer)
|
||||
dyn_buffer = (char *) realloc (dyn_buffer, length);
|
||||
else
|
||||
dyn_buffer = (char *) malloc (length);
|
||||
|
||||
strcpy (dyn_buffer + dyn_buffer_size - 1, input_ptr);
|
||||
dyn_buffer_size = length;
|
||||
}
|
||||
@ -123,15 +123,18 @@ static char *extract_socket_path (const char *info)
|
||||
|
||||
pos += strlen (search_str);
|
||||
pos = strchr (pos, PATH_SEP_C);
|
||||
|
||||
if (!pos)
|
||||
return NULL;
|
||||
|
||||
end = strchr (pos, '\n');
|
||||
|
||||
if (!end)
|
||||
return NULL;
|
||||
|
||||
*end = '\0';
|
||||
end = strrchr (pos, '.');
|
||||
|
||||
if (!end)
|
||||
return NULL;
|
||||
|
||||
@ -147,14 +150,17 @@ static int detect_gnu_screen ()
|
||||
char *dyn_buffer = NULL;
|
||||
|
||||
socket_name = getenv ("STY");
|
||||
|
||||
if (!socket_name)
|
||||
goto nomplex;
|
||||
|
||||
session_info_stream = popen ("env LC_ALL=C screen -ls", "r");
|
||||
|
||||
if (!session_info_stream)
|
||||
goto nomplex;
|
||||
|
||||
dyn_buffer = read_into_dyn_buffer (session_info_stream);
|
||||
|
||||
if (!dyn_buffer)
|
||||
goto nomplex;
|
||||
|
||||
@ -162,6 +168,7 @@ static int detect_gnu_screen ()
|
||||
session_info_stream = NULL;
|
||||
|
||||
socket_path = extract_socket_path (dyn_buffer);
|
||||
|
||||
if (!socket_path)
|
||||
goto nomplex;
|
||||
|
||||
@ -181,23 +188,29 @@ static int detect_gnu_screen ()
|
||||
return 1;
|
||||
|
||||
nomplex:
|
||||
|
||||
if (session_info_stream)
|
||||
pclose (session_info_stream);
|
||||
|
||||
if (dyn_buffer)
|
||||
free (dyn_buffer);
|
||||
|
||||
if (socket_path)
|
||||
free(socket_path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int detect_tmux ()
|
||||
{
|
||||
char *tmux_env = getenv ("TMUX"), *pos;
|
||||
|
||||
if (!tmux_env)
|
||||
return 0;
|
||||
|
||||
/* find second separator */
|
||||
pos = strrchr (tmux_env, ',');
|
||||
|
||||
if (!pos)
|
||||
return 0;
|
||||
|
||||
@ -230,6 +243,7 @@ static int gnu_screen_is_detached ()
|
||||
return 0;
|
||||
|
||||
struct stat sb;
|
||||
|
||||
if (stat (mplex_data, &sb) != 0)
|
||||
return 0;
|
||||
|
||||
@ -257,10 +271,12 @@ static int tmux_is_detached ()
|
||||
const int numstr_len = strlen (mplex_data);
|
||||
|
||||
session_info_stream = popen ("env LC_ALL=C tmux list-sessions", "r");
|
||||
|
||||
if (!session_info_stream)
|
||||
goto fail;
|
||||
|
||||
dyn_buffer = read_into_dyn_buffer (session_info_stream);
|
||||
|
||||
if (!dyn_buffer)
|
||||
goto fail;
|
||||
|
||||
@ -295,12 +311,16 @@ static int tmux_is_detached ()
|
||||
return attached_pos == NULL || attached_pos > nl_pos;
|
||||
|
||||
fail:
|
||||
|
||||
if (session_info_stream)
|
||||
pclose (session_info_stream);
|
||||
|
||||
if (dyn_buffer)
|
||||
free (dyn_buffer);
|
||||
|
||||
if (search_str)
|
||||
free (search_str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -332,15 +352,11 @@ static void mplex_timer_handler (Tox *m)
|
||||
current_status = tox_self_get_status (m);
|
||||
pthread_mutex_unlock (&Winthread.lock);
|
||||
|
||||
if (auto_away_active && current_status == TOX_USER_STATUS_AWAY && !detached)
|
||||
{
|
||||
if (auto_away_active && current_status == TOX_USER_STATUS_AWAY && !detached) {
|
||||
auto_away_active = false;
|
||||
new_status = prev_status;
|
||||
new_note = prev_note;
|
||||
}
|
||||
else
|
||||
if (current_status == TOX_USER_STATUS_NONE && detached)
|
||||
{
|
||||
} else if (current_status == TOX_USER_STATUS_NONE && detached) {
|
||||
auto_away_active = true;
|
||||
prev_status = current_status;
|
||||
new_status = TOX_USER_STATUS_AWAY;
|
||||
@ -350,8 +366,7 @@ static void mplex_timer_handler (Tox *m)
|
||||
prev_note[slen] = '\0';
|
||||
pthread_mutex_unlock (&Winthread.lock);
|
||||
new_note = user_settings->mplex_away_note;
|
||||
}
|
||||
else
|
||||
} else
|
||||
return;
|
||||
|
||||
char argv[3][MAX_STR_SIZE];
|
||||
|
50
src/toxic.c
50
src/toxic.c
@ -320,8 +320,10 @@ static int password_prompt(char *buf, int size)
|
||||
/* eat overflowed stdin and return error */
|
||||
if (buf[--len] != '\n') {
|
||||
int ch;
|
||||
|
||||
while ((ch = getchar()) != '\n' && ch > 0)
|
||||
;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -338,6 +340,7 @@ static int password_eval(char *buf, int size)
|
||||
|
||||
/* Run password_eval command */
|
||||
FILE *f = popen(user_settings->password_eval, "r");
|
||||
|
||||
if (f == NULL) {
|
||||
fprintf(stderr, "Executing password_eval failed\n");
|
||||
return 0;
|
||||
@ -345,6 +348,7 @@ static int password_eval(char *buf, int size)
|
||||
|
||||
/* Get output from command */
|
||||
char *ret = fgets(buf, size, f);
|
||||
|
||||
if (ret == NULL) {
|
||||
fprintf(stderr, "Reading password from password_eval command failed\n");
|
||||
pclose(f);
|
||||
@ -353,6 +357,7 @@ static int password_eval(char *buf, int size)
|
||||
|
||||
/* Get exit status */
|
||||
int status = pclose(f);
|
||||
|
||||
if (status != 0) {
|
||||
fprintf(stderr, "password_eval command returned error %d\n", status);
|
||||
return 0;
|
||||
@ -360,6 +365,7 @@ static int password_eval(char *buf, int size)
|
||||
|
||||
/* Removez whitespace or \n at end */
|
||||
int i, len = strlen(buf);
|
||||
|
||||
for (i = len - 1; i > 0 && isspace(buf[i]); i--) {
|
||||
buf[i] = 0;
|
||||
len--;
|
||||
@ -514,24 +520,23 @@ int store_data(Tox *m, const char *path)
|
||||
|
||||
static void init_tox_callbacks(Tox *m)
|
||||
{
|
||||
tox_callback_self_connection_status(m, prompt_onSelfConnectionChange, NULL);
|
||||
tox_callback_friend_connection_status(m, on_connectionchange, NULL);
|
||||
tox_callback_friend_typing(m, on_typing_change, NULL);
|
||||
tox_callback_friend_request(m, on_request, NULL);
|
||||
tox_callback_friend_message(m, on_message, NULL);
|
||||
tox_callback_friend_name(m, on_nickchange, NULL);
|
||||
tox_callback_friend_status(m, on_statuschange, NULL);
|
||||
tox_callback_friend_status_message(m, on_statusmessagechange, NULL);
|
||||
tox_callback_friend_read_receipt(m, on_read_receipt, NULL);
|
||||
tox_callback_group_invite(m, on_groupinvite, NULL);
|
||||
tox_callback_group_message(m, on_groupmessage, NULL);
|
||||
tox_callback_group_action(m, on_groupaction, NULL);
|
||||
tox_callback_group_namelist_change(m, on_group_namelistchange, NULL);
|
||||
tox_callback_group_title(m, on_group_titlechange, NULL);
|
||||
tox_callback_file_recv(m, on_file_recv, NULL);
|
||||
tox_callback_file_chunk_request(m, on_file_chunk_request, NULL);
|
||||
tox_callback_file_recv_control(m, on_file_control, NULL);
|
||||
tox_callback_file_recv_chunk(m, on_file_recv_chunk, NULL);
|
||||
tox_callback_self_connection_status(m, prompt_onSelfConnectionChange);
|
||||
tox_callback_friend_connection_status(m, on_connectionchange);
|
||||
tox_callback_friend_typing(m, on_typing_change);
|
||||
tox_callback_friend_request(m, on_request);
|
||||
tox_callback_friend_message(m, on_message);
|
||||
tox_callback_friend_name(m, on_nickchange);
|
||||
tox_callback_friend_status(m, on_statuschange);
|
||||
tox_callback_friend_status_message(m, on_statusmessagechange);
|
||||
tox_callback_friend_read_receipt(m, on_read_receipt);
|
||||
tox_callback_conference_invite(m, on_groupinvite);
|
||||
tox_callback_conference_message(m, on_groupmessage);
|
||||
tox_callback_conference_namelist_change(m, on_group_namelistchange);
|
||||
tox_callback_conference_title(m, on_group_titlechange);
|
||||
tox_callback_file_recv(m, on_file_recv);
|
||||
tox_callback_file_chunk_request(m, on_file_chunk_request);
|
||||
tox_callback_file_recv_control(m, on_file_control);
|
||||
tox_callback_file_recv_chunk(m, on_file_recv_chunk);
|
||||
}
|
||||
|
||||
static void init_tox_options(struct Tox_Options *tox_opts)
|
||||
@ -612,6 +617,7 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, TOX_ERR_NEW
|
||||
|
||||
size_t pwlen = 0;
|
||||
int pweval = user_settings->password_eval[0];
|
||||
|
||||
if (!pweval) {
|
||||
system("clear"); // TODO: is this portable?
|
||||
printf("Enter password (q to quit) ");
|
||||
@ -626,6 +632,7 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, TOX_ERR_NEW
|
||||
} else {
|
||||
pwlen = password_prompt(user_password.pass, sizeof(user_password.pass));
|
||||
}
|
||||
|
||||
user_password.len = pwlen;
|
||||
|
||||
if (strcasecmp(user_password.pass, "q") == 0) {
|
||||
@ -739,7 +746,7 @@ static void do_toxic(Tox *m)
|
||||
return;
|
||||
}
|
||||
|
||||
tox_iterate(m);
|
||||
tox_iterate(m, NULL);
|
||||
do_tox_connection(m);
|
||||
pthread_mutex_unlock(&Winthread.lock);
|
||||
}
|
||||
@ -1139,8 +1146,10 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
#ifdef X11
|
||||
|
||||
if (init_xtra(DnD_callback) == -1)
|
||||
queue_init_message("X failed to initialize");
|
||||
|
||||
#endif
|
||||
|
||||
Tox *m = load_toxic(DATA_FILE);
|
||||
@ -1182,6 +1191,7 @@ int main(int argc, char **argv)
|
||||
set_primary_device(output, user_settings->audio_out_dev);
|
||||
|
||||
#elif SOUND_NOTIFY
|
||||
|
||||
if ( init_devices() == de_InternalError )
|
||||
queue_init_message("Failed to init audio devices");
|
||||
|
||||
@ -1219,8 +1229,10 @@ int main(int argc, char **argv)
|
||||
|
||||
if (timed_out(last_save, AUTOSAVE_FREQ)) {
|
||||
pthread_mutex_lock(&Winthread.lock);
|
||||
|
||||
if (store_data(m, DATA_FILE) != 0)
|
||||
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, "WARNING: Failed to save to data file");
|
||||
|
||||
pthread_mutex_unlock(&Winthread.lock);
|
||||
|
||||
last_save = cur_time;
|
||||
|
19
src/toxic.h
19
src/toxic.h
@ -107,18 +107,23 @@ int store_data(Tox *m, const char *path);
|
||||
/* callbacks */
|
||||
void on_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata);
|
||||
void on_connectionchange(Tox *m, uint32_t friendnumber, TOX_CONNECTION status, void *userdata);
|
||||
void on_message(Tox *m, uint32_t friendnumber, TOX_MESSAGE_TYPE type, const uint8_t *string, size_t length, void *userdata);
|
||||
void on_message(Tox *m, uint32_t friendnumber, TOX_MESSAGE_TYPE type, const uint8_t *string, size_t length,
|
||||
void *userdata);
|
||||
void on_action(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata);
|
||||
void on_nickchange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata);
|
||||
void on_statuschange(Tox *m, uint32_t friendnumber, TOX_USER_STATUS status, void *userdata);
|
||||
void on_statusmessagechange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata);
|
||||
void on_friendadded(Tox *m, uint32_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, uint8_t type, 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_group_titlechange(Tox *m, int groupnumber, int peernumber, const uint8_t *title, uint8_t length, void *userdata);
|
||||
void on_file_chunk_request(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length, void *userdata);
|
||||
void on_groupmessage(Tox *m, uint32_t groupnumber, uint32_t peernumber, TOX_MESSAGE_TYPE type,
|
||||
const uint8_t *message, size_t length, void *userdata);
|
||||
void on_groupinvite(Tox *m, uint32_t friendnumber, TOX_CONFERENCE_TYPE type, const uint8_t *group_pub_key,
|
||||
size_t length, void *userdata);
|
||||
void on_group_namelistchange(Tox *m, uint32_t groupnumber, uint32_t peernumber, TOX_CONFERENCE_STATE_CHANGE change,
|
||||
void *userdata);
|
||||
void on_group_titlechange(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *title, size_t length,
|
||||
void *userdata);
|
||||
void on_file_chunk_request(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length,
|
||||
void *userdata);
|
||||
void on_file_recv_chunk(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,
|
||||
size_t length, void *userdata);
|
||||
void on_file_control (Tox *m, uint32_t friendnumber, uint32_t filenumber, TOX_FILE_CONTROL control, void *userdata);
|
||||
|
@ -246,6 +246,7 @@ void fetch_hist_item(ChatContext *ctx, int key_dir)
|
||||
void strsubst(char *str, char old, char new)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; str[i] != '\0'; ++i)
|
||||
if (str[i] == old)
|
||||
str[i] = new;
|
||||
@ -254,6 +255,7 @@ void strsubst(char* str, char old, char new)
|
||||
void wstrsubst(wchar_t *str, wchar_t old, wchar_t new)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; str[i] != L'\0'; ++i)
|
||||
if (str[i] == old)
|
||||
str[i] = new;
|
||||
|
@ -82,6 +82,7 @@ ToxAV *init_video(ToxWindow *self, Tox *tox)
|
||||
void terminate_video()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CALLS; ++i) {
|
||||
Call *this_call = &CallControl.calls[i];
|
||||
|
||||
@ -94,7 +95,8 @@ void terminate_video()
|
||||
terminate_video_devices();
|
||||
}
|
||||
|
||||
void read_video_device_callback(int16_t width, int16_t height, const uint8_t* y, const uint8_t* u, const uint8_t* v, void* data)
|
||||
void read_video_device_callback(int16_t width, int16_t height, const uint8_t *y, const uint8_t *u, const uint8_t *v,
|
||||
void *data)
|
||||
{
|
||||
uint32_t friend_number = *((uint32_t *)data); /* TODO: Or pass an array of call_idx's */
|
||||
Call *this_call = &CallControl.calls[friend_number];
|
||||
@ -216,6 +218,7 @@ void callback_video_starting(uint32_t friend_number)
|
||||
|
||||
if (error == TOXAV_ERR_CALL_CONTROL_OK) {
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
if ( windows[i].is_call && windows[i].num == friend_number ) {
|
||||
if ( 0 != start_video_transmission(&windows[i], CallControl.av, this_call) ) {
|
||||
@ -394,11 +397,11 @@ void cmd_ccur_video_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, ch
|
||||
/* If call is active, change device */
|
||||
if ( self->is_call ) {
|
||||
Call *this_call = &CallControl.calls[self->num];
|
||||
|
||||
if ( this_call->ttas ) {
|
||||
|
||||
if ( type == vdt_output ) {
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* TODO: check for failure */
|
||||
close_video_device(vdt_input, this_call->vin_idx);
|
||||
open_video_device(vdt_input, selection, &this_call->vin_idx);
|
||||
|
@ -111,6 +111,7 @@ static void yuv420tobgr(uint16_t width, uint16_t height, const uint8_t *y,
|
||||
unsigned int ustride, unsigned int vstride, uint8_t *out)
|
||||
{
|
||||
unsigned long int i, j;
|
||||
|
||||
for (i = 0; i < height; ++i) {
|
||||
for (j = 0; j < width; ++j) {
|
||||
uint8_t *point = out + 4 * ((i * width) + j);
|
||||
@ -136,8 +137,10 @@ static void yuv422to420(uint8_t *plane_y, uint8_t *plane_u, uint8_t *plane_v,
|
||||
uint8_t *input, uint16_t width, uint16_t height)
|
||||
{
|
||||
uint8_t *end = input + width * height * 2;
|
||||
|
||||
while (input != end) {
|
||||
uint8_t *line_end = input + width * 2;
|
||||
|
||||
while (input != line_end) {
|
||||
*plane_y++ = *input++;
|
||||
*plane_u++ = *input++;
|
||||
@ -146,6 +149,7 @@ static void yuv422to420(uint8_t *plane_y, uint8_t *plane_u, uint8_t *plane_v,
|
||||
}
|
||||
|
||||
line_end = input + width * 2;
|
||||
|
||||
while (input != line_end) {
|
||||
*plane_y++ = *input++;
|
||||
input++;//u
|
||||
@ -178,12 +182,14 @@ VideoDeviceError init_video_devices()
|
||||
size[vdt_input] = 0;
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
|
||||
for (; size[vdt_input] <= MAX_DEVICES; ++size[vdt_input]) {
|
||||
int fd;
|
||||
char device_address[] = "/dev/videoXX";
|
||||
snprintf(device_address + 10, sizeof(char) * strlen(device_address) - 10, "%i", size[vdt_input]);
|
||||
|
||||
fd = open(device_address, O_RDWR | O_NONBLOCK, 0);
|
||||
|
||||
if ( fd == -1 ) {
|
||||
break;
|
||||
} else {
|
||||
@ -203,6 +209,7 @@ VideoDeviceError init_video_devices()
|
||||
strcat(video_input_name, device_address);
|
||||
strcat(video_input_name, ")");
|
||||
}
|
||||
|
||||
video_devices_names[vdt_input][size[vdt_input]] = video_input_name;
|
||||
|
||||
close(fd);
|
||||
@ -210,8 +217,10 @@ VideoDeviceError init_video_devices()
|
||||
}
|
||||
|
||||
#else /* __OSX__ */
|
||||
|
||||
if ( osx_video_init((char **)video_devices_names[vdt_input], &size[vdt_input]) != 0 )
|
||||
return vde_InternalError;
|
||||
|
||||
#endif
|
||||
|
||||
size[vdt_output] = 1;
|
||||
@ -223,6 +232,7 @@ VideoDeviceError init_video_devices()
|
||||
return vde_InternalError;
|
||||
|
||||
pthread_t thread_id;
|
||||
|
||||
if ( pthread_create(&thread_id, NULL, video_thread_poll, NULL) != 0 || pthread_detach(thread_id) != 0 )
|
||||
return vde_InternalError;
|
||||
|
||||
@ -243,6 +253,7 @@ VideoDeviceError terminate_video_devices()
|
||||
usleep(20000);
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size[vdt_input]; ++i) {
|
||||
free((void *)video_devices_names[vdt_input][i]);
|
||||
}
|
||||
@ -261,11 +272,16 @@ VideoDeviceError register_video_device_callback(int32_t friend_number, uint32_t
|
||||
VideoDataHandleCallback callback, void *data)
|
||||
{
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
if ( size[vdt_input] <= device_idx || !video_devices_running[vdt_input][device_idx] || !video_devices_running[vdt_input][device_idx]->fd )
|
||||
|
||||
if ( size[vdt_input] <= device_idx || !video_devices_running[vdt_input][device_idx]
|
||||
|| !video_devices_running[vdt_input][device_idx]->fd )
|
||||
return vde_InvalidSelection;
|
||||
|
||||
#else /* __OSX__ */
|
||||
|
||||
if ( size[vdt_input] <= device_idx || !video_devices_running[vdt_input][device_idx] )
|
||||
return vde_InvalidSelection;
|
||||
|
||||
#endif
|
||||
|
||||
lock;
|
||||
@ -345,6 +361,7 @@ VideoDeviceError open_video_device(VideoDeviceType type, int32_t selection, uint
|
||||
snprintf(device_address + 10 , sizeof(device_address) - 10, "%i", selection);
|
||||
|
||||
device->fd = open(device_address, O_RDWR);
|
||||
|
||||
if ( device->fd == -1 ) {
|
||||
unlock;
|
||||
return vde_FailedStart;
|
||||
@ -352,6 +369,7 @@ VideoDeviceError open_video_device(VideoDeviceType type, int32_t selection, uint
|
||||
|
||||
/* Obtain video device capabilities */
|
||||
struct v4l2_capability cap;
|
||||
|
||||
if ( -1 == xioctl(device->fd, VIDIOC_QUERYCAP, &cap) ) {
|
||||
close(device->fd);
|
||||
free(device);
|
||||
@ -365,6 +383,7 @@ VideoDeviceError open_video_device(VideoDeviceType type, int32_t selection, uint
|
||||
|
||||
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
|
||||
|
||||
if ( -1 == xioctl(device->fd, VIDIOC_S_FMT, &fmt) ) {
|
||||
close(device->fd);
|
||||
free(device);
|
||||
@ -381,6 +400,7 @@ VideoDeviceError open_video_device(VideoDeviceType type, int32_t selection, uint
|
||||
req.count = 4;
|
||||
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
req.memory = V4L2_MEMORY_MMAP;
|
||||
|
||||
if ( -1 == xioctl(device->fd, VIDIOC_REQBUFS, &req) ) {
|
||||
close(device->fd);
|
||||
free(device);
|
||||
@ -422,12 +442,14 @@ VideoDeviceError open_video_device(VideoDeviceType type, int32_t selection, uint
|
||||
if ( MAP_FAILED == device->buffers[i].start ) {
|
||||
for (i = 0; i < buf.index; ++i)
|
||||
munmap(device->buffers[i].start, device->buffers[i].length);
|
||||
|
||||
close(device->fd);
|
||||
free(device);
|
||||
unlock;
|
||||
return vde_FailedStart;
|
||||
}
|
||||
}
|
||||
|
||||
device->n_buffers = i;
|
||||
|
||||
enum v4l2_buf_type type;
|
||||
@ -443,6 +465,7 @@ VideoDeviceError open_video_device(VideoDeviceType type, int32_t selection, uint
|
||||
if ( -1 == xioctl(device->fd, VIDIOC_QBUF, &buf) ) {
|
||||
for (i = 0; i < device->n_buffers; ++i)
|
||||
munmap(device->buffers[i].start, device->buffers[i].length);
|
||||
|
||||
close(device->fd);
|
||||
free(device);
|
||||
unlock;
|
||||
@ -460,11 +483,13 @@ VideoDeviceError open_video_device(VideoDeviceType type, int32_t selection, uint
|
||||
}
|
||||
|
||||
#else /* __OSX__ */
|
||||
|
||||
if ( osx_video_open_device(selection, &device->video_width, &device->video_height) != 0 ) {
|
||||
free(device);
|
||||
unlock;
|
||||
return vde_FailedStart;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Create X11 window associated to device */
|
||||
@ -619,16 +644,19 @@ void* video_thread_poll (void* arg) // TODO: maybe use thread for every input so
|
||||
|
||||
while (1) {
|
||||
lock;
|
||||
|
||||
if (!video_thread_running) {
|
||||
unlock;
|
||||
break;
|
||||
}
|
||||
|
||||
unlock;
|
||||
|
||||
if ( video_thread_paused ) usleep(10000); /* Wait for unpause. */
|
||||
else {
|
||||
for (i = 0; i < size[vdt_input]; ++i) {
|
||||
lock;
|
||||
|
||||
if ( video_devices_running[vdt_input][i] != NULL ) {
|
||||
/* Obtain frame image data from device buffers */
|
||||
VideoDevice *device = video_devices_running[vdt_input][i];
|
||||
@ -656,10 +684,12 @@ void* video_thread_poll (void* arg) // TODO: maybe use thread for every input so
|
||||
yuv422to420(y, u, v, data, video_width, video_height);
|
||||
|
||||
#else /* __OSX__*/
|
||||
|
||||
if ( osx_video_read_device(y, u, v, &video_width, &video_height) != 0 ) {
|
||||
unlock;
|
||||
continue;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Send frame data to friend through ToxAV */
|
||||
@ -697,15 +727,19 @@ void* video_thread_poll (void* arg) // TODO: maybe use thread for every input so
|
||||
free(img_data);
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
|
||||
if ( -1 == xioctl(device->fd, VIDIOC_QBUF, &buf) ) {
|
||||
unlock;
|
||||
continue;
|
||||
}
|
||||
|
||||
#endif /* __linux__ */
|
||||
|
||||
}
|
||||
|
||||
unlock;
|
||||
}
|
||||
|
||||
usleep(1000 * 1000 / 24);
|
||||
}
|
||||
}
|
||||
@ -733,13 +767,16 @@ VideoDeviceError close_video_device(VideoDeviceType type, uint32_t device_idx)
|
||||
if ( type == vdt_input ) {
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
|
||||
if ( -1 == xioctl(device->fd, VIDIOC_STREAMOFF, &buf_type) ) {}
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < device->n_buffers; ++i) {
|
||||
if ( -1 == munmap(device->buffers[i].start, device->buffers[i].length) ) {
|
||||
}
|
||||
}
|
||||
|
||||
close(device->fd);
|
||||
|
||||
#else /* __OSX__ */
|
||||
@ -765,8 +802,7 @@ VideoDeviceError close_video_device(VideoDeviceType type, uint32_t device_idx)
|
||||
free(device);
|
||||
}
|
||||
|
||||
}
|
||||
else device->ref_count--;
|
||||
} else device->ref_count--;
|
||||
|
||||
unlock;
|
||||
return rc;
|
||||
|
@ -45,7 +45,8 @@ typedef enum VideoDeviceError {
|
||||
vde_CaptureError = -9,
|
||||
} VideoDeviceError;
|
||||
|
||||
typedef void (*VideoDataHandleCallback) (int16_t width, int16_t height, const uint8_t* y, const uint8_t* u, const uint8_t* v, void* data);
|
||||
typedef void (*VideoDataHandleCallback) (int16_t width, int16_t height, const uint8_t *y, const uint8_t *u,
|
||||
const uint8_t *v, void *data);
|
||||
|
||||
#ifdef VIDEO
|
||||
VideoDeviceError init_video_devices(ToxAV *av);
|
||||
@ -56,7 +57,8 @@ VideoDeviceError init_video_devices();
|
||||
VideoDeviceError terminate_video_devices();
|
||||
|
||||
/* Callback handles ready data from INPUT device */
|
||||
VideoDeviceError register_video_device_callback(int32_t call_idx, uint32_t device_idx, VideoDataHandleCallback callback, void* data);
|
||||
VideoDeviceError register_video_device_callback(int32_t call_idx, uint32_t device_idx, VideoDataHandleCallback callback,
|
||||
void *data);
|
||||
void *get_video_device_callback_data(uint32_t device_idx);
|
||||
|
||||
VideoDeviceError set_primary_video_device(VideoDeviceType type, int32_t selection);
|
||||
@ -67,7 +69,8 @@ VideoDeviceError open_video_device(VideoDeviceType type, int32_t selection, uint
|
||||
VideoDeviceError close_video_device(VideoDeviceType type, uint32_t device_idx);
|
||||
|
||||
/* Write data to device */
|
||||
VideoDeviceError write_video_out(uint16_t width, uint16_t height, uint8_t const *y, uint8_t const *u, uint8_t const *v, int32_t ystride, int32_t ustride, int32_t vstride, void *user_data);
|
||||
VideoDeviceError write_video_out(uint16_t width, uint16_t height, uint8_t const *y, uint8_t const *u, uint8_t const *v,
|
||||
int32_t ystride, int32_t ustride, int32_t vstride, void *user_data);
|
||||
|
||||
void print_video_devices(ToxWindow *self, VideoDeviceType type);
|
||||
void get_primary_video_device_name(VideoDeviceType type, char *buf, int size);
|
||||
|
@ -151,8 +151,8 @@ void on_friendadded(Tox *m, uint32_t friendnumber, bool sort)
|
||||
store_data(m, DATA_FILE);
|
||||
}
|
||||
|
||||
void on_groupmessage(Tox *m, int groupnumber, int peernumber, const uint8_t *message, uint16_t length,
|
||||
void *userdata)
|
||||
void on_groupmessage(Tox *m, uint32_t groupnumber, uint32_t peernumber, TOX_MESSAGE_TYPE type,
|
||||
const uint8_t *message, size_t length, void *userdata)
|
||||
{
|
||||
char msg[MAX_STR_SIZE + 1];
|
||||
length = copy_tox_str(msg, sizeof(msg), (const char *) message, length);
|
||||
@ -161,26 +161,12 @@ void on_groupmessage(Tox *m, int groupnumber, int peernumber, const uint8_t *mes
|
||||
|
||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
if (windows[i].onGroupMessage != NULL)
|
||||
windows[i].onGroupMessage(&windows[i], m, groupnumber, peernumber, msg, length);
|
||||
windows[i].onGroupMessage(&windows[i], m, groupnumber, peernumber, type, msg, length);
|
||||
}
|
||||
}
|
||||
|
||||
void on_groupaction(Tox *m, int groupnumber, int peernumber, const uint8_t *action, uint16_t length,
|
||||
void *userdata)
|
||||
{
|
||||
char msg[MAX_STR_SIZE + 1];
|
||||
length = copy_tox_str(msg, sizeof(msg), (const char *) action, length);
|
||||
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
if (windows[i].onGroupAction != NULL)
|
||||
windows[i].onGroupAction(&windows[i], m, groupnumber, peernumber, msg, length);
|
||||
}
|
||||
}
|
||||
|
||||
void on_groupinvite(Tox *m, int32_t friendnumber, uint8_t type, const uint8_t *group_pub_key, uint16_t length,
|
||||
void *userdata)
|
||||
void on_groupinvite(Tox *m, uint32_t friendnumber, TOX_CONFERENCE_TYPE type, const uint8_t *group_pub_key,
|
||||
size_t length, void *userdata)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
@ -190,7 +176,8 @@ void on_groupinvite(Tox *m, int32_t friendnumber, uint8_t type, const uint8_t *g
|
||||
}
|
||||
}
|
||||
|
||||
void on_group_namelistchange(Tox *m, int groupnumber, int peernumber, uint8_t change, void *userdata)
|
||||
void on_group_namelistchange(Tox *m, uint32_t groupnumber, uint32_t peernumber, TOX_CONFERENCE_STATE_CHANGE change,
|
||||
void *userdata)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
@ -200,7 +187,7 @@ void on_group_namelistchange(Tox *m, int groupnumber, int peernumber, uint8_t ch
|
||||
}
|
||||
}
|
||||
|
||||
void on_group_titlechange(Tox *m, int groupnumber, int peernumber, const uint8_t *title, uint8_t length,
|
||||
void on_group_titlechange(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *title, size_t length,
|
||||
void *userdata)
|
||||
{
|
||||
char data[MAX_STR_SIZE + 1];
|
||||
@ -445,10 +432,12 @@ void on_window_resize(void)
|
||||
}
|
||||
|
||||
#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 */
|
||||
|
||||
scrollok(w->chatwin->history, 0);
|
||||
@ -458,14 +447,18 @@ void on_window_resize(void)
|
||||
static void draw_window_tab(ToxWindow *toxwin)
|
||||
{
|
||||
pthread_mutex_lock(&Winthread.lock);
|
||||
|
||||
if (toxwin->alert != WINDOW_ALERT_NONE) attron(COLOR_PAIR(toxwin->alert));
|
||||
|
||||
pthread_mutex_unlock(&Winthread.lock);
|
||||
|
||||
clrtoeol();
|
||||
printw(" [%s]", toxwin->name);
|
||||
|
||||
pthread_mutex_lock(&Winthread.lock);
|
||||
|
||||
if (toxwin->alert != WINDOW_ALERT_NONE) attroff(COLOR_PAIR(toxwin->alert));
|
||||
|
||||
pthread_mutex_unlock(&Winthread.lock);
|
||||
}
|
||||
|
||||
|
@ -121,11 +121,10 @@ struct ToxWindow {
|
||||
void(*onNickChange)(ToxWindow *, Tox *, uint32_t, const char *, size_t);
|
||||
void(*onStatusChange)(ToxWindow *, Tox *, uint32_t, TOX_USER_STATUS);
|
||||
void(*onStatusMessageChange)(ToxWindow *, uint32_t, const char *, size_t);
|
||||
void(*onGroupMessage)(ToxWindow *, Tox *, int, int, const char *, uint16_t);
|
||||
void(*onGroupAction)(ToxWindow *, Tox *, int, int, const char *, uint16_t);
|
||||
void(*onGroupMessage)(ToxWindow *, Tox *, uint32_t, uint32_t, TOX_MESSAGE_TYPE, const char *, size_t);
|
||||
void(*onGroupInvite)(ToxWindow *, Tox *, int32_t, uint8_t, const char *, uint16_t);
|
||||
void(*onGroupNamelistChange)(ToxWindow *, Tox *, int, int, uint8_t);
|
||||
void(*onGroupTitleChange)(ToxWindow *, Tox *, int, int, const char *, uint8_t);
|
||||
void(*onGroupNamelistChange)(ToxWindow *, Tox *, uint32_t, uint32_t, TOX_CONFERENCE_STATE_CHANGE);
|
||||
void(*onGroupTitleChange)(ToxWindow *, Tox *, uint32_t, uint32_t, const char *, size_t);
|
||||
void(*onFileChunkRequest)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, size_t);
|
||||
void(*onFileRecvChunk)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, const char *, size_t);
|
||||
void(*onFileControl)(ToxWindow *, Tox *, uint32_t, uint32_t, TOX_FILE_CONTROL);
|
||||
|
25
src/xtra.c
25
src/xtra.c
@ -57,8 +57,7 @@ struct _Xtra {
|
||||
Atom expecting_type;
|
||||
} Xtra;
|
||||
|
||||
typedef struct _Property
|
||||
{
|
||||
typedef struct _Property {
|
||||
unsigned char *data;
|
||||
int read_format;
|
||||
unsigned long read_num;
|
||||
@ -97,9 +96,11 @@ Property read_property(Window s, Atom p)
|
||||
Atom get_dnd_type(long *a, int l)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (; i < l; i ++) {
|
||||
if (a[i] != XtraNil) return a[i]; /* Get first valid */
|
||||
}
|
||||
|
||||
return XtraNil;
|
||||
}
|
||||
|
||||
@ -199,12 +200,12 @@ static void handle_xdnd_selection(XSelectionEvent* e)
|
||||
|
||||
|
||||
/* Call callback for every entry */
|
||||
if (Xtra.on_drop && p.read_num)
|
||||
{
|
||||
if (Xtra.on_drop && p.read_num) {
|
||||
char *sptr;
|
||||
char *str = strtok_r((char *) p.data, "\n\r", &sptr);
|
||||
|
||||
if (str) Xtra.on_drop(str, dt);
|
||||
|
||||
while ((str = strtok_r(NULL, "\n\r", &sptr)))
|
||||
Xtra.on_drop(str, dt);
|
||||
}
|
||||
@ -221,30 +222,27 @@ void *event_loop(void* p)
|
||||
XEvent event;
|
||||
int pending;
|
||||
|
||||
while (Xtra.display)
|
||||
{
|
||||
while (Xtra.display) {
|
||||
/* NEEDMOEVENTSFODEMPROGRAMS */
|
||||
|
||||
XLockDisplay(Xtra.display);
|
||||
|
||||
if ((pending = XPending(Xtra.display))) XNextEvent(Xtra.display, &event);
|
||||
|
||||
if (!pending)
|
||||
{
|
||||
if (!pending) {
|
||||
XUnlockDisplay(Xtra.display);
|
||||
usleep(10000);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (event.type == ClientMessage)
|
||||
{
|
||||
if (event.type == ClientMessage) {
|
||||
Atom type = event.xclient.message_type;
|
||||
|
||||
if (type == XdndEnter) handle_xdnd_enter(&event.xclient);
|
||||
else if (type == XdndPosition) handle_xdnd_position(&event.xclient);
|
||||
else if (type == XdndDrop) handle_xdnd_drop(&event.xclient);
|
||||
else if (type == XtraTerminate) break;
|
||||
}
|
||||
else if (event.type == SelectionNotify) handle_xdnd_selection(&event.xselection);
|
||||
} else if (event.type == SelectionNotify) handle_xdnd_selection(&event.xselection);
|
||||
/* AINNOBODYCANHANDLEDEMEVENTS*/
|
||||
else XSendEvent(Xtra.display, Xtra.terminal_window, 0, 0, &event);
|
||||
|
||||
@ -256,6 +254,7 @@ void *event_loop(void* p)
|
||||
* otherwise HEWUSAGUDBOI happens
|
||||
*/
|
||||
if (Xtra.display) XCloseDisplay(Xtra.display);
|
||||
|
||||
return (Xtra.display = NULL);
|
||||
}
|
||||
|
||||
@ -267,6 +266,7 @@ int init_xtra(drop_callback d)
|
||||
else Xtra.on_drop = d;
|
||||
|
||||
XInitThreads();
|
||||
|
||||
if ( !(Xtra.display = XOpenDisplay(NULL))) return -1;
|
||||
|
||||
Xtra.terminal_window = focused_window_id();
|
||||
@ -338,6 +338,7 @@ int init_xtra(drop_callback d)
|
||||
(unsigned char *)&XdndVersion, 1);
|
||||
|
||||
pthread_t id;
|
||||
|
||||
if (pthread_create(&id, NULL, event_loop, NULL) != 0)
|
||||
return -1;
|
||||
|
||||
|
Reference in New Issue
Block a user