mirror of
https://github.com/Tha14/toxic.git
synced 2025-06-29 13:06:45 +02:00
Compare commits
29 Commits
Author | SHA1 | Date | |
---|---|---|---|
8660047ec1 | |||
9476db02a9 | |||
04fbf5f724 | |||
3cc629cbc1 | |||
50fca4cddf | |||
a047cead05 | |||
1131b73299 | |||
196af10d01 | |||
1e0e93e5c6 | |||
ac01d6d316 | |||
654e404e0e | |||
f0f1138c54 | |||
bc94e08970 | |||
42c3ede963 | |||
174568d769 | |||
4587d8ebbd | |||
98aae242fb | |||
7abd8d5ee5 | |||
98ac4d7983 | |||
933d46553f | |||
7e667a8028 | |||
d4e41d6053 | |||
f30dccf726 | |||
ea3fcd5b79 | |||
e61d070def | |||
b5f34f42a8 | |||
4426eaddd9 | |||
83f0720a39 | |||
ce4f293574 |
@ -5,7 +5,7 @@ compiler:
|
|||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
# Installing yasm (needed for compiling vpx) and openal
|
# Installing yasm (needed for compiling vpx) and openal
|
||||||
- sudo apt-get -yq install yasm libopenal-dev
|
- sudo apt-get -yq install yasm libopenal-dev libconfig-dev libalut-dev
|
||||||
# Installing libsodium, needed for toxcore
|
# Installing libsodium, needed for toxcore
|
||||||
- git clone https://github.com/jedisct1/libsodium.git libsodium
|
- git clone https://github.com/jedisct1/libsodium.git libsodium
|
||||||
- cd libsodium
|
- cd libsodium
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# Toxic [](https://travis-ci.org/Tox/toxic)
|
# Toxic [](https://travis-ci.org/Tox/toxic)
|
||||||
Toxic is a [Tox](https://tox.im)-based instant messenging client which formerly resided in the [Tox core repository](https://github.com/irungentoo/toxcore), and is now available as a standalone application.
|
Toxic is a [Tox](https://tox.im)-based instant messenging client which formerly resided in the [Tox core repository](https://github.com/irungentoo/toxcore), and is now available as a standalone application.
|
||||||
|
|
||||||
.
|
.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@ -9,10 +9,15 @@ Toxic is a [Tox](https://tox.im)-based instant messenging client which formerly
|
|||||||
##### Base
|
##### Base
|
||||||
* [libtoxcore](https://github.com/irungentoo/toxcore)
|
* [libtoxcore](https://github.com/irungentoo/toxcore)
|
||||||
* [ncurses](https://www.gnu.org/software/ncurses) (for Debian based systems, 'libncursesw5-dev')
|
* [ncurses](https://www.gnu.org/software/ncurses) (for Debian based systems, 'libncursesw5-dev')
|
||||||
|
* [libconfig](http://www.hyperrealm.com/libconfig) (for Debian based systems, 'libconfig-dev')
|
||||||
|
|
||||||
##### Audio
|
##### Audio
|
||||||
* libtoxav (libtoxcore compiled with audio support)
|
* libtoxav (libtoxcore compiled with audio support)
|
||||||
|
* [openal](http://openal.org) (for Debian based systems, 'libopenal-dev')
|
||||||
|
|
||||||
|
##### Sound notifications
|
||||||
* [openal](http://openal.org)
|
* [openal](http://openal.org)
|
||||||
|
* [openalut](http://openal.org) (for Debian based systems, 'libalut-dev')
|
||||||
|
|
||||||
### Compiling
|
### Compiling
|
||||||
1. `cd build/`
|
1. `cd build/`
|
||||||
@ -24,6 +29,8 @@ Toxic is a [Tox](https://tox.im)-based instant messenging client which formerly
|
|||||||
* You can pass your own flags to the Makefile with `CFLAGS=""` and/or `LDFLAGS=""` (this will supersede the default ones)
|
* You can pass your own flags to the Makefile with `CFLAGS=""` and/or `LDFLAGS=""` (this will supersede the default ones)
|
||||||
* Audio call support is automatically enabled if all dependencies are found
|
* Audio call support is automatically enabled if all dependencies are found
|
||||||
* If you want to build toxic without audio call support, you can use `make DISABLE_AV=1`
|
* If you want to build toxic without audio call support, you can use `make DISABLE_AV=1`
|
||||||
|
* Sound notifications support is automatically enabled if all dependencies are found
|
||||||
|
* If you want to build toxic without sound notifications support, you can use `make DISABLE_NOTIFY=1`
|
||||||
|
|
||||||
### Packaging
|
### Packaging
|
||||||
* For packaging purpose, you can use `DESTDIR=""` to specify a directory where to store installed files
|
* For packaging purpose, you can use `DESTDIR=""` to specify a directory where to store installed files
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
TOXIC_VERSION = 0.4.5
|
TOXIC_VERSION = 0.4.6
|
||||||
REV = $(shell git rev-list HEAD --count)
|
REV = $(shell git rev-list HEAD --count)
|
||||||
VERSION = $(TOXIC_VERSION)_r$(REV)
|
VERSION = $(TOXIC_VERSION)_r$(REV)
|
||||||
|
|
||||||
@ -6,14 +6,18 @@ CFG_DIR = ../cfg
|
|||||||
SRC_DIR = ../src
|
SRC_DIR = ../src
|
||||||
MISC_DIR = ../misc
|
MISC_DIR = ../misc
|
||||||
DOC_DIR = ../doc
|
DOC_DIR = ../doc
|
||||||
|
SND_DIR = ../sounds
|
||||||
PREFIX = /usr/local
|
PREFIX = /usr/local
|
||||||
BINDIR = $(PREFIX)/bin
|
BINDIR = $(PREFIX)/bin
|
||||||
DATADIR = $(PREFIX)/share/toxic
|
DATADIR = $(PREFIX)/share/toxic
|
||||||
MANDIR = $(PREFIX)/man
|
MANDIR = $(PREFIX)/man
|
||||||
DATAFILES = DHTnodes toxic.conf.example
|
DATAFILES = DHTnodes toxic.conf.example
|
||||||
MANFILES = toxic.1 toxic.conf.5
|
MANFILES = toxic.1 toxic.conf.5
|
||||||
|
SNDFILES = ContactLogsIn.wav ContactLogsOut.wav Error.wav IncomingCall.wav
|
||||||
|
SNDFILES += LogIn.wav LogOut.wav NewMessage.wav OutgoingCall.wav
|
||||||
|
SNDFILES += TransferComplete.wav TransferPending.wav
|
||||||
|
|
||||||
LIBS = libtoxcore ncursesw
|
LIBS = libtoxcore ncursesw libconfig
|
||||||
|
|
||||||
CFLAGS = -std=gnu99 -pthread -Wall -g
|
CFLAGS = -std=gnu99 -pthread -Wall -g
|
||||||
CFLAGS += -DTOXICVER="\"$(VERSION)\"" -DHAVE_WIDECHAR -D_XOPEN_SOURCE_EXTENDED
|
CFLAGS += -DTOXICVER="\"$(VERSION)\"" -DHAVE_WIDECHAR -D_XOPEN_SOURCE_EXTENDED
|
||||||
@ -21,14 +25,18 @@ CFLAGS += -DPACKAGE_DATADIR="\"$(abspath $(DATADIR))\""
|
|||||||
CFLAGS += $(USER_CFLAGS)
|
CFLAGS += $(USER_CFLAGS)
|
||||||
LDFLAGS = $(USER_LDFLAGS)
|
LDFLAGS = $(USER_LDFLAGS)
|
||||||
|
|
||||||
OBJ = chat.o chat_commands.o configdir.o dns.o execute.o file_senders.o
|
OBJ = chat.o chat_commands.o configdir.o dns.o execute.o file_senders.o notify.o
|
||||||
OBJ += friendlist.o global_commands.o groupchat.o line_info.o input.o help.o
|
OBJ += friendlist.o global_commands.o groupchat.o line_info.o input.o help.o autocomplete.o
|
||||||
OBJ += log.o misc_tools.o prompt.o settings.o toxic.o toxic_strings.o windows.o
|
OBJ += log.o misc_tools.o prompt.o settings.o toxic.o toxic_strings.o windows.o
|
||||||
|
|
||||||
# Variables for audio support
|
# Variables for audio call support
|
||||||
AUDIO_LIBS = libtoxav openal
|
AUDIO_LIBS = libtoxav openal
|
||||||
AUDIO_CFLAGS = -D_SUPPORT_AUDIO
|
AUDIO_CFLAGS = -D_AUDIO
|
||||||
AUDIO_OBJ = device.o audio_call.o
|
AUDIO_OBJ = audio_call.o
|
||||||
|
|
||||||
|
# Variables for sound notify support
|
||||||
|
SND_NOTIFY_LIBS = openal freealut
|
||||||
|
SND_NOTIFY_CFLAGS = -D_SOUND_NOTIFY
|
||||||
|
|
||||||
# Check on wich system we are running
|
# Check on wich system we are running
|
||||||
UNAME_S = $(shell uname -s)
|
UNAME_S = $(shell uname -s)
|
||||||
@ -57,6 +65,13 @@ ifneq ($(filter arm%, $(UNAME_M)),)
|
|||||||
-include $(CFG_DIR)/arm.mk
|
-include $(CFG_DIR)/arm.mk
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Check if we can use X11
|
||||||
|
CHECK_X11_LIBS = $(shell pkg-config x11 || echo -n "error")
|
||||||
|
ifneq ($(CHECK_X11_LIBS), error)
|
||||||
|
LIBS += x11
|
||||||
|
CFLAGS += -D_X11
|
||||||
|
endif
|
||||||
|
|
||||||
# Check if we want/can build audio
|
# Check if we want/can build audio
|
||||||
ifneq ($(DISABLE_AV), 1)
|
ifneq ($(DISABLE_AV), 1)
|
||||||
CHECK_AUDIO_LIBS = $(shell pkg-config $(AUDIO_LIBS) || echo -n "error")
|
CHECK_AUDIO_LIBS = $(shell pkg-config $(AUDIO_LIBS) || echo -n "error")
|
||||||
@ -64,6 +79,7 @@ ifneq ($(CHECK_AUDIO_LIBS), error)
|
|||||||
LIBS += $(AUDIO_LIBS)
|
LIBS += $(AUDIO_LIBS)
|
||||||
CFLAGS += $(AUDIO_CFLAGS)
|
CFLAGS += $(AUDIO_CFLAGS)
|
||||||
OBJ += $(AUDIO_OBJ)
|
OBJ += $(AUDIO_OBJ)
|
||||||
|
NEED_AV = 1
|
||||||
else
|
else
|
||||||
ifneq ($(MAKECMDGOALS), clean)
|
ifneq ($(MAKECMDGOALS), clean)
|
||||||
MISSING_AUDIO_LIBS = $(shell for lib in $(AUDIO_LIBS) ; do if ! pkg-config $$lib ; then echo $$lib ; fi ; done)
|
MISSING_AUDIO_LIBS = $(shell for lib in $(AUDIO_LIBS) ; do if ! pkg-config $$lib ; then echo $$lib ; fi ; done)
|
||||||
@ -74,6 +90,29 @@ endif
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Check if we want/can build sound notify support
|
||||||
|
ifneq ($(DISABLE_NOTIFY), 1)
|
||||||
|
CHECK_NOTIFY_LIBS = $(shell pkg-config $(SND_NOTIFY_LIBS) || echo -n "error")
|
||||||
|
ifneq ($(CHECK_NOTIFY_LIBS), error)
|
||||||
|
LIBS += $(SND_NOTIFY_LIBS)
|
||||||
|
CFLAGS += $(SND_NOTIFY_CFLAGS)
|
||||||
|
NEED_AV = 1
|
||||||
|
|
||||||
|
else
|
||||||
|
ifneq ($(MAKECMDGOALS), clean)
|
||||||
|
MISSING_NOTIFY_LIBS = $(shell for lib in $(SND_NOTIFY_LIBS) ; do if ! pkg-config $$lib ; then echo $$lib ; fi ; done)
|
||||||
|
$(warning WARNING -- Toxic will be compiled without sound notify support)
|
||||||
|
$(warning WARNING -- You need these libraries for sound notify support)
|
||||||
|
$(warning WARNING -- $(MISSING_NOTIFY_LIBS))
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
# device.o is needed for both audio calls and notifications but should only be loaded once
|
||||||
|
ifeq ($(NEED_AV), 1)
|
||||||
|
OBJ += device.o
|
||||||
|
endif
|
||||||
|
|
||||||
# Check if we can build Toxic
|
# Check if we can build Toxic
|
||||||
CHECK_LIBS = $(shell pkg-config $(LIBS) || echo -n "error")
|
CHECK_LIBS = $(shell pkg-config $(LIBS) || echo -n "error")
|
||||||
ifneq ($(CHECK_LIBS), error)
|
ifneq ($(CHECK_LIBS), error)
|
||||||
@ -99,12 +138,18 @@ toxic: $(OBJ)
|
|||||||
install: toxic
|
install: toxic
|
||||||
mkdir -p $(abspath $(DESTDIR)/$(BINDIR))
|
mkdir -p $(abspath $(DESTDIR)/$(BINDIR))
|
||||||
mkdir -p $(abspath $(DESTDIR)/$(DATADIR))
|
mkdir -p $(abspath $(DESTDIR)/$(DATADIR))
|
||||||
|
mkdir -p $(abspath $(DESTDIR)/$(DATADIR))/sounds
|
||||||
mkdir -p $(abspath $(DESTDIR)/$(MANDIR))
|
mkdir -p $(abspath $(DESTDIR)/$(MANDIR))
|
||||||
@echo "Installing toxic executable"
|
@echo "Installing toxic executable"
|
||||||
@install -m 0755 toxic $(abspath $(DESTDIR)/$(BINDIR))
|
@install -m 0755 toxic $(abspath $(DESTDIR)/$(BINDIR))
|
||||||
@echo "Installing data files"
|
@echo "Installing data files"
|
||||||
@for f in $(DATAFILES) ; do \
|
@for f in $(DATAFILES) ; do \
|
||||||
install -m 0644 $(MISC_DIR)/$$f $(abspath $(DESTDIR)/$(DATADIR)) ;\
|
install -m 0644 $(MISC_DIR)/$$f $(abspath $(DESTDIR)/$(DATADIR)) ;\
|
||||||
|
file=$(abspath $(DESTDIR)/$(DATADIR))/$$f ;\
|
||||||
|
sed -i'' -e 's:__DATADIR__:'$(abspath $(DATADIR))':g' $$file ;\
|
||||||
|
done
|
||||||
|
@for f in $(SNDFILES) ; do \
|
||||||
|
install -m 0644 $(SND_DIR)/$$f $(abspath $(DESTDIR)/$(DATADIR))/sounds ;\
|
||||||
done
|
done
|
||||||
@echo "Installing man pages"
|
@echo "Installing man pages"
|
||||||
@for f in $(MANFILES) ; do \
|
@for f in $(MANFILES) ; do \
|
||||||
|
@ -9,6 +9,7 @@ help:
|
|||||||
@echo
|
@echo
|
||||||
@echo "-- Variables --"
|
@echo "-- Variables --"
|
||||||
@echo " DISABLE_AV: Set to \"1\" to force building without audio call support"
|
@echo " DISABLE_AV: Set to \"1\" to force building without audio call support"
|
||||||
|
@echo " DISABLE_NOTIFY: Set to \"1\" to force building without sound notify support"
|
||||||
@echo " USER_CFLAGS: Add custom flags to default CFLAGS"
|
@echo " USER_CFLAGS: Add custom flags to default CFLAGS"
|
||||||
@echo " USER_LDFLAGS: Add custom flags to default LDFLAGS"
|
@echo " USER_LDFLAGS: Add custom flags to default LDFLAGS"
|
||||||
@echo " PREFIX: Specify a prefix directory for binaries, data files,... (default is \"$(abspath $(PREFIX))\")"
|
@echo " PREFIX: Specify a prefix directory for binaries, data files,... (default is \"$(abspath $(PREFIX))\")"
|
||||||
|
251
doc/toxic.conf.5
251
doc/toxic.conf.5
@ -8,38 +8,62 @@ file is the main configuration file for
|
|||||||
.BR toxic (1)
|
.BR toxic (1)
|
||||||
client.
|
client.
|
||||||
.SH SYNTAX
|
.SH SYNTAX
|
||||||
.IB <KEY> : <VALUE> ;
|
.I <SECTION>
|
||||||
|
.B = {
|
||||||
.PP
|
.PP
|
||||||
Lines starting with "#" are comments and will be ignored.
|
.IB <KEY1> : <BOOL_VALUE> ;
|
||||||
|
.br
|
||||||
|
.IB <KEY2> = <NOT_BOOL_VALUE> ;
|
||||||
|
.br
|
||||||
|
...
|
||||||
|
.PP
|
||||||
|
.B };
|
||||||
|
.PP
|
||||||
|
Uses syntax accepted by libconfig.
|
||||||
|
.br
|
||||||
|
Lines starting with "//" are comments and will be ignored.
|
||||||
|
.PP
|
||||||
|
Sections:
|
||||||
|
.PP
|
||||||
|
.B ui
|
||||||
|
.RS
|
||||||
|
Configurations related to user interface.
|
||||||
.PP
|
.PP
|
||||||
Keys:
|
Keys:
|
||||||
.PP
|
|
||||||
.B time
|
|
||||||
.RS
|
|
||||||
Select between 24 and 12 hour time.
|
|
||||||
.br
|
.br
|
||||||
Values: 24, 12
|
|
||||||
.RE
|
|
||||||
.PP
|
|
||||||
.B timestamps
|
.B timestamps
|
||||||
.RS
|
.RS
|
||||||
Enable or disable timestamps.
|
Enable or disable timestamps.
|
||||||
.br
|
.br
|
||||||
Values: 1 to enable, 0 to disable
|
Values: 'true' to enable, 'false' to disable
|
||||||
.RE
|
|
||||||
.PP
|
|
||||||
.B autolog
|
|
||||||
.RS
|
|
||||||
Enable or disable autologging.
|
|
||||||
.br
|
|
||||||
Values: 1 to enable, 0 to disable
|
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
.B alerts
|
.B alerts
|
||||||
.RS
|
.RS
|
||||||
Enable or disable terminal alerts on events.
|
Enable or disable terminal alerts on events.
|
||||||
.br
|
.br
|
||||||
Values: 1 to enable, 0 to disable
|
Values: 'true' to enable, 'false' to disable
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
.B native_colors
|
||||||
|
.RS
|
||||||
|
Select between native terminal colors and toxic color theme.
|
||||||
|
.br
|
||||||
|
Values: 'true' for terminal colours, 'false' for toxic colours
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
.B autolog
|
||||||
|
.RS
|
||||||
|
Enable or disable autologging.
|
||||||
|
.br
|
||||||
|
Values: 'true' to enable, 'false' to disable
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
.B time_format
|
||||||
|
.RS
|
||||||
|
Select between 24 and 12 hour time.
|
||||||
|
.br
|
||||||
|
Values: 24, 12
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
.B history_size
|
.B history_size
|
||||||
@ -48,54 +72,211 @@ Maximum lines for chat window history.
|
|||||||
.br
|
.br
|
||||||
Values: <INTEGER> (for example: 700)
|
Values: <INTEGER> (for example: 700)
|
||||||
.RE
|
.RE
|
||||||
.PP
|
|
||||||
.B colour_theme
|
|
||||||
.RS
|
|
||||||
Select between toxic colour theme and native terminal colours.
|
|
||||||
.br
|
|
||||||
Values: 0 for toxic colours, 1 for terminal colours
|
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
.B audio_in_dev
|
.B audio
|
||||||
|
.RS
|
||||||
|
Configurations related to audio devices.
|
||||||
|
.PP
|
||||||
|
Keys:
|
||||||
|
.br
|
||||||
|
.B input_device
|
||||||
.RS
|
.RS
|
||||||
Audio input device.
|
Audio input device.
|
||||||
.br
|
.br
|
||||||
Values: <INTEGER> (number correspond to "/lsdev in")
|
Values: <INTEGER> (number correspond to "/lsdev in")
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
.B audio_out_dev
|
.B output_device
|
||||||
.RS
|
.RS
|
||||||
Audio output device.
|
Audio output device.
|
||||||
.br
|
.br
|
||||||
Values: <INTEGER> (number correspond to "/lsdev out")
|
Values: <INTEGER> (number correspond to "/lsdev out")
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
|
.B VAD_treshold
|
||||||
|
.RS
|
||||||
|
Voice Activity Detection treshold.
|
||||||
|
.br
|
||||||
|
Values: <FLOAT> (recommended values are around 40.0)
|
||||||
|
.RE
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
.B tox
|
||||||
|
.RS
|
||||||
|
Configurations related to file transfer.
|
||||||
|
.PP
|
||||||
|
Keys:
|
||||||
|
.br
|
||||||
.B download_path
|
.B download_path
|
||||||
.RS
|
.RS
|
||||||
Default path for downloads.
|
Default path for downloads.
|
||||||
.br
|
.br
|
||||||
Values: <STRING> (absolute path where to store downloaded files)
|
Values: <STRING> (absolute path where to store downloaded files)
|
||||||
.RE
|
.RE
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
.B sounds
|
||||||
|
.RS
|
||||||
|
Configurations related to notification sounds.
|
||||||
|
.PP
|
||||||
|
Keys:
|
||||||
|
.br
|
||||||
|
.B error
|
||||||
|
.RS
|
||||||
|
Sound to play when an error occurs.
|
||||||
|
.br
|
||||||
|
Values: <STRING> (sound file absolute path)
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
.B self_log_in
|
||||||
|
.RS
|
||||||
|
Sound to play when you log in.
|
||||||
|
.br
|
||||||
|
Values: <STRING> (sound file absolute path)
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
.B self_log_out
|
||||||
|
.RS
|
||||||
|
Sound to play when you log out.
|
||||||
|
.br
|
||||||
|
Values: <STRING> (sound file absolute path)
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
.B user_log_in
|
||||||
|
.RS
|
||||||
|
Sound to play when a contact become online.
|
||||||
|
.br
|
||||||
|
Values: <STRING> (sound file absolute path)
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
.B user_log_out
|
||||||
|
.RS
|
||||||
|
Sound to play when a contact become offline.
|
||||||
|
.br
|
||||||
|
Values: <STRING> (sound file absolute path)
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
.B call_incoming
|
||||||
|
.RS
|
||||||
|
Sound to play when you receive an incoming call.
|
||||||
|
.br
|
||||||
|
Values: <STRING> (sound file absolute path)
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
.B call_outgoing
|
||||||
|
.RS
|
||||||
|
Sound to play when you start a call.
|
||||||
|
.br
|
||||||
|
Values: <STRING> (sound file absolute path)
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
.B generic_message
|
||||||
|
.RS
|
||||||
|
Sound to play when an event occurs.
|
||||||
|
.br
|
||||||
|
Values: <STRING> (sound file absolute path)
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
.B transfer_pending
|
||||||
|
.RS
|
||||||
|
Sound to play when you receive a file transfer request.
|
||||||
|
.br
|
||||||
|
Values: <STRING> (sound file absolute path)
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
.B transfer_completed
|
||||||
|
.RS
|
||||||
|
Sound to play when a file transfer is completed.
|
||||||
|
.br
|
||||||
|
Values: <STRING> (sound file absolute path)
|
||||||
|
.RE
|
||||||
|
.RE
|
||||||
.SH EXAMPLES
|
.SH EXAMPLES
|
||||||
Default settings from __DATADIR__/toxic.conf.exmaple:
|
Default settings from __DATADIR__/toxic.conf.exmaple:
|
||||||
.PP
|
.PP
|
||||||
time:24;
|
// SAMPLE TOXIC CONFIGURATION
|
||||||
.br
|
.br
|
||||||
timestamps:1;
|
// USES LIBCONFIG-ACCEPTED SYNTAX
|
||||||
.br
|
.br
|
||||||
autolog:0;
|
ui = {
|
||||||
.br
|
.br
|
||||||
alerts:1;
|
// true to enable timestamps, false to disable
|
||||||
.br
|
.br
|
||||||
history_size:700;
|
timestamps:true;
|
||||||
.br
|
.br
|
||||||
colour_theme:0;
|
|
||||||
.br
|
.br
|
||||||
audio_in_dev:0;
|
// true to enable terminal alerts on messages, false to disable
|
||||||
.br
|
.br
|
||||||
audio_out_dev:0;
|
alerts:true;
|
||||||
.br
|
.br
|
||||||
download_path:/home/USERNAME/Downloads/;
|
// true to use native terminal colours, false to use toxic default colour theme
|
||||||
|
.br
|
||||||
|
native_colors:false;
|
||||||
|
.br
|
||||||
|
// true to enable autologging, false to disable
|
||||||
|
.br
|
||||||
|
autolog:false;
|
||||||
|
.br
|
||||||
|
// 24 or 12 hour time
|
||||||
|
.br
|
||||||
|
time_format=24;
|
||||||
|
.br
|
||||||
|
// maximum lines for chat window history
|
||||||
|
.br
|
||||||
|
history_size=700;
|
||||||
|
.br
|
||||||
|
};
|
||||||
|
.br
|
||||||
|
audio = {
|
||||||
|
.br
|
||||||
|
// preferred audio input device; numbers correspond to /lsdev in
|
||||||
|
.br
|
||||||
|
input_device=2;
|
||||||
|
.br
|
||||||
|
// preferred audio output device; numbers correspond to /lsdev out
|
||||||
|
.br
|
||||||
|
output_device=0;
|
||||||
|
.br
|
||||||
|
// default VAD treshold; float (recommended values are around 40)
|
||||||
|
.br
|
||||||
|
VAD_treshold=40.0;
|
||||||
|
.br
|
||||||
|
};
|
||||||
|
.br
|
||||||
|
tox = {
|
||||||
|
.br
|
||||||
|
// where to store received files
|
||||||
|
.br
|
||||||
|
// download_path="/home/USERNAME/Downloads/";
|
||||||
|
.br
|
||||||
|
};
|
||||||
|
.br
|
||||||
|
// To disable a sound set the path to "silent"
|
||||||
|
.br
|
||||||
|
sounds = {
|
||||||
|
.br
|
||||||
|
error="__DATADIR__/sounds/Error.wav";
|
||||||
|
.br
|
||||||
|
self_log_in="__DATADIR__/sounds/LogIn.wav";
|
||||||
|
.br
|
||||||
|
self_log_out="__DATADIR__/sounds/LogOut.wav";
|
||||||
|
.br
|
||||||
|
user_log_in="__DATADIR__/sounds/ContactLogsIn.wav";
|
||||||
|
.br
|
||||||
|
user_log_out="__DATADIR__/sounds/ContactLogsOut.wav";
|
||||||
|
.br
|
||||||
|
call_incoming="__DATADIR__/sounds/IncomingCall.wav";
|
||||||
|
.br
|
||||||
|
call_outgoing="__DATADIR__/sounds/OutgoingCall.wav";
|
||||||
|
.br
|
||||||
|
generic_message="__DATADIR__/sounds/NewMessage.wav";
|
||||||
|
.br
|
||||||
|
transfer_pending="__DATADIR__/sounds/TransferPending.wav";
|
||||||
|
.br
|
||||||
|
transfer_completed="__DATADIR__/sounds/TransferComplete.wav";
|
||||||
|
.br
|
||||||
|
};
|
||||||
.SH FILES
|
.SH FILES
|
||||||
.IP ~/.config/tox/toxic.conf
|
.IP ~/.config/tox/toxic.conf
|
||||||
Main configuration file.
|
Main configuration file.
|
||||||
|
@ -1,26 +1,52 @@
|
|||||||
# 24 or 12 hour time
|
// SAMPLE TOXIC CONFIGURATION
|
||||||
time:24;
|
// USES LIBCONFIG-ACCEPTED SYNTAX
|
||||||
|
|
||||||
# 1 to enable timestamps, 0 to disable
|
ui = {
|
||||||
timestamps:1;
|
// true to enable timestamps, false to disable
|
||||||
|
timestamps:true;
|
||||||
|
|
||||||
# 1 to enable autologging, 0 to disable
|
// true to enable terminal alerts on messages, false to disable
|
||||||
autolog:0;
|
alerts:true;
|
||||||
|
|
||||||
# 1 to disbale terminal alerts on messages, 0 to enable
|
// true to use native terminal colours, false to use toxic default colour theme
|
||||||
alerts:1;
|
native_colors:false;
|
||||||
|
|
||||||
# maximum lines for chat window history
|
// true to enable autologging, false to disable
|
||||||
history_size:700;
|
autolog:false;
|
||||||
|
|
||||||
# 1 to use native terminal colours, 0 to use toxic default colour theme
|
// 24 or 12 hour time
|
||||||
colour_theme:0;
|
time_format=24;
|
||||||
|
|
||||||
# preferred audio input device; numbers correspond to /lsdev in
|
// maximum lines for chat window history
|
||||||
audio_in_dev:0;
|
history_size=700;
|
||||||
|
};
|
||||||
|
|
||||||
# preferred audio output device; numbers correspond to /lsdev out
|
audio = {
|
||||||
audio_out_dev:0;
|
// preferred audio input device; numbers correspond to /lsdev in
|
||||||
|
input_device=2;
|
||||||
|
|
||||||
# preferred path for downloads
|
// preferred audio output device; numbers correspond to /lsdev out
|
||||||
download_path:/home/USERNAME/Downloads/;
|
output_device=0;
|
||||||
|
|
||||||
|
// default VAD treshold; float (recommended values are around 40)
|
||||||
|
VAD_treshold=40.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
tox = {
|
||||||
|
// where to store received files
|
||||||
|
// download_path="/home/USERNAME/Downloads/";
|
||||||
|
};
|
||||||
|
|
||||||
|
// To disable a sound set the path to "silent"
|
||||||
|
sounds = {
|
||||||
|
error="__DATADIR__/sounds/Error.wav";
|
||||||
|
self_log_in="__DATADIR__/sounds/LogIn.wav";
|
||||||
|
self_log_out="__DATADIR__/sounds/LogOut.wav";
|
||||||
|
user_log_in="__DATADIR__/sounds/ContactLogsIn.wav";
|
||||||
|
user_log_out="__DATADIR__/sounds/ContactLogsOut.wav";
|
||||||
|
call_incoming="__DATADIR__/sounds/IncomingCall.wav";
|
||||||
|
call_outgoing="__DATADIR__/sounds/OutgoingCall.wav";
|
||||||
|
generic_message="__DATADIR__/sounds/NewMessage.wav";
|
||||||
|
transfer_pending="__DATADIR__/sounds/TransferPending.wav";
|
||||||
|
transfer_completed="__DATADIR__/sounds/TransferComplete.wav";
|
||||||
|
};
|
||||||
|
BIN
sounds/ContactLogsIn.wav
Normal file
BIN
sounds/ContactLogsIn.wav
Normal file
Binary file not shown.
BIN
sounds/ContactLogsOut.wav
Normal file
BIN
sounds/ContactLogsOut.wav
Normal file
Binary file not shown.
BIN
sounds/Error.wav
Normal file
BIN
sounds/Error.wav
Normal file
Binary file not shown.
BIN
sounds/IncomingCall.wav
Normal file
BIN
sounds/IncomingCall.wav
Normal file
Binary file not shown.
BIN
sounds/LogIn.wav
Normal file
BIN
sounds/LogIn.wav
Normal file
Binary file not shown.
BIN
sounds/LogOut.wav
Normal file
BIN
sounds/LogOut.wav
Normal file
Binary file not shown.
BIN
sounds/NewMessage.wav
Normal file
BIN
sounds/NewMessage.wav
Normal file
Binary file not shown.
BIN
sounds/OutgoingCall.wav
Normal file
BIN
sounds/OutgoingCall.wav
Normal file
Binary file not shown.
BIN
sounds/TransferComplete.wav
Normal file
BIN
sounds/TransferComplete.wav
Normal file
Binary file not shown.
BIN
sounds/TransferPending.wav
Normal file
BIN
sounds/TransferPending.wav
Normal file
Binary file not shown.
1
sounds/license
Normal file
1
sounds/license
Normal file
@ -0,0 +1 @@
|
|||||||
|
Tox's sounds are licensed under the "Creative Commons Attribution 3.0 Unported", all credit attributed to Adam Reid.
|
@ -27,6 +27,7 @@
|
|||||||
#include "chat_commands.h"
|
#include "chat_commands.h"
|
||||||
#include "global_commands.h"
|
#include "global_commands.h"
|
||||||
#include "line_info.h"
|
#include "line_info.h"
|
||||||
|
#include "notify.h"
|
||||||
|
|
||||||
#include <curses.h>
|
#include <curses.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -82,17 +83,17 @@ struct _ASettings {
|
|||||||
Call calls[MAX_CALLS];
|
Call calls[MAX_CALLS];
|
||||||
} ASettins;
|
} ASettins;
|
||||||
|
|
||||||
void callback_recv_invite ( int32_t call_index, void *arg );
|
void callback_recv_invite ( void* av, int32_t call_index, void *arg );
|
||||||
void callback_recv_ringing ( int32_t call_index, void *arg );
|
void callback_recv_ringing ( void* av, int32_t call_index, void *arg );
|
||||||
void callback_recv_starting ( int32_t call_index, void *arg );
|
void callback_recv_starting ( void* av, int32_t call_index, void *arg );
|
||||||
void callback_recv_ending ( int32_t call_index, void *arg );
|
void callback_recv_ending ( void* av, int32_t call_index, void *arg );
|
||||||
void callback_recv_error ( int32_t call_index, void *arg );
|
void callback_call_started ( void* av, int32_t call_index, void *arg );
|
||||||
void callback_call_started ( int32_t call_index, void *arg );
|
void callback_call_canceled ( void* av, int32_t call_index, void *arg );
|
||||||
void callback_call_canceled ( int32_t call_index, void *arg );
|
void callback_call_rejected ( void* av, int32_t call_index, void *arg );
|
||||||
void callback_call_rejected ( int32_t call_index, void *arg );
|
void callback_call_ended ( void* av, int32_t call_index, void *arg );
|
||||||
void callback_call_ended ( int32_t call_index, void *arg );
|
void callback_requ_timeout ( void* av, int32_t call_index, void *arg );
|
||||||
void callback_requ_timeout ( int32_t call_index, void *arg );
|
void callback_peer_timeout ( void* av, int32_t call_index, void *arg );
|
||||||
void callback_peer_timeout ( int32_t call_index, void *arg );
|
void callback_media_change ( void* av, int32_t call_index, void *arg );
|
||||||
|
|
||||||
int stop_transmission(int call_index);
|
int stop_transmission(int call_index);
|
||||||
void write_device_callback(ToxAv* av, int32_t call_index, int16_t* data, int size);
|
void write_device_callback(ToxAv* av, int32_t call_index, int16_t* data, int size);
|
||||||
@ -127,19 +128,19 @@ ToxAv *init_audio(ToxWindow *self, Tox *tox)
|
|||||||
return ASettins.av = NULL;
|
return ASettins.av = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
toxav_register_callstate_callback(callback_call_started, av_OnStart, self);
|
toxav_register_callstate_callback(ASettins.av, callback_call_started, av_OnStart, self);
|
||||||
toxav_register_callstate_callback(callback_call_canceled, av_OnCancel, self);
|
toxav_register_callstate_callback(ASettins.av, callback_call_canceled, av_OnCancel, self);
|
||||||
toxav_register_callstate_callback(callback_call_rejected, av_OnReject, self);
|
toxav_register_callstate_callback(ASettins.av, callback_call_rejected, av_OnReject, self);
|
||||||
toxav_register_callstate_callback(callback_call_ended, av_OnEnd, self);
|
toxav_register_callstate_callback(ASettins.av, callback_call_ended, av_OnEnd, self);
|
||||||
toxav_register_callstate_callback(callback_recv_invite, av_OnInvite, self);
|
toxav_register_callstate_callback(ASettins.av, callback_recv_invite, av_OnInvite, self);
|
||||||
|
|
||||||
toxav_register_callstate_callback(callback_recv_ringing, av_OnRinging, self);
|
toxav_register_callstate_callback(ASettins.av, callback_recv_ringing, av_OnRinging, self);
|
||||||
toxav_register_callstate_callback(callback_recv_starting, av_OnStarting, self);
|
toxav_register_callstate_callback(ASettins.av, callback_recv_starting, av_OnStarting, self);
|
||||||
toxav_register_callstate_callback(callback_recv_ending, av_OnEnding, self);
|
toxav_register_callstate_callback(ASettins.av, callback_recv_ending, av_OnEnding, self);
|
||||||
|
|
||||||
toxav_register_callstate_callback(callback_recv_error, av_OnError, self);
|
toxav_register_callstate_callback(ASettins.av, callback_requ_timeout, av_OnRequestTimeout, self);
|
||||||
toxav_register_callstate_callback(callback_requ_timeout, av_OnRequestTimeout, self);
|
toxav_register_callstate_callback(ASettins.av, callback_peer_timeout, av_OnPeerTimeout, self);
|
||||||
toxav_register_callstate_callback(callback_peer_timeout, av_OnPeerTimeout, self);
|
toxav_register_callstate_callback(ASettins.av, callback_media_change, av_OnMediaChange, self);
|
||||||
|
|
||||||
toxav_register_audio_recv_callback(ASettins.av, write_device_callback);
|
toxav_register_audio_recv_callback(ASettins.av, write_device_callback);
|
||||||
|
|
||||||
@ -191,7 +192,8 @@ int start_transmission(ToxWindow *self)
|
|||||||
|
|
||||||
set_call(&ASettins.calls[self->call_idx], _True);
|
set_call(&ASettins.calls[self->call_idx], _True);
|
||||||
|
|
||||||
if ( open_primary_device(input, &ASettins.calls[self->call_idx].in_idx) != de_None )
|
if ( open_primary_device(input, &ASettins.calls[self->call_idx].in_idx,
|
||||||
|
av_DefaultSettings.audio_sample_rate, av_DefaultSettings.audio_frame_duration) != de_None )
|
||||||
line_info_add(self, NULL, NULL, NULL, "Failed to open input device!", SYS_MSG, 0, 0);
|
line_info_add(self, NULL, NULL, NULL, "Failed to open input device!", SYS_MSG, 0, 0);
|
||||||
|
|
||||||
if ( register_device_callback(self->call_idx, ASettins.calls[self->call_idx].in_idx,
|
if ( register_device_callback(self->call_idx, ASettins.calls[self->call_idx].in_idx,
|
||||||
@ -199,7 +201,8 @@ int start_transmission(ToxWindow *self)
|
|||||||
/* Set VAD as true for all; TODO: Make it more dynamic */
|
/* Set VAD as true for all; TODO: Make it more dynamic */
|
||||||
line_info_add(self, NULL, NULL, NULL, "Failed to register input handler!", SYS_MSG, 0, 0);
|
line_info_add(self, NULL, NULL, NULL, "Failed to register input handler!", SYS_MSG, 0, 0);
|
||||||
|
|
||||||
if ( open_primary_device(output, &ASettins.calls[self->call_idx].out_idx) != de_None ) {
|
if ( open_primary_device(output, &ASettins.calls[self->call_idx].out_idx,
|
||||||
|
av_DefaultSettings.audio_sample_rate, av_DefaultSettings.audio_frame_duration) != de_None ) {
|
||||||
line_info_add(self, NULL, NULL, NULL, "Failed to open output device!", SYS_MSG, 0, 0);
|
line_info_add(self, NULL, NULL, NULL, "Failed to open output device!", SYS_MSG, 0, 0);
|
||||||
ASettins.calls[self->call_idx].has_output = 0;
|
ASettins.calls[self->call_idx].has_output = 0;
|
||||||
}
|
}
|
||||||
@ -240,15 +243,15 @@ int stop_transmission(int call_index)
|
|||||||
#define CB_BODY(call_idx, Arg, onFunc) do { ToxWindow* windows = (Arg); int i;\
|
#define CB_BODY(call_idx, Arg, onFunc) do { ToxWindow* windows = (Arg); int i;\
|
||||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) if (windows[i].onFunc != NULL) windows[i].onFunc(&windows[i], ASettins.av, call_idx); } while (0)
|
for (i = 0; i < MAX_WINDOWS_NUM; ++i) if (windows[i].onFunc != NULL) windows[i].onFunc(&windows[i], ASettins.av, call_idx); } while (0)
|
||||||
|
|
||||||
void callback_recv_invite ( int32_t call_index, void* arg )
|
void callback_recv_invite ( void* av, int32_t call_index, void* arg )
|
||||||
{
|
{
|
||||||
CB_BODY(call_index, arg, onInvite);
|
CB_BODY(call_index, arg, onInvite);
|
||||||
}
|
}
|
||||||
void callback_recv_ringing ( int32_t call_index, void* arg )
|
void callback_recv_ringing ( void* av, int32_t call_index, void* arg )
|
||||||
{
|
{
|
||||||
CB_BODY(call_index, arg, onRinging);
|
CB_BODY(call_index, arg, onRinging);
|
||||||
}
|
}
|
||||||
void callback_recv_starting ( int32_t call_index, void* arg )
|
void callback_recv_starting ( void* av, int32_t call_index, void* arg )
|
||||||
{
|
{
|
||||||
ToxWindow* windows = arg;
|
ToxWindow* windows = arg;
|
||||||
int i;
|
int i;
|
||||||
@ -261,17 +264,13 @@ void callback_recv_starting ( int32_t call_index, void* arg )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void callback_recv_ending ( int32_t call_index, void* arg )
|
void callback_recv_ending ( void* av, int32_t call_index, void* arg )
|
||||||
{
|
{
|
||||||
CB_BODY(call_index, arg, onEnding);
|
CB_BODY(call_index, arg, onEnding);
|
||||||
stop_transmission(call_index);
|
stop_transmission(call_index);
|
||||||
}
|
}
|
||||||
void callback_recv_error ( int32_t call_index, void* arg )
|
|
||||||
{
|
void callback_call_started ( void* av, int32_t call_index, void* arg )
|
||||||
CB_BODY(call_index, arg, onError);
|
|
||||||
stop_transmission(call_index);
|
|
||||||
}
|
|
||||||
void callback_call_started ( int32_t call_index, void* arg )
|
|
||||||
{
|
{
|
||||||
ToxWindow* windows = arg;
|
ToxWindow* windows = arg;
|
||||||
int i;
|
int i;
|
||||||
@ -284,28 +283,28 @@ void callback_call_started ( int32_t call_index, void* arg )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void callback_call_canceled ( int32_t call_index, void* arg )
|
void callback_call_canceled ( void* av, int32_t call_index, void* arg )
|
||||||
{
|
{
|
||||||
CB_BODY(call_index, arg, onCancel);
|
CB_BODY(call_index, arg, onCancel);
|
||||||
|
|
||||||
/* In case call is active */
|
/* In case call is active */
|
||||||
stop_transmission(call_index);
|
stop_transmission(call_index);
|
||||||
}
|
}
|
||||||
void callback_call_rejected ( int32_t call_index, void* arg )
|
void callback_call_rejected ( void* av, int32_t call_index, void* arg )
|
||||||
{
|
{
|
||||||
CB_BODY(call_index, arg, onReject);
|
CB_BODY(call_index, arg, onReject);
|
||||||
}
|
}
|
||||||
void callback_call_ended ( int32_t call_index, void* arg )
|
void callback_call_ended ( void* av, int32_t call_index, void* arg )
|
||||||
{
|
{
|
||||||
CB_BODY(call_index, arg, onEnd);
|
CB_BODY(call_index, arg, onEnd);
|
||||||
stop_transmission(call_index);
|
stop_transmission(call_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void callback_requ_timeout ( int32_t call_index, void* arg )
|
void callback_requ_timeout ( void* av, int32_t call_index, void* arg )
|
||||||
{
|
{
|
||||||
CB_BODY(call_index, arg, onRequestTimeout);
|
CB_BODY(call_index, arg, onRequestTimeout);
|
||||||
}
|
}
|
||||||
void callback_peer_timeout ( int32_t call_index, void* arg )
|
void callback_peer_timeout ( void* av, int32_t call_index, void* arg )
|
||||||
{
|
{
|
||||||
CB_BODY(call_index, arg, onPeerTimeout);
|
CB_BODY(call_index, arg, onPeerTimeout);
|
||||||
stop_transmission(call_index);
|
stop_transmission(call_index);
|
||||||
@ -314,6 +313,10 @@ void callback_peer_timeout ( int32_t call_index, void* arg )
|
|||||||
*/
|
*/
|
||||||
toxav_stop_call(ASettins.av, call_index);
|
toxav_stop_call(ASettins.av, call_index);
|
||||||
}
|
}
|
||||||
|
void callback_media_change(void* av, int32_t call_index, void* arg)
|
||||||
|
{
|
||||||
|
/*... TODO cancel all media change requests */
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* End of Callbacks
|
* End of Callbacks
|
||||||
*/
|
*/
|
||||||
@ -476,6 +479,10 @@ void cmd_cancel(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
|
|||||||
goto on_error;
|
goto on_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
stop_sound(self->active_sound);
|
||||||
|
self->active_sound = -1;
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
/* Callback will print status... */
|
/* Callback will print status... */
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -612,14 +619,16 @@ void cmd_ccur_device(WINDOW * window, ToxWindow * self, Tox *m, int argc, char (
|
|||||||
if (type == output) {
|
if (type == output) {
|
||||||
pthread_mutex_lock(&this_call->mutex);
|
pthread_mutex_lock(&this_call->mutex);
|
||||||
close_device(output, this_call->out_idx);
|
close_device(output, this_call->out_idx);
|
||||||
this_call->has_output = open_device(output, selection, &this_call->out_idx)
|
this_call->has_output = open_device(output, selection, &this_call->out_idx,
|
||||||
|
av_DefaultSettings.audio_sample_rate, av_DefaultSettings.audio_frame_duration)
|
||||||
== de_None ? 1 : 0;
|
== de_None ? 1 : 0;
|
||||||
pthread_mutex_unlock(&this_call->mutex);
|
pthread_mutex_unlock(&this_call->mutex);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* TODO: check for failure */
|
/* TODO: check for failure */
|
||||||
close_device(input, this_call->in_idx);
|
close_device(input, this_call->in_idx);
|
||||||
open_device(input, selection, &this_call->in_idx);
|
open_device(input, selection, &this_call->in_idx,
|
||||||
|
av_DefaultSettings.audio_sample_rate, av_DefaultSettings.audio_frame_duration);
|
||||||
/* Set VAD as true for all; TODO: Make it more dynamic */
|
/* Set VAD as true for all; TODO: Make it more dynamic */
|
||||||
register_device_callback(self->call_idx, this_call->in_idx, read_device_callback, &self->call_idx, _True);
|
register_device_callback(self->call_idx, this_call->in_idx, read_device_callback, &self->call_idx, _True);
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,6 @@
|
|||||||
|
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
|
||||||
#define VAD_THRESHOLD_DEFAULT 40.0
|
|
||||||
|
|
||||||
typedef enum _AudioError {
|
typedef enum _AudioError {
|
||||||
ae_None = 0,
|
ae_None = 0,
|
||||||
ae_StartingCaptureDevice = 1 << 0,
|
ae_StartingCaptureDevice = 1 << 0,
|
||||||
|
289
src/autocomplete.c
Normal file
289
src/autocomplete.c
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
/* autocomplete.c
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Toxic All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file is part of Toxic.
|
||||||
|
*
|
||||||
|
* Toxic is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Toxic is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Toxic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/dir.h>
|
||||||
|
#else
|
||||||
|
#include <dirent.h>
|
||||||
|
#endif /* ifdef __APPLE__ */
|
||||||
|
|
||||||
|
#include "windows.h"
|
||||||
|
#include "toxic.h"
|
||||||
|
#include "misc_tools.h"
|
||||||
|
#include "line_info.h"
|
||||||
|
#include "execute.h"
|
||||||
|
#include "configdir.h"
|
||||||
|
|
||||||
|
static void print_matches(ToxWindow *self, Tox *m, const void *list, int n_items, int size)
|
||||||
|
{
|
||||||
|
if (m)
|
||||||
|
execute(self->chatwin->history, self, m, "/clear", GLOBAL_COMMAND_MODE);
|
||||||
|
|
||||||
|
const char *L = (char *) list;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < n_items; ++i)
|
||||||
|
line_info_add(self, NULL, NULL, NULL, &L[i * size], SYS_MSG, 0, 0);
|
||||||
|
|
||||||
|
line_info_add(self, NULL, NULL, NULL, "", SYS_MSG, 0, 0); /* formatting */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* puts match in match buffer. if more than one match, add first n chars that are identical.
|
||||||
|
e.g. if matches contains: [foo, foobar, foe] we put fo in matches. */
|
||||||
|
static void get_str_match(ToxWindow *self, char *match, char (*matches)[MAX_STR_SIZE], int n)
|
||||||
|
{
|
||||||
|
if (n == 1) {
|
||||||
|
strcpy(match, matches[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_STR_SIZE; ++i) {
|
||||||
|
char ch1 = matches[0][i];
|
||||||
|
int j;
|
||||||
|
|
||||||
|
for (j = 0; j < n; ++j) {
|
||||||
|
char ch2 = matches[j][i];
|
||||||
|
|
||||||
|
if (ch1 != ch2 || !ch1) {
|
||||||
|
strcpy(match, matches[0]);
|
||||||
|
match[i] = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(match, matches[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* looks for all instances in list that begin with the last entered word in line according to pos,
|
||||||
|
then fills line with the complete word. e.g. "Hello jo" would complete the line
|
||||||
|
with "Hello john". If multiple matches, prints out all the matches and semi-completes line.
|
||||||
|
|
||||||
|
list is a pointer to the list of strings being compared, n_items is the number of items
|
||||||
|
in the list, and size is the size of each item in the list.
|
||||||
|
|
||||||
|
Returns the difference between the old len and new len of line on success, -1 if error */
|
||||||
|
int complete_line(ToxWindow *self, const void *list, int n_items, int size)
|
||||||
|
{
|
||||||
|
ChatContext *ctx = self->chatwin;
|
||||||
|
|
||||||
|
if (ctx->pos <= 0 || ctx->len <= 0 || ctx->len >= MAX_STR_SIZE || size > MAX_STR_SIZE)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
const char *L = (char *) list;
|
||||||
|
const char *endchrs = " ";
|
||||||
|
char ubuf[MAX_STR_SIZE];
|
||||||
|
|
||||||
|
/* work with multibyte string copy of buf for simplicity */
|
||||||
|
if (wcs_to_mbs_buf(ubuf, ctx->line, sizeof(ubuf)) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
bool dir_search = strncmp(ubuf, "/sendfile", strlen("/sendfile")) == 0;
|
||||||
|
|
||||||
|
/* isolate substring from space behind pos to pos */
|
||||||
|
char tmp[MAX_STR_SIZE];
|
||||||
|
snprintf(tmp, sizeof(tmp), "%s", ubuf);
|
||||||
|
tmp[ctx->pos] = '\0';
|
||||||
|
|
||||||
|
const char *s = dir_search ? strchr(tmp, '\"') : strrchr(tmp, ' ');
|
||||||
|
char *sub = malloc(strlen(ubuf) + 1);
|
||||||
|
|
||||||
|
if (sub == NULL)
|
||||||
|
exit_toxic_err("failed in complete_line", FATALERR_MEMORY);
|
||||||
|
|
||||||
|
if (!s && !dir_search) {
|
||||||
|
strcpy(sub, tmp);
|
||||||
|
|
||||||
|
if (sub[0] != '/')
|
||||||
|
endchrs = ": ";
|
||||||
|
} else if (s) {
|
||||||
|
strcpy(sub, &s[1]);
|
||||||
|
|
||||||
|
if (dir_search) {
|
||||||
|
int sub_len = strlen(sub);
|
||||||
|
int si = char_rfind(sub, '/', sub_len);
|
||||||
|
|
||||||
|
if (si || *sub == '/')
|
||||||
|
memmove(sub, &sub[si + 1], sub_len - si);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string_is_empty(sub)) {
|
||||||
|
free(sub);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int s_len = strlen(sub);
|
||||||
|
const char *str;
|
||||||
|
int n_matches = 0;
|
||||||
|
char matches[n_items][MAX_STR_SIZE];
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
/* put all list matches in matches array */
|
||||||
|
for (i = 0; i < n_items; ++i) {
|
||||||
|
str = &L[i * size];
|
||||||
|
|
||||||
|
if (strncasecmp(str, sub, s_len) == 0)
|
||||||
|
strcpy(matches[n_matches++], str);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(sub);
|
||||||
|
|
||||||
|
if (!n_matches)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!dir_search && n_matches > 1)
|
||||||
|
print_matches(self, NULL, matches, n_matches, MAX_STR_SIZE);
|
||||||
|
|
||||||
|
char match[MAX_STR_SIZE];
|
||||||
|
get_str_match(self, match, matches, n_matches);
|
||||||
|
|
||||||
|
if (dir_search) {
|
||||||
|
if (n_matches == 1)
|
||||||
|
endchrs = char_rfind(match, '.', strlen(match)) ? "\"" : "/";
|
||||||
|
else
|
||||||
|
endchrs = "";
|
||||||
|
} else if (n_matches > 1) {
|
||||||
|
endchrs = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* put match in correct spot in buf and append endchars */
|
||||||
|
int n_endchrs = strlen(endchrs);
|
||||||
|
int m_len = strlen(match);
|
||||||
|
int strt = ctx->pos - s_len;
|
||||||
|
int diff = m_len - s_len + n_endchrs;
|
||||||
|
|
||||||
|
if (ctx->len + diff > MAX_STR_SIZE)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
char tmpend[MAX_STR_SIZE];
|
||||||
|
strcpy(tmpend, &ubuf[ctx->pos]);
|
||||||
|
strcpy(&ubuf[strt], match);
|
||||||
|
strcpy(&ubuf[strt + m_len], endchrs);
|
||||||
|
strcpy(&ubuf[strt + m_len + n_endchrs], tmpend);
|
||||||
|
|
||||||
|
/* convert to widechar and copy back to original buf */
|
||||||
|
wchar_t newbuf[MAX_STR_SIZE];
|
||||||
|
|
||||||
|
if (mbs_to_wcs_buf(newbuf, ubuf, MAX_STR_SIZE) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
wcscpy(ctx->line, newbuf);
|
||||||
|
|
||||||
|
ctx->len += diff;
|
||||||
|
ctx->pos += diff;
|
||||||
|
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* transforms a sendfile tab complete contaning the shorthand "~/" into the full home directory.*/
|
||||||
|
static void complt_home_dir(ToxWindow *self, char *path)
|
||||||
|
{
|
||||||
|
ChatContext *ctx = self->chatwin;
|
||||||
|
|
||||||
|
char homedir[MAX_STR_SIZE];
|
||||||
|
get_home_dir(homedir, sizeof(homedir));
|
||||||
|
|
||||||
|
char newline[MAX_STR_SIZE];
|
||||||
|
const char *isqt = !strchr(path, '\"') ? "\"" : "";
|
||||||
|
snprintf(newline, sizeof(newline), "/sendfile %s%s/", isqt, homedir);
|
||||||
|
|
||||||
|
wchar_t wline[MAX_STR_SIZE];
|
||||||
|
|
||||||
|
if (mbs_to_wcs_buf(wline, newline, sizeof(wline)) == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int newlen = wcslen(wline);
|
||||||
|
|
||||||
|
if (ctx->len + newlen > MAX_STR_SIZE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wmemcpy(ctx->line, wline, newlen + 1);
|
||||||
|
ctx->pos = newlen;
|
||||||
|
ctx->len = ctx->pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* attempts to match /sendfile "<incomplete-dir>" line to matching directories.
|
||||||
|
|
||||||
|
if only one match, auto-complete line.
|
||||||
|
return diff between old len and new len of ctx->line, -1 if no matches
|
||||||
|
*/
|
||||||
|
#define MAX_DIRS 256
|
||||||
|
|
||||||
|
int dir_match(ToxWindow *self, Tox *m, wchar_t *line)
|
||||||
|
{
|
||||||
|
char b_path[MAX_STR_SIZE];
|
||||||
|
char b_name[MAX_STR_SIZE];
|
||||||
|
|
||||||
|
if (wcs_to_mbs_buf(b_path, line, sizeof(b_path)) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!strncmp(b_path, "\"~/", 3) || !strncmp(b_path, "~/", 2)) {
|
||||||
|
complt_home_dir(self, b_path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int si = char_rfind(b_path, '/', strlen(b_path));
|
||||||
|
|
||||||
|
if (!b_path[0]) { /* list everything in pwd */
|
||||||
|
b_path[0] = '.';
|
||||||
|
b_path[1] = '\0';
|
||||||
|
} else if (!si && b_path[0] != '/') { /* look for matches in pwd */
|
||||||
|
char tmp[MAX_STR_SIZE];
|
||||||
|
snprintf(tmp, sizeof(tmp), ".%s", b_path);
|
||||||
|
strcpy(b_path, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(b_name, &b_path[si + 1]);
|
||||||
|
b_path[si + 1] = '\0';
|
||||||
|
int b_name_len = strlen(b_name);
|
||||||
|
|
||||||
|
DIR *dp = opendir(b_path);
|
||||||
|
|
||||||
|
if (dp == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
char dirnames[MAX_DIRS][NAME_MAX];
|
||||||
|
struct dirent *entry;
|
||||||
|
int dircount = 0;
|
||||||
|
|
||||||
|
while ((entry = readdir(dp)) && dircount < MAX_DIRS) {
|
||||||
|
if (strncmp(entry->d_name, b_name, b_name_len) == 0) {
|
||||||
|
snprintf(dirnames[dircount], sizeof(dirnames[dircount]), "%s", entry->d_name);
|
||||||
|
++dircount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dircount == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (dircount > 1)
|
||||||
|
print_matches(self, m, dirnames, dircount, NAME_MAX);
|
||||||
|
|
||||||
|
return complete_line(self, dirnames, dircount, NAME_MAX);
|
||||||
|
}
|
43
src/autocomplete.h
Normal file
43
src/autocomplete.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/* autocomplete.h
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Toxic All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file is part of Toxic.
|
||||||
|
*
|
||||||
|
* Toxic is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Toxic is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Toxic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _autocomplete_h
|
||||||
|
#define _autocomplete_h
|
||||||
|
|
||||||
|
/* looks for all instances in list that begin with the last entered word in line according to pos,
|
||||||
|
then fills line with the complete word. e.g. "Hello jo" would complete the line
|
||||||
|
with "Hello john". If multiple matches, prints out all the matches and semi-completes line.
|
||||||
|
|
||||||
|
list is a pointer to the list of strings being compared, n_items is the number of items
|
||||||
|
in the list, and size is the size of each item in the list.
|
||||||
|
|
||||||
|
Returns the difference between the old len and new len of line on success, -1 if error */
|
||||||
|
int complete_line(ToxWindow *self, const void *list, int n_items, int size);
|
||||||
|
|
||||||
|
/* matches /sendfile "<incomplete-dir>" line to matching directories.
|
||||||
|
|
||||||
|
if only one match, auto-complete line.
|
||||||
|
return diff between old len and new len of ctx->line, or -1 if no matches
|
||||||
|
*/
|
||||||
|
int dir_match(ToxWindow *self, Tox *m, const wchar_t *line);
|
||||||
|
|
||||||
|
#endif /* #define _autocomplete_h */
|
146
src/chat.c
146
src/chat.c
@ -41,10 +41,13 @@
|
|||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "help.h"
|
#include "help.h"
|
||||||
|
#include "autocomplete.h"
|
||||||
|
#include "notify.h"
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
#include "audio_call.h"
|
#include "audio_call.h"
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
|
|
||||||
extern char *DATA_FILE;
|
extern char *DATA_FILE;
|
||||||
|
|
||||||
@ -52,18 +55,18 @@ extern FileSender file_senders[MAX_FILES];
|
|||||||
extern ToxicFriend friends[MAX_FRIENDS_NUM];
|
extern ToxicFriend friends[MAX_FRIENDS_NUM];
|
||||||
|
|
||||||
extern struct _Winthread Winthread;
|
extern struct _Winthread Winthread;
|
||||||
extern struct user_settings *user_settings;
|
extern struct user_settings *user_settings_;
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
static void init_infobox(ToxWindow *self);
|
static void init_infobox(ToxWindow *self);
|
||||||
static void kill_infobox(ToxWindow *self);
|
static void kill_infobox(ToxWindow *self);
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
#define AC_NUM_CHAT_COMMANDS 26
|
#define AC_NUM_CHAT_COMMANDS 26
|
||||||
#else
|
#else
|
||||||
#define AC_NUM_CHAT_COMMANDS 18
|
#define AC_NUM_CHAT_COMMANDS 18
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
/* Array of chat command names used for tab completion. */
|
/* Array of chat command names used for tab completion. */
|
||||||
static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = {
|
static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = {
|
||||||
@ -86,7 +89,7 @@ static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = {
|
|||||||
{ "/sendfile" },
|
{ "/sendfile" },
|
||||||
{ "/status" },
|
{ "/status" },
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
|
|
||||||
{ "/call" },
|
{ "/call" },
|
||||||
{ "/cancel" },
|
{ "/cancel" },
|
||||||
@ -97,7 +100,7 @@ static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = {
|
|||||||
{ "/mute" },
|
{ "/mute" },
|
||||||
{ "/sense" },
|
{ "/sense" },
|
||||||
|
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
};
|
};
|
||||||
|
|
||||||
static void set_typingstatus(ToxWindow *self, Tox *m, uint8_t is_typing)
|
static void set_typingstatus(ToxWindow *self, Tox *m, uint8_t is_typing)
|
||||||
@ -126,7 +129,7 @@ void kill_chat_window(ToxWindow *self)
|
|||||||
log_disable(ctx->log);
|
log_disable(ctx->log);
|
||||||
line_info_cleanup(ctx->hst);
|
line_info_cleanup(ctx->hst);
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
stop_current_call(self);
|
stop_current_call(self);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -159,7 +162,8 @@ static void chat_onMessage(ToxWindow *self, Tox *m, int32_t num, const char *msg
|
|||||||
|
|
||||||
line_info_add(self, timefrmt, nick, NULL, msg, IN_MSG, 0, 0);
|
line_info_add(self, timefrmt, nick, NULL, msg, IN_MSG, 0, 0);
|
||||||
write_to_log(msg, nick, ctx->log, false);
|
write_to_log(msg, nick, ctx->log, false);
|
||||||
alert_window(self, WINDOW_ALERT_1, true);
|
|
||||||
|
notify(self, generic_message, NT_WNDALERT_1 | NT_NOFOCUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void chat_onConnectionChange(ToxWindow *self, Tox *m, int32_t num, uint8_t status)
|
static void chat_onConnectionChange(ToxWindow *self, Tox *m, int32_t num, uint8_t status)
|
||||||
@ -169,12 +173,14 @@ static void chat_onConnectionChange(ToxWindow *self, Tox *m, int32_t num, uint8_
|
|||||||
|
|
||||||
StatusBar *statusbar = self->stb;
|
StatusBar *statusbar = self->stb;
|
||||||
|
|
||||||
if (status == 1) {
|
if (status == 1) { /* Friend shows online */
|
||||||
statusbar->is_online = true;
|
statusbar->is_online = true;
|
||||||
friends[num].is_typing = tox_get_is_typing(m, num);
|
friends[num].is_typing = tox_get_is_typing(m, num);
|
||||||
} else {
|
notify(self, user_log_in, NT_NOFOCUS);
|
||||||
|
} else { /* Friend goes offline */
|
||||||
statusbar->is_online = false;
|
statusbar->is_online = false;
|
||||||
friends[num].is_typing = 0;
|
friends[num].is_typing = 0;
|
||||||
|
notify(self, user_log_out, NT_NOFOCUS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,7 +207,7 @@ static void chat_onAction(ToxWindow *self, Tox *m, int32_t num, const char *acti
|
|||||||
|
|
||||||
line_info_add(self, timefrmt, nick, NULL, action, ACTION, 0, 0);
|
line_info_add(self, timefrmt, nick, NULL, action, ACTION, 0, 0);
|
||||||
write_to_log(action, nick, ctx->log, true);
|
write_to_log(action, nick, ctx->log, true);
|
||||||
alert_window(self, WINDOW_ALERT_1, true);
|
notify(self, generic_message, NT_WNDALERT_1 | NT_NOFOCUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void chat_onNickChange(ToxWindow *self, Tox *m, int32_t num, const char *nick, uint16_t len)
|
static void chat_onNickChange(ToxWindow *self, Tox *m, int32_t num, const char *nick, uint16_t len)
|
||||||
@ -271,9 +277,9 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* use specified path in config if possible */
|
/* use specified path in config if possible */
|
||||||
if (user_settings->download_path[0]) {
|
if (user_settings_->download_path[0]) {
|
||||||
snprintf(filename_path, sizeof(filename_path), "%s%s", user_settings->download_path, filename_nopath);
|
snprintf(filename_path, sizeof(filename_path), "%s%s", user_settings_->download_path, filename_nopath);
|
||||||
len += strlen(user_settings->download_path);
|
len += strlen(user_settings_->download_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len >= sizeof(friends[num].file_receiver.filenames[filenum])) {
|
if (len >= sizeof(friends[num].file_receiver.filenames[filenum])) {
|
||||||
@ -321,7 +327,7 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t
|
|||||||
friends[num].file_receiver.size[filenum] = filesize;
|
friends[num].file_receiver.size[filenum] = filesize;
|
||||||
strcpy(friends[num].file_receiver.filenames[filenum], filename);
|
strcpy(friends[num].file_receiver.filenames[filenum], filename);
|
||||||
|
|
||||||
alert_window(self, WINDOW_ALERT_2, true);
|
notify(self, transfer_pending, NT_WNDALERT_2 | NT_NOFOCUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void chat_close_file_receiver(int32_t num, uint8_t filenum)
|
static void chat_close_file_receiver(int32_t num, uint8_t filenum)
|
||||||
@ -360,6 +366,7 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t rec
|
|||||||
if (receive_send == 1) {
|
if (receive_send == 1) {
|
||||||
snprintf(msg, sizeof(msg), "File transfer for '%s' accepted (%.1f%%)", filename, 0.0);
|
snprintf(msg, sizeof(msg), "File transfer for '%s' accepted (%.1f%%)", filename, 0.0);
|
||||||
file_senders[i].line_id = self->chatwin->hst->line_end->id + 1;
|
file_senders[i].line_id = self->chatwin->hst->line_end->id + 1;
|
||||||
|
notify(self, silent, NT_NOFOCUS | NT_BEEP | NT_WNDALERT_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -370,19 +377,20 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t rec
|
|||||||
if (receive_send == 0)
|
if (receive_send == 0)
|
||||||
chat_close_file_receiver(num, filenum);
|
chat_close_file_receiver(num, filenum);
|
||||||
|
|
||||||
|
notify(self, error, NT_NOFOCUS | NT_WNDALERT_2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOX_FILECONTROL_FINISHED:
|
case TOX_FILECONTROL_FINISHED:
|
||||||
if (receive_send == 0) {
|
if (receive_send == 0) {
|
||||||
snprintf(msg, sizeof(msg), "File transfer for '%s' complete.", filename);
|
snprintf(msg, sizeof(msg), "File transfer for '%s' complete.", filename);
|
||||||
chat_close_file_receiver(num, filenum);
|
chat_close_file_receiver(num, filenum);
|
||||||
|
notify(self, transfer_completed, NT_NOFOCUS | NT_WNDALERT_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
alert_window(self, WINDOW_ALERT_2, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void chat_onFileData(ToxWindow *self, Tox *m, int32_t num, uint8_t filenum, const char *data,
|
static void chat_onFileData(ToxWindow *self, Tox *m, int32_t num, uint8_t filenum, const char *data,
|
||||||
@ -435,11 +443,12 @@ static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, co
|
|||||||
sizeof(friends[friendnumber].groupchat_key));
|
sizeof(friends[friendnumber].groupchat_key));
|
||||||
friends[friendnumber].groupchat_pending = true;
|
friends[friendnumber].groupchat_pending = true;
|
||||||
|
|
||||||
alert_window(self, WINDOW_ALERT_2, true);
|
|
||||||
|
notify(self, generic_message, NT_WNDALERT_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Av Stuff */
|
/* Av Stuff */
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
|
|
||||||
void chat_onInvite (ToxWindow *self, ToxAv *av, int call_index)
|
void chat_onInvite (ToxWindow *self, ToxAv *av, int call_index)
|
||||||
{
|
{
|
||||||
@ -450,7 +459,11 @@ void chat_onInvite (ToxWindow *self, ToxAv *av, int call_index)
|
|||||||
|
|
||||||
self->call_idx = call_index;
|
self->call_idx = call_index;
|
||||||
line_info_add(self, NULL, NULL, NULL, "Incoming audio call! Type: \"/answer\" or \"/reject\"", SYS_MSG, 0, 0);
|
line_info_add(self, NULL, NULL, NULL, "Incoming audio call! Type: \"/answer\" or \"/reject\"", SYS_MSG, 0, 0);
|
||||||
alert_window(self, WINDOW_ALERT_0, true);
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
if (self->active_sound == -1)
|
||||||
|
self->active_sound = notify(self, call_incoming, NT_LOOP | NT_WNDALERT_0);
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
}
|
}
|
||||||
|
|
||||||
void chat_onRinging (ToxWindow *self, ToxAv *av, int call_index)
|
void chat_onRinging (ToxWindow *self, ToxAv *av, int call_index)
|
||||||
@ -459,6 +472,11 @@ void chat_onRinging (ToxWindow *self, ToxAv *av, int call_index)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
line_info_add(self, NULL, NULL, NULL, "Ringing...\"cancel\" ?", SYS_MSG, 0, 0);
|
line_info_add(self, NULL, NULL, NULL, "Ringing...\"cancel\" ?", SYS_MSG, 0, 0);
|
||||||
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
if (self->active_sound == -1)
|
||||||
|
self->active_sound = notify(self, call_outgoing, NT_LOOP);
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
}
|
}
|
||||||
|
|
||||||
void chat_onStarting (ToxWindow *self, ToxAv *av, int call_index)
|
void chat_onStarting (ToxWindow *self, ToxAv *av, int call_index)
|
||||||
@ -469,6 +487,11 @@ void chat_onStarting (ToxWindow *self, ToxAv *av, int call_index)
|
|||||||
init_infobox(self);
|
init_infobox(self);
|
||||||
|
|
||||||
line_info_add(self, NULL, NULL, NULL, "Call started! Type: \"/hangup\" to end it.", SYS_MSG, 0, 0);
|
line_info_add(self, NULL, NULL, NULL, "Call started! Type: \"/hangup\" to end it.", SYS_MSG, 0, 0);
|
||||||
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
stop_sound(self->active_sound);
|
||||||
|
self->active_sound = -1;
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
}
|
}
|
||||||
|
|
||||||
void chat_onEnding (ToxWindow *self, ToxAv *av, int call_index)
|
void chat_onEnding (ToxWindow *self, ToxAv *av, int call_index)
|
||||||
@ -479,6 +502,11 @@ void chat_onEnding (ToxWindow *self, ToxAv *av, int call_index)
|
|||||||
kill_infobox(self);
|
kill_infobox(self);
|
||||||
self->call_idx = -1;
|
self->call_idx = -1;
|
||||||
line_info_add(self, NULL, NULL, NULL, "Call ended!", SYS_MSG, 0, 0);
|
line_info_add(self, NULL, NULL, NULL, "Call ended!", SYS_MSG, 0, 0);
|
||||||
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
stop_sound(self->active_sound);
|
||||||
|
self->active_sound = -1;
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
}
|
}
|
||||||
|
|
||||||
void chat_onError (ToxWindow *self, ToxAv *av, int call_index)
|
void chat_onError (ToxWindow *self, ToxAv *av, int call_index)
|
||||||
@ -488,6 +516,11 @@ void chat_onError (ToxWindow *self, ToxAv *av, int call_index)
|
|||||||
|
|
||||||
self->call_idx = -1;
|
self->call_idx = -1;
|
||||||
line_info_add(self, NULL, NULL, NULL, "Error!", SYS_MSG, 0, 0);
|
line_info_add(self, NULL, NULL, NULL, "Error!", SYS_MSG, 0, 0);
|
||||||
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
stop_sound(self->active_sound);
|
||||||
|
self->active_sound = -1;
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
}
|
}
|
||||||
|
|
||||||
void chat_onStart (ToxWindow *self, ToxAv *av, int call_index)
|
void chat_onStart (ToxWindow *self, ToxAv *av, int call_index)
|
||||||
@ -498,6 +531,11 @@ void chat_onStart (ToxWindow *self, ToxAv *av, int call_index)
|
|||||||
init_infobox(self);
|
init_infobox(self);
|
||||||
|
|
||||||
line_info_add(self, NULL, NULL, NULL, "Call started! Type: \"/hangup\" to end it.", SYS_MSG, 0, 0);
|
line_info_add(self, NULL, NULL, NULL, "Call started! Type: \"/hangup\" to end it.", SYS_MSG, 0, 0);
|
||||||
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
stop_sound(self->active_sound);
|
||||||
|
self->active_sound = -1;
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
}
|
}
|
||||||
|
|
||||||
void chat_onCancel (ToxWindow *self, ToxAv *av, int call_index)
|
void chat_onCancel (ToxWindow *self, ToxAv *av, int call_index)
|
||||||
@ -508,6 +546,11 @@ void chat_onCancel (ToxWindow *self, ToxAv *av, int call_index)
|
|||||||
kill_infobox(self);
|
kill_infobox(self);
|
||||||
self->call_idx = -1;
|
self->call_idx = -1;
|
||||||
line_info_add(self, NULL, NULL, NULL, "Call canceled!", SYS_MSG, 0, 0);
|
line_info_add(self, NULL, NULL, NULL, "Call canceled!", SYS_MSG, 0, 0);
|
||||||
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
stop_sound(self->active_sound);
|
||||||
|
self->active_sound = -1;
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
}
|
}
|
||||||
|
|
||||||
void chat_onReject (ToxWindow *self, ToxAv *av, int call_index)
|
void chat_onReject (ToxWindow *self, ToxAv *av, int call_index)
|
||||||
@ -517,6 +560,11 @@ void chat_onReject (ToxWindow *self, ToxAv *av, int call_index)
|
|||||||
|
|
||||||
self->call_idx = -1;
|
self->call_idx = -1;
|
||||||
line_info_add(self, NULL, NULL, NULL, "Rejected!", SYS_MSG, 0, 0);
|
line_info_add(self, NULL, NULL, NULL, "Rejected!", SYS_MSG, 0, 0);
|
||||||
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
stop_sound(self->active_sound);
|
||||||
|
self->active_sound = -1;
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
}
|
}
|
||||||
|
|
||||||
void chat_onEnd (ToxWindow *self, ToxAv *av, int call_index)
|
void chat_onEnd (ToxWindow *self, ToxAv *av, int call_index)
|
||||||
@ -527,6 +575,11 @@ void chat_onEnd (ToxWindow *self, ToxAv *av, int call_index)
|
|||||||
kill_infobox(self);
|
kill_infobox(self);
|
||||||
self->call_idx = -1;
|
self->call_idx = -1;
|
||||||
line_info_add(self, NULL, NULL, NULL, "Call ended!", SYS_MSG, 0, 0);
|
line_info_add(self, NULL, NULL, NULL, "Call ended!", SYS_MSG, 0, 0);
|
||||||
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
stop_sound(self->active_sound);
|
||||||
|
self->active_sound = -1;
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
}
|
}
|
||||||
|
|
||||||
void chat_onRequestTimeout (ToxWindow *self, ToxAv *av, int call_index)
|
void chat_onRequestTimeout (ToxWindow *self, ToxAv *av, int call_index)
|
||||||
@ -536,6 +589,11 @@ void chat_onRequestTimeout (ToxWindow *self, ToxAv *av, int call_index)
|
|||||||
|
|
||||||
self->call_idx = -1;
|
self->call_idx = -1;
|
||||||
line_info_add(self, NULL, NULL, NULL, "No answer!", SYS_MSG, 0, 0);
|
line_info_add(self, NULL, NULL, NULL, "No answer!", SYS_MSG, 0, 0);
|
||||||
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
stop_sound(self->active_sound);
|
||||||
|
self->active_sound = -1;
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
}
|
}
|
||||||
|
|
||||||
void chat_onPeerTimeout (ToxWindow *self, ToxAv *av, int call_index)
|
void chat_onPeerTimeout (ToxWindow *self, ToxAv *av, int call_index)
|
||||||
@ -546,8 +604,14 @@ void chat_onPeerTimeout (ToxWindow *self, ToxAv *av, int call_index)
|
|||||||
kill_infobox(self);
|
kill_infobox(self);
|
||||||
self->call_idx = -1;
|
self->call_idx = -1;
|
||||||
line_info_add(self, NULL, NULL, NULL, "Peer disconnected; call ended!", SYS_MSG, 0, 0);
|
line_info_add(self, NULL, NULL, NULL, "Peer disconnected; call ended!", SYS_MSG, 0, 0);
|
||||||
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
stop_sound(self->active_sound);
|
||||||
|
self->active_sound = -1;
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _AUDIO
|
||||||
static void init_infobox(ToxWindow *self)
|
static void init_infobox(ToxWindow *self)
|
||||||
{
|
{
|
||||||
ChatContext *ctx = self->chatwin;
|
ChatContext *ctx = self->chatwin;
|
||||||
@ -560,10 +624,11 @@ static void init_infobox(ToxWindow *self)
|
|||||||
|
|
||||||
ctx->infobox.win = newwin(INFOBOX_HEIGHT, INFOBOX_WIDTH + 1, 1, x2 - INFOBOX_WIDTH);
|
ctx->infobox.win = newwin(INFOBOX_HEIGHT, INFOBOX_WIDTH + 1, 1, x2 - INFOBOX_WIDTH);
|
||||||
ctx->infobox.starttime = get_unix_time();
|
ctx->infobox.starttime = get_unix_time();
|
||||||
ctx->infobox.vad_lvl = VAD_THRESHOLD_DEFAULT;
|
ctx->infobox.vad_lvl = user_settings_->VAD_treshold;
|
||||||
ctx->infobox.active = true;
|
ctx->infobox.active = true;
|
||||||
strcpy(ctx->infobox.timestr, "00");
|
strcpy(ctx->infobox.timestr, "00");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void kill_infobox(ToxWindow *self)
|
static void kill_infobox(ToxWindow *self)
|
||||||
{
|
{
|
||||||
@ -630,7 +695,7 @@ static void draw_infobox(ToxWindow *self)
|
|||||||
wrefresh(infobox->win);
|
wrefresh(infobox->win);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
static void send_action(ToxWindow *self, ChatContext *ctx, Tox *m, char *action)
|
static void send_action(ToxWindow *self, ChatContext *ctx, Tox *m, char *action)
|
||||||
{
|
{
|
||||||
@ -685,21 +750,24 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
|||||||
|
|
||||||
input_handle(self, key, x, y, x2, y2);
|
input_handle(self, key, x, y, x2, y2);
|
||||||
|
|
||||||
if (key == '\t') { /* TAB key: auto-completes command */
|
if (key == '\t' && ctx->len > 1 && ctx->line[0] == '/') { /* TAB key: auto-complete */
|
||||||
if (ctx->len > 1 && ctx->line[0] == '/') {
|
int diff = -1;
|
||||||
int diff = complete_line(ctx, chat_cmd_list, AC_NUM_CHAT_COMMANDS, MAX_CMDNAME_SIZE);
|
int sf_len = 11;
|
||||||
|
|
||||||
|
if (wcsncmp(ctx->line, L"/sendfile \"", sf_len) == 0) {
|
||||||
|
diff = dir_match(self, m, &ctx->line[sf_len]);
|
||||||
|
} else {
|
||||||
|
diff = complete_line(self, chat_cmd_list, AC_NUM_CHAT_COMMANDS, MAX_CMDNAME_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
if (diff != -1) {
|
if (diff != -1) {
|
||||||
if (x + diff > x2 - 1) {
|
if (x + diff > x2 - 1) {
|
||||||
wmove(self->window, y, x + diff);
|
int wlen = wcswidth(ctx->line, sizeof(ctx->line));
|
||||||
ctx->start += diff;
|
ctx->start = wlen < x2 ? 0 : wlen - x2 + 1;
|
||||||
} else {
|
|
||||||
wmove(self->window, y, x + diff);
|
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
beep();
|
|
||||||
} else
|
|
||||||
beep();
|
beep();
|
||||||
|
}
|
||||||
|
|
||||||
} else if (key == '\n') {
|
} else if (key == '\n') {
|
||||||
rm_trailing_spaces_buf(ctx);
|
rm_trailing_spaces_buf(ctx);
|
||||||
@ -856,7 +924,7 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
|
|||||||
|
|
||||||
wrefresh(self->window);
|
wrefresh(self->window);
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
if (ctx->infobox.active) {
|
if (ctx->infobox.active) {
|
||||||
draw_infobox(self);
|
draw_infobox(self);
|
||||||
wrefresh(self->window);
|
wrefresh(self->window);
|
||||||
@ -938,7 +1006,7 @@ ToxWindow new_chat(Tox *m, int32_t friendnum)
|
|||||||
ret.onFileControl = &chat_onFileControl;
|
ret.onFileControl = &chat_onFileControl;
|
||||||
ret.onFileData = &chat_onFileData;
|
ret.onFileData = &chat_onFileData;
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
ret.onInvite = &chat_onInvite;
|
ret.onInvite = &chat_onInvite;
|
||||||
ret.onRinging = &chat_onRinging;
|
ret.onRinging = &chat_onRinging;
|
||||||
ret.onStarting = &chat_onStarting;
|
ret.onStarting = &chat_onStarting;
|
||||||
@ -953,7 +1021,11 @@ ToxWindow new_chat(Tox *m, int32_t friendnum)
|
|||||||
|
|
||||||
ret.call_idx = -1;
|
ret.call_idx = -1;
|
||||||
ret.device_selection[0] = ret.device_selection[1] = -1;
|
ret.device_selection[0] = ret.device_selection[1] = -1;
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
ret.active_sound = -1;
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
|
|
||||||
char nick[TOX_MAX_NAME_LENGTH];
|
char nick[TOX_MAX_NAME_LENGTH];
|
||||||
int n_len = get_nick_truncate(m, nick, friendnum);
|
int n_len = get_nick_truncate(m, nick, friendnum);
|
||||||
|
@ -31,7 +31,7 @@ void cmd_join_group(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR
|
|||||||
void cmd_savefile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
void cmd_savefile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
void cmd_sendfile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
void cmd_sendfile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
void cmd_call(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
void cmd_call(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
void cmd_answer(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
void cmd_answer(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
void cmd_reject(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
void cmd_reject(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
@ -40,6 +40,6 @@ void cmd_cancel(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZ
|
|||||||
void cmd_ccur_device(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
void cmd_ccur_device(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
void cmd_mute(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
void cmd_mute(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
void cmd_sense(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
void cmd_sense(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
#endif /* #define _chat_commands_h */
|
#endif /* #define _chat_commands_h */
|
||||||
|
@ -31,51 +31,53 @@
|
|||||||
|
|
||||||
#include "configdir.h"
|
#include "configdir.h"
|
||||||
|
|
||||||
/**
|
/* get the user's home directory */
|
||||||
* @brief Get the users config directory.
|
void get_home_dir(char *home, int size)
|
||||||
*
|
|
||||||
* This is without a trailing slash.
|
|
||||||
*
|
|
||||||
* @return The users config dir or NULL on error.
|
|
||||||
*/
|
|
||||||
char *get_user_config_dir(void)
|
|
||||||
{
|
{
|
||||||
char *user_config_dir;
|
|
||||||
|
|
||||||
#ifndef NSS_BUFLEN_PASSWD
|
|
||||||
#define NSS_BUFLEN_PASSWD 4096
|
|
||||||
#endif /* NSS_BUFLEN_PASSWD */
|
|
||||||
|
|
||||||
struct passwd pwd;
|
struct passwd pwd;
|
||||||
struct passwd *pwdbuf;
|
struct passwd *pwdbuf;
|
||||||
const char *home;
|
const char *hmstr;
|
||||||
char buf[NSS_BUFLEN_PASSWD];
|
char buf[NSS_BUFLEN_PASSWD];
|
||||||
size_t len;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
|
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
home = pwd.pw_dir;
|
hmstr = pwd.pw_dir;
|
||||||
} else {
|
} else {
|
||||||
home = getenv("HOME");
|
hmstr = getenv("HOME");
|
||||||
|
|
||||||
if (home == NULL) {
|
if (hmstr == NULL)
|
||||||
return NULL;
|
return;
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "%s", hmstr);
|
||||||
|
hmstr = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* env variables can be tainted */
|
snprintf(home, size, "%s", hmstr);
|
||||||
snprintf(buf, sizeof(buf), "%s", home);
|
|
||||||
home = buf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the user's config directory.
|
||||||
|
*
|
||||||
|
* This is without a trailing slash. Resulting string must be freed.
|
||||||
|
*
|
||||||
|
* @return The users config dir or NULL on error.
|
||||||
|
*/
|
||||||
|
char *get_user_config_dir(void)
|
||||||
|
{
|
||||||
|
char home[NSS_BUFLEN_PASSWD];
|
||||||
|
get_home_dir(home, sizeof(home));
|
||||||
|
|
||||||
|
char *user_config_dir;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
# if defined(__APPLE__)
|
# if defined(__APPLE__)
|
||||||
len = strlen(home) + strlen("/Library/Application Support") + 1;
|
len = strlen(home) + strlen("/Library/Application Support") + 1;
|
||||||
user_config_dir = malloc(len);
|
user_config_dir = malloc(len);
|
||||||
|
|
||||||
if (user_config_dir == NULL) {
|
if (user_config_dir == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(user_config_dir, len, "%s/Library/Application Support", home);
|
snprintf(user_config_dir, len, "%s/Library/Application Support", home);
|
||||||
# else /* __APPLE__ */
|
# else /* __APPLE__ */
|
||||||
@ -86,9 +88,8 @@ char *get_user_config_dir(void)
|
|||||||
len = strlen(home) + strlen("/.config") + 1;
|
len = strlen(home) + strlen("/.config") + 1;
|
||||||
user_config_dir = malloc(len);
|
user_config_dir = malloc(len);
|
||||||
|
|
||||||
if (user_config_dir == NULL) {
|
if (user_config_dir == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(user_config_dir, len, "%s/.config", home);
|
snprintf(user_config_dir, len, "%s/.config", home);
|
||||||
} else {
|
} else {
|
||||||
@ -98,7 +99,6 @@ char *get_user_config_dir(void)
|
|||||||
# endif /* __APPLE__ */
|
# endif /* __APPLE__ */
|
||||||
|
|
||||||
return user_config_dir;
|
return user_config_dir;
|
||||||
#undef NSS_BUFLEN_PASSWD
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -23,6 +23,10 @@
|
|||||||
#ifndef _configdir_h
|
#ifndef _configdir_h
|
||||||
#define _configdir_h
|
#define _configdir_h
|
||||||
|
|
||||||
|
#ifndef NSS_BUFLEN_PASSWD
|
||||||
|
#define NSS_BUFLEN_PASSWD 4096
|
||||||
|
#endif
|
||||||
|
|
||||||
#define CONFIGDIR "/tox/"
|
#define CONFIGDIR "/tox/"
|
||||||
|
|
||||||
#ifndef S_ISDIR
|
#ifndef S_ISDIR
|
||||||
@ -30,7 +34,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
char *get_user_config_dir(void);
|
char *get_user_config_dir(void);
|
||||||
|
void get_home_dir(char *home, int size);
|
||||||
int create_user_config_dir(char *path);
|
int create_user_config_dir(char *path);
|
||||||
|
|
||||||
#endif /* #define _configdir_h */
|
#endif /* #define _configdir_h */
|
||||||
|
76
src/device.c
76
src/device.c
@ -20,8 +20,14 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
|
||||||
|
#ifdef _AUDIO
|
||||||
#include "audio_call.h"
|
#include "audio_call.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "line_info.h"
|
#include "line_info.h"
|
||||||
|
#include "settings.h"
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <OpenAL/al.h>
|
#include <OpenAL/al.h>
|
||||||
@ -37,12 +43,10 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include <tox/toxav.h>
|
#define OPENAL_BUFS 5
|
||||||
|
|
||||||
#define openal_bufs 5
|
|
||||||
#define sample_rate 48000
|
|
||||||
#define inline__ inline __attribute__((always_inline))
|
#define inline__ inline __attribute__((always_inline))
|
||||||
#define frame_size (av_DefaultSettings.audio_sample_rate * av_DefaultSettings.audio_frame_duration / 1000)
|
|
||||||
|
extern struct user_settings *user_settings_;
|
||||||
|
|
||||||
typedef struct _Device {
|
typedef struct _Device {
|
||||||
ALCdevice *dhndl; /* Handle of device selected/opened */
|
ALCdevice *dhndl; /* Handle of device selected/opened */
|
||||||
@ -51,13 +55,17 @@ typedef struct _Device {
|
|||||||
void* cb_data; /* Data to be passed to callback */
|
void* cb_data; /* Data to be passed to callback */
|
||||||
int32_t call_idx; /* ToxAv call index */
|
int32_t call_idx; /* ToxAv call index */
|
||||||
|
|
||||||
uint32_t source, buffers[openal_bufs]; /* Playback source/buffers */
|
uint32_t source, buffers[OPENAL_BUFS]; /* Playback source/buffers */
|
||||||
size_t ref_count;
|
size_t ref_count;
|
||||||
int32_t selection;
|
int32_t selection;
|
||||||
_Bool enable_VAD;
|
_Bool enable_VAD;
|
||||||
_Bool muted;
|
_Bool muted;
|
||||||
float VAD_treshold; /* 40 is usually recommended value */
|
|
||||||
pthread_mutex_t mutex[1];
|
pthread_mutex_t mutex[1];
|
||||||
|
uint32_t sample_rate;
|
||||||
|
uint32_t frame_duration;
|
||||||
|
#ifdef _AUDIO
|
||||||
|
float VAD_treshold; /* 40 is usually recommended value */
|
||||||
|
#endif
|
||||||
} Device;
|
} Device;
|
||||||
|
|
||||||
const char *ddevice_names[2]; /* Default device */
|
const char *ddevice_names[2]; /* Default device */
|
||||||
@ -66,7 +74,9 @@ static int size[2]; /* Size of above containers */
|
|||||||
Device *running[2][MAX_DEVICES]; /* Running devices */
|
Device *running[2][MAX_DEVICES]; /* Running devices */
|
||||||
uint32_t primary_device[2]; /* Primary device */
|
uint32_t primary_device[2]; /* Primary device */
|
||||||
|
|
||||||
|
#ifdef _AUDIO
|
||||||
static ToxAv* av = NULL;
|
static ToxAv* av = NULL;
|
||||||
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
/* q_mutex */
|
/* q_mutex */
|
||||||
#define lock pthread_mutex_lock(&mutex)
|
#define lock pthread_mutex_lock(&mutex)
|
||||||
@ -79,7 +89,11 @@ _Bool thread_running = _True,
|
|||||||
|
|
||||||
void* thread_poll(void*);
|
void* thread_poll(void*);
|
||||||
/* Meet devices */
|
/* Meet devices */
|
||||||
|
#ifdef _AUDIO
|
||||||
DeviceError init_devices(ToxAv* av_)
|
DeviceError init_devices(ToxAv* av_)
|
||||||
|
#else
|
||||||
|
DeviceError init_devices()
|
||||||
|
#endif /* _AUDIO */
|
||||||
{
|
{
|
||||||
const char *stringed_device_list;
|
const char *stringed_device_list;
|
||||||
|
|
||||||
@ -115,9 +129,11 @@ DeviceError init_devices(ToxAv* av_)
|
|||||||
if ( pthread_create(&thread_id, NULL, thread_poll, NULL) != 0 || pthread_detach(thread_id) != 0)
|
if ( pthread_create(&thread_id, NULL, thread_poll, NULL) != 0 || pthread_detach(thread_id) != 0)
|
||||||
return de_InternalError;
|
return de_InternalError;
|
||||||
|
|
||||||
|
#ifdef _AUDIO
|
||||||
av = av_;
|
av = av_;
|
||||||
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
return (DeviceError) ae_None;
|
return (DeviceError) de_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceError terminate_devices()
|
DeviceError terminate_devices()
|
||||||
@ -128,7 +144,7 @@ DeviceError terminate_devices()
|
|||||||
|
|
||||||
pthread_mutex_destroy(&mutex);
|
pthread_mutex_destroy(&mutex);
|
||||||
|
|
||||||
return (DeviceError) ae_None;
|
return (DeviceError) de_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceError device_mute(DeviceType type, uint32_t device_idx)
|
DeviceError device_mute(DeviceType type, uint32_t device_idx)
|
||||||
@ -149,6 +165,7 @@ DeviceError device_mute(DeviceType type, uint32_t device_idx)
|
|||||||
return de_None;
|
return de_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _AUDIO
|
||||||
DeviceError device_set_VAD_treshold(uint32_t device_idx, float value)
|
DeviceError device_set_VAD_treshold(uint32_t device_idx, float value)
|
||||||
{
|
{
|
||||||
if (device_idx >= MAX_DEVICES) return de_InvalidSelection;
|
if (device_idx >= MAX_DEVICES) return de_InvalidSelection;
|
||||||
@ -166,6 +183,8 @@ DeviceError device_set_VAD_treshold(uint32_t device_idx, float value)
|
|||||||
unlock;
|
unlock;
|
||||||
return de_None;
|
return de_None;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
DeviceError set_primary_device(DeviceType type, int32_t selection)
|
DeviceError set_primary_device(DeviceType type, int32_t selection)
|
||||||
{
|
{
|
||||||
@ -175,28 +194,33 @@ DeviceError set_primary_device(DeviceType type, int32_t selection)
|
|||||||
return de_None;
|
return de_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceError open_primary_device(DeviceType type, uint32_t* device_idx)
|
DeviceError open_primary_device(DeviceType type, uint32_t* device_idx, uint32_t sample_rate, uint32_t frame_duration)
|
||||||
{
|
{
|
||||||
return open_device(type, primary_device[type], device_idx);
|
return open_device(type, primary_device[type], device_idx, sample_rate, frame_duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: generate buffers separately
|
// TODO: generate buffers separately
|
||||||
DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx)
|
DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx, uint32_t sample_rate, uint32_t frame_duration)
|
||||||
{
|
{
|
||||||
if (size[type] <= selection || selection < 0) return de_InvalidSelection;
|
if (size[type] <= selection || selection < 0) return de_InvalidSelection;
|
||||||
|
|
||||||
lock;
|
lock;
|
||||||
|
|
||||||
|
const uint32_t frame_size = (sample_rate * frame_duration / 1000);
|
||||||
|
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
for (i = 0; i < MAX_DEVICES && running[type][i] != NULL; i ++);
|
for (i = 0; i < MAX_DEVICES && running[type][i] != NULL; i ++);
|
||||||
|
|
||||||
if (i == MAX_DEVICES) { unlock; return de_AllDevicesBusy; }
|
if (i == MAX_DEVICES) { unlock; return de_AllDevicesBusy; }
|
||||||
else *device_idx = i;
|
else *device_idx = i;
|
||||||
|
|
||||||
Device* device = running[type][*device_idx] = calloc(1, sizeof(Device));;
|
Device* device = running[type][*device_idx] = calloc(1, sizeof(Device));
|
||||||
device->selection = selection;
|
device->selection = selection;
|
||||||
|
|
||||||
|
device->sample_rate = sample_rate;
|
||||||
|
device->frame_duration = frame_duration;
|
||||||
|
|
||||||
for (i = 0; i < *device_idx; i ++) { /* Check if any previous has the same selection */
|
for (i = 0; i < *device_idx; i ++) { /* Check if any previous has the same selection */
|
||||||
if ( running[type][i]->selection == selection ) {
|
if ( running[type][i]->selection == selection ) {
|
||||||
device->dhndl = running[type][i]->dhndl;
|
device->dhndl = running[type][i]->dhndl;
|
||||||
@ -214,8 +238,10 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx
|
|||||||
|
|
||||||
if (type == input) {
|
if (type == input) {
|
||||||
device->dhndl = alcCaptureOpenDevice(devices_names[type][selection],
|
device->dhndl = alcCaptureOpenDevice(devices_names[type][selection],
|
||||||
av_DefaultSettings.audio_sample_rate, AL_FORMAT_MONO16, frame_size * 2);
|
sample_rate, AL_FORMAT_MONO16, frame_size * 2);
|
||||||
device->VAD_treshold = VAD_THRESHOLD_DEFAULT;
|
#ifdef _AUDIO
|
||||||
|
device->VAD_treshold = user_settings_->VAD_treshold;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
device->dhndl = alcOpenDevice(devices_names[type][selection]);
|
device->dhndl = alcOpenDevice(devices_names[type][selection]);
|
||||||
@ -229,18 +255,18 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx
|
|||||||
device->ctx = alcCreateContext(device->dhndl, NULL);
|
device->ctx = alcCreateContext(device->dhndl, NULL);
|
||||||
alcMakeContextCurrent(device->ctx);
|
alcMakeContextCurrent(device->ctx);
|
||||||
|
|
||||||
alGenBuffers(openal_bufs, device->buffers);
|
alGenBuffers(OPENAL_BUFS, device->buffers);
|
||||||
alGenSources((uint32_t)1, &device->source);
|
alGenSources((uint32_t)1, &device->source);
|
||||||
alSourcei(device->source, AL_LOOPING, AL_FALSE);
|
alSourcei(device->source, AL_LOOPING, AL_FALSE);
|
||||||
|
|
||||||
uint16_t zeros[frame_size];
|
uint16_t zeros[frame_size];
|
||||||
memset(zeros, 0, frame_size*2);
|
memset(zeros, 0, frame_size*2);
|
||||||
|
|
||||||
for ( i =0; i < openal_bufs; ++i) {
|
for ( i =0; i < OPENAL_BUFS; ++i) {
|
||||||
alBufferData(device->buffers[i], AL_FORMAT_MONO16, zeros, frame_size*2, sample_rate);
|
alBufferData(device->buffers[i], AL_FORMAT_MONO16, zeros, frame_size*2, sample_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
alSourceQueueBuffers(device->source, openal_bufs, device->buffers);
|
alSourceQueueBuffers(device->source, OPENAL_BUFS, device->buffers);
|
||||||
alSourcePlay(device->source);
|
alSourcePlay(device->source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,7 +312,7 @@ DeviceError close_device(DeviceType type, uint32_t device_idx)
|
|||||||
if (alcGetCurrentContext() != device->ctx) alcMakeContextCurrent(device->ctx);
|
if (alcGetCurrentContext() != device->ctx) alcMakeContextCurrent(device->ctx);
|
||||||
|
|
||||||
alDeleteSources(1, &device->source);
|
alDeleteSources(1, &device->source);
|
||||||
alDeleteBuffers(openal_bufs, device->buffers);
|
alDeleteBuffers(OPENAL_BUFS, device->buffers);
|
||||||
|
|
||||||
if ( !alcCloseDevice(device->dhndl) ) rc = de_AlError;
|
if ( !alcCloseDevice(device->dhndl) ) rc = de_AlError;
|
||||||
alcMakeContextCurrent(NULL);
|
alcMakeContextCurrent(NULL);
|
||||||
@ -346,7 +372,7 @@ inline__ DeviceError write_out(uint32_t device_idx, int16_t* data, uint32_t leng
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
alBufferData(bufid, AL_FORMAT_MONO16, data, lenght * 2 * channels, av_DefaultSettings.audio_sample_rate);
|
alBufferData(bufid, AL_FORMAT_MONO16, data, lenght * 2 * channels, device->sample_rate);
|
||||||
alSourceQueueBuffers(device->source, 1, &bufid);
|
alSourceQueueBuffers(device->source, 1, &bufid);
|
||||||
|
|
||||||
ALint state;
|
ALint state;
|
||||||
@ -368,7 +394,6 @@ void* thread_poll (void* arg) // TODO: maybe use thread for every input source
|
|||||||
uint32_t i;
|
uint32_t i;
|
||||||
int32_t sample = 0;
|
int32_t sample = 0;
|
||||||
|
|
||||||
int f_size = frame_size;
|
|
||||||
|
|
||||||
while (thread_running)
|
while (thread_running)
|
||||||
{
|
{
|
||||||
@ -382,6 +407,8 @@ void* thread_poll (void* arg) // TODO: maybe use thread for every input source
|
|||||||
{
|
{
|
||||||
alcGetIntegerv(running[input][i]->dhndl, ALC_CAPTURE_SAMPLES, sizeof(int32_t), &sample);
|
alcGetIntegerv(running[input][i]->dhndl, ALC_CAPTURE_SAMPLES, sizeof(int32_t), &sample);
|
||||||
|
|
||||||
|
int f_size = (running[input][i]->sample_rate * running[input][i]->frame_duration / 1000);
|
||||||
|
|
||||||
if (sample < f_size) {
|
if (sample < f_size) {
|
||||||
unlock;
|
unlock;
|
||||||
continue;
|
continue;
|
||||||
@ -391,8 +418,11 @@ void* thread_poll (void* arg) // TODO: maybe use thread for every input source
|
|||||||
int16_t frame[4096];
|
int16_t frame[4096];
|
||||||
alcCaptureSamples(device->dhndl, frame, f_size);
|
alcCaptureSamples(device->dhndl, frame, f_size);
|
||||||
|
|
||||||
if ( device->muted ||
|
if ( device->muted
|
||||||
(device->enable_VAD && !toxav_has_activity(av, device->call_idx, frame, f_size, device->VAD_treshold)))
|
#ifdef _AUDIO
|
||||||
|
|| (device->enable_VAD && !toxav_has_activity(av, device->call_idx, frame, f_size, device->VAD_treshold))
|
||||||
|
#endif /* _AUDIO */
|
||||||
|
)
|
||||||
{ unlock; continue; } /* Skip if no voice activity */
|
{ unlock; continue; } /* Skip if no voice activity */
|
||||||
|
|
||||||
if ( device->cb ) device->cb(frame, f_size, device->cb_data);
|
if ( device->cb ) device->cb(frame, f_size, device->cb_data);
|
||||||
|
11
src/device.h
11
src/device.h
@ -56,7 +56,12 @@ typedef enum DeviceError {
|
|||||||
typedef void (*DataHandleCallback) (const int16_t*, uint32_t size, void* data);
|
typedef void (*DataHandleCallback) (const int16_t*, uint32_t size, void* data);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _AUDIO
|
||||||
DeviceError init_devices(ToxAv* av);
|
DeviceError init_devices(ToxAv* av);
|
||||||
|
#else
|
||||||
|
DeviceError init_devices();
|
||||||
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
DeviceError terminate_devices();
|
DeviceError terminate_devices();
|
||||||
|
|
||||||
/* Callback handles ready data from INPUT device */
|
/* Callback handles ready data from INPUT device */
|
||||||
@ -66,12 +71,14 @@ void* get_device_callback_data(uint32_t device_idx);
|
|||||||
/* toggle device mute */
|
/* toggle device mute */
|
||||||
DeviceError device_mute(DeviceType type, uint32_t device_idx);
|
DeviceError device_mute(DeviceType type, uint32_t device_idx);
|
||||||
|
|
||||||
|
#ifdef _AUDIO
|
||||||
DeviceError device_set_VAD_treshold(uint32_t device_idx, float value);
|
DeviceError device_set_VAD_treshold(uint32_t device_idx, float value);
|
||||||
|
#endif
|
||||||
|
|
||||||
DeviceError set_primary_device(DeviceType type, int32_t selection);
|
DeviceError set_primary_device(DeviceType type, int32_t selection);
|
||||||
DeviceError open_primary_device(DeviceType type, uint32_t* device_idx);
|
DeviceError open_primary_device(DeviceType type, uint32_t* device_idx, uint32_t sample_rate, uint32_t frame_duration);
|
||||||
/* Start device */
|
/* Start device */
|
||||||
DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx);
|
DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx, uint32_t sample_rate, uint32_t frame_duration);
|
||||||
/* Stop device */
|
/* Stop device */
|
||||||
DeviceError close_device(DeviceType type, uint32_t device_idx);
|
DeviceError close_device(DeviceType type, uint32_t device_idx);
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "global_commands.h"
|
#include "global_commands.h"
|
||||||
#include "line_info.h"
|
#include "line_info.h"
|
||||||
#include "misc_tools.h"
|
#include "misc_tools.h"
|
||||||
|
#include "notify.h"
|
||||||
|
|
||||||
struct cmd_func {
|
struct cmd_func {
|
||||||
const char *name;
|
const char *name;
|
||||||
@ -53,10 +54,10 @@ static struct cmd_func global_commands[] = {
|
|||||||
{ "/quit", cmd_quit },
|
{ "/quit", cmd_quit },
|
||||||
{ "/status", cmd_status },
|
{ "/status", cmd_status },
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
{ "/lsdev", cmd_list_devices },
|
{ "/lsdev", cmd_list_devices },
|
||||||
{ "/sdev", cmd_change_device },
|
{ "/sdev", cmd_change_device },
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct cmd_func chat_commands[] = {
|
static struct cmd_func chat_commands[] = {
|
||||||
@ -65,7 +66,7 @@ static struct cmd_func chat_commands[] = {
|
|||||||
{ "/savefile", cmd_savefile },
|
{ "/savefile", cmd_savefile },
|
||||||
{ "/sendfile", cmd_sendfile },
|
{ "/sendfile", cmd_sendfile },
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
{ "/call", cmd_call },
|
{ "/call", cmd_call },
|
||||||
{ "/cancel", cmd_cancel },
|
{ "/cancel", cmd_cancel },
|
||||||
{ "/answer", cmd_answer },
|
{ "/answer", cmd_answer },
|
||||||
@ -74,42 +75,49 @@ static struct cmd_func chat_commands[] = {
|
|||||||
{ "/sdev", cmd_ccur_device },
|
{ "/sdev", cmd_ccur_device },
|
||||||
{ "/mute", cmd_mute },
|
{ "/mute", cmd_mute },
|
||||||
{ "/sense", cmd_sense },
|
{ "/sense", cmd_sense },
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Parses input command and puts args into arg array.
|
/* Parses input command and puts args into arg array.
|
||||||
Returns number of arguments on success, -1 on failure. */
|
Returns number of arguments on success, -1 on failure. */
|
||||||
static int parse_command(WINDOW *w, ToxWindow *self, char *cmd, char (*args)[MAX_STR_SIZE])
|
static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*args)[MAX_STR_SIZE])
|
||||||
{
|
{
|
||||||
|
char *cmd = strdup(input);
|
||||||
|
|
||||||
|
if (cmd == NULL)
|
||||||
|
exit_toxic_err("failed in parse_command", FATALERR_MEMORY);
|
||||||
|
|
||||||
int num_args = 0;
|
int num_args = 0;
|
||||||
bool cmd_end = false; /* flags when we get to the end of cmd */
|
int i = 0; /* index of last char in an argument */
|
||||||
char *end; /* points to the end of the current arg */
|
|
||||||
|
|
||||||
/* characters wrapped in double quotes count as one arg */
|
/* characters wrapped in double quotes count as one arg */
|
||||||
while (!cmd_end && num_args < MAX_NUM_ARGS) {
|
while (num_args < MAX_NUM_ARGS) {
|
||||||
if (*cmd == '\"') {
|
int qt_ofst = 0; /* set to 1 to offset index for quote char at end of arg */
|
||||||
end = strchr(cmd + 1, '\"');
|
|
||||||
|
|
||||||
if (end++ == NULL) { /* Increment past the end quote */
|
if (*cmd == '\"') {
|
||||||
|
qt_ofst = 1;
|
||||||
|
i = char_find(1, cmd, '\"');
|
||||||
|
|
||||||
|
if (cmd[i] == '\0') {
|
||||||
char *errmsg = "Invalid argument. Did you forget a closing \"?";
|
char *errmsg = "Invalid argument. Did you forget a closing \"?";
|
||||||
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||||
|
free(cmd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_end = *end == '\0';
|
|
||||||
} else {
|
} else {
|
||||||
end = strchr(cmd, ' ');
|
i = char_find(0, cmd, ' ');
|
||||||
cmd_end = end == NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cmd_end)
|
memcpy(args[num_args], cmd, i + qt_ofst);
|
||||||
*end++ = '\0'; /* mark end of current argument */
|
args[num_args++][i + qt_ofst] = '\0';
|
||||||
|
|
||||||
/* Copy from start of current arg to where we just inserted the null byte */
|
if (cmd[i] == '\0') /* no more args */
|
||||||
strcpy(args[num_args++], cmd);
|
break;
|
||||||
cmd = end;
|
|
||||||
|
strcpy(cmd, &cmd[i + 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(cmd);
|
||||||
return num_args;
|
return num_args;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,13 +137,13 @@ static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, int num_
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute(WINDOW *w, ToxWindow *self, Tox *m, char *cmd, int mode)
|
void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode)
|
||||||
{
|
{
|
||||||
if (string_is_empty(cmd))
|
if (string_is_empty(input))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
char args[MAX_NUM_ARGS][MAX_STR_SIZE];
|
char args[MAX_NUM_ARGS][MAX_STR_SIZE];
|
||||||
int num_args = parse_command(w, self, cmd, args);
|
int num_args = parse_command(w, self, input, args);
|
||||||
|
|
||||||
if (num_args == -1)
|
if (num_args == -1)
|
||||||
return;
|
return;
|
||||||
@ -158,5 +166,7 @@ void execute(WINDOW *w, ToxWindow *self, Tox *m, char *cmd, int mode)
|
|||||||
if (do_command(w, self, m, num_args, GLOBAL_NUM_COMMANDS, global_commands, args) == 0)
|
if (do_command(w, self, m, num_args, GLOBAL_NUM_COMMANDS, global_commands, args) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
line_info_add(self, NULL, NULL, NULL, "Invalid command.", SYS_MSG, 0, 0);
|
/* Just play sound instead */
|
||||||
|
/*line_info_add(self, NULL, NULL, NULL, "Invalid command.", SYS_MSG, 0, 0);*/
|
||||||
|
notify(self, error, 0);
|
||||||
}
|
}
|
||||||
|
@ -28,13 +28,13 @@
|
|||||||
|
|
||||||
#define MAX_NUM_ARGS 4 /* Includes command */
|
#define MAX_NUM_ARGS 4 /* Includes command */
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
#define GLOBAL_NUM_COMMANDS 16
|
#define GLOBAL_NUM_COMMANDS 16
|
||||||
#define CHAT_NUM_COMMANDS 12
|
#define CHAT_NUM_COMMANDS 12
|
||||||
#else
|
#else
|
||||||
#define GLOBAL_NUM_COMMANDS 14
|
#define GLOBAL_NUM_COMMANDS 14
|
||||||
#define CHAT_NUM_COMMANDS 4
|
#define CHAT_NUM_COMMANDS 4
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
GLOBAL_COMMAND_MODE,
|
GLOBAL_COMMAND_MODE,
|
||||||
@ -42,6 +42,6 @@ enum {
|
|||||||
GROUPCHAT_COMMAND_MODE,
|
GROUPCHAT_COMMAND_MODE,
|
||||||
};
|
};
|
||||||
|
|
||||||
void execute(WINDOW *w, ToxWindow *self, Tox *m, char *cmd, int mode);
|
void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode);
|
||||||
|
|
||||||
#endif /* #define _execute_h */
|
#endif /* #define _execute_h */
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "file_senders.h"
|
#include "file_senders.h"
|
||||||
#include "line_info.h"
|
#include "line_info.h"
|
||||||
#include "misc_tools.h"
|
#include "misc_tools.h"
|
||||||
|
#include "notify.h"
|
||||||
|
|
||||||
FileSender file_senders[MAX_FILES];
|
FileSender file_senders[MAX_FILES];
|
||||||
uint8_t max_file_senders_index;
|
uint8_t max_file_senders_index;
|
||||||
@ -48,10 +49,9 @@ static void set_max_file_senders_index(void)
|
|||||||
|
|
||||||
static void close_file_sender(ToxWindow *self, Tox *m, int i, char *msg, int CTRL, int filenum, int32_t friendnum)
|
static void close_file_sender(ToxWindow *self, Tox *m, int i, char *msg, int CTRL, int filenum, int32_t friendnum)
|
||||||
{
|
{
|
||||||
if (self->chatwin != NULL) {
|
if (self->chatwin != NULL)
|
||||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
alert_window(file_senders[i].toxwin, WINDOW_ALERT_2, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
tox_file_send_control(m, friendnum, 0, filenum, CTRL, 0, 0);
|
tox_file_send_control(m, friendnum, 0, filenum, CTRL, 0, 0);
|
||||||
fclose(file_senders[i].file);
|
fclose(file_senders[i].file);
|
||||||
@ -94,6 +94,7 @@ void do_file_senders(Tox *m)
|
|||||||
if (timed_out(file_senders[i].timestamp, get_unix_time(), TIMEOUT_FILESENDER)) {
|
if (timed_out(file_senders[i].timestamp, get_unix_time(), TIMEOUT_FILESENDER)) {
|
||||||
snprintf(msg, sizeof(msg), "File transfer for '%s' timed out.", pathname);
|
snprintf(msg, sizeof(msg), "File transfer for '%s' timed out.", pathname);
|
||||||
close_file_sender(self, m, i, msg, TOX_FILECONTROL_KILL, filenum, friendnum);
|
close_file_sender(self, m, i, msg, TOX_FILECONTROL_KILL, filenum, friendnum);
|
||||||
|
notify(self, error, NT_NOFOCUS | NT_WNDALERT_2);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,6 +123,7 @@ void do_file_senders(Tox *m)
|
|||||||
if (file_senders[i].piecelen == 0) {
|
if (file_senders[i].piecelen == 0) {
|
||||||
snprintf(msg, sizeof(msg), "File '%s' successfuly sent.", pathname);
|
snprintf(msg, sizeof(msg), "File '%s' successfuly sent.", pathname);
|
||||||
close_file_sender(self, m, i, msg, TOX_FILECONTROL_FINISHED, filenum, friendnum);
|
close_file_sender(self, m, i, msg, TOX_FILECONTROL_FINISHED, filenum, friendnum);
|
||||||
|
notify(self, transfer_completed, NT_NOFOCUS | NT_WNDALERT_2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,11 +34,13 @@
|
|||||||
#include "misc_tools.h"
|
#include "misc_tools.h"
|
||||||
#include "line_info.h"
|
#include "line_info.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
#include "notify.h"
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
#include "audio_call.h"
|
#include "audio_call.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
extern char *DATA_FILE;
|
extern char *DATA_FILE;
|
||||||
extern ToxWindow *prompt;
|
extern ToxWindow *prompt;
|
||||||
|
|
||||||
@ -47,7 +49,7 @@ static int num_selected = 0;
|
|||||||
static int num_friends = 0;
|
static int num_friends = 0;
|
||||||
|
|
||||||
extern struct _Winthread Winthread;
|
extern struct _Winthread Winthread;
|
||||||
extern struct user_settings *user_settings;
|
extern struct user_settings *user_settings_;
|
||||||
|
|
||||||
ToxicFriend friends[MAX_FRIENDS_NUM];
|
ToxicFriend friends[MAX_FRIENDS_NUM];
|
||||||
static int friendlist_index[MAX_FRIENDS_NUM] = {0};
|
static int friendlist_index[MAX_FRIENDS_NUM] = {0};
|
||||||
@ -91,7 +93,7 @@ static void update_friend_last_online(int32_t num, uint64_t timestamp)
|
|||||||
friends[num].last_online.tm = *localtime((const time_t*)×tamp);
|
friends[num].last_online.tm = *localtime((const time_t*)×tamp);
|
||||||
|
|
||||||
/* if the format changes make sure TIME_STR_SIZE is the correct size */
|
/* if the format changes make sure TIME_STR_SIZE is the correct size */
|
||||||
const char *t = user_settings->time == TIME_12 ? "%I:%M %p" : "%H:%M";
|
const char *t = user_settings_->time == TIME_12 ? "%I:%M %p" : "%H:%M";
|
||||||
strftime(friends[num].last_online.hour_min_str, TIME_STR_SIZE, t,
|
strftime(friends[num].last_online.hour_min_str, TIME_STR_SIZE, t,
|
||||||
&friends[num].last_online.tm);
|
&friends[num].last_online.tm);
|
||||||
}
|
}
|
||||||
@ -104,6 +106,7 @@ static void friendlist_onMessage(ToxWindow *self, Tox *m, int32_t num, const cha
|
|||||||
if (friends[num].chatwin == -1) {
|
if (friends[num].chatwin == -1) {
|
||||||
if (get_num_active_windows() < MAX_WINDOWS_NUM) {
|
if (get_num_active_windows() < MAX_WINDOWS_NUM) {
|
||||||
friends[num].chatwin = add_window(m, new_chat(m, friends[num].num));
|
friends[num].chatwin = add_window(m, new_chat(m, friends[num].num));
|
||||||
|
notify(self, generic_message, NT_NOFOCUS);
|
||||||
} else {
|
} else {
|
||||||
char nick[TOX_MAX_NAME_LENGTH];
|
char nick[TOX_MAX_NAME_LENGTH];
|
||||||
get_nick_truncate(m, nick, num);
|
get_nick_truncate(m, nick, num);
|
||||||
@ -115,7 +118,7 @@ static void friendlist_onMessage(ToxWindow *self, Tox *m, int32_t num, const cha
|
|||||||
|
|
||||||
char *msg = "* Warning: Too many windows are open.";
|
char *msg = "* Warning: Too many windows are open.";
|
||||||
line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, RED);
|
line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, RED);
|
||||||
alert_window(prompt, WINDOW_ALERT_1, true);
|
notify(prompt, error, NT_WNDALERT_1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -176,7 +179,7 @@ void friendlist_onFriendAdded(ToxWindow *self, Tox *m, int32_t num, bool sort)
|
|||||||
friends[i].chatwin = -1;
|
friends[i].chatwin = -1;
|
||||||
friends[i].online = false;
|
friends[i].online = false;
|
||||||
friends[i].status = TOX_USERSTATUS_NONE;
|
friends[i].status = TOX_USERSTATUS_NONE;
|
||||||
friends[i].logging_on = (bool) user_settings->autolog == AUTOLOG_ON;
|
friends[i].logging_on = (bool) user_settings_->autolog == AUTOLOG_ON;
|
||||||
tox_get_client_id(m, num, (uint8_t *) friends[i].pub_key);
|
tox_get_client_id(m, num, (uint8_t *) friends[i].pub_key);
|
||||||
update_friend_last_online(i, tox_get_last_online(m, i));
|
update_friend_last_online(i, tox_get_last_online(m, i));
|
||||||
|
|
||||||
@ -213,6 +216,7 @@ static void friendlist_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, u
|
|||||||
if (friends[num].chatwin == -1) {
|
if (friends[num].chatwin == -1) {
|
||||||
if (get_num_active_windows() < MAX_WINDOWS_NUM) {
|
if (get_num_active_windows() < MAX_WINDOWS_NUM) {
|
||||||
friends[num].chatwin = add_window(m, new_chat(m, friends[num].num));
|
friends[num].chatwin = add_window(m, new_chat(m, friends[num].num));
|
||||||
|
notify(self, transfer_pending, NT_NOFOCUS);
|
||||||
} else {
|
} else {
|
||||||
tox_file_send_control(m, num, 1, filenum, TOX_FILECONTROL_KILL, 0, 0);
|
tox_file_send_control(m, num, 1, filenum, TOX_FILECONTROL_KILL, 0, 0);
|
||||||
|
|
||||||
@ -223,7 +227,7 @@ static void friendlist_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, u
|
|||||||
snprintf(msg, sizeof(msg), "* File transfer from %s failed: too many windows are open.", nick);
|
snprintf(msg, sizeof(msg), "* File transfer from %s failed: too many windows are open.", nick);
|
||||||
line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, RED);
|
line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, RED);
|
||||||
|
|
||||||
alert_window(prompt, WINDOW_ALERT_1, true);
|
notify(prompt, error, NT_WNDALERT_1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -236,6 +240,8 @@ static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, const
|
|||||||
if (friends[num].chatwin == -1) {
|
if (friends[num].chatwin == -1) {
|
||||||
if (get_num_active_windows() < MAX_WINDOWS_NUM) {
|
if (get_num_active_windows() < MAX_WINDOWS_NUM) {
|
||||||
friends[num].chatwin = add_window(m, new_chat(m, friends[num].num));
|
friends[num].chatwin = add_window(m, new_chat(m, friends[num].num));
|
||||||
|
notify(self, generic_message, NT_NOFOCUS);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
char nick[TOX_MAX_NAME_LENGTH];
|
char nick[TOX_MAX_NAME_LENGTH];
|
||||||
get_nick_truncate(m, nick, num);
|
get_nick_truncate(m, nick, num);
|
||||||
@ -244,7 +250,7 @@ static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, const
|
|||||||
snprintf(msg, sizeof(msg), "* Group chat invite from %s failed: too many windows are open.", nick);
|
snprintf(msg, sizeof(msg), "* Group chat invite from %s failed: too many windows are open.", nick);
|
||||||
line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, RED);
|
line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, RED);
|
||||||
|
|
||||||
alert_window(prompt, WINDOW_ALERT_1, true);
|
notify(prompt, error, NT_WNDALERT_1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -348,7 +354,7 @@ static void friendlist_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
|||||||
char *msg = "* Warning: Too many windows are open.";
|
char *msg = "* Warning: Too many windows are open.";
|
||||||
line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, RED);
|
line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, RED);
|
||||||
|
|
||||||
alert_window(prompt, WINDOW_ALERT_1, true);
|
notify(prompt, error, NT_WNDALERT_1);
|
||||||
}
|
}
|
||||||
} else if (key == KEY_DC) {
|
} else if (key == KEY_DC) {
|
||||||
del_friend_activate(self, m, f);
|
del_friend_activate(self, m, f);
|
||||||
@ -545,7 +551,7 @@ void disable_chatwin(int32_t f_num)
|
|||||||
friends[f_num].chatwin = -1;
|
friends[f_num].chatwin = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
static void friendlist_onAv(ToxWindow *self, ToxAv *av, int call_index)
|
static void friendlist_onAv(ToxWindow *self, ToxAv *av, int call_index)
|
||||||
{
|
{
|
||||||
int id = toxav_get_peer_id(av, call_index, 0);
|
int id = toxav_get_peer_id(av, call_index, 0);
|
||||||
@ -558,8 +564,9 @@ static void friendlist_onAv(ToxWindow *self, ToxAv *av, int call_index)
|
|||||||
|
|
||||||
if (friends[id].chatwin == -1) {
|
if (friends[id].chatwin == -1) {
|
||||||
if (get_num_active_windows() < MAX_WINDOWS_NUM) {
|
if (get_num_active_windows() < MAX_WINDOWS_NUM) {
|
||||||
if (toxav_get_call_state(av, call_index) == av_CallStarting) /* Only open windows when call is incoming */
|
if (toxav_get_call_state(av, call_index) == av_CallStarting) { /* Only open windows when call is incoming */
|
||||||
friends[id].chatwin = add_window(m, new_chat(m, friends[id].num));
|
friends[id].chatwin = add_window(m, new_chat(m, friends[id].num));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
char nick[TOX_MAX_NAME_LENGTH];
|
char nick[TOX_MAX_NAME_LENGTH];
|
||||||
get_nick_truncate(m, nick, friends[id].num);
|
get_nick_truncate(m, nick, friends[id].num);
|
||||||
@ -571,11 +578,11 @@ static void friendlist_onAv(ToxWindow *self, ToxAv *av, int call_index)
|
|||||||
char *errmsg = "* Warning: Too many windows are open.";
|
char *errmsg = "* Warning: Too many windows are open.";
|
||||||
line_info_add(prompt, NULL, NULL, NULL, errmsg, SYS_MSG, 0, RED);
|
line_info_add(prompt, NULL, NULL, NULL, errmsg, SYS_MSG, 0, RED);
|
||||||
|
|
||||||
alert_window(prompt, WINDOW_ALERT_0, true);
|
notify(prompt, error, NT_WNDALERT_1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
ToxWindow new_friendlist(void)
|
ToxWindow new_friendlist(void)
|
||||||
{
|
{
|
||||||
@ -597,7 +604,7 @@ ToxWindow new_friendlist(void)
|
|||||||
ret.onFileSendRequest = &friendlist_onFileSendRequest;
|
ret.onFileSendRequest = &friendlist_onFileSendRequest;
|
||||||
ret.onGroupInvite = &friendlist_onGroupInvite;
|
ret.onGroupInvite = &friendlist_onGroupInvite;
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
ret.onInvite = &friendlist_onAv;
|
ret.onInvite = &friendlist_onAv;
|
||||||
ret.onRinging = &friendlist_onAv;
|
ret.onRinging = &friendlist_onAv;
|
||||||
ret.onStarting = &friendlist_onAv;
|
ret.onStarting = &friendlist_onAv;
|
||||||
@ -612,7 +619,11 @@ ToxWindow new_friendlist(void)
|
|||||||
|
|
||||||
ret.call_idx = -1;
|
ret.call_idx = -1;
|
||||||
ret.device_selection[0] = ret.device_selection[1] = -1;
|
ret.device_selection[0] = ret.device_selection[1] = -1;
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
ret.active_sound = -1;
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
|
|
||||||
strcpy(ret.name, "contacts");
|
strcpy(ret.name, "contacts");
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -41,9 +41,9 @@ void cmd_status(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZ
|
|||||||
|
|
||||||
void cmd_add_helper(ToxWindow *self, Tox *m, char *id_bin, char *msg);
|
void cmd_add_helper(ToxWindow *self, Tox *m, char *id_bin, char *msg);
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
void cmd_list_devices(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
void cmd_list_devices(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
void cmd_change_device(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
void cmd_change_device(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
#endif /* #define _global_commands_h */
|
#endif /* #define _global_commands_h */
|
||||||
|
@ -41,13 +41,15 @@
|
|||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "help.h"
|
#include "help.h"
|
||||||
|
#include "notify.h"
|
||||||
|
#include "autocomplete.h"
|
||||||
|
|
||||||
extern char *DATA_FILE;
|
extern char *DATA_FILE;
|
||||||
|
|
||||||
static GroupChat groupchats[MAX_GROUPCHAT_NUM];
|
static GroupChat groupchats[MAX_GROUPCHAT_NUM];
|
||||||
static int max_groupchat_index = 0;
|
static int max_groupchat_index = 0;
|
||||||
|
|
||||||
extern struct user_settings *user_settings;
|
extern struct user_settings *user_settings_;
|
||||||
|
|
||||||
/* temporary until group chats have unique commands */
|
/* temporary until group chats have unique commands */
|
||||||
extern const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE];
|
extern const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE];
|
||||||
@ -134,25 +136,18 @@ static void groupchat_onGroupMessage(ToxWindow *self, Tox *m, int groupnum, int
|
|||||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH - 1); /* enforce client max name length */
|
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH - 1); /* enforce client max name length */
|
||||||
nick[n_len] = '\0';
|
nick[n_len] = '\0';
|
||||||
|
|
||||||
/* check if message contains own name and alert appropriately */
|
|
||||||
int alert_type = WINDOW_ALERT_1;
|
|
||||||
bool beep = false;
|
|
||||||
|
|
||||||
char selfnick[TOX_MAX_NAME_LENGTH];
|
char selfnick[TOX_MAX_NAME_LENGTH];
|
||||||
uint16_t sn_len = tox_get_self_name(m, (uint8_t *) selfnick);
|
uint16_t sn_len = tox_get_self_name(m, (uint8_t *) selfnick);
|
||||||
selfnick[sn_len] = '\0';
|
selfnick[sn_len] = '\0';
|
||||||
|
|
||||||
int nick_clr = strcmp(nick, selfnick) == 0 ? GREEN : CYAN;
|
int nick_clr = strcmp(nick, selfnick) == 0 ? GREEN : CYAN;
|
||||||
|
|
||||||
bool nick_match = strcasestr(msg, selfnick) && strncmp(selfnick, nick, TOXIC_MAX_NAME_LENGTH - 1);
|
/* Only play sound if mentioned */
|
||||||
|
if (strcasestr(msg, selfnick) && strncmp(selfnick, nick, TOXIC_MAX_NAME_LENGTH - 1)) {
|
||||||
if (nick_match) {
|
notify(self, generic_message, NT_WNDALERT_0);
|
||||||
alert_type = WINDOW_ALERT_0;
|
|
||||||
beep = true;
|
|
||||||
nick_clr = RED;
|
nick_clr = RED;
|
||||||
}
|
}
|
||||||
|
else notify(self, silent, NT_WNDALERT_1);
|
||||||
alert_window(self, alert_type, beep);
|
|
||||||
|
|
||||||
char timefrmt[TIME_STR_SIZE];
|
char timefrmt[TIME_STR_SIZE];
|
||||||
get_time_str(timefrmt, sizeof(timefrmt));
|
get_time_str(timefrmt, sizeof(timefrmt));
|
||||||
@ -169,22 +164,14 @@ static void groupchat_onGroupAction(ToxWindow *self, Tox *m, int groupnum, int p
|
|||||||
|
|
||||||
ChatContext *ctx = self->chatwin;
|
ChatContext *ctx = self->chatwin;
|
||||||
|
|
||||||
/* check if message contains own name and alert appropriately */
|
|
||||||
int alert_type = WINDOW_ALERT_1;
|
|
||||||
bool beep = false;
|
|
||||||
|
|
||||||
char selfnick[TOX_MAX_NAME_LENGTH];
|
char selfnick[TOX_MAX_NAME_LENGTH];
|
||||||
uint16_t n_len = tox_get_self_name(m, (uint8_t *) selfnick);
|
uint16_t n_len = tox_get_self_name(m, (uint8_t *) selfnick);
|
||||||
selfnick[n_len] = '\0';
|
selfnick[n_len] = '\0';
|
||||||
|
|
||||||
bool nick_match = strcasestr(action, selfnick);
|
if (strcasestr(action, selfnick)) {
|
||||||
|
notify(self, generic_message, NT_WNDALERT_0);
|
||||||
if (nick_match) {
|
|
||||||
alert_type = WINDOW_ALERT_0;
|
|
||||||
beep = true;
|
|
||||||
}
|
}
|
||||||
|
else notify(self, silent, NT_WNDALERT_1);
|
||||||
alert_window(self, alert_type, beep);
|
|
||||||
|
|
||||||
char nick[TOX_MAX_NAME_LENGTH];
|
char nick[TOX_MAX_NAME_LENGTH];
|
||||||
n_len = tox_group_peername(m, groupnum, peernum, (uint8_t *) nick);
|
n_len = tox_group_peername(m, groupnum, peernum, (uint8_t *) nick);
|
||||||
@ -317,7 +304,7 @@ static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnu
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
alert_window(self, WINDOW_ALERT_2, false);
|
notify(self, silent, NT_WNDALERT_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_group_action(ToxWindow *self, ChatContext *ctx, Tox *m, char *action)
|
static void send_group_action(ToxWindow *self, ChatContext *ctx, Tox *m, char *action)
|
||||||
@ -365,17 +352,15 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
|||||||
int diff;
|
int diff;
|
||||||
|
|
||||||
if ((ctx->line[0] != '/') || (ctx->line[1] == 'm' && ctx->line[2] == 'e'))
|
if ((ctx->line[0] != '/') || (ctx->line[1] == 'm' && ctx->line[2] == 'e'))
|
||||||
diff = complete_line(ctx, groupchats[self->num].peer_names,
|
diff = complete_line(self, groupchats[self->num].peer_names,
|
||||||
groupchats[self->num].num_peers, TOX_MAX_NAME_LENGTH);
|
groupchats[self->num].num_peers, TOX_MAX_NAME_LENGTH);
|
||||||
else
|
else
|
||||||
diff = complete_line(ctx, glob_cmd_list, AC_NUM_GLOB_COMMANDS, MAX_CMDNAME_SIZE);
|
diff = complete_line(self, glob_cmd_list, AC_NUM_GLOB_COMMANDS, MAX_CMDNAME_SIZE);
|
||||||
|
|
||||||
if (diff != -1) {
|
if (diff != -1) {
|
||||||
if (x + diff > x2 - 1) {
|
if (x + diff > x2 - 1) {
|
||||||
wmove(self->window, y, x + diff);
|
int wlen = wcswidth(ctx->line, sizeof(ctx->line));
|
||||||
ctx->start += diff;
|
ctx->start = wlen < x2 ? 0 : wlen - x2 + 1;
|
||||||
} else {
|
|
||||||
wmove(self->window, y, x + diff);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
beep();
|
beep();
|
||||||
@ -502,7 +487,7 @@ static void groupchat_onInit(ToxWindow *self, Tox *m)
|
|||||||
|
|
||||||
line_info_init(ctx->hst);
|
line_info_init(ctx->hst);
|
||||||
|
|
||||||
if (user_settings->autolog == AUTOLOG_ON)
|
if (user_settings_->autolog == AUTOLOG_ON)
|
||||||
log_enable(self->name, NULL, ctx->log);
|
log_enable(self->name, NULL, ctx->log);
|
||||||
|
|
||||||
execute(ctx->history, self, m, "/log", GLOBAL_COMMAND_MODE);
|
execute(ctx->history, self, m, "/log", GLOBAL_COMMAND_MODE);
|
||||||
|
12
src/help.c
12
src/help.c
@ -144,14 +144,14 @@ static void help_draw_global(ToxWindow *self)
|
|||||||
wprintw(win, " /close : Close the current chat window\n");
|
wprintw(win, " /close : Close the current chat window\n");
|
||||||
wprintw(win, " /quit or /exit : Exit Toxic\n");
|
wprintw(win, " /quit or /exit : Exit Toxic\n");
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
wattron(win, A_BOLD);
|
wattron(win, A_BOLD);
|
||||||
wprintw(win, "\n Audio:\n");
|
wprintw(win, "\n Audio:\n");
|
||||||
wattroff(win, A_BOLD);
|
wattroff(win, A_BOLD);
|
||||||
|
|
||||||
wprintw(win, " /lsdev <type> : List devices where type: in|out\n");
|
wprintw(win, " /lsdev <type> : List devices where type: in|out\n");
|
||||||
wprintw(win, " /sdev <type> <id> : Set active device\n");
|
wprintw(win, " /sdev <type> <id> : Set active device\n");
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
help_draw_bottom_menu(win);
|
help_draw_bottom_menu(win);
|
||||||
|
|
||||||
@ -174,7 +174,7 @@ static void help_draw_chat(ToxWindow *self)
|
|||||||
wprintw(win, " /sendfile <path> : Send a file\n");
|
wprintw(win, " /sendfile <path> : Send a file\n");
|
||||||
wprintw(win, " /savefile <n> : Receive a file\n");
|
wprintw(win, " /savefile <n> : Receive a file\n");
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
wattron(win, A_BOLD);
|
wattron(win, A_BOLD);
|
||||||
wprintw(win, "\n Audio:\n");
|
wprintw(win, "\n Audio:\n");
|
||||||
wattroff(win, A_BOLD);
|
wattroff(win, A_BOLD);
|
||||||
@ -187,7 +187,7 @@ static void help_draw_chat(ToxWindow *self)
|
|||||||
wprintw(win, " /sdev <type> <id> : Change active device\n");
|
wprintw(win, " /sdev <type> <id> : Change active device\n");
|
||||||
wprintw(win, " /mute <type> : Mute active device if in call\n");
|
wprintw(win, " /mute <type> : Mute active device if in call\n");
|
||||||
wprintw(win, " /sense <n> : VAD sensitivity treshold\n");
|
wprintw(win, " /sense <n> : VAD sensitivity treshold\n");
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
help_draw_bottom_menu(win);
|
help_draw_bottom_menu(win);
|
||||||
|
|
||||||
@ -226,7 +226,7 @@ void help_onKey(ToxWindow *self, wint_t key)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
help_init_window(self, 19, 80);
|
help_init_window(self, 19, 80);
|
||||||
#else
|
#else
|
||||||
help_init_window(self, 9, 80);
|
help_init_window(self, 9, 80);
|
||||||
@ -235,7 +235,7 @@ void help_onKey(ToxWindow *self, wint_t key)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'g':
|
case 'g':
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
help_init_window(self, 21, 80);
|
help_init_window(self, 21, 80);
|
||||||
#else
|
#else
|
||||||
help_init_window(self, 17, 80);
|
help_init_window(self, 17, 80);
|
||||||
|
@ -185,7 +185,8 @@ static void input_history(ToxWindow *self, wint_t key, int mx_x)
|
|||||||
ChatContext *ctx = self->chatwin;
|
ChatContext *ctx = self->chatwin;
|
||||||
|
|
||||||
fetch_hist_item(ctx, key);
|
fetch_hist_item(ctx, key);
|
||||||
ctx->start = mx_x * (ctx->len / mx_x);
|
int wlen = wcswidth(ctx->line, sizeof(ctx->line));
|
||||||
|
ctx->start = wlen < mx_x ? 0 : wlen - mx_x + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handles non-printable input keys that behave the same for all types of chat windows.
|
/* Handles non-printable input keys that behave the same for all types of chat windows.
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
#include "groupchat.h"
|
#include "groupchat.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
extern struct user_settings *user_settings;
|
extern struct user_settings *user_settings_;
|
||||||
|
|
||||||
void line_info_init(struct history *hst)
|
void line_info_init(struct history *hst)
|
||||||
{
|
{
|
||||||
@ -207,7 +207,7 @@ static void line_info_check_queue(ToxWindow *self)
|
|||||||
if (line == NULL)
|
if (line == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (hst->start_id > user_settings->history_size)
|
if (hst->start_id > user_settings_->history_size)
|
||||||
line_info_root_fwd(hst);
|
line_info_root_fwd(hst);
|
||||||
|
|
||||||
line->id = hst->line_end->id + 1;
|
line->id = hst->line_end->id + 1;
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
extern struct user_settings *user_settings;
|
extern struct user_settings *user_settings_;
|
||||||
|
|
||||||
/* Creates/fetches log file by appending to the config dir the name and a pseudo-unique identity */
|
/* Creates/fetches log file by appending to the config dir the name and a pseudo-unique identity */
|
||||||
void init_logging_session(char *name, char *key, struct chatlog *log)
|
void init_logging_session(char *name, char *key, struct chatlog *log)
|
||||||
@ -99,7 +99,7 @@ void write_to_log(const char *msg, char *name, struct chatlog *log, bool event)
|
|||||||
else
|
else
|
||||||
snprintf(name_frmt, sizeof(name_frmt), "%s:", name);
|
snprintf(name_frmt, sizeof(name_frmt), "%s:", name);
|
||||||
|
|
||||||
const char *t = user_settings->time == TIME_12 ? "%Y/%m/%d [%I:%M:%S %p]" : "%Y/%m/%d [%H:%M:%S]";
|
const char *t = user_settings_->time == TIME_12 ? "%Y/%m/%d [%I:%M:%S %p]" : "%Y/%m/%d [%H:%M:%S]";
|
||||||
char s[MAX_STR_SIZE];
|
char s[MAX_STR_SIZE];
|
||||||
strftime(s, MAX_STR_SIZE, t, get_time());
|
strftime(s, MAX_STR_SIZE, t, get_time());
|
||||||
fprintf(log->file, "%s %s %s\n", s, name_frmt, msg);
|
fprintf(log->file, "%s %s %s\n", s, name_frmt, msg);
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
#include "toxic.h"
|
#include "toxic.h"
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
@ -32,7 +33,7 @@
|
|||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
extern ToxWindow *prompt;
|
extern ToxWindow *prompt;
|
||||||
extern struct user_settings *user_settings;
|
extern struct user_settings *user_settings_;
|
||||||
|
|
||||||
static uint64_t current_unix_time;
|
static uint64_t current_unix_time;
|
||||||
|
|
||||||
@ -64,12 +65,12 @@ struct tm *get_time(void)
|
|||||||
/*Puts the current time in buf in the format of [HH:mm:ss] */
|
/*Puts the current time in buf in the format of [HH:mm:ss] */
|
||||||
void get_time_str(char *buf, int bufsize)
|
void get_time_str(char *buf, int bufsize)
|
||||||
{
|
{
|
||||||
if (user_settings->timestamps == TIMESTAMPS_OFF) {
|
if (user_settings_->timestamps == TIMESTAMPS_OFF) {
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *t = user_settings->time == TIME_12 ? "[%-I:%M:%S] " : "[%H:%M:%S] ";
|
const char *t = user_settings_->time == TIME_12 ? "[%-I:%M:%S] " : "[%H:%M:%S] ";
|
||||||
strftime(buf, bufsize, t, get_time());
|
strftime(buf, bufsize, t, get_time());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +109,7 @@ char *hex_string_to_bin(const char *hex_string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Returns 1 if the string is empty, 0 otherwise */
|
/* Returns 1 if the string is empty, 0 otherwise */
|
||||||
int string_is_empty(char *string)
|
int string_is_empty(const char *string)
|
||||||
{
|
{
|
||||||
return string[0] == '\0';
|
return string[0] == '\0';
|
||||||
}
|
}
|
||||||
@ -141,29 +142,6 @@ int wcs_to_mbs_buf(char *buf, const wchar_t *string, size_t n)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Colours the window tab according to type. Beeps if is_beep is true */
|
|
||||||
void alert_window(ToxWindow *self, int type, bool is_beep)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case WINDOW_ALERT_0:
|
|
||||||
self->alert0 = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WINDOW_ALERT_1:
|
|
||||||
self->alert1 = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WINDOW_ALERT_2:
|
|
||||||
self->alert2 = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusBar *stb = prompt->stb;
|
|
||||||
|
|
||||||
if (is_beep && stb->status != TOX_USERSTATUS_BUSY && user_settings->alerts == ALERTS_ENABLED)
|
|
||||||
beep();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* case-insensitive string compare function for use with qsort */
|
/* case-insensitive string compare function for use with qsort */
|
||||||
int qsort_strcasecmp_hlpr(const void *nick1, const void *nick2)
|
int qsort_strcasecmp_hlpr(const void *nick1, const void *nick2)
|
||||||
{
|
{
|
||||||
@ -197,23 +175,29 @@ int valid_nick(char *nick)
|
|||||||
void get_file_name(char *namebuf, int bufsize, const char *pathname)
|
void get_file_name(char *namebuf, int bufsize, const char *pathname)
|
||||||
{
|
{
|
||||||
int idx = strlen(pathname) - 1;
|
int idx = strlen(pathname) - 1;
|
||||||
|
char *path = strdup(pathname);
|
||||||
|
|
||||||
char tmpname[MAX_STR_SIZE];
|
if (path == NULL)
|
||||||
snprintf(tmpname, sizeof(tmpname), "%s", pathname);
|
exit_toxic_err("failed in get_file_name", FATALERR_MEMORY);
|
||||||
|
|
||||||
while (idx >= 0 && pathname[idx] == '/')
|
while (idx >= 0 && pathname[idx] == '/')
|
||||||
tmpname[idx--] = '\0';
|
path[idx--] = '\0';
|
||||||
|
|
||||||
char *filename = strrchr(tmpname, '/');
|
char *finalname = strdup(path);
|
||||||
|
|
||||||
if (filename != NULL) {
|
if (finalname == NULL)
|
||||||
if (!strlen(++filename))
|
exit_toxic_err("failed in get_file_name", FATALERR_MEMORY);
|
||||||
filename = tmpname;
|
|
||||||
} else {
|
const char *basenm = strrchr(path, '/');
|
||||||
filename = tmpname;
|
|
||||||
|
if (basenm != NULL) {
|
||||||
|
if (basenm[1])
|
||||||
|
strcpy(finalname, &basenm[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(namebuf, bufsize, "%s", filename);
|
snprintf(namebuf, bufsize, "%s", finalname);
|
||||||
|
free(finalname);
|
||||||
|
free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* converts str to all lowercase */
|
/* converts str to all lowercase */
|
||||||
@ -234,3 +218,31 @@ int get_nick_truncate(Tox *m, char *buf, int friendnum)
|
|||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* returns index of the first instance of ch in s starting at idx.
|
||||||
|
returns length of s if char not found */
|
||||||
|
int char_find(int idx, const char *s, char ch)
|
||||||
|
{
|
||||||
|
int i = idx;
|
||||||
|
|
||||||
|
for (i = idx; s[i]; ++i) {
|
||||||
|
if (s[i] == ch)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returns index of the last instance of ch in s starting at len
|
||||||
|
returns 0 if char not found (skips 0th index) */
|
||||||
|
int char_rfind(const char *s, char ch, int len)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (i = len; i > 0; --i) {
|
||||||
|
if (s[i] == ch)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
@ -52,7 +52,7 @@ struct tm *get_time(void);
|
|||||||
void update_unix_time(void);
|
void update_unix_time(void);
|
||||||
|
|
||||||
/* Returns 1 if the string is empty, 0 otherwise */
|
/* Returns 1 if the string is empty, 0 otherwise */
|
||||||
int string_is_empty(char *string);
|
int string_is_empty(const char *string);
|
||||||
|
|
||||||
/* convert a multibyte string to a wide character string (must provide buffer) */
|
/* convert a multibyte string to a wide character string (must provide buffer) */
|
||||||
int char_to_wcs_buf(wchar_t *buf, const char *string, size_t n);
|
int char_to_wcs_buf(wchar_t *buf, const char *string, size_t n);
|
||||||
@ -89,4 +89,12 @@ void str_to_lower(char *str);
|
|||||||
Returns nick len on success, -1 on failure */
|
Returns nick len on success, -1 on failure */
|
||||||
int get_nick_truncate(Tox *m, char *buf, int friendnum);
|
int get_nick_truncate(Tox *m, char *buf, int friendnum);
|
||||||
|
|
||||||
|
/* returns index of the first instance of ch in s starting at idx.
|
||||||
|
returns length of s if char not found */
|
||||||
|
int char_find(int idx, const char *s, char ch);
|
||||||
|
|
||||||
|
/* returns index of the last instance of ch in s
|
||||||
|
returns 0 if char not found */
|
||||||
|
int char_rfind(const char *s, char ch, int len);
|
||||||
|
|
||||||
#endif /* #define _misc_tools_h */
|
#endif /* #define _misc_tools_h */
|
||||||
|
335
src/notify.c
Normal file
335
src/notify.c
Normal file
@ -0,0 +1,335 @@
|
|||||||
|
/* notify.c
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Toxic All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file is part of Toxic.
|
||||||
|
*
|
||||||
|
* Toxic is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Toxic is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Toxic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "notify.h"
|
||||||
|
#include "device.h"
|
||||||
|
#include "settings.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <OpenAL/al.h>
|
||||||
|
#include <OpenAL/alc.h>
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
#include <OpenAL/alut.h> /* Is this good? */
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#include <AL/al.h>
|
||||||
|
#include <AL/alc.h>
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
#include <AL/alut.h> /* freealut packet */
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _X11
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#endif /* _X11 */
|
||||||
|
|
||||||
|
#define SOUNDS_SIZE 10
|
||||||
|
#define ACTIVE_SOUNDS_MAX 50
|
||||||
|
|
||||||
|
extern struct user_settings *user_settings_;
|
||||||
|
|
||||||
|
struct _Control {
|
||||||
|
time_t cooldown;
|
||||||
|
unsigned long this_window;
|
||||||
|
#ifdef _X11
|
||||||
|
Display *display;
|
||||||
|
#endif /* _X11 */
|
||||||
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
pthread_mutex_t poll_mutex[1];
|
||||||
|
uint32_t device_idx; /* index of output device */
|
||||||
|
_Bool poll_active;
|
||||||
|
char* sounds[SOUNDS_SIZE];
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
|
} Control = {0};
|
||||||
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
struct _ActiveSounds {
|
||||||
|
uint32_t source;
|
||||||
|
uint32_t buffer;
|
||||||
|
_Bool active;
|
||||||
|
_Bool looping;
|
||||||
|
} actives[ACTIVE_SOUNDS_MAX] = {{0}};
|
||||||
|
#endif
|
||||||
|
/**********************************************************************************/
|
||||||
|
/**********************************************************************************/
|
||||||
|
/**********************************************************************************/
|
||||||
|
/**********************************************************************************/
|
||||||
|
/**********************************************************************************/
|
||||||
|
|
||||||
|
long unsigned int get_focused_window_id()
|
||||||
|
{
|
||||||
|
#ifdef _X11
|
||||||
|
if (!Control.display) return 0;
|
||||||
|
|
||||||
|
Window focus;
|
||||||
|
int revert;
|
||||||
|
XGetInputFocus(Control.display, &focus, &revert);
|
||||||
|
return focus;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif /* _X11 */
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
|
||||||
|
_Bool is_playing(int source)
|
||||||
|
{
|
||||||
|
int ready;
|
||||||
|
alGetSourcei(source, AL_SOURCE_STATE, &ready);
|
||||||
|
return ready == AL_PLAYING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Terminate all sounds but wait them to finish first */
|
||||||
|
void graceful_clear()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
pthread_mutex_lock(Control.poll_mutex);
|
||||||
|
while (1) {
|
||||||
|
for (i = 0; i < ACTIVE_SOUNDS_MAX; i ++) {
|
||||||
|
if (actives[i].active) {
|
||||||
|
if ( actives[i].looping ) {
|
||||||
|
stop_sound(i);
|
||||||
|
} else {
|
||||||
|
if (!is_playing(actives[i].source))
|
||||||
|
memset(&actives[i], 0, sizeof(struct _ActiveSounds));
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == ACTIVE_SOUNDS_MAX) {
|
||||||
|
pthread_mutex_unlock(Control.poll_mutex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
usleep(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void* do_playing(void* _p)
|
||||||
|
{
|
||||||
|
(void)_p;
|
||||||
|
int i;
|
||||||
|
while(Control.poll_active) {
|
||||||
|
pthread_mutex_lock(Control.poll_mutex);
|
||||||
|
for (i = 0; i < ACTIVE_SOUNDS_MAX; i ++) {
|
||||||
|
if (actives[i].active && !actives[i].looping) {
|
||||||
|
if (!is_playing(actives[i].source)) {
|
||||||
|
/* Close */
|
||||||
|
|
||||||
|
alSourceStop(actives[i].source);
|
||||||
|
alDeleteSources(1, &actives[i].source);
|
||||||
|
alDeleteBuffers(1,&actives[i].buffer);
|
||||||
|
memset(&actives[i], 0, sizeof(struct _ActiveSounds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(Control.poll_mutex);
|
||||||
|
usleep(10000);
|
||||||
|
}
|
||||||
|
pthread_exit(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int play_source(uint32_t source, uint32_t buffer, _Bool looping)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(Control.poll_mutex);
|
||||||
|
int i = 0;
|
||||||
|
for (; i < ACTIVE_SOUNDS_MAX && actives[i].active; i ++);
|
||||||
|
if ( i == ACTIVE_SOUNDS_MAX ) {
|
||||||
|
pthread_mutex_unlock(Control.poll_mutex);
|
||||||
|
return -1; /* Full */
|
||||||
|
}
|
||||||
|
|
||||||
|
alSourcePlay(source);
|
||||||
|
|
||||||
|
actives[i].active = 1;
|
||||||
|
actives[i].source = source;
|
||||||
|
actives[i].buffer = buffer;
|
||||||
|
actives[i].looping = looping;
|
||||||
|
|
||||||
|
pthread_mutex_unlock(Control.poll_mutex);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/**********************************************************************************/
|
||||||
|
/**********************************************************************************/
|
||||||
|
/**********************************************************************************/
|
||||||
|
/**********************************************************************************/
|
||||||
|
/**********************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Opens primary device */
|
||||||
|
int init_notify(int login_cooldown)
|
||||||
|
{
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
alutInitWithoutContext(NULL, NULL);
|
||||||
|
if (open_primary_device(output, &Control.device_idx, 48000, 20) != de_None)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
pthread_mutex_init(Control.poll_mutex, NULL);
|
||||||
|
pthread_t thread;
|
||||||
|
if (pthread_create(&thread, NULL, do_playing, NULL) != 0 || pthread_detach(thread) != 0 ) {
|
||||||
|
pthread_mutex_destroy(Control.poll_mutex);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
Control.poll_active = 1;
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
|
|
||||||
|
Control.cooldown = time(NULL) + login_cooldown;
|
||||||
|
#ifdef _X11
|
||||||
|
Control.display = XOpenDisplay(NULL);
|
||||||
|
Control.this_window = get_focused_window_id();
|
||||||
|
#else
|
||||||
|
Control.this_window = 1;
|
||||||
|
#endif /* _X11 */
|
||||||
|
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void terminate_notify()
|
||||||
|
{
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
if ( !Control.poll_active ) return;
|
||||||
|
Control.poll_active = 0;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (; i < SOUNDS_SIZE; i ++) free(Control.sounds[i]);
|
||||||
|
|
||||||
|
graceful_clear();
|
||||||
|
close_device(output, Control.device_idx);
|
||||||
|
alutExit();
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
int set_sound(Notification sound, const char* value)
|
||||||
|
{
|
||||||
|
free(Control.sounds[sound]);
|
||||||
|
|
||||||
|
size_t len = strlen(value) + 1;
|
||||||
|
Control.sounds[sound] = calloc(1, len);
|
||||||
|
memcpy(Control.sounds[sound], value, len);
|
||||||
|
|
||||||
|
struct stat buf;
|
||||||
|
return stat(value, &buf) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int play_sound_internal(Notification what, _Bool loop)
|
||||||
|
{
|
||||||
|
uint32_t source;
|
||||||
|
uint32_t buffer;
|
||||||
|
|
||||||
|
alGenSources(1, &source);
|
||||||
|
alGenBuffers(1, &buffer);
|
||||||
|
buffer = alutCreateBufferFromFile((const char*)Control.sounds[what]);
|
||||||
|
alSourcei(source, AL_BUFFER, buffer);
|
||||||
|
alSourcei(source, AL_LOOPING, loop);
|
||||||
|
|
||||||
|
int rc = play_source(source, buffer, loop);
|
||||||
|
if (rc < 0) {
|
||||||
|
alSourceStop(source);
|
||||||
|
alDeleteSources(1, &source);
|
||||||
|
alDeleteBuffers(1,&buffer);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int play_notify_sound(Notification notif, uint64_t flags)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (flags & NT_BEEP) beep();
|
||||||
|
else if (notif != silent) {
|
||||||
|
if ( !Control.poll_active || (flags & NT_RESTOL && Control.cooldown > time(NULL)) || !Control.sounds[notif] )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
rc = play_sound_internal(notif, flags & NT_LOOP ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void stop_sound(int sound)
|
||||||
|
{
|
||||||
|
if (sound >= 0 && sound < ACTIVE_SOUNDS_MAX && actives[sound].looping && actives[sound].active) {
|
||||||
|
alSourcei(actives[sound].source, AL_LOOPING, false);
|
||||||
|
alSourceStop(actives[sound].source);
|
||||||
|
alDeleteSources(1, &actives[sound].source);
|
||||||
|
alDeleteBuffers(1,&actives[sound].buffer);
|
||||||
|
memset(&actives[sound], 0, sizeof(struct _ActiveSounds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int m_play_sound(Notification notif, uint64_t flags)
|
||||||
|
{
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
return play_notify_sound(notif, flags);
|
||||||
|
#else
|
||||||
|
if (notif != silent)
|
||||||
|
beep();
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int notify(ToxWindow* self, Notification notif, uint64_t flags)
|
||||||
|
{
|
||||||
|
if (flags & NT_NOFOCUS && Control.this_window == get_focused_window_id())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int rc = -1;
|
||||||
|
|
||||||
|
if (self && (!self->stb || self->stb->status != TOX_USERSTATUS_BUSY) && user_settings_->alerts == ALERTS_ENABLED)
|
||||||
|
rc = m_play_sound(notif, flags);
|
||||||
|
|
||||||
|
else if (flags & NT_ALWAYS)
|
||||||
|
rc = m_play_sound(notif, flags);
|
||||||
|
|
||||||
|
if (flags & NT_NOTIFWND) {
|
||||||
|
/* TODO: pop notify window */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self && self->alert == WINDOW_ALERT_NONE) {
|
||||||
|
if (flags & NT_WNDALERT_0) self->alert = WINDOW_ALERT_0;
|
||||||
|
else if (flags & NT_WNDALERT_1) self->alert = WINDOW_ALERT_1;
|
||||||
|
else if (flags & NT_WNDALERT_2) self->alert = WINDOW_ALERT_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
73
src/notify.h
Normal file
73
src/notify.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/* notify.h
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Toxic All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file is part of Toxic.
|
||||||
|
*
|
||||||
|
* Toxic is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Toxic is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Toxic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _notify_h
|
||||||
|
#define _notify_h
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include "windows.h"
|
||||||
|
|
||||||
|
typedef enum _Notification
|
||||||
|
{
|
||||||
|
silent = -1,
|
||||||
|
error,
|
||||||
|
self_log_in,
|
||||||
|
self_log_out,
|
||||||
|
user_log_in,
|
||||||
|
user_log_out,
|
||||||
|
call_incoming,
|
||||||
|
call_outgoing,
|
||||||
|
generic_message,
|
||||||
|
transfer_pending,
|
||||||
|
transfer_completed,
|
||||||
|
} Notification;
|
||||||
|
|
||||||
|
typedef enum _Flags {
|
||||||
|
NT_NOFOCUS = 1 << 0, /* Notify when focus is not on this terminal. NOTE: only works with x11,
|
||||||
|
* if no x11 present this flag is ignored
|
||||||
|
*/
|
||||||
|
NT_BEEP = 1 << 1, /* Play native sound instead: \a */
|
||||||
|
NT_LOOP = 1 << 2, /* Loop sound. If this setting active, notify() will return id of the sound
|
||||||
|
* so it could be stopped. It will return 0 if error or NT_NATIVE flag is set and play \a instead
|
||||||
|
*/
|
||||||
|
NT_RESTOL = 1 << 3, /* Respect tolerance. Usually used to stop flood at toxic startup
|
||||||
|
* Only works if login_cooldown is true when calling init_notify()
|
||||||
|
*/
|
||||||
|
NT_NOTIFWND = 1 << 4, /* Pop notify window. NOTE: only works(/WILL WORK) if libnotify is present */
|
||||||
|
NT_WNDALERT_0 = 1 << 5, /* Alert toxic */
|
||||||
|
NT_WNDALERT_1 = 1 << 6, /* Alert toxic */
|
||||||
|
NT_WNDALERT_2 = 1 << 7, /* Alert toxic */
|
||||||
|
|
||||||
|
NT_ALWAYS = 1 << 8, /* Force sound to play */
|
||||||
|
} Flags;
|
||||||
|
|
||||||
|
int init_notify(int login_cooldown);
|
||||||
|
void terminate_notify();
|
||||||
|
|
||||||
|
int notify(ToxWindow* self, Notification notif, uint64_t flags);
|
||||||
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
int set_sound(Notification sound, const char* value);
|
||||||
|
void stop_sound(int sound);
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
|
|
||||||
|
#endif /* _notify_h */
|
36
src/prompt.c
36
src/prompt.c
@ -39,13 +39,15 @@
|
|||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "help.h"
|
#include "help.h"
|
||||||
|
#include "notify.h"
|
||||||
|
#include "autocomplete.h"
|
||||||
|
|
||||||
char pending_frnd_requests[MAX_FRIENDS_NUM][TOX_CLIENT_ID_SIZE];
|
char pending_frnd_requests[MAX_FRIENDS_NUM][TOX_CLIENT_ID_SIZE];
|
||||||
uint16_t num_frnd_requests = 0;
|
uint16_t num_frnd_requests = 0;
|
||||||
extern ToxWindow *prompt;
|
extern ToxWindow *prompt;
|
||||||
struct _Winthread Winthread;
|
struct _Winthread Winthread;
|
||||||
|
|
||||||
extern struct user_settings *user_settings;
|
extern struct user_settings *user_settings_;
|
||||||
|
|
||||||
/* Array of global command names used for tab completion. */
|
/* Array of global command names used for tab completion. */
|
||||||
const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = {
|
const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = {
|
||||||
@ -57,7 +59,6 @@ const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = {
|
|||||||
{ "/exit" },
|
{ "/exit" },
|
||||||
{ "/groupchat" },
|
{ "/groupchat" },
|
||||||
{ "/help" },
|
{ "/help" },
|
||||||
{ "/join" },
|
|
||||||
{ "/log" },
|
{ "/log" },
|
||||||
{ "/myid" },
|
{ "/myid" },
|
||||||
{ "/nick" },
|
{ "/nick" },
|
||||||
@ -65,12 +66,12 @@ const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = {
|
|||||||
{ "/quit" },
|
{ "/quit" },
|
||||||
{ "/status" },
|
{ "/status" },
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
|
|
||||||
{ "/lsdev" },
|
{ "/lsdev" },
|
||||||
{ "/sdev" },
|
{ "/sdev" },
|
||||||
|
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
};
|
};
|
||||||
|
|
||||||
void kill_prompt_window(ToxWindow *self)
|
void kill_prompt_window(ToxWindow *self)
|
||||||
@ -176,14 +177,12 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
|||||||
|
|
||||||
if (key == '\t') { /* TAB key: auto-completes command */
|
if (key == '\t') { /* TAB key: auto-completes command */
|
||||||
if (ctx->len > 1 && ctx->line[0] == '/') {
|
if (ctx->len > 1 && ctx->line[0] == '/') {
|
||||||
int diff = complete_line(ctx, glob_cmd_list, AC_NUM_GLOB_COMMANDS, MAX_CMDNAME_SIZE);
|
int diff = complete_line(self, glob_cmd_list, AC_NUM_GLOB_COMMANDS, MAX_CMDNAME_SIZE);
|
||||||
|
|
||||||
if (diff != -1) {
|
if (diff != -1) {
|
||||||
if (x + diff > x2 - 1) {
|
if (x + diff > x2 - 1) {
|
||||||
wmove(self->window, y, x + diff);
|
int wlen = wcswidth(ctx->line, sizeof(ctx->line));
|
||||||
ctx->start += diff;
|
ctx->start = wlen < x2 ? 0 : wlen - x2 + 1;
|
||||||
} else {
|
|
||||||
wmove(self->window, y, x + diff);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
beep();
|
beep();
|
||||||
@ -309,11 +308,22 @@ static void prompt_onConnectionChange(ToxWindow *self, Tox *m, int32_t friendnum
|
|||||||
msg = "has come online";
|
msg = "has come online";
|
||||||
line_info_add(self, timefrmt, nick, NULL, msg, CONNECTION, 0, GREEN);
|
line_info_add(self, timefrmt, nick, NULL, msg, CONNECTION, 0, GREEN);
|
||||||
write_to_log(msg, nick, ctx->log, true);
|
write_to_log(msg, nick, ctx->log, true);
|
||||||
alert_window(self, WINDOW_ALERT_2, false);
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
notify(self, user_log_in, NT_WNDALERT_2 | NT_NOTIFWND | NT_RESTOL);
|
||||||
|
#else
|
||||||
|
notify(self, silent, NT_WNDALERT_2 | NT_NOTIFWND | NT_RESTOL);
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
} else {
|
} else {
|
||||||
msg = "has gone offline";
|
msg = "has gone offline";
|
||||||
line_info_add(self, timefrmt, nick, NULL, msg, CONNECTION, 0, RED);
|
line_info_add(self, timefrmt, nick, NULL, msg, CONNECTION, 0, RED);
|
||||||
write_to_log(msg, nick, ctx->log, true);
|
write_to_log(msg, nick, ctx->log, true);
|
||||||
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
notify(self, user_log_out, NT_WNDALERT_2 | NT_NOTIFWND | NT_RESTOL);
|
||||||
|
#else
|
||||||
|
notify(self, silent, NT_WNDALERT_2 | NT_NOTIFWND | NT_RESTOL);
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,7 +351,7 @@ static void prompt_onFriendRequest(ToxWindow *self, Tox *m, const char *key, con
|
|||||||
|
|
||||||
snprintf(msg, sizeof(msg), "Type \"/accept %d\" to accept it.", n);
|
snprintf(msg, sizeof(msg), "Type \"/accept %d\" to accept it.", n);
|
||||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
alert_window(self, WINDOW_ALERT_1, true);
|
notify(self, generic_message, NT_WNDALERT_1 | NT_NOTIFWND);
|
||||||
}
|
}
|
||||||
|
|
||||||
void prompt_init_statusbar(ToxWindow *self, Tox *m)
|
void prompt_init_statusbar(ToxWindow *self, Tox *m)
|
||||||
@ -372,7 +382,7 @@ void prompt_init_statusbar(ToxWindow *self, Tox *m)
|
|||||||
strcpy(ver, TOXICVER);
|
strcpy(ver, TOXICVER);
|
||||||
const char *toxic_ver = strtok(ver, "_");
|
const char *toxic_ver = strtok(ver, "_");
|
||||||
|
|
||||||
if ( (!strcmp("Online", statusmsg) || !strncmp("Toxing on Toxic", statusmsg, 15)) && toxic_ver != NULL) {
|
if ( (!statusmsg[0] || !strncmp("Toxing on Toxic", statusmsg, 15)) && toxic_ver != NULL) {
|
||||||
snprintf(statusmsg, MAX_STR_SIZE, "Toxing on Toxic v.%s", toxic_ver);
|
snprintf(statusmsg, MAX_STR_SIZE, "Toxing on Toxic v.%s", toxic_ver);
|
||||||
s_len = strlen(statusmsg);
|
s_len = strlen(statusmsg);
|
||||||
statusmsg[s_len] = '\0';
|
statusmsg[s_len] = '\0';
|
||||||
@ -420,7 +430,7 @@ static void prompt_onInit(ToxWindow *self, Tox *m)
|
|||||||
|
|
||||||
line_info_init(ctx->hst);
|
line_info_init(ctx->hst);
|
||||||
|
|
||||||
if (user_settings->autolog == AUTOLOG_ON) {
|
if (user_settings_->autolog == AUTOLOG_ON) {
|
||||||
char myid[TOX_FRIEND_ADDRESS_SIZE];
|
char myid[TOX_FRIEND_ADDRESS_SIZE];
|
||||||
tox_get_address(m, (uint8_t *) myid);
|
tox_get_address(m, (uint8_t *) myid);
|
||||||
log_enable(self->name, myid, ctx->log);
|
log_enable(self->name, myid, ctx->log);
|
||||||
|
@ -26,11 +26,11 @@
|
|||||||
#include "toxic.h"
|
#include "toxic.h"
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
#define AC_NUM_GLOB_COMMANDS 17
|
#define AC_NUM_GLOB_COMMANDS 16
|
||||||
#else
|
#else
|
||||||
#define AC_NUM_GLOB_COMMANDS 15
|
#define AC_NUM_GLOB_COMMANDS 14
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
ToxWindow new_prompt(void);
|
ToxWindow new_prompt(void);
|
||||||
void prep_prompt_win(void);
|
void prep_prompt_win(void);
|
||||||
|
396
src/settings.c
396
src/settings.c
@ -22,207 +22,261 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <libconfig.h>
|
||||||
|
|
||||||
#include "toxic.h"
|
#include "toxic.h"
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
#include "configdir.h"
|
#include "configdir.h"
|
||||||
|
#include "notify.h"
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "line_info.h"
|
#include "line_info.h"
|
||||||
|
|
||||||
static void uset_autolog(struct user_settings *s, const char *val);
|
#ifndef PACKAGE_DATADIR
|
||||||
static void uset_time(struct user_settings *s, const char *val);
|
#define PACKAGE_DATADIR "."
|
||||||
static void uset_timestamps(struct user_settings *s, const char *val);
|
|
||||||
static void uset_alerts(struct user_settings *s, const char *val);
|
|
||||||
static void uset_colours(struct user_settings *s, const char *val);
|
|
||||||
static void uset_hst_size(struct user_settings *s, const char *val);
|
|
||||||
static void uset_dwnld_path(struct user_settings *s, const char *val);
|
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
|
||||||
static void uset_ain_dev(struct user_settings *s, const char *val);
|
|
||||||
static void uset_aout_dev(struct user_settings *s, const char *val);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct {
|
#define NO_SOUND "silent"
|
||||||
const char *key;
|
|
||||||
void (*func)(struct user_settings *s, const char *val);
|
|
||||||
} user_settings_list[] = {
|
|
||||||
{ "autolog", uset_autolog },
|
|
||||||
{ "time", uset_time },
|
|
||||||
{ "timestamps", uset_timestamps },
|
|
||||||
{ "alerts", uset_alerts },
|
|
||||||
{ "colour_theme", uset_colours },
|
|
||||||
{ "history_size", uset_hst_size },
|
|
||||||
{ "download_path", uset_dwnld_path },
|
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
const struct _ui_strings {
|
||||||
{ "audio_in_dev", uset_ain_dev },
|
const char* self;
|
||||||
{ "audio_out_dev", uset_aout_dev },
|
const char* timestamps;
|
||||||
#endif
|
const char* alerts;
|
||||||
|
const char* native_colors;
|
||||||
|
const char* autolog;
|
||||||
|
const char* time_format;
|
||||||
|
const char* history_size;
|
||||||
|
} ui_strings = {
|
||||||
|
"ui",
|
||||||
|
"timestamps",
|
||||||
|
"alerts",
|
||||||
|
"native_colors",
|
||||||
|
"autolog",
|
||||||
|
"time_format",
|
||||||
|
"history_size"
|
||||||
|
};
|
||||||
|
static void ui_defaults(struct user_settings* settings)
|
||||||
|
{
|
||||||
|
settings->timestamps = TIMESTAMPS_ON;
|
||||||
|
settings->time = TIME_24;
|
||||||
|
settings->autolog = AUTOLOG_OFF;
|
||||||
|
settings->alerts = ALERTS_ENABLED;
|
||||||
|
settings->colour_theme = DFLT_COLS;
|
||||||
|
settings->history_size = 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct _tox_strings {
|
||||||
|
const char* self;
|
||||||
|
const char* download_path;
|
||||||
|
} tox_strings = {
|
||||||
|
"tox",
|
||||||
|
"download_path",
|
||||||
};
|
};
|
||||||
|
|
||||||
static void uset_autolog(struct user_settings *s, const char *val)
|
static void tox_defaults(struct user_settings* settings)
|
||||||
{
|
{
|
||||||
int n = atoi(val);
|
strcpy(settings->download_path, ""); /* explicitly set default to pwd */
|
||||||
|
|
||||||
/* default off if invalid value */
|
|
||||||
s->autolog = n == AUTOLOG_ON ? AUTOLOG_ON : AUTOLOG_OFF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void uset_time(struct user_settings *s, const char *val)
|
#ifdef _AUDIO
|
||||||
|
const struct _audio_strings {
|
||||||
|
const char* self;
|
||||||
|
const char* input_device;
|
||||||
|
const char* output_device;
|
||||||
|
const char* VAD_treshold;
|
||||||
|
} audio_strings = {
|
||||||
|
"audio",
|
||||||
|
"input_device",
|
||||||
|
"output_device",
|
||||||
|
"VAD_treshold",
|
||||||
|
};
|
||||||
|
static void audio_defaults(struct user_settings* settings)
|
||||||
{
|
{
|
||||||
int n = atoi(val);
|
settings->audio_in_dev = 0;
|
||||||
|
settings->audio_out_dev = 0;
|
||||||
/* default to 24 hour time if invalid value */
|
settings->VAD_treshold = 40.0;
|
||||||
s->time = n == TIME_12 ? TIME_12 : TIME_24;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void uset_timestamps(struct user_settings *s, const char *val)
|
|
||||||
{
|
|
||||||
int n = atoi(val);
|
|
||||||
|
|
||||||
/* default on if invalid value */
|
|
||||||
s->timestamps = n == TIMESTAMPS_OFF ? TIMESTAMPS_OFF : TIMESTAMPS_ON;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void uset_alerts(struct user_settings *s, const char *val)
|
|
||||||
{
|
|
||||||
int n = atoi(val);
|
|
||||||
|
|
||||||
/* alerts default on if invalid value */
|
|
||||||
s->alerts = n == ALERTS_DISABLED ? ALERTS_DISABLED : ALERTS_ENABLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void uset_colours(struct user_settings *s, const char *val)
|
|
||||||
{
|
|
||||||
int n = atoi(val);
|
|
||||||
|
|
||||||
/* use default toxic colours if invalid value */
|
|
||||||
s->colour_theme = n == NATIVE_COLS ? NATIVE_COLS : DFLT_COLS;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
|
||||||
|
|
||||||
static void uset_ain_dev(struct user_settings *s, const char *val)
|
|
||||||
{
|
|
||||||
int n = atoi(val);
|
|
||||||
|
|
||||||
if (n < 0 || n > MAX_DEVICES)
|
|
||||||
n = (long int) 0;
|
|
||||||
|
|
||||||
s->audio_in_dev = (long int) n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void uset_aout_dev(struct user_settings *s, const char *val)
|
|
||||||
{
|
|
||||||
int n = atoi(val);
|
|
||||||
|
|
||||||
if (n < 0 || n > MAX_DEVICES)
|
|
||||||
n = (long int) 0;
|
|
||||||
|
|
||||||
s->audio_out_dev = (long int) n;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _SUPPORT_AUDIO */
|
|
||||||
|
|
||||||
static void uset_hst_size(struct user_settings *s, const char *val)
|
|
||||||
{
|
|
||||||
int n = atoi(val);
|
|
||||||
|
|
||||||
/* if val is out of range use default history size */
|
|
||||||
s->history_size = (n > MAX_HISTORY || n < MIN_HISTORY) ? DFLT_HST_SIZE : n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void uset_dwnld_path(struct user_settings *s, const char *val)
|
|
||||||
{
|
|
||||||
memset(s->download_path, 0, sizeof(s->download_path));
|
|
||||||
|
|
||||||
if (val == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int len = strlen(val);
|
|
||||||
|
|
||||||
if (len >= sizeof(s->download_path) - 2) /* leave room for null and '/' */
|
|
||||||
return;
|
|
||||||
|
|
||||||
FILE *fp = fopen(val, "r");
|
|
||||||
|
|
||||||
if (fp == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
strcpy(s->download_path, val);
|
|
||||||
|
|
||||||
if (val[len - 1] != '/')
|
|
||||||
strcat(s->download_path, "/");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_default_settings(struct user_settings *s)
|
|
||||||
{
|
|
||||||
/* see settings_values enum in settings.h for defaults */
|
|
||||||
uset_autolog(s, "0");
|
|
||||||
uset_time(s, "24");
|
|
||||||
uset_timestamps(s, "1");
|
|
||||||
uset_alerts(s, "1");
|
|
||||||
uset_colours(s, "0");
|
|
||||||
uset_hst_size(s, "700");
|
|
||||||
uset_dwnld_path(s, NULL);
|
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
|
||||||
uset_ain_dev(s, "0");
|
|
||||||
uset_aout_dev(s, "0");
|
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
int settings_load(struct user_settings *s, char *path)
|
#ifdef _SOUND_NOTIFY
|
||||||
|
const struct _sound_strings {
|
||||||
|
const char* self;
|
||||||
|
const char* error;
|
||||||
|
const char* self_log_in;
|
||||||
|
const char* self_log_out;
|
||||||
|
const char* user_log_in;
|
||||||
|
const char* user_log_out;
|
||||||
|
const char* call_incoming;
|
||||||
|
const char* call_outgoing;
|
||||||
|
const char* generic_message;
|
||||||
|
const char* transfer_pending;
|
||||||
|
const char* transfer_completed;
|
||||||
|
} sound_strings = {
|
||||||
|
"sounds",
|
||||||
|
"error",
|
||||||
|
"self_log_in",
|
||||||
|
"self_log_out",
|
||||||
|
"user_log_in",
|
||||||
|
"user_log_out",
|
||||||
|
"call_incoming",
|
||||||
|
"call_outgoing",
|
||||||
|
"generic_message",
|
||||||
|
"transfer_pending",
|
||||||
|
"transfer_completed",
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int settings_load(struct user_settings *s, const char *patharg)
|
||||||
{
|
{
|
||||||
|
config_t cfg[1];
|
||||||
|
config_setting_t *setting;
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
/* Load default settings */
|
||||||
|
ui_defaults(s);
|
||||||
|
tox_defaults(s);
|
||||||
|
#ifdef _AUDIO
|
||||||
|
audio_defaults(s);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
config_init(cfg);
|
||||||
|
|
||||||
|
char path[MAX_STR_SIZE];
|
||||||
|
|
||||||
|
/* use default config file path */
|
||||||
|
if (patharg == NULL) {
|
||||||
char *user_config_dir = get_user_config_dir();
|
char *user_config_dir = get_user_config_dir();
|
||||||
FILE *fp = NULL;
|
snprintf(path, sizeof(path), "%s%stoxic.conf", user_config_dir, CONFIGDIR);
|
||||||
char dflt_path[MAX_STR_SIZE];
|
|
||||||
|
|
||||||
if (path) {
|
|
||||||
fp = fopen(path, "r");
|
|
||||||
} else {
|
|
||||||
snprintf(dflt_path, sizeof(dflt_path), "%s%stoxic.conf", user_config_dir, CONFIGDIR);
|
|
||||||
fp = fopen(dflt_path, "r");
|
|
||||||
}
|
|
||||||
|
|
||||||
free(user_config_dir);
|
free(user_config_dir);
|
||||||
|
|
||||||
set_default_settings(s);
|
/* make sure path exists or is created on first time running */
|
||||||
|
FILE *fp = fopen(path, "r");
|
||||||
|
|
||||||
if (fp == NULL && !path) {
|
if (fp == NULL) {
|
||||||
if ((fp = fopen(dflt_path, "w")) == NULL)
|
if ((fp = fopen(path, "w")) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
} else if (fp == NULL && path) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char line[MAX_STR_SIZE];
|
|
||||||
|
|
||||||
while (fgets(line, sizeof(line), fp)) {
|
|
||||||
if (line[0] == '#' || !line[0])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const char *key = strtok(line, ":");
|
|
||||||
const char *val = strtok(NULL, ";");
|
|
||||||
|
|
||||||
if (key == NULL || val == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < NUM_SETTINGS; ++i) {
|
|
||||||
if (strcmp(user_settings_list[i].key, key) == 0) {
|
|
||||||
(user_settings_list[i].func)(s, val);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
} else {
|
||||||
|
snprintf(path, sizeof(path), "%s", patharg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config_read_file(cfg, path)) {
|
||||||
|
config_destroy(cfg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ui */
|
||||||
|
if ((setting = config_lookup(cfg, ui_strings.self)) != NULL) {
|
||||||
|
config_setting_lookup_bool(setting, ui_strings.timestamps, &s->timestamps);
|
||||||
|
config_setting_lookup_bool(setting, ui_strings.alerts, &s->alerts);
|
||||||
|
config_setting_lookup_bool(setting, ui_strings.autolog, &s->autolog);
|
||||||
|
config_setting_lookup_bool(setting, ui_strings.native_colors, &s->colour_theme);
|
||||||
|
|
||||||
|
config_setting_lookup_int(setting, ui_strings.history_size, &s->history_size);
|
||||||
|
config_setting_lookup_int(setting, ui_strings.time_format, &s->time);
|
||||||
|
s->time = s->time == TIME_24 || s->time == TIME_12 ? s->time : TIME_24; /* Check defaults */
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((setting = config_lookup(cfg, tox_strings.self)) != NULL) {
|
||||||
|
if ( config_setting_lookup_string(setting, tox_strings.download_path, &str) ) {
|
||||||
|
strcpy(s->download_path, str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#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;
|
||||||
|
|
||||||
|
config_setting_lookup_int(setting, audio_strings.output_device, &s->audio_out_dev);
|
||||||
|
s->audio_out_dev = s->audio_out_dev < 0 || s->audio_out_dev > MAX_DEVICES ? 0 : s->audio_out_dev;
|
||||||
|
|
||||||
|
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.error, &str) != CONFIG_TRUE) ||
|
||||||
|
!set_sound(error, str) ) {
|
||||||
|
if (strcasecmp(str, NO_SOUND))
|
||||||
|
set_sound(error, PACKAGE_DATADIR "/sounds/Error.wav");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !config_setting_lookup_string(setting, sound_strings.user_log_in, &str) ||
|
||||||
|
!set_sound(user_log_in, str) ) {
|
||||||
|
if (strcasecmp(str, NO_SOUND))
|
||||||
|
set_sound(user_log_in, PACKAGE_DATADIR "/sounds/ContactLogsIn.wav");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !config_setting_lookup_string(setting, sound_strings.self_log_in, &str) ||
|
||||||
|
!set_sound(self_log_in, str) ) {
|
||||||
|
if (strcasecmp(str, NO_SOUND))
|
||||||
|
set_sound(self_log_in, PACKAGE_DATADIR "/sounds/LogIn.wav");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !config_setting_lookup_string(setting, sound_strings.user_log_out, &str) ||
|
||||||
|
!set_sound(user_log_out, str) ) {
|
||||||
|
if (strcasecmp(str, NO_SOUND))
|
||||||
|
set_sound(user_log_out, PACKAGE_DATADIR "/sounds/ContactLogsOut.wav");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !config_setting_lookup_string(setting, sound_strings.self_log_out, &str) ||
|
||||||
|
!set_sound(self_log_out, str) ) {
|
||||||
|
if (strcasecmp(str, NO_SOUND))
|
||||||
|
set_sound(self_log_out, PACKAGE_DATADIR "/sounds/LogOut.wav");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !config_setting_lookup_string(setting, sound_strings.call_incoming, &str) ||
|
||||||
|
!set_sound(call_incoming, str) ) {
|
||||||
|
if (strcasecmp(str, NO_SOUND))
|
||||||
|
set_sound(call_incoming, PACKAGE_DATADIR "/sounds/IncomingCall.wav");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !config_setting_lookup_string(setting, sound_strings.call_outgoing, &str) ||
|
||||||
|
!set_sound(call_outgoing, str) ) {
|
||||||
|
if (strcasecmp(str, NO_SOUND))
|
||||||
|
set_sound(call_outgoing, PACKAGE_DATADIR "/sounds/OutgoingCall.wav");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( config_setting_lookup_string(setting, sound_strings.generic_message, &str) ||
|
||||||
|
!set_sound(generic_message, str) ) {
|
||||||
|
if (strcasecmp(str, NO_SOUND))
|
||||||
|
set_sound(generic_message, PACKAGE_DATADIR "/sounds/NewMessage.wav");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !config_setting_lookup_string(setting, sound_strings.transfer_pending, &str) ||
|
||||||
|
!set_sound(transfer_pending, str) ) {
|
||||||
|
if (strcasecmp(str, NO_SOUND))
|
||||||
|
set_sound(transfer_pending, PACKAGE_DATADIR "/sounds/TransferPending.wav");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !config_setting_lookup_string(setting, sound_strings.transfer_completed, &str) ||
|
||||||
|
!set_sound(transfer_completed, str) ) {
|
||||||
|
if (strcasecmp(str, NO_SOUND))
|
||||||
|
set_sound(transfer_completed, PACKAGE_DATADIR "/sounds/TransferComplete.wav");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
set_sound(error, PACKAGE_DATADIR "/sounds/Error.wav");
|
||||||
|
set_sound(user_log_in, PACKAGE_DATADIR "/sounds/ContactLogsIn.wav");
|
||||||
|
set_sound(self_log_in, PACKAGE_DATADIR "/sounds/LogIn.wav");
|
||||||
|
set_sound(user_log_out, PACKAGE_DATADIR "/sounds/ContactLogsOut.wav");
|
||||||
|
set_sound(self_log_out, PACKAGE_DATADIR "/sounds/LogOut.wav");
|
||||||
|
set_sound(call_incoming, PACKAGE_DATADIR "/sounds/IncomingCall.wav");
|
||||||
|
set_sound(call_outgoing, PACKAGE_DATADIR "/sounds/OutgoingCall.wav");
|
||||||
|
set_sound(generic_message, PACKAGE_DATADIR "/sounds/NewMessage.wav");
|
||||||
|
set_sound(transfer_pending, PACKAGE_DATADIR "/sounds/TransferPending.wav");
|
||||||
|
set_sound(transfer_completed, PACKAGE_DATADIR "/sounds/TransferComplete.wav");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
config_destroy(cfg);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -23,14 +23,6 @@
|
|||||||
#ifndef _settings_h
|
#ifndef _settings_h
|
||||||
#define _settings_h
|
#define _settings_h
|
||||||
|
|
||||||
#include "toxic.h"
|
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
|
||||||
#define NUM_SETTINGS 9
|
|
||||||
#else
|
|
||||||
#define NUM_SETTINGS 7
|
|
||||||
#endif /* _SUPPORT_AUDIO */
|
|
||||||
|
|
||||||
/* holds user setting values */
|
/* holds user setting values */
|
||||||
struct user_settings {
|
struct user_settings {
|
||||||
int autolog; /* boolean */
|
int autolog; /* boolean */
|
||||||
@ -41,9 +33,10 @@ struct user_settings {
|
|||||||
int history_size; /* int between MIN_HISTORY and MAX_HISTORY */
|
int history_size; /* int between MIN_HISTORY and MAX_HISTORY */
|
||||||
char download_path[MAX_STR_SIZE];
|
char download_path[MAX_STR_SIZE];
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
long int audio_in_dev;
|
int audio_in_dev;
|
||||||
long int audio_out_dev;
|
int audio_out_dev;
|
||||||
|
double VAD_treshold;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -66,6 +59,6 @@ enum {
|
|||||||
DFLT_HST_SIZE = 700,
|
DFLT_HST_SIZE = 700,
|
||||||
} settings_values;
|
} settings_values;
|
||||||
|
|
||||||
int settings_load(struct user_settings *s, char *path);
|
int settings_load(struct user_settings *s, const char *patharg);
|
||||||
|
|
||||||
#endif /* #define _settings_h */
|
#endif /* #define _settings_h */
|
||||||
|
80
src/toxic.c
80
src/toxic.c
@ -50,18 +50,20 @@
|
|||||||
#include "line_info.h"
|
#include "line_info.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "notify.h"
|
||||||
|
#include "device.h"
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
#include "audio_call.h"
|
#include "audio_call.h"
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
#ifndef PACKAGE_DATADIR
|
#ifndef PACKAGE_DATADIR
|
||||||
#define PACKAGE_DATADIR "."
|
#define PACKAGE_DATADIR "."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
ToxAv *av;
|
ToxAv *av;
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
/* Export for use in Callbacks */
|
/* Export for use in Callbacks */
|
||||||
char *DATA_FILE = NULL;
|
char *DATA_FILE = NULL;
|
||||||
@ -78,7 +80,7 @@ struct arg_opts {
|
|||||||
} arg_opts;
|
} arg_opts;
|
||||||
|
|
||||||
struct _Winthread Winthread;
|
struct _Winthread Winthread;
|
||||||
struct user_settings *user_settings = NULL;
|
struct user_settings *user_settings_ = NULL;
|
||||||
|
|
||||||
static void catch_SIGINT(int sig)
|
static void catch_SIGINT(int sig)
|
||||||
{
|
{
|
||||||
@ -97,11 +99,15 @@ void exit_toxic_success(Tox *m)
|
|||||||
kill_all_windows();
|
kill_all_windows();
|
||||||
|
|
||||||
free(DATA_FILE);
|
free(DATA_FILE);
|
||||||
free(user_settings);
|
free(user_settings_);
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _SOUND_NOTIFY
|
||||||
|
notify(NULL, self_log_out, NT_ALWAYS);
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
|
terminate_notify();
|
||||||
|
#ifdef _AUDIO
|
||||||
terminate_audio();
|
terminate_audio();
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
tox_kill(m);
|
tox_kill(m);
|
||||||
endwin();
|
endwin();
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
@ -141,7 +147,7 @@ static void init_term(void)
|
|||||||
short bg_color = COLOR_BLACK;
|
short bg_color = COLOR_BLACK;
|
||||||
start_color();
|
start_color();
|
||||||
|
|
||||||
if (user_settings->colour_theme == NATIVE_COLS) {
|
if (user_settings_->colour_theme == NATIVE_COLS) {
|
||||||
if (assume_default_colors(-1, -1) == OK)
|
if (assume_default_colors(-1, -1) == OK)
|
||||||
bg_color = -1;
|
bg_color = -1;
|
||||||
}
|
}
|
||||||
@ -369,7 +375,7 @@ static void load_friendlist(Tox *m)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Store Messenger to given location
|
* Store Messenger to given location
|
||||||
* Return 0 stored successfully
|
* Return 0 stored successfully or ignoring data file
|
||||||
* Return 1 file path is NULL
|
* Return 1 file path is NULL
|
||||||
* Return 2 malloc failed
|
* Return 2 malloc failed
|
||||||
* Return 3 opening path failed
|
* Return 3 opening path failed
|
||||||
@ -383,19 +389,15 @@ int store_data(Tox *m, char *path)
|
|||||||
if (path == NULL)
|
if (path == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
FILE *fd;
|
int len = tox_size(m);
|
||||||
int len;
|
char *buf = malloc(len);
|
||||||
char *buf;
|
|
||||||
|
|
||||||
len = tox_size(m);
|
|
||||||
buf = malloc(len);
|
|
||||||
|
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
tox_save(m, (uint8_t *) buf);
|
tox_save(m, (uint8_t *) buf);
|
||||||
|
|
||||||
fd = fopen(path, "wb");
|
FILE *fd = fopen(path, "wb");
|
||||||
|
|
||||||
if (fd == NULL) {
|
if (fd == NULL) {
|
||||||
free(buf);
|
free(buf);
|
||||||
@ -419,15 +421,13 @@ static void load_data(Tox *m, char *path)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
FILE *fd;
|
FILE *fd;
|
||||||
int len;
|
|
||||||
char *buf;
|
|
||||||
|
|
||||||
if ((fd = fopen(path, "rb")) != NULL) {
|
if ((fd = fopen(path, "rb")) != NULL) {
|
||||||
fseek(fd, 0, SEEK_END);
|
fseek(fd, 0, SEEK_END);
|
||||||
len = ftell(fd);
|
int len = ftell(fd);
|
||||||
fseek(fd, 0, SEEK_SET);
|
fseek(fd, 0, SEEK_SET);
|
||||||
|
|
||||||
buf = malloc(len);
|
char *buf = malloc(len);
|
||||||
|
|
||||||
if (buf == NULL) {
|
if (buf == NULL) {
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
@ -526,6 +526,10 @@ static void parse_args(int argc, char *argv[])
|
|||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'f':
|
case 'f':
|
||||||
DATA_FILE = strdup(optarg);
|
DATA_FILE = strdup(optarg);
|
||||||
|
|
||||||
|
if (DATA_FILE == NULL)
|
||||||
|
exit_toxic_err("failed in parse_args", FATALERR_MEMORY);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'x':
|
case 'x':
|
||||||
@ -573,6 +577,9 @@ int main(int argc, char *argv[])
|
|||||||
if (DATA_FILE == NULL ) {
|
if (DATA_FILE == NULL ) {
|
||||||
if (config_err) {
|
if (config_err) {
|
||||||
DATA_FILE = strdup("data");
|
DATA_FILE = strdup("data");
|
||||||
|
|
||||||
|
if (DATA_FILE == NULL)
|
||||||
|
exit_toxic_err("failed in main", FATALERR_MEMORY);
|
||||||
} else {
|
} else {
|
||||||
DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1);
|
DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1);
|
||||||
|
|
||||||
@ -588,15 +595,13 @@ int main(int argc, char *argv[])
|
|||||||
free(user_config_dir);
|
free(user_config_dir);
|
||||||
|
|
||||||
/* init user_settings struct and load settings from conf file */
|
/* init user_settings struct and load settings from conf file */
|
||||||
user_settings = malloc(sizeof(struct user_settings));
|
user_settings_ = calloc(1, sizeof(struct user_settings));
|
||||||
|
|
||||||
if (user_settings == NULL)
|
if (user_settings_ == NULL)
|
||||||
exit_toxic_err("failed in main", FATALERR_MEMORY);
|
exit_toxic_err("failed in main", FATALERR_MEMORY);
|
||||||
|
|
||||||
memset(user_settings, 0, sizeof(struct user_settings));
|
|
||||||
|
|
||||||
char *p = arg_opts.config_path[0] ? arg_opts.config_path : NULL;
|
char *p = arg_opts.config_path[0] ? arg_opts.config_path : NULL;
|
||||||
int settings_err = settings_load(user_settings, p);
|
int settings_err = settings_load(user_settings_, p);
|
||||||
|
|
||||||
Tox *m = init_tox(arg_opts.use_ipv4);
|
Tox *m = init_tox(arg_opts.use_ipv4);
|
||||||
init_term();
|
init_term();
|
||||||
@ -616,17 +621,26 @@ int main(int argc, char *argv[])
|
|||||||
if (pthread_create(&Winthread.tid, NULL, thread_winref, (void *) m) != 0)
|
if (pthread_create(&Winthread.tid, NULL, thread_winref, (void *) m) != 0)
|
||||||
exit_toxic_err("failed in main", FATALERR_THREAD_CREATE);
|
exit_toxic_err("failed in main", FATALERR_THREAD_CREATE);
|
||||||
|
|
||||||
char *msg;
|
#ifdef _AUDIO
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
|
||||||
|
|
||||||
av = init_audio(prompt, m);
|
av = init_audio(prompt, m);
|
||||||
|
|
||||||
|
|
||||||
set_primary_device(input, user_settings->audio_in_dev);
|
set_primary_device(input, user_settings_->audio_in_dev);
|
||||||
set_primary_device(output, user_settings->audio_out_dev);
|
set_primary_device(output, user_settings_->audio_out_dev);
|
||||||
|
#elif _SOUND_NOTIFY
|
||||||
|
if ( init_devices() == de_InternalError )
|
||||||
|
line_info_add(prompt, NULL, NULL, NULL, "Failed to init devices", SYS_MSG, 0, 0);
|
||||||
|
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
|
init_notify(60);
|
||||||
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
notify(prompt, self_log_in, 0);
|
||||||
|
#endif /* _SOUND_NOTIFY */
|
||||||
|
|
||||||
|
char *msg;
|
||||||
|
|
||||||
if (config_err) {
|
if (config_err) {
|
||||||
msg = "Unable to determine configuration directory. Defaulting to 'data' for a keyfile...";
|
msg = "Unable to determine configuration directory. Defaulting to 'data' for a keyfile...";
|
||||||
@ -641,7 +655,7 @@ int main(int argc, char *argv[])
|
|||||||
sort_friendlist_index();
|
sort_friendlist_index();
|
||||||
prompt_init_statusbar(prompt, m);
|
prompt_init_statusbar(prompt, m);
|
||||||
|
|
||||||
uint64_t last_save = get_unix_time();
|
uint64_t last_save = (uint64_t) time(NULL);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
update_unix_time();
|
update_unix_time();
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
|
|
||||||
#define UNKNOWN_NAME "Anonymous"
|
#define UNKNOWN_NAME "Anonymous"
|
||||||
|
|
||||||
#define MAX_FRIENDS_NUM 500
|
#define MAX_FRIENDS_NUM 999
|
||||||
#define MAX_STR_SIZE TOX_MAX_MESSAGE_LENGTH
|
#define MAX_STR_SIZE TOX_MAX_MESSAGE_LENGTH
|
||||||
#define MAX_CMDNAME_SIZE 64
|
#define MAX_CMDNAME_SIZE 64
|
||||||
#define TOXIC_MAX_NAME_LENGTH 32 /* Must be <= TOX_MAX_NAME_LENGTH */
|
#define TOXIC_MAX_NAME_LENGTH 32 /* Must be <= TOX_MAX_NAME_LENGTH */
|
||||||
|
@ -208,86 +208,3 @@ void fetch_hist_item(ChatContext *ctx, int key_dir)
|
|||||||
ctx->pos = h_len;
|
ctx->pos = h_len;
|
||||||
ctx->len = h_len;
|
ctx->len = h_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* looks for the first instance in list that begins with the last entered word in line according to pos,
|
|
||||||
then fills line with the complete word. e.g. "Hello jo" would complete the line
|
|
||||||
with "Hello john".
|
|
||||||
|
|
||||||
list is a pointer to the list of strings being compared, n_items is the number of items
|
|
||||||
in the list, and size is the size of each item in the list.
|
|
||||||
|
|
||||||
Returns the difference between the old len and new len of line on success, -1 if error */
|
|
||||||
int complete_line(ChatContext *ctx, const void *list, int n_items, int size)
|
|
||||||
{
|
|
||||||
if (ctx->pos <= 0 || ctx->len <= 0 || ctx->len >= MAX_STR_SIZE)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
const char *L = (char *) list;
|
|
||||||
|
|
||||||
char ubuf[MAX_STR_SIZE];
|
|
||||||
|
|
||||||
/* work with multibyte string copy of buf for simplicity */
|
|
||||||
if (wcs_to_mbs_buf(ubuf, ctx->line, sizeof(ubuf)) == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* isolate substring from space behind pos to pos */
|
|
||||||
char tmp[MAX_STR_SIZE];
|
|
||||||
snprintf(tmp, sizeof(tmp), "%s", ubuf);
|
|
||||||
tmp[ctx->pos] = '\0';
|
|
||||||
char *sub = strrchr(tmp, ' ');
|
|
||||||
int n_endchrs = 1; /* 1 = append space to end of match, 2 = append ": " */
|
|
||||||
|
|
||||||
if (!sub++) {
|
|
||||||
sub = tmp;
|
|
||||||
|
|
||||||
if (sub[0] != '/') /* make sure it's not a command */
|
|
||||||
n_endchrs = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string_is_empty(sub))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
int s_len = strlen(sub);
|
|
||||||
const char *match;
|
|
||||||
bool is_match = false;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* look for a match in list */
|
|
||||||
for (i = 0; i < n_items; ++i) {
|
|
||||||
match = &L[i * size];
|
|
||||||
|
|
||||||
if ((is_match = strncasecmp(match, sub, s_len) == 0))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_match)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* put match in correct spot in buf and append endchars (space or ": ") */
|
|
||||||
const char *endchrs = n_endchrs == 1 ? " " : ": ";
|
|
||||||
int m_len = strlen(match);
|
|
||||||
int strt = ctx->pos - s_len;
|
|
||||||
int diff = m_len - s_len + n_endchrs;
|
|
||||||
|
|
||||||
if (ctx->len + diff > MAX_STR_SIZE)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
char tmpend[MAX_STR_SIZE];
|
|
||||||
strcpy(tmpend, &ubuf[ctx->pos]);
|
|
||||||
strcpy(&ubuf[strt], match);
|
|
||||||
strcpy(&ubuf[strt + m_len], endchrs);
|
|
||||||
strcpy(&ubuf[strt + m_len + n_endchrs], tmpend);
|
|
||||||
|
|
||||||
/* convert to widechar and copy back to original buf */
|
|
||||||
wchar_t newbuf[MAX_STR_SIZE];
|
|
||||||
|
|
||||||
if (mbs_to_wcs_buf(newbuf, ubuf, MAX_STR_SIZE) == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
wcscpy(ctx->line, newbuf);
|
|
||||||
|
|
||||||
ctx->len += diff;
|
|
||||||
ctx->pos += diff;
|
|
||||||
|
|
||||||
return diff;
|
|
||||||
}
|
|
||||||
|
@ -52,16 +52,6 @@ int yank_buf(ChatContext *ctx);
|
|||||||
/* Removes trailing spaces from line. */
|
/* Removes trailing spaces from line. */
|
||||||
void rm_trailing_spaces_buf(ChatContext *ctx);
|
void rm_trailing_spaces_buf(ChatContext *ctx);
|
||||||
|
|
||||||
/* looks for the first instance in list that begins with the last entered word in line according to pos,
|
|
||||||
then fills line with the complete word. e.g. "Hello jo" would complete the line
|
|
||||||
with "Hello john".
|
|
||||||
|
|
||||||
list is a pointer to the list of strings being compared, n_items is the number of items
|
|
||||||
in the list, and size is the size of each item in the list.
|
|
||||||
|
|
||||||
Returns the difference between the old len and new len of line on success, -1 if error */
|
|
||||||
int complete_line(ChatContext *ctx, const void *list, int n_items, int size);
|
|
||||||
|
|
||||||
/* adds a line to the ln_history buffer at hst_pos and sets hst_pos to last history item. */
|
/* adds a line to the ln_history buffer at hst_pos and sets hst_pos to last history item. */
|
||||||
void add_line_to_hist(ChatContext *ctx);
|
void add_line_to_hist(ChatContext *ctx);
|
||||||
|
|
||||||
|
@ -355,12 +355,12 @@ void on_window_resize(void)
|
|||||||
w->stb->topline = subwin(w->window, 2, x2, 0, 0);
|
w->stb->topline = subwin(w->window, 2, x2, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
if (w->chatwin->infobox.active) {
|
if (w->chatwin->infobox.active) {
|
||||||
delwin(w->chatwin->infobox.win);
|
delwin(w->chatwin->infobox.win);
|
||||||
w->chatwin->infobox.win = newwin(INFOBOX_HEIGHT, INFOBOX_WIDTH + 1, 1, x2 - INFOBOX_WIDTH);
|
w->chatwin->infobox.win = newwin(INFOBOX_HEIGHT, INFOBOX_WIDTH + 1, 1, x2 - INFOBOX_WIDTH);
|
||||||
}
|
}
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
scrollok(w->chatwin->history, 0);
|
scrollok(w->chatwin->history, 0);
|
||||||
}
|
}
|
||||||
@ -368,23 +368,11 @@ void on_window_resize(void)
|
|||||||
|
|
||||||
static void draw_window_tab(ToxWindow toxwin)
|
static void draw_window_tab(ToxWindow toxwin)
|
||||||
{
|
{
|
||||||
/* alert0 takes priority */
|
if (toxwin.alert) attron(COLOR_PAIR(toxwin.alert));
|
||||||
if (toxwin.alert0)
|
|
||||||
attron(COLOR_PAIR(GREEN));
|
|
||||||
else if (toxwin.alert1)
|
|
||||||
attron(COLOR_PAIR(RED));
|
|
||||||
else if (toxwin.alert2)
|
|
||||||
attron(COLOR_PAIR(MAGENTA));
|
|
||||||
|
|
||||||
clrtoeol();
|
clrtoeol();
|
||||||
printw(" [%s]", toxwin.name);
|
printw(" [%s]", toxwin.name);
|
||||||
|
|
||||||
if (toxwin.alert0)
|
if (toxwin.alert) attroff(COLOR_PAIR(toxwin.alert));
|
||||||
attroff(COLOR_PAIR(GREEN));
|
|
||||||
else if (toxwin.alert1)
|
|
||||||
attroff(COLOR_PAIR(RED));
|
|
||||||
else if (toxwin.alert2)
|
|
||||||
attroff(COLOR_PAIR(MAGENTA));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_bar(void)
|
static void draw_bar(void)
|
||||||
@ -432,9 +420,7 @@ static void draw_bar(void)
|
|||||||
void draw_active_window(Tox *m)
|
void draw_active_window(Tox *m)
|
||||||
{
|
{
|
||||||
ToxWindow *a = active_window;
|
ToxWindow *a = active_window;
|
||||||
a->alert0 = false;
|
a->alert = WINDOW_ALERT_NONE;
|
||||||
a->alert1 = false;
|
|
||||||
a->alert2 = false;
|
|
||||||
|
|
||||||
wint_t ch = 0;
|
wint_t ch = 0;
|
||||||
|
|
||||||
|
@ -29,9 +29,9 @@
|
|||||||
|
|
||||||
#include <tox/tox.h>
|
#include <tox/tox.h>
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
#include <tox/toxav.h>
|
#include <tox/toxav.h>
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
#include "toxic.h"
|
#include "toxic.h"
|
||||||
|
|
||||||
@ -53,10 +53,11 @@ enum {
|
|||||||
} C_COLOURS;
|
} C_COLOURS;
|
||||||
|
|
||||||
/* tab alert types: lower types take priority */
|
/* tab alert types: lower types take priority */
|
||||||
enum {
|
typedef enum {
|
||||||
WINDOW_ALERT_0,
|
WINDOW_ALERT_NONE = 0,
|
||||||
WINDOW_ALERT_1,
|
WINDOW_ALERT_0 = GREEN,
|
||||||
WINDOW_ALERT_2,
|
WINDOW_ALERT_1 = RED,
|
||||||
|
WINDOW_ALERT_2 = MAGENTA,
|
||||||
} WINDOW_ALERTS;
|
} WINDOW_ALERTS;
|
||||||
|
|
||||||
/* Fixes text color problem on some terminals.
|
/* Fixes text color problem on some terminals.
|
||||||
@ -97,7 +98,7 @@ struct ToxWindow {
|
|||||||
void(*onFileData)(ToxWindow *, Tox *, int32_t, uint8_t, const char *, uint16_t);
|
void(*onFileData)(ToxWindow *, Tox *, int32_t, uint8_t, const char *, uint16_t);
|
||||||
void(*onTypingChange)(ToxWindow *, Tox *, int32_t, uint8_t);
|
void(*onTypingChange)(ToxWindow *, Tox *, int32_t, uint8_t);
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
|
|
||||||
void(*onInvite)(ToxWindow *, ToxAv *, int);
|
void(*onInvite)(ToxWindow *, ToxAv *, int);
|
||||||
void(*onRinging)(ToxWindow *, ToxAv *, int);
|
void(*onRinging)(ToxWindow *, ToxAv *, int);
|
||||||
@ -115,7 +116,11 @@ struct ToxWindow {
|
|||||||
* Don't modify outside av callbacks. */
|
* Don't modify outside av callbacks. */
|
||||||
int device_selection[2]; /* -1 if not set, if set uses these selections instead of primary device */
|
int device_selection[2]; /* -1 if not set, if set uses these selections instead of primary device */
|
||||||
|
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
|
#ifdef _SOUND_NOTIFY
|
||||||
|
int active_sound;
|
||||||
|
#endif
|
||||||
|
|
||||||
char name[TOXIC_MAX_NAME_LENGTH];
|
char name[TOXIC_MAX_NAME_LENGTH];
|
||||||
int32_t num; /* corresponds to friendnumber in chat windows */
|
int32_t num; /* corresponds to friendnumber in chat windows */
|
||||||
@ -127,9 +132,7 @@ struct ToxWindow {
|
|||||||
bool is_prompt;
|
bool is_prompt;
|
||||||
bool is_friendlist;
|
bool is_friendlist;
|
||||||
|
|
||||||
bool alert0;
|
WINDOW_ALERTS alert;
|
||||||
bool alert1;
|
|
||||||
bool alert2;
|
|
||||||
|
|
||||||
ChatContext *chatwin;
|
ChatContext *chatwin;
|
||||||
StatusBar *stb;
|
StatusBar *stb;
|
||||||
@ -149,7 +152,7 @@ struct StatusBar {
|
|||||||
bool is_online;
|
bool is_online;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
|
|
||||||
|
|
||||||
#define INFOBOX_HEIGHT 7
|
#define INFOBOX_HEIGHT 7
|
||||||
@ -168,7 +171,7 @@ struct infobox {
|
|||||||
|
|
||||||
WINDOW *win;
|
WINDOW *win;
|
||||||
};
|
};
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
|
||||||
#define MAX_LINE_HIST 128
|
#define MAX_LINE_HIST 128
|
||||||
|
|
||||||
@ -189,7 +192,7 @@ struct ChatContext {
|
|||||||
struct history *hst;
|
struct history *hst;
|
||||||
struct chatlog *log;
|
struct chatlog *log;
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _AUDIO
|
||||||
struct infobox infobox;
|
struct infobox infobox;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user