diff --git a/misc/toxic.conf.example b/misc/toxic.conf.example index af99157..9b6acde 100644 --- a/misc/toxic.conf.example +++ b/misc/toxic.conf.example @@ -1,26 +1,51 @@ -# 24 or 12 hour time -time:24; +// SAMPLE TOXIC CONFIGURATION +// USES LIBCONFIG-ACCEPTED SYNTAX -# 1 to enable timestamps, 0 to disable -timestamps:1; +ui = { + // true to enable timestamps, false to disable + timestamps:true; -# 1 to enable autologging, 0 to disable -autolog:0; + // true to disabale terminal alerts on messages, false to enable + alerts:true; -# 1 to disbale terminal alerts on messages, 0 to enable -alerts:1; + // true to use native terminal colours, false to use toxic default colour theme + native_colors:true; -# maximum lines for chat window history -history_size:700; + // true to enable autologging, false to disable + autolog:false; + + // 24 or 12 hour time + time_format=24; -# 1 to use native terminal colours, 0 to use toxic default colour theme -colour_theme:0; + // maximum lines for chat window history + history_size=700; +}; -# preferred audio input device; numbers correspond to /lsdev in -audio_in_dev:0; +audio = { + // preferred audio input device; numbers correspond to /lsdev in + input_device=2; -# preferred audio output device; numbers correspond to /lsdev out -audio_out_dev:0; + // preferred audio output device; numbers correspond to /lsdev out + output_device=0; + + // default VAD treshold; float (recommended values are around 40) + VAD_treshold=40.0; +}; -# preferred path for downloads -download_path:/home/USERNAME/Downloads/; \ No newline at end of file +tox = { + // where to store received files + download_path="/home/USERNAME/Downloads/"; +}; + +sounds = { + error="/usr/local/toxic/sounds/Error.wav"; + self_log_in="/usr/local/toxic/sounds/Log In.wav"; + self_log_out="/usr/local/toxic/sounds/Log Out.wav"; + user_log_in="/usr/local/toxic/sounds/Contact Logs In.wav"; + user_log_out="/usr/local/toxic/sounds/Contact Logs Out.wav"; + call_incoming="/usr/local/toxic/sounds/Incoming Call.wav"; + call_outgoing="/usr/local/toxic/sounds/Outgoing Call.wav"; + generic_message="/usr/local/toxic/sounds/New Message.wav"; + transfer_pending="/usr/local/toxic/sounds/Transfer Pending.wav"; + transfer_completed="/usr/local/toxic/sounds/Transfer Complete.wav"; +}; \ No newline at end of file diff --git a/sounds/Contact Logs In.wav b/sounds/Contact Logs In.wav new file mode 100755 index 0000000..168fca8 Binary files /dev/null and b/sounds/Contact Logs In.wav differ diff --git a/sounds/Contact Logs Out.wav b/sounds/Contact Logs Out.wav new file mode 100755 index 0000000..53c2726 Binary files /dev/null and b/sounds/Contact Logs Out.wav differ diff --git a/sounds/Error.wav b/sounds/Error.wav new file mode 100755 index 0000000..cc35d7c Binary files /dev/null and b/sounds/Error.wav differ diff --git a/sounds/Incoming Call.wav b/sounds/Incoming Call.wav new file mode 100755 index 0000000..f761237 Binary files /dev/null and b/sounds/Incoming Call.wav differ diff --git a/sounds/Log In.wav b/sounds/Log In.wav new file mode 100755 index 0000000..971c21e Binary files /dev/null and b/sounds/Log In.wav differ diff --git a/sounds/Log Out.wav b/sounds/Log Out.wav new file mode 100755 index 0000000..a3c1ccf Binary files /dev/null and b/sounds/Log Out.wav differ diff --git a/sounds/New Message.wav b/sounds/New Message.wav new file mode 100755 index 0000000..f510000 Binary files /dev/null and b/sounds/New Message.wav differ diff --git a/sounds/Outgoing Call.wav b/sounds/Outgoing Call.wav new file mode 100755 index 0000000..de1f7e7 Binary files /dev/null and b/sounds/Outgoing Call.wav differ diff --git a/sounds/Transfer Complete.wav b/sounds/Transfer Complete.wav new file mode 100755 index 0000000..9c35ed5 Binary files /dev/null and b/sounds/Transfer Complete.wav differ diff --git a/sounds/Transfer Pending.wav b/sounds/Transfer Pending.wav new file mode 100755 index 0000000..7b2e49a Binary files /dev/null and b/sounds/Transfer Pending.wav differ diff --git a/sounds/license b/sounds/license new file mode 100644 index 0000000..530d3d7 --- /dev/null +++ b/sounds/license @@ -0,0 +1 @@ +Tox's sounds are licensed under the "Creative Commons Attribution 3.0 Unported", all credit attributed to Adam Reid. diff --git a/src/audio_call.c b/src/audio_call.c index c8154ab..86209db 100644 --- a/src/audio_call.c +++ b/src/audio_call.c @@ -27,6 +27,7 @@ #include "chat_commands.h" #include "global_commands.h" #include "line_info.h" +#include "notify.h" #include #include @@ -82,17 +83,17 @@ struct _ASettings { Call calls[MAX_CALLS]; } ASettins; -void callback_recv_invite ( int32_t call_index, void *arg ); -void callback_recv_ringing ( int32_t call_index, void *arg ); -void callback_recv_starting ( int32_t call_index, void *arg ); -void callback_recv_ending ( int32_t call_index, void *arg ); -void callback_recv_error ( int32_t call_index, void *arg ); -void callback_call_started ( int32_t call_index, void *arg ); -void callback_call_canceled ( int32_t call_index, void *arg ); -void callback_call_rejected ( int32_t call_index, void *arg ); -void callback_call_ended ( int32_t call_index, void *arg ); -void callback_requ_timeout ( int32_t call_index, void *arg ); -void callback_peer_timeout ( int32_t call_index, void *arg ); +void callback_recv_invite ( void* av, int32_t call_index, void *arg ); +void callback_recv_ringing ( void* av, int32_t call_index, void *arg ); +void callback_recv_starting ( void* av, int32_t call_index, void *arg ); +void callback_recv_ending ( void* av, int32_t call_index, void *arg ); +void callback_call_started ( void* av, int32_t call_index, void *arg ); +void callback_call_canceled ( void* av, int32_t call_index, void *arg ); +void callback_call_rejected ( void* av, int32_t call_index, void *arg ); +void callback_call_ended ( void* av, int32_t call_index, void *arg ); +void callback_requ_timeout ( void* av, int32_t call_index, void *arg ); +void callback_peer_timeout ( void* av, int32_t call_index, void *arg ); +void callback_media_change ( void* av, int32_t call_index, void *arg ); int stop_transmission(int call_index); 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; } - toxav_register_callstate_callback(callback_call_started, av_OnStart, self); - toxav_register_callstate_callback(callback_call_canceled, av_OnCancel, self); - toxav_register_callstate_callback(callback_call_rejected, av_OnReject, self); - toxav_register_callstate_callback(callback_call_ended, av_OnEnd, self); - toxav_register_callstate_callback(callback_recv_invite, av_OnInvite, self); + toxav_register_callstate_callback(ASettins.av, callback_call_started, av_OnStart, self); + toxav_register_callstate_callback(ASettins.av, callback_call_canceled, av_OnCancel, self); + toxav_register_callstate_callback(ASettins.av, callback_call_rejected, av_OnReject, self); + toxav_register_callstate_callback(ASettins.av, callback_call_ended, av_OnEnd, 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(callback_recv_starting, av_OnStarting, self); - toxav_register_callstate_callback(callback_recv_ending, av_OnEnding, self); + toxav_register_callstate_callback(ASettins.av, callback_recv_ringing, av_OnRinging, self); + toxav_register_callstate_callback(ASettins.av, callback_recv_starting, av_OnStarting, 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(callback_requ_timeout, av_OnRequestTimeout, self); - toxav_register_callstate_callback(callback_peer_timeout, av_OnPeerTimeout, self); + toxav_register_callstate_callback(ASettins.av, callback_requ_timeout, av_OnRequestTimeout, self); + toxav_register_callstate_callback(ASettins.av, 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); @@ -240,15 +241,15 @@ int stop_transmission(int call_index) #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) -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); } -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); } -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; int i; @@ -261,17 +262,13 @@ void callback_recv_starting ( int32_t call_index, void* arg ) 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); stop_transmission(call_index); } -void callback_recv_error ( 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 ) + +void callback_call_started ( void* av, int32_t call_index, void* arg ) { ToxWindow* windows = arg; int i; @@ -284,28 +281,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); /* In case call is active */ 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); } -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); 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); } -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); stop_transmission(call_index); @@ -314,6 +311,10 @@ void callback_peer_timeout ( int32_t call_index, void* arg ) */ 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 */ @@ -476,6 +477,10 @@ void cmd_cancel(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[ goto on_error; } +#ifdef _SOUND_NOTIFY + stop_sound(self->active_sound); + self->active_sound = -1; +#endif /* _SOUND_NOTIFY */ /* Callback will print status... */ return; diff --git a/src/chat.c b/src/chat.c index 2e981c2..b540036 100644 --- a/src/chat.c +++ b/src/chat.c @@ -42,10 +42,12 @@ #include "input.h" #include "help.h" #include "autocomplete.h" +#include "notify.h" + +#ifdef _AUDIO + #include "audio_call.h" +#endif /* _AUDIO */ -#ifdef _SUPPORT_AUDIO -#include "audio_call.h" -#endif /* _SUPPORT_AUDIO */ extern char *DATA_FILE; @@ -53,18 +55,18 @@ extern FileSender file_senders[MAX_FILES]; extern ToxicFriend friends[MAX_FRIENDS_NUM]; 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 kill_infobox(ToxWindow *self); -#endif /* _SUPPORT_AUDIO */ +#endif /* _AUDIO */ -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO #define AC_NUM_CHAT_COMMANDS 26 #else #define AC_NUM_CHAT_COMMANDS 18 -#endif /* _SUPPORT_AUDIO */ +#endif /* _AUDIO */ /* Array of chat command names used for tab completion. */ static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = { @@ -87,7 +89,7 @@ static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = { { "/sendfile" }, { "/status" }, -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO { "/call" }, { "/cancel" }, @@ -98,7 +100,7 @@ static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = { { "/mute" }, { "/sense" }, -#endif /* _SUPPORT_AUDIO */ +#endif /* _AUDIO */ }; static void set_typingstatus(ToxWindow *self, Tox *m, uint8_t is_typing) @@ -127,7 +129,7 @@ void kill_chat_window(ToxWindow *self) log_disable(ctx->log); line_info_cleanup(ctx->hst); -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO stop_current_call(self); #endif @@ -160,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); 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) @@ -170,12 +173,14 @@ static void chat_onConnectionChange(ToxWindow *self, Tox *m, int32_t num, uint8_ StatusBar *statusbar = self->stb; - if (status == 1) { + if (status == 1) { /* Friend shows online */ statusbar->is_online = true; 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; friends[num].is_typing = 0; + notify(self, user_log_out, NT_NOFOCUS); } } @@ -202,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); 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) @@ -272,9 +277,9 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t } /* use specified path in config if possible */ - if (user_settings->download_path[0]) { - snprintf(filename_path, sizeof(filename_path), "%s%s", user_settings->download_path, filename_nopath); - len += strlen(user_settings->download_path); + if (user_settings_->download_path[0]) { + snprintf(filename_path, sizeof(filename_path), "%s%s", user_settings_->download_path, filename_nopath); + len += strlen(user_settings_->download_path); } if (len >= sizeof(friends[num].file_receiver.filenames[filenum])) { @@ -322,7 +327,7 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t friends[num].file_receiver.size[filenum] = filesize; 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) @@ -361,6 +366,7 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t rec if (receive_send == 1) { 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; + notify(self, silent, NT_NOFOCUS | NT_BEEP | NT_WNDALERT_2); } break; @@ -371,19 +377,20 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t rec if (receive_send == 0) chat_close_file_receiver(num, filenum); + notify(self, error, NT_NOFOCUS | NT_WNDALERT_2); break; case TOX_FILECONTROL_FINISHED: if (receive_send == 0) { snprintf(msg, sizeof(msg), "File transfer for '%s' complete.", filename); chat_close_file_receiver(num, filenum); + notify(self, transfer_completed, NT_NOFOCUS | NT_WNDALERT_2); } break; } 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, @@ -436,11 +443,12 @@ static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, co sizeof(friends[friendnumber].groupchat_key)); friends[friendnumber].groupchat_pending = true; - alert_window(self, WINDOW_ALERT_2, true); + + notify(self, generic_message, NT_WNDALERT_2); } /* Av Stuff */ -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO void chat_onInvite (ToxWindow *self, ToxAv *av, int call_index) { @@ -451,7 +459,11 @@ void chat_onInvite (ToxWindow *self, ToxAv *av, int 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); - 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) @@ -460,6 +472,11 @@ void chat_onRinging (ToxWindow *self, ToxAv *av, int call_index) return; 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) @@ -470,6 +487,11 @@ void chat_onStarting (ToxWindow *self, ToxAv *av, int call_index) init_infobox(self); 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) @@ -480,6 +502,11 @@ void chat_onEnding (ToxWindow *self, ToxAv *av, int call_index) kill_infobox(self); self->call_idx = -1; 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) @@ -489,6 +516,11 @@ void chat_onError (ToxWindow *self, ToxAv *av, int call_index) self->call_idx = -1; 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) @@ -499,6 +531,11 @@ void chat_onStart (ToxWindow *self, ToxAv *av, int call_index) init_infobox(self); 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) @@ -509,6 +546,11 @@ void chat_onCancel (ToxWindow *self, ToxAv *av, int call_index) kill_infobox(self); self->call_idx = -1; 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) @@ -518,6 +560,11 @@ void chat_onReject (ToxWindow *self, ToxAv *av, int call_index) self->call_idx = -1; 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) @@ -528,6 +575,11 @@ void chat_onEnd (ToxWindow *self, ToxAv *av, int call_index) kill_infobox(self); self->call_idx = -1; 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) @@ -537,6 +589,11 @@ void chat_onRequestTimeout (ToxWindow *self, ToxAv *av, int call_index) self->call_idx = -1; 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) @@ -547,6 +604,11 @@ void chat_onPeerTimeout (ToxWindow *self, ToxAv *av, int call_index) kill_infobox(self); self->call_idx = -1; 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 */ } static void init_infobox(ToxWindow *self) @@ -631,7 +693,7 @@ static void draw_infobox(ToxWindow *self) wrefresh(infobox->win); } -#endif /* _SUPPORT_AUDIO */ +#endif /* _AUDIO */ static void send_action(ToxWindow *self, ChatContext *ctx, Tox *m, char *action) { @@ -702,7 +764,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) ctx->start = wlen < x2 ? 0 : wlen - x2 + 1; } } else { - beep(); + notify(self, error, 0); } } else if (key == '\n') { @@ -860,7 +922,7 @@ static void chat_onDraw(ToxWindow *self, Tox *m) wrefresh(self->window); -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO if (ctx->infobox.active) { draw_infobox(self); wrefresh(self->window); @@ -942,7 +1004,7 @@ ToxWindow new_chat(Tox *m, int32_t friendnum) ret.onFileControl = &chat_onFileControl; ret.onFileData = &chat_onFileData; -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO ret.onInvite = &chat_onInvite; ret.onRinging = &chat_onRinging; ret.onStarting = &chat_onStarting; @@ -957,8 +1019,12 @@ ToxWindow new_chat(Tox *m, int32_t friendnum) ret.call_idx = -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]; int n_len = get_nick_truncate(m, nick, friendnum); chat_set_window_name(&ret, nick, n_len); diff --git a/src/chat_commands.h b/src/chat_commands.h index 4b8ffc2..3220545 100644 --- a/src/chat_commands.h +++ b/src/chat_commands.h @@ -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_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_answer(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_mute(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_sense(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); -#endif /* _SUPPORT_AUDIO */ +#endif /* _AUDIO */ #endif /* #define _chat_commands_h */ diff --git a/src/device.c b/src/device.c index 9f466b1..54b4174 100644 --- a/src/device.c +++ b/src/device.c @@ -66,7 +66,9 @@ static int size[2]; /* Size of above containers */ Device *running[2][MAX_DEVICES]; /* Running devices */ uint32_t primary_device[2]; /* Primary device */ +#ifdef _AUDIO static ToxAv* av = NULL; +#endif /* _AUDIO */ /* q_mutex */ #define lock pthread_mutex_lock(&mutex) @@ -79,7 +81,11 @@ _Bool thread_running = _True, void* thread_poll(void*); /* Meet devices */ +#ifdef _AUDIO DeviceError init_devices(ToxAv* av_) +#else +DeviceError init_devices() +#endif /* _AUDIO */ { const char *stringed_device_list; @@ -115,7 +121,9 @@ DeviceError init_devices(ToxAv* av_) if ( pthread_create(&thread_id, NULL, thread_poll, NULL) != 0 || pthread_detach(thread_id) != 0) return de_InternalError; +#ifdef _AUDIO av = av_; +#endif /* _AUDIO */ return (DeviceError) ae_None; } @@ -391,8 +399,11 @@ void* thread_poll (void* arg) // TODO: maybe use thread for every input source int16_t frame[4096]; alcCaptureSamples(device->dhndl, frame, f_size); - if ( device->muted || - (device->enable_VAD && !toxav_has_activity(av, device->call_idx, frame, f_size, device->VAD_treshold))) + if ( device->muted + #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 */ if ( device->cb ) device->cb(frame, f_size, device->cb_data); diff --git a/src/device.h b/src/device.h index 6b368a5..dfda7e3 100644 --- a/src/device.h +++ b/src/device.h @@ -56,7 +56,12 @@ typedef enum DeviceError { typedef void (*DataHandleCallback) (const int16_t*, uint32_t size, void* data); +#ifdef _AUDIO DeviceError init_devices(ToxAv* av); +#else +DeviceError init_devices(); +#endif /* _AUDIO */ + DeviceError terminate_devices(); /* Callback handles ready data from INPUT device */ diff --git a/src/execute.c b/src/execute.c index 457b71f..c35dd24 100644 --- a/src/execute.c +++ b/src/execute.c @@ -31,6 +31,7 @@ #include "global_commands.h" #include "line_info.h" #include "misc_tools.h" +#include "notify.h" struct cmd_func { const char *name; @@ -53,10 +54,10 @@ static struct cmd_func global_commands[] = { { "/quit", cmd_quit }, { "/status", cmd_status }, -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO { "/lsdev", cmd_list_devices }, { "/sdev", cmd_change_device }, -#endif /* _SUPPORT_AUDIO */ +#endif /* _AUDIO */ }; static struct cmd_func chat_commands[] = { @@ -65,7 +66,7 @@ static struct cmd_func chat_commands[] = { { "/savefile", cmd_savefile }, { "/sendfile", cmd_sendfile }, -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO { "/call", cmd_call }, { "/cancel", cmd_cancel }, { "/answer", cmd_answer }, @@ -74,7 +75,7 @@ static struct cmd_func chat_commands[] = { { "/sdev", cmd_ccur_device }, { "/mute", cmd_mute }, { "/sense", cmd_sense }, -#endif /* _SUPPORT_AUDIO */ +#endif /* _AUDIO */ }; /* Parses input command and puts args into arg array. @@ -165,5 +166,7 @@ void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode) if (do_command(w, self, m, num_args, GLOBAL_NUM_COMMANDS, global_commands, args) == 0) 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); } diff --git a/src/execute.h b/src/execute.h index d604e19..9b704bc 100644 --- a/src/execute.h +++ b/src/execute.h @@ -28,13 +28,13 @@ #define MAX_NUM_ARGS 4 /* Includes command */ -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO #define GLOBAL_NUM_COMMANDS 16 #define CHAT_NUM_COMMANDS 12 #else #define GLOBAL_NUM_COMMANDS 14 #define CHAT_NUM_COMMANDS 4 -#endif /* _SUPPORT_AUDIO */ +#endif /* _AUDIO */ enum { GLOBAL_COMMAND_MODE, diff --git a/src/file_senders.c b/src/file_senders.c index 5ffad2f..34e7d14 100644 --- a/src/file_senders.c +++ b/src/file_senders.c @@ -30,6 +30,7 @@ #include "file_senders.h" #include "line_info.h" #include "misc_tools.h" +#include "notify.h" FileSender file_senders[MAX_FILES]; 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) { - if (self->chatwin != NULL) { + if (self->chatwin != NULL) 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); 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)) { snprintf(msg, sizeof(msg), "File transfer for '%s' timed out.", pathname); close_file_sender(self, m, i, msg, TOX_FILECONTROL_KILL, filenum, friendnum); + notify(self, error, NT_NOFOCUS | NT_WNDALERT_2); continue; } @@ -122,6 +123,7 @@ void do_file_senders(Tox *m) if (file_senders[i].piecelen == 0) { snprintf(msg, sizeof(msg), "File '%s' successfuly sent.", pathname); close_file_sender(self, m, i, msg, TOX_FILECONTROL_FINISHED, filenum, friendnum); + notify(self, transfer_completed, NT_NOFOCUS | NT_WNDALERT_2); break; } } diff --git a/src/friendlist.c b/src/friendlist.c index 9aad1e6..0e0fe58 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -34,11 +34,13 @@ #include "misc_tools.h" #include "line_info.h" #include "settings.h" +#include "notify.h" -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO #include "audio_call.h" #endif + extern char *DATA_FILE; extern ToxWindow *prompt; @@ -47,7 +49,7 @@ static int num_selected = 0; static int num_friends = 0; extern struct _Winthread Winthread; -extern struct user_settings *user_settings; +extern struct user_settings *user_settings_; ToxicFriend friends[MAX_FRIENDS_NUM]; 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); /* 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, &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 (get_num_active_windows() < MAX_WINDOWS_NUM) { friends[num].chatwin = add_window(m, new_chat(m, friends[num].num)); + notify(self, generic_message, NT_NOFOCUS); } else { char nick[TOX_MAX_NAME_LENGTH]; 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."; 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); } } } @@ -126,6 +129,7 @@ static void friendlist_onConnectionChange(ToxWindow *self, Tox *m, int32_t num, return; friends[num].online = status; + notify(self, status==1 ? user_log_in : user_log_out, NT_RESTOL | NT_NOTIFWND ); update_friend_last_online(num, get_unix_time()); store_data(m, DATA_FILE); sort_friendlist_index(); @@ -176,7 +180,7 @@ void friendlist_onFriendAdded(ToxWindow *self, Tox *m, int32_t num, bool sort) friends[i].chatwin = -1; friends[i].online = false; 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); update_friend_last_online(i, tox_get_last_online(m, i)); @@ -213,6 +217,7 @@ static void friendlist_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, u if (friends[num].chatwin == -1) { if (get_num_active_windows() < MAX_WINDOWS_NUM) { friends[num].chatwin = add_window(m, new_chat(m, friends[num].num)); + notify(self, transfer_pending, NT_NOFOCUS); } else { tox_file_send_control(m, num, 1, filenum, TOX_FILECONTROL_KILL, 0, 0); @@ -222,8 +227,8 @@ static void friendlist_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, u char msg[MAX_STR_SIZE]; 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); - - alert_window(prompt, WINDOW_ALERT_1, true); + + notify(prompt, error, NT_WNDALERT_1); } } } @@ -236,6 +241,8 @@ static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, const if (friends[num].chatwin == -1) { if (get_num_active_windows() < MAX_WINDOWS_NUM) { friends[num].chatwin = add_window(m, new_chat(m, friends[num].num)); + notify(self, generic_message, NT_NOFOCUS); + } else { char nick[TOX_MAX_NAME_LENGTH]; get_nick_truncate(m, nick, num); @@ -243,8 +250,8 @@ static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, const char msg[MAX_STR_SIZE]; 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); - - alert_window(prompt, WINDOW_ALERT_1, true); + + notify(prompt, error, NT_WNDALERT_1); } } } @@ -348,7 +355,7 @@ static void friendlist_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) char *msg = "* Warning: Too many windows are open."; 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) { del_friend_activate(self, m, f); @@ -545,7 +552,7 @@ void disable_chatwin(int32_t f_num) friends[f_num].chatwin = -1; } -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO static void friendlist_onAv(ToxWindow *self, ToxAv *av, int call_index) { int id = toxav_get_peer_id(av, call_index, 0); @@ -558,8 +565,9 @@ static void friendlist_onAv(ToxWindow *self, ToxAv *av, int call_index) if (friends[id].chatwin == -1) { 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)); + } } else { char nick[TOX_MAX_NAME_LENGTH]; get_nick_truncate(m, nick, friends[id].num); @@ -570,12 +578,12 @@ static void friendlist_onAv(ToxWindow *self, ToxAv *av, int call_index) char *errmsg = "* Warning: Too many windows are open."; 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) { @@ -597,7 +605,7 @@ ToxWindow new_friendlist(void) ret.onFileSendRequest = &friendlist_onFileSendRequest; ret.onGroupInvite = &friendlist_onGroupInvite; -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO ret.onInvite = &friendlist_onAv; ret.onRinging = &friendlist_onAv; ret.onStarting = &friendlist_onAv; @@ -612,8 +620,12 @@ ToxWindow new_friendlist(void) ret.call_idx = -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"); return ret; } diff --git a/src/global_commands.h b/src/global_commands.h index e0e88ba..89f10bc 100644 --- a/src/global_commands.h +++ b/src/global_commands.h @@ -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); -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO void cmd_list_devices(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_change_device(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); -#endif /* _SUPPORT_AUDIO */ +#endif /* _AUDIO */ #endif /* #define _global_commands_h */ diff --git a/src/groupchat.c b/src/groupchat.c index 5fc8f6b..a7b11db 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -41,6 +41,7 @@ #include "settings.h" #include "input.h" #include "help.h" +#include "notify.h" #include "autocomplete.h" extern char *DATA_FILE; @@ -48,7 +49,7 @@ extern char *DATA_FILE; static GroupChat groupchats[MAX_GROUPCHAT_NUM]; static int max_groupchat_index = 0; -extern struct user_settings *user_settings; +extern struct user_settings *user_settings_; /* temporary until group chats have unique commands */ extern const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE]; @@ -135,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 */ 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]; uint16_t sn_len = tox_get_self_name(m, (uint8_t *) selfnick); selfnick[sn_len] = '\0'; int nick_clr = strcmp(nick, selfnick) == 0 ? GREEN : CYAN; - bool nick_match = strcasestr(msg, selfnick) && strncmp(selfnick, nick, TOXIC_MAX_NAME_LENGTH - 1); - - if (nick_match) { - alert_type = WINDOW_ALERT_0; - beep = true; + /* Only play sound if mentioned */ + if (strcasestr(msg, selfnick) && strncmp(selfnick, nick, TOXIC_MAX_NAME_LENGTH - 1)) { + notify(self, generic_message, NT_WNDALERT_0); nick_clr = RED; } - - alert_window(self, alert_type, beep); + else notify(self, silent, NT_WNDALERT_1); char timefrmt[TIME_STR_SIZE]; get_time_str(timefrmt, sizeof(timefrmt)); @@ -170,22 +164,14 @@ static void groupchat_onGroupAction(ToxWindow *self, Tox *m, int groupnum, int p 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]; uint16_t n_len = tox_get_self_name(m, (uint8_t *) selfnick); selfnick[n_len] = '\0'; - const char *nick_match = strcasestr(action, selfnick); - - if (nick_match) { - alert_type = WINDOW_ALERT_0; - beep = true; + if (strcasestr(action, selfnick)) { + notify(self, generic_message, NT_WNDALERT_0); } - - alert_window(self, alert_type, beep); + else notify(self, silent, NT_WNDALERT_1); char nick[TOX_MAX_NAME_LENGTH]; n_len = tox_group_peername(m, groupnum, peernum, (uint8_t *) nick); @@ -318,7 +304,7 @@ static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnu 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) @@ -501,7 +487,7 @@ static void groupchat_onInit(ToxWindow *self, Tox *m) line_info_init(ctx->hst); - if (user_settings->autolog == AUTOLOG_ON) + if (user_settings_->autolog == AUTOLOG_ON) log_enable(self->name, NULL, ctx->log); execute(ctx->history, self, m, "/log", GLOBAL_COMMAND_MODE); diff --git a/src/help.c b/src/help.c index cec76f7..cbfdae3 100644 --- a/src/help.c +++ b/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, " /quit or /exit : Exit Toxic\n"); -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO wattron(win, A_BOLD); wprintw(win, "\n Audio:\n"); wattroff(win, A_BOLD); wprintw(win, " /lsdev : List devices where type: in|out\n"); wprintw(win, " /sdev : Set active device\n"); -#endif /* _SUPPORT_AUDIO */ +#endif /* _AUDIO */ help_draw_bottom_menu(win); @@ -174,7 +174,7 @@ static void help_draw_chat(ToxWindow *self) wprintw(win, " /sendfile : Send a file\n"); wprintw(win, " /savefile : Receive a file\n"); -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO wattron(win, A_BOLD); wprintw(win, "\n Audio:\n"); wattroff(win, A_BOLD); @@ -187,7 +187,7 @@ static void help_draw_chat(ToxWindow *self) wprintw(win, " /sdev : Change active device\n"); wprintw(win, " /mute : Mute active device if in call\n"); wprintw(win, " /sense : VAD sensitivity treshold\n"); -#endif /* _SUPPORT_AUDIO */ +#endif /* _AUDIO */ help_draw_bottom_menu(win); @@ -226,7 +226,7 @@ void help_onKey(ToxWindow *self, wint_t key) break; case 'c': -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO help_init_window(self, 19, 80); #else help_init_window(self, 9, 80); @@ -235,7 +235,7 @@ void help_onKey(ToxWindow *self, wint_t key) break; case 'g': -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO help_init_window(self, 21, 80); #else help_init_window(self, 17, 80); diff --git a/src/line_info.c b/src/line_info.c index 4e7fb40..1ddc824 100644 --- a/src/line_info.c +++ b/src/line_info.c @@ -30,7 +30,7 @@ #include "groupchat.h" #include "settings.h" -extern struct user_settings *user_settings; +extern struct user_settings *user_settings_; void line_info_init(struct history *hst) { @@ -207,7 +207,7 @@ static void line_info_check_queue(ToxWindow *self) if (line == NULL) return; - if (hst->start_id > user_settings->history_size) + if (hst->start_id > user_settings_->history_size) line_info_root_fwd(hst); line->id = hst->line_end->id + 1; diff --git a/src/log.c b/src/log.c index 251c39c..cc5838e 100644 --- a/src/log.c +++ b/src/log.c @@ -31,7 +31,7 @@ #include "log.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 */ 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 snprintf(name_frmt, sizeof(name_frmt), "%s:", name); - const char *t = user_settings->time == TIME_12 ? "%Y/%m/%d [%I:%M:%S %p]" : "%Y/%m/%d [%H:%M:%S]"; + const char *t = user_settings_->time == TIME_12 ? "%Y/%m/%d [%I:%M:%S %p]" : "%Y/%m/%d [%H:%M:%S]"; char s[MAX_STR_SIZE]; strftime(s, MAX_STR_SIZE, t, get_time()); fprintf(log->file, "%s %s %s\n", s, name_frmt, msg); diff --git a/src/misc_tools.c b/src/misc_tools.c index 2090e87..9d31c61 100644 --- a/src/misc_tools.c +++ b/src/misc_tools.c @@ -33,7 +33,7 @@ #include "settings.h" extern ToxWindow *prompt; -extern struct user_settings *user_settings; +extern struct user_settings *user_settings_; static uint64_t current_unix_time; @@ -65,12 +65,12 @@ struct tm *get_time(void) /*Puts the current time in buf in the format of [HH:mm:ss] */ void get_time_str(char *buf, int bufsize) { - if (user_settings->timestamps == TIMESTAMPS_OFF) { + if (user_settings_->timestamps == TIMESTAMPS_OFF) { buf[0] = '\0'; return; } - const char *t = user_settings->time == TIME_12 ? "[%-I:%M:%S] " : "[%H:%M:%S] "; + const char *t = user_settings_->time == TIME_12 ? "[%-I:%M:%S] " : "[%H:%M:%S] "; strftime(buf, bufsize, t, get_time()); } @@ -142,29 +142,6 @@ int wcs_to_mbs_buf(char *buf, const wchar_t *string, size_t n) 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 */ int qsort_strcasecmp_hlpr(const void *nick1, const void *nick2) { @@ -268,4 +245,4 @@ int char_rfind(const char *s, char ch, int len) } return i; -} +} \ No newline at end of file diff --git a/src/notify.c b/src/notify.c new file mode 100644 index 0000000..0f98fe1 --- /dev/null +++ b/src/notify.c @@ -0,0 +1,333 @@ +/* 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 . + * + */ + +#include "notify.h" +#include "device.h" +#include "settings.h" + +#include +#include +#include +#include +#include + +#ifdef __APPLE__ + #include + #include + #ifdef _SOUND_NOTIFY + #include /* Is this good? */ + #endif +#else + #include + #include + #ifdef _SOUND_NOTIFY + #include /* freealut packet */ + #endif +#endif + +#ifdef _X11 + #include +#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); + } +} + + +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 + if (open_primary_device(output, &Control.device_idx) != 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); +#endif /* _SOUND_NOTIFY */ +} + +#ifdef _SOUND_NOTIFY +void 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); +} + +int play_sound_internal(Notification what, _Bool loop) +{ + char* data; + int format; + int clockrate; + int buffer_size; + char loop_; + uint32_t source; + uint32_t buffer; + + alutLoadWAVFile(Control.sounds[what], &format, (void**)&data, &buffer_size, &clockrate, &loop_); + alGenSources(1, &source); + alGenBuffers(1, &buffer); + alBufferData(buffer, format, data, buffer_size, clockrate); + alSourcei(source, AL_BUFFER, buffer); + alSourcei(source, AL_LOOPING, loop); + alutUnloadWAV(format, data, buffer_size, clockrate); + + 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 + 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; +} \ No newline at end of file diff --git a/src/notify.h b/src/notify.h new file mode 100644 index 0000000..1a3089c --- /dev/null +++ b/src/notify.h @@ -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 . + * + */ + +#ifndef _notify_h +#define _notify_h + +#include +#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 +void set_sound(Notification sound, const char* value); +void stop_sound(int sound); +#endif /* _SOUND_NOTIFY */ + +#endif /* _notify_h */ \ No newline at end of file diff --git a/src/prompt.c b/src/prompt.c index e986052..0fdca1b 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -39,6 +39,7 @@ #include "settings.h" #include "input.h" #include "help.h" +#include "notify.h" #include "autocomplete.h" char pending_frnd_requests[MAX_FRIENDS_NUM][TOX_CLIENT_ID_SIZE]; @@ -46,7 +47,7 @@ uint16_t num_frnd_requests = 0; extern ToxWindow *prompt; struct _Winthread Winthread; -extern struct user_settings *user_settings; +extern struct user_settings *user_settings_; /* Array of global command names used for tab completion. */ const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = { @@ -66,12 +67,12 @@ const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = { { "/quit" }, { "/status" }, -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO { "/lsdev" }, { "/sdev" }, -#endif /* _SUPPORT_AUDIO */ +#endif /* _AUDIO */ }; void kill_prompt_window(ToxWindow *self) @@ -308,11 +309,13 @@ static void prompt_onConnectionChange(ToxWindow *self, Tox *m, int32_t friendnum msg = "has come online"; line_info_add(self, timefrmt, nick, NULL, msg, CONNECTION, 0, GREEN); write_to_log(msg, nick, ctx->log, true); - alert_window(self, WINDOW_ALERT_2, false); + notify(self, user_log_in, NT_WNDALERT_2 | NT_NOTIFWND | NT_RESTOL); + } else { msg = "has gone offline"; line_info_add(self, timefrmt, nick, NULL, msg, CONNECTION, 0, RED); write_to_log(msg, nick, ctx->log, true); + notify(self, user_log_out, NT_WNDALERT_2 | NT_NOTIFWND | NT_RESTOL); } } @@ -340,7 +343,7 @@ static void prompt_onFriendRequest(ToxWindow *self, Tox *m, const char *key, con snprintf(msg, sizeof(msg), "Type \"/accept %d\" to accept it.", n); 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) @@ -419,7 +422,7 @@ static void prompt_onInit(ToxWindow *self, Tox *m) line_info_init(ctx->hst); - if (user_settings->autolog == AUTOLOG_ON) { + if (user_settings_->autolog == AUTOLOG_ON) { char myid[TOX_FRIEND_ADDRESS_SIZE]; tox_get_address(m, (uint8_t *) myid); log_enable(self->name, myid, ctx->log); diff --git a/src/prompt.h b/src/prompt.h index 93de1e5..b2b3620 100644 --- a/src/prompt.h +++ b/src/prompt.h @@ -26,11 +26,11 @@ #include "toxic.h" #include "windows.h" -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO #define AC_NUM_GLOB_COMMANDS 17 #else #define AC_NUM_GLOB_COMMANDS 15 -#endif /* _SUPPORT_AUDIO */ +#endif /* _AUDIO */ ToxWindow new_prompt(void); void prep_prompt_win(void); diff --git a/src/settings.c b/src/settings.c index bf71bae..11e7897 100644 --- a/src/settings.c +++ b/src/settings.c @@ -22,207 +22,194 @@ #include #include +#include #include "toxic.h" #include "windows.h" #include "configdir.h" +#include "notify.h" -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO #include "device.h" -#endif /* _SUPPORT_AUDIO */ +#endif /* _AUDIO */ #include "settings.h" #include "line_info.h" -static void uset_autolog(struct user_settings *s, const char *val); -static void uset_time(struct user_settings *s, const char *val); -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); +const struct _ui_strings { + const char* self; + const char* timestamps; + 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; +} -#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 - -struct { - 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 - { "audio_in_dev", uset_ain_dev }, - { "audio_out_dev", uset_aout_dev }, -#endif +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); - - /* default off if invalid value */ - s->autolog = n == AUTOLOG_ON ? AUTOLOG_ON : AUTOLOG_OFF; + /*settings->download_path;*/ /* TODO: Set this? */ } -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); - - /* default to 24 hour time if invalid value */ - s->time = n == TIME_12 ? TIME_12 : TIME_24; + settings->audio_in_dev = 0; + settings->audio_out_dev = 0; + settings->VAD_treshold = 40.0; } - -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 -} + +#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, char *path) { - char *user_config_dir = get_user_config_dir(); - FILE *fp = NULL; - 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); - - set_default_settings(s); - - if (fp == NULL && !path) { - if ((fp = fopen(dflt_path, "w")) == NULL) - return -1; - } else if (fp == NULL && path) { + 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); + + if(!config_read_file(cfg, path)) + { + config_destroy(cfg); 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; - } + + /* 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) ) { + s->download_path = calloc(1, strlen(str) + 1); + 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 - fclose(fp); +#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 ( config_setting_lookup_string(setting, sound_strings.user_log_in, &str) ) + set_sound(user_log_in, str); + + if ( config_setting_lookup_string(setting, sound_strings.self_log_in, &str) ) + set_sound(self_log_in, str); + + if ( config_setting_lookup_string(setting, sound_strings.user_log_out, &str) ) + set_sound(user_log_out, str); + + if ( config_setting_lookup_string(setting, sound_strings.self_log_out, &str) ) + set_sound(self_log_out, str); + + if ( config_setting_lookup_string(setting, sound_strings.call_incoming, &str) ) + set_sound(call_incoming, str); + + if ( config_setting_lookup_string(setting, sound_strings.call_outgoing, &str) ) + set_sound(call_outgoing, str); + + if ( config_setting_lookup_string(setting, sound_strings.generic_message, &str) ) + set_sound(generic_message, str); + + if ( config_setting_lookup_string(setting, sound_strings.transfer_pending, &str) ) + set_sound(transfer_pending, str); + + if ( config_setting_lookup_string(setting, sound_strings.transfer_completed, &str) ) + set_sound(transfer_completed, str); + } +#endif + + config_destroy(cfg); return 0; -} +} \ No newline at end of file diff --git a/src/settings.h b/src/settings.h index 64bb099..cd5243e 100644 --- a/src/settings.h +++ b/src/settings.h @@ -23,14 +23,6 @@ #ifndef _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 */ struct user_settings { int autolog; /* boolean */ @@ -39,11 +31,12 @@ struct user_settings { int timestamps; /* boolean */ int colour_theme; /* boolean (0 for default toxic colours) */ int history_size; /* int between MIN_HISTORY and MAX_HISTORY */ - char download_path[MAX_STR_SIZE]; + char* download_path; -#ifdef _SUPPORT_AUDIO - long int audio_in_dev; - long int audio_out_dev; +#ifdef _AUDIO + int audio_in_dev; + int audio_out_dev; + double VAD_treshold; #endif }; diff --git a/src/toxic.c b/src/toxic.c index e782128..269e68f 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -50,18 +50,20 @@ #include "line_info.h" #include "settings.h" #include "log.h" +#include "notify.h" +#include "device.h" -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO #include "audio_call.h" -#endif /* _SUPPORT_AUDIO */ +#endif /* _AUDIO */ #ifndef PACKAGE_DATADIR #define PACKAGE_DATADIR "." #endif -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO ToxAv *av; -#endif /* _SUPPORT_AUDIO */ +#endif /* _AUDIO */ /* Export for use in Callbacks */ char *DATA_FILE = NULL; @@ -78,7 +80,7 @@ struct arg_opts { } arg_opts; struct _Winthread Winthread; -struct user_settings *user_settings = NULL; +struct user_settings *user_settings_ = NULL; static void catch_SIGINT(int sig) { @@ -97,11 +99,13 @@ void exit_toxic_success(Tox *m) kill_all_windows(); free(DATA_FILE); - free(user_settings); + free(user_settings_); -#ifdef _SUPPORT_AUDIO + notify(NULL, self_log_out, NT_ALWAYS); + terminate_notify(); +#ifdef _AUDIO terminate_audio(); -#endif /* _SUPPORT_AUDIO */ +#endif /* _AUDIO */ tox_kill(m); endwin(); exit(EXIT_SUCCESS); @@ -141,7 +145,7 @@ static void init_term(void) short bg_color = COLOR_BLACK; start_color(); - if (user_settings->colour_theme == NATIVE_COLS) { + if (user_settings_->colour_theme == NATIVE_COLS) { if (assume_default_colors(-1, -1) == OK) bg_color = -1; } @@ -564,7 +568,7 @@ int main(int argc, char *argv[]) /* Make sure all written files are read/writeable only by the current user. */ umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); - signal(SIGINT, catch_SIGINT); +// signal(SIGINT, catch_SIGINT); config_err = create_user_config_dir(user_config_dir); @@ -589,15 +593,13 @@ int main(int argc, char *argv[]) free(user_config_dir); /* 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); - memset(user_settings, 0, sizeof(struct user_settings)); - 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); init_term(); @@ -619,16 +621,21 @@ int main(int argc, char *argv[]) char *msg; -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO av = init_audio(prompt, m); - set_primary_device(input, user_settings->audio_in_dev); - set_primary_device(output, user_settings->audio_out_dev); + set_primary_device(input, user_settings_->audio_in_dev); + set_primary_device(output, user_settings_->audio_out_dev); +#elif _SOUND_NOTIFY + if ( init_devices() == de_InternalError ) + line_info_add(prompt, NULL, NULL, NULL, "Failed to init devices", SYS_MSG, 0, 0); +#endif /* _AUDIO */ + + init_notify(60); + notify(prompt, self_log_in, 0); -#endif /* _SUPPORT_AUDIO */ - if (config_err) { msg = "Unable to determine configuration directory. Defaulting to 'data' for a keyfile..."; line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, 0); diff --git a/src/windows.c b/src/windows.c index 1880e1a..37c3e3d 100644 --- a/src/windows.c +++ b/src/windows.c @@ -355,12 +355,12 @@ void on_window_resize(void) w->stb->topline = subwin(w->window, 2, x2, 0, 0); } -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO if (w->chatwin->infobox.active) { delwin(w->chatwin->infobox.win); w->chatwin->infobox.win = newwin(INFOBOX_HEIGHT, INFOBOX_WIDTH + 1, 1, x2 - INFOBOX_WIDTH); } -#endif /* _SUPPORT_AUDIO */ +#endif /* _AUDIO */ scrollok(w->chatwin->history, 0); } @@ -368,23 +368,11 @@ void on_window_resize(void) static void draw_window_tab(ToxWindow toxwin) { - /* alert0 takes priority */ - if (toxwin.alert0) - attron(COLOR_PAIR(GREEN)); - else if (toxwin.alert1) - attron(COLOR_PAIR(RED)); - else if (toxwin.alert2) - attron(COLOR_PAIR(MAGENTA)); - + if (toxwin.alert) attron(COLOR_PAIR(toxwin.alert)); clrtoeol(); printw(" [%s]", toxwin.name); - if (toxwin.alert0) - attroff(COLOR_PAIR(GREEN)); - else if (toxwin.alert1) - attroff(COLOR_PAIR(RED)); - else if (toxwin.alert2) - attroff(COLOR_PAIR(MAGENTA)); + if (toxwin.alert) attroff(COLOR_PAIR(toxwin.alert)); } static void draw_bar(void) @@ -432,9 +420,7 @@ static void draw_bar(void) void draw_active_window(Tox *m) { ToxWindow *a = active_window; - a->alert0 = false; - a->alert1 = false; - a->alert2 = false; + a->alert = WINDOW_ALERT_NONE; wint_t ch = 0; diff --git a/src/windows.h b/src/windows.h index 2fa993a..d56fa43 100644 --- a/src/windows.h +++ b/src/windows.h @@ -29,9 +29,9 @@ #include -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO #include -#endif /* _SUPPORT_AUDIO */ +#endif /* _AUDIO */ #include "toxic.h" @@ -53,10 +53,11 @@ enum { } C_COLOURS; /* tab alert types: lower types take priority */ -enum { - WINDOW_ALERT_0, - WINDOW_ALERT_1, - WINDOW_ALERT_2, +typedef enum { + WINDOW_ALERT_NONE = 0, + WINDOW_ALERT_0 = GREEN, + WINDOW_ALERT_1 = RED, + WINDOW_ALERT_2 = MAGENTA, } WINDOW_ALERTS; /* 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(*onTypingChange)(ToxWindow *, Tox *, int32_t, uint8_t); -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO void(*onInvite)(ToxWindow *, ToxAv *, int); void(*onRinging)(ToxWindow *, ToxAv *, int); @@ -115,7 +116,11 @@ struct ToxWindow { * Don't modify outside av callbacks. */ 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]; int32_t num; /* corresponds to friendnumber in chat windows */ @@ -127,9 +132,7 @@ struct ToxWindow { bool is_prompt; bool is_friendlist; - bool alert0; - bool alert1; - bool alert2; + WINDOW_ALERTS alert; ChatContext *chatwin; StatusBar *stb; @@ -149,7 +152,7 @@ struct StatusBar { bool is_online; }; -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO #define INFOBOX_HEIGHT 7 @@ -168,7 +171,7 @@ struct infobox { WINDOW *win; }; -#endif /* _SUPPORT_AUDIO */ +#endif /* _AUDIO */ #define MAX_LINE_HIST 128 @@ -189,7 +192,7 @@ struct ChatContext { struct history *hst; struct chatlog *log; -#ifdef _SUPPORT_AUDIO +#ifdef _AUDIO struct infobox infobox; #endif