Skip to content

Commit f6d679a

Browse files
committed
feat: Make notify device cooldown configurable and cleanup constants.
- Add `device_cooldown` option to `Client_Config`, defaulting to 5 seconds. - Load `device_cooldown` from configuration file. - Replace hardcoded `sleep_thread` durations in `src/notify.c` with named constants.
1 parent 0b9ed3b commit f6d679a

File tree

7 files changed

+105
-117
lines changed

7 files changed

+105
-117
lines changed

doc/toxic.conf.5.asc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ OPTIONS
108108
*notification_timeout*;;
109109
Time in milliseconds to display a notification. Integer value. (for example: 3000)
110110

111+
*device_cooldown*;;
112+
Time in seconds to keep the audio device open after playing a notification sound. Integer value. (default: 5)
113+
111114
*line_join*;;
112115
Indicator for when someone connects or joins a group.
113116
Three characters max for line_ settings.

misc/toxic.conf.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ ui = {
8585
// time in milliseconds to display a notification
8686
notification_timeout=6000;
8787

88+
// time in seconds to keep the audio device open after playing a notification sound
89+
device_cooldown=5;
90+
8891
// true to pad every wrapped line of a message with enough spaces to
8992
// align it to the beginning of the first line
9093
line_padding=true;

src/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1449,7 +1449,7 @@ int main(int argc, char **argv)
14491449

14501450
#endif /* PYTHON */
14511451

1452-
init_notify(60, c_config->notification_timeout);
1452+
init_notify(60, c_config->notification_timeout, c_config->device_cooldown);
14531453

14541454
/* screen/tmux auto-away timer */
14551455
if (init_mplex_away_timer(toxic) == -1) {

src/notify.c

Lines changed: 92 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ static_assert(sizeof(CONTENT_HIDDEN_MESSAGE) < MAX_BOX_MSG_LEN,
6262
static struct Control {
6363
time_t cooldown;
6464
time_t notif_timeout;
65+
int device_cooldown;
6566

6667
#if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY)
6768
pthread_mutex_t poll_mutex[1];
@@ -159,16 +160,17 @@ static void control_unlock(void)
159160
}
160161

161162
#ifdef SOUND_NOTIFY
163+
#define SLEEP_1_MS 1000L
164+
#define SLEEP_100_MS 100000L
165+
162166
static bool is_playing(int source)
163167
{
164168
int ready;
165169
alGetSourcei(source, AL_SOURCE_STATE, &ready);
166170
return ready == AL_PLAYING;
167171
}
168172

169-
/* TODO maybe find better way to do this */
170173
/* cooldown is in seconds */
171-
#define DEVICE_COOLDOWN 5 /* TODO perhaps load this from config? */
172174
static bool device_opened = false;
173175
static time_t last_opened_update = 0;
174176

@@ -246,7 +248,7 @@ static void graceful_clear(void)
246248
return;
247249
}
248250

249-
sleep_thread(1000L);
251+
sleep_thread(SLEEP_1_MS);
250252
}
251253

252254
control_unlock();
@@ -315,16 +317,16 @@ static void *do_playing(void *_p)
315317
#endif /* BOX_NOTIFY */
316318
}
317319

318-
/* device is opened and no activity in under DEVICE_COOLDOWN time, close device*/
320+
/* device is opened and no activity in under device_cooldown time, close device*/
319321
if (device_opened && !has_looping &&
320-
(time(NULL) - last_opened_update) > DEVICE_COOLDOWN) {
322+
(time(NULL) - last_opened_update) > Control.device_cooldown) {
321323
m_close_device();
322324
}
323325

324326
has_looping = false;
325327

326328
control_unlock();
327-
sleep_thread(100000L);
329+
sleep_thread(SLEEP_100_MS);
328330
}
329331

330332
pthread_exit(NULL);
@@ -351,6 +353,8 @@ static int play_source(uint32_t source, uint32_t buffer, bool looping)
351353
}
352354

353355
#elif BOX_NOTIFY
356+
#define SLEEP_10_MS 10000L
357+
354358
static void *do_playing(void *_p)
355359
{
356360
UNUSED_VAR(_p);
@@ -372,7 +376,7 @@ static void *do_playing(void *_p)
372376
}
373377

374378
control_unlock();
375-
sleep_thread(10000L);
379+
sleep_thread(SLEEP_10_MS);
376380
}
377381

378382
pthread_exit(NULL);
@@ -431,7 +435,7 @@ void kill_notifs(int id)
431435

432436

433437
/* Opens primary device */
434-
int init_notify(int login_cooldown, int notification_timeout)
438+
int init_notify(int login_cooldown, int notification_timeout, int device_cooldown)
435439
{
436440
#ifdef SOUND_NOTIFY
437441
alutInitWithoutContext(NULL, NULL);
@@ -460,6 +464,7 @@ int init_notify(int login_cooldown, int notification_timeout)
460464
notify_init("Toxic");
461465
#endif
462466
Control.notif_timeout = notification_timeout;
467+
Control.device_cooldown = device_cooldown;
463468
return 1;
464469
}
465470

@@ -692,6 +697,69 @@ int sound_notify2(ToxWindow *self, const Toxic *toxic, Notification notif, uint6
692697
#endif /* SOUND_NOTIFY */
693698
}
694699

700+
#ifdef BOX_NOTIFY
701+
__attribute__((format(printf, 4, 0)))
702+
static void create_box_notification_internal(int id, const Client_Config *c_config,
703+
const char *title, const char *format, va_list args)
704+
{
705+
snprintf(actives[id].title, sizeof(actives[id].title), "%s", title);
706+
707+
if (strlen(title) > 23) {
708+
memcpy(actives[id].title + 20, "...", 4);
709+
}
710+
711+
if (c_config->show_notification_content) {
712+
vsnprintf(actives[id].messages[0], sizeof(actives[id].messages[0]), format, args);
713+
} else {
714+
snprintf(actives[id].messages[0], sizeof(actives[id].messages[0]), "%s", CONTENT_HIDDEN_MESSAGE);
715+
}
716+
717+
if (strlen(actives[id].messages[0]) > MAX_BOX_MSG_LEN - 3) {
718+
memcpy(actives[id].messages[0] + MAX_BOX_MSG_LEN - 3, "...", 4);
719+
}
720+
721+
actives[id].box = notify_notification_new(actives[id].title, actives[id].messages[0], NULL);
722+
actives[id].size++;
723+
actives[id].n_timeout = get_unix_time() + Control.notif_timeout / 1000;
724+
725+
notify_notification_set_timeout(actives[id].box, Control.notif_timeout);
726+
notify_notification_set_app_name(actives[id].box, "toxic");
727+
notify_notification_show(actives[id].box, NULL);
728+
}
729+
730+
__attribute__((format(printf, 3, 0)))
731+
static void update_box_notification_internal(int id, const Client_Config *c_config,
732+
const char *format, va_list args)
733+
{
734+
if (c_config->show_notification_content) {
735+
vsnprintf(actives[id].messages[actives[id].size], sizeof(actives[id].messages[actives[id].size]), format, args);
736+
} else {
737+
snprintf(actives[id].messages[actives[id].size], sizeof(actives[id].messages[actives[id].size]), "%s",
738+
CONTENT_HIDDEN_MESSAGE);
739+
}
740+
741+
if (strlen(actives[id].messages[actives[id].size]) > MAX_BOX_MSG_LEN - 3) {
742+
memcpy(actives[id].messages[actives[id].size] + MAX_BOX_MSG_LEN - 3, "...", 4);
743+
}
744+
745+
actives[id].size++;
746+
actives[id].n_timeout = get_unix_time() + Control.notif_timeout / 1000;
747+
748+
char *formatted = calloc(1, sizeof(char) * ((MAX_BOX_MSG_LEN + 1) * (MAX_BOX_MSG_LEN + 2)));
749+
750+
for (size_t i = 0; i < actives[id].size; ++i) {
751+
strcat(formatted, actives[id].messages[i]);
752+
strcat(formatted, "\n");
753+
}
754+
755+
notify_notification_update(actives[id].box, actives[id].title, formatted, NULL);
756+
notify_notification_show(actives[id].box, NULL);
757+
758+
free(formatted);
759+
}
760+
761+
#endif /* BOX_NOTIFY */
762+
695763
int box_notify(ToxWindow *self, const Toxic *toxic, Notification notif, uint64_t flags,
696764
int *id_indicator, const char *title, const char *format, ...)
697765
{
@@ -736,32 +804,10 @@ int box_notify(ToxWindow *self, const Toxic *toxic, Notification notif, uint64_t
736804

737805
#endif /* SOUND_NOTIFY */
738806

739-
snprintf(actives[id].title, sizeof(actives[id].title), "%s", title);
740-
741-
if (strlen(title) > 23) {
742-
memcpy(actives[id].title + 20, "...", 4);
743-
}
744-
745-
if (c_config->show_notification_content) {
746-
va_list __ARGS__;
747-
va_start(__ARGS__, format);
748-
vsnprintf(actives[id].messages[0], sizeof(actives[id].messages[0]), format, __ARGS__);
749-
va_end(__ARGS__);
750-
} else {
751-
snprintf(actives[id].messages[0], sizeof(actives[id].messages[0]), "%s", CONTENT_HIDDEN_MESSAGE);
752-
}
753-
754-
if (strlen(actives[id].messages[0]) > MAX_BOX_MSG_LEN - 3) {
755-
memcpy(actives[id].messages[0] + MAX_BOX_MSG_LEN - 3, "...", 4);
756-
}
757-
758-
actives[id].box = notify_notification_new(actives[id].title, actives[id].messages[0], NULL);
759-
actives[id].size++;
760-
actives[id].n_timeout = get_unix_time() + Control.notif_timeout / 1000;
761-
762-
notify_notification_set_timeout(actives[id].box, Control.notif_timeout);
763-
notify_notification_set_app_name(actives[id].box, "toxic");
764-
notify_notification_show(actives[id].box, NULL);
807+
va_list args;
808+
va_start(args, format);
809+
create_box_notification_internal(id, c_config, title, format, args);
810+
va_end(args);
765811

766812
control_unlock();
767813
return id;
@@ -793,34 +839,10 @@ int box_notify2(ToxWindow *self, const Toxic *toxic, Notification notif, uint64_
793839
return -1;
794840
}
795841

796-
if (c_config->show_notification_content) {
797-
va_list __ARGS__;
798-
va_start(__ARGS__, format);
799-
vsnprintf(actives[id].messages[actives[id].size], sizeof(actives[id].messages[actives[id].size]), format, __ARGS__);
800-
va_end(__ARGS__);
801-
} else {
802-
snprintf(actives[id].messages[actives[id].size], sizeof(actives[id].messages[actives[id].size]), "%s",
803-
CONTENT_HIDDEN_MESSAGE);
804-
}
805-
806-
if (strlen(actives[id].messages[actives[id].size]) > MAX_BOX_MSG_LEN - 3) {
807-
memcpy(actives[id].messages[actives[id].size] + MAX_BOX_MSG_LEN - 3, "...", 4);
808-
}
809-
810-
actives[id].size++;
811-
actives[id].n_timeout = get_unix_time() + Control.notif_timeout / 1000;
812-
813-
char *formatted = calloc(1, sizeof(char) * ((MAX_BOX_MSG_LEN + 1) * (MAX_BOX_MSG_LEN + 2)));
814-
815-
for (size_t i = 0; i < actives[id].size; ++i) {
816-
strcat(formatted, actives[id].messages[i]);
817-
strcat(formatted, "\n");
818-
}
819-
820-
notify_notification_update(actives[id].box, actives[id].title, formatted, NULL);
821-
notify_notification_show(actives[id].box, NULL);
822-
823-
free(formatted);
842+
va_list args;
843+
va_start(args, format);
844+
update_box_notification_internal(id, c_config, format, args);
845+
va_end(args);
824846

825847
control_unlock();
826848

@@ -859,33 +881,12 @@ int box_silent_notify(ToxWindow *self, const Toxic *toxic, uint64_t flags, int *
859881
*id_indicator = id;
860882
}
861883

862-
snprintf(actives[id].title, sizeof(actives[id].title), "%s", title);
863-
864-
if (strlen(title) > 23) {
865-
memcpy(actives[id].title + 20, "...", 4);
866-
}
867-
868-
if (c_config->show_notification_content) {
869-
va_list __ARGS__;
870-
va_start(__ARGS__, format);
871-
vsnprintf(actives[id].messages[0], sizeof(actives[id].messages[0]), format, __ARGS__);
872-
va_end(__ARGS__);
873-
} else {
874-
snprintf(actives[id].messages[0], sizeof(actives[id].messages[0]), "%s", CONTENT_HIDDEN_MESSAGE);
875-
}
876-
877-
if (strlen(actives[id].messages[0]) > MAX_BOX_MSG_LEN - 3) {
878-
memcpy(actives[id].messages[0] + MAX_BOX_MSG_LEN - 3, "...", 4);
879-
}
880-
881884
actives[id].active = 1;
882-
actives[id].box = notify_notification_new(actives[id].title, actives[id].messages[0], NULL);
883-
actives[id].size ++;
884-
actives[id].n_timeout = get_unix_time() + Control.notif_timeout / 1000;
885885

886-
notify_notification_set_timeout(actives[id].box, Control.notif_timeout);
887-
notify_notification_set_app_name(actives[id].box, "toxic");
888-
notify_notification_show(actives[id].box, NULL);
886+
va_list args;
887+
va_start(args, format);
888+
create_box_notification_internal(id, c_config, title, format, args);
889+
va_end(args);
889890

890891
control_unlock();
891892
return id;
@@ -914,34 +915,10 @@ int box_silent_notify2(ToxWindow *self, const Toxic *toxic, uint64_t flags, int
914915
return -1;
915916
}
916917

917-
if (c_config->show_notification_content) {
918-
va_list __ARGS__;
919-
va_start(__ARGS__, format);
920-
vsnprintf(actives[id].messages[actives[id].size], sizeof(actives[id].messages[actives[id].size]), format, __ARGS__);
921-
va_end(__ARGS__);
922-
} else {
923-
snprintf(actives[id].messages[actives[id].size], sizeof(actives[id].messages[actives[id].size]), "%s",
924-
CONTENT_HIDDEN_MESSAGE);
925-
}
926-
927-
if (strlen(actives[id].messages[actives[id].size]) > MAX_BOX_MSG_LEN - 3) {
928-
memcpy(actives[id].messages[actives[id].size] + MAX_BOX_MSG_LEN - 3, "...", 4);
929-
}
930-
931-
actives[id].size ++;
932-
actives[id].n_timeout = get_unix_time() + Control.notif_timeout / 1000;
933-
934-
char *formatted = calloc(1, sizeof(char) * ((MAX_BOX_MSG_LEN + 1) * (MAX_BOX_MSG_LEN + 2)));
935-
936-
for (size_t i = 0; i < actives[id].size; ++i) {
937-
strcat(formatted, actives[id].messages[i]);
938-
strcat(formatted, "\n");
939-
}
940-
941-
notify_notification_update(actives[id].box, actives[id].title, formatted, NULL);
942-
notify_notification_show(actives[id].box, NULL);
943-
944-
free(formatted);
918+
va_list args;
919+
va_start(args, format);
920+
update_box_notification_internal(id, c_config, format, args);
921+
va_end(args);
945922

946923
control_unlock();
947924

src/notify.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ typedef enum _Flags {
4747
NT_NO_INCREMENT = 1 << 9, /* Prevents notification from incrementing pending message counter in window's tab */
4848
} Flags;
4949

50-
int init_notify(int login_cooldown, int notification_timeout);
50+
int init_notify(int login_cooldown, int notification_timeout, int device_cooldown);
5151
void terminate_notify(void);
5252

5353
/* Kills all notifications for `id`. This must be called before freeing a ToxWindow. */

src/settings.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ static struct ui_strings {
6767
const char *show_network_info;
6868
const char *nodeslist_update_freq;
6969
const char *autosave_freq;
70+
const char *device_cooldown;
7071

7172
const char *line_padding;
7273
const char *line_join;
@@ -108,6 +109,7 @@ static struct ui_strings {
108109
"show_network_info",
109110
"nodeslist_update_freq",
110111
"autosave_freq",
112+
"device_cooldown",
111113
"line_padding",
112114
"line_join",
113115
"line_quit",
@@ -148,6 +150,7 @@ static void ui_defaults(Client_Config *settings)
148150
settings->show_network_info = false;
149151
settings->nodeslist_update_freq = 1;
150152
settings->autosave_freq = 600;
153+
settings->device_cooldown = 5;
151154

152155
settings->line_padding = true;
153156
snprintf(settings->line_join, sizeof(settings->line_join), "%s", LINE_JOIN);
@@ -817,6 +820,7 @@ static void settings_load_ui(config_t *cfg, Client_Config *s)
817820
config_setting_lookup_int(setting, ui_strings.notification_timeout, &s->notification_timeout);
818821
config_setting_lookup_int(setting, ui_strings.nodeslist_update_freq, &s->nodeslist_update_freq);
819822
config_setting_lookup_int(setting, ui_strings.autosave_freq, &s->autosave_freq);
823+
config_setting_lookup_int(setting, ui_strings.device_cooldown, &s->device_cooldown);
820824

821825
if (config_setting_lookup_bool(setting, ui_strings.line_padding, &bool_val)) {
822826
s->line_padding = bool_val != 0;

src/settings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ typedef struct Client_Config {
4949

5050
int history_size; /* int between MIN_HISTORY and MAX_HISTORY */
5151
int notification_timeout;
52+
int device_cooldown;
5253
int nodeslist_update_freq; /* <= 0 to disable updates */
5354
int autosave_freq; /* <= 0 to disable autosave */
5455

0 commit comments

Comments
 (0)