[BACK]Return to alerts.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Annotation of src/usr.bin/tmux/alerts.c, Revision 1.10

1.10    ! nicm        1: /* $OpenBSD: alerts.c,v 1.9 2016/01/16 00:36:53 nicm Exp $ */
1.1       nicm        2:
                      3: /*
1.10    ! nicm        4:  * Copyright (c) 2015 Nicholas Marriott <nicholas.marriott@gmail.com>
1.1       nicm        5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
                     15:  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
                     16:  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18:
                     19: #include <sys/types.h>
                     20:
                     21: #include <event.h>
                     22:
                     23: #include "tmux.h"
                     24:
                     25: int    alerts_fired;
                     26:
                     27: void   alerts_timer(int, short, void *);
                     28: int    alerts_enabled(struct window *, int);
                     29: void   alerts_callback(int, short, void *);
                     30: void   alerts_reset(struct window *);
                     31:
1.9       nicm       32: void   alerts_run_hook(struct session *, struct winlink *, int);
1.8       nicm       33: int    alerts_check_all(struct session *, struct winlink *);
1.1       nicm       34: int    alerts_check_bell(struct session *, struct winlink *);
                     35: int    alerts_check_activity(struct session *, struct winlink *);
                     36: int    alerts_check_silence(struct session *, struct winlink *);
                     37: void   alerts_ring_bell(struct session *);
                     38:
                     39: void
1.5       nicm       40: alerts_timer(__unused int fd, __unused short events, void *arg)
1.1       nicm       41: {
                     42:        struct window   *w = arg;
                     43:
                     44:        log_debug("@%u alerts timer expired", w->id);
                     45:        alerts_reset(w);
                     46:        alerts_queue(w, WINDOW_SILENCE);
                     47: }
                     48:
                     49: void
1.5       nicm       50: alerts_callback(__unused int fd, __unused short events, __unused void *arg)
1.1       nicm       51: {
                     52:        struct window   *w;
                     53:        struct session  *s;
                     54:        struct winlink  *wl;
                     55:        int              flags, alerts;
                     56:
                     57:        RB_FOREACH(w, windows, &windows) {
                     58:                RB_FOREACH(s, sessions, &sessions) {
                     59:                        RB_FOREACH(wl, winlinks, &s->windows) {
                     60:                                if (wl->window != w)
                     61:                                        continue;
                     62:                                flags = w->flags;
                     63:
1.8       nicm       64:                                alerts = alerts_check_all(s, wl);
1.1       nicm       65:
                     66:                                log_debug("%s:%d @%u alerts check, alerts %#x, "
                     67:                                    "flags %#x", s->name, wl->idx, w->id,
                     68:                                    alerts, flags);
                     69:                        }
                     70:                }
                     71:        }
                     72:        alerts_fired = 0;
                     73: }
                     74:
1.9       nicm       75: void
                     76: alerts_run_hook(struct session *s, struct winlink *wl, int flags)
                     77: {
                     78:        struct cmd_find_state    fs;
                     79:
                     80:        if (cmd_find_from_winlink(&fs, s, wl) != 0)
                     81:                return;
                     82:
                     83:        if (flags & WINDOW_BELL)
                     84:                hooks_run(s->hooks, NULL, &fs, "alert-bell");
                     85:        if (flags & WINDOW_SILENCE)
                     86:                hooks_run(s->hooks, NULL, &fs, "alert-silence");
                     87:        if (flags & WINDOW_ACTIVITY)
                     88:                hooks_run(s->hooks, NULL, &fs, "alert-activity");
                     89: }
                     90:
1.1       nicm       91: int
1.8       nicm       92: alerts_check_all(struct session *s, struct winlink *wl)
                     93: {
                     94:        int     alerts;
                     95:
                     96:        alerts  = alerts_check_bell(s, wl);
                     97:        alerts |= alerts_check_activity(s, wl);
                     98:        alerts |= alerts_check_silence(s, wl);
1.9       nicm       99:        if (alerts != 0) {
                    100:                alerts_run_hook(s, wl, alerts);
1.8       nicm      101:                server_status_session(s);
1.9       nicm      102:        }
1.8       nicm      103:
                    104:        return (alerts);
                    105: }
                    106:
                    107: void
                    108: alerts_check_session(struct session *s)
                    109: {
                    110:        struct winlink  *wl;
                    111:
                    112:        RB_FOREACH(wl, winlinks, &s->windows)
                    113:                alerts_check_all(s, wl);
                    114: }
                    115:
                    116: int
1.1       nicm      117: alerts_enabled(struct window *w, int flags)
                    118: {
1.7       nicm      119:        if (flags & WINDOW_BELL)
                    120:                return (1);
1.1       nicm      121:        if (flags & WINDOW_ACTIVITY) {
1.4       nicm      122:                if (options_get_number(w->options, "monitor-activity"))
1.1       nicm      123:                        return (1);
                    124:        }
                    125:        if (flags & WINDOW_SILENCE) {
1.4       nicm      126:                if (options_get_number(w->options, "monitor-silence") != 0)
1.1       nicm      127:                        return (1);
                    128:        }
                    129:        return (0);
                    130: }
                    131:
                    132: void
                    133: alerts_reset_all(void)
                    134: {
                    135:        struct window   *w;
                    136:
                    137:        RB_FOREACH(w, windows, &windows)
                    138:                alerts_reset(w);
                    139: }
                    140:
                    141: void
                    142: alerts_reset(struct window *w)
                    143: {
                    144:        struct timeval  tv;
                    145:
                    146:        w->flags &= ~WINDOW_SILENCE;
                    147:        event_del(&w->alerts_timer);
                    148:
                    149:        timerclear(&tv);
1.4       nicm      150:        tv.tv_sec = options_get_number(w->options, "monitor-silence");
1.1       nicm      151:
                    152:        log_debug("@%u alerts timer reset %u", w->id, (u_int)tv.tv_sec);
                    153:        if (tv.tv_sec != 0)
                    154:                event_add(&w->alerts_timer, &tv);
                    155: }
                    156:
                    157: void
                    158: alerts_queue(struct window *w, int flags)
                    159: {
1.3       nicm      160:        if (w->flags & WINDOW_ACTIVITY)
                    161:                alerts_reset(w);
                    162:
1.1       nicm      163:        if (!event_initialized(&w->alerts_timer))
                    164:                evtimer_set(&w->alerts_timer, alerts_timer, w);
                    165:
1.6       nicm      166:        if (!alerts_fired) {
                    167:                w->flags |= flags;
                    168:                log_debug("@%u alerts flags added %#x", w->id, flags);
                    169:
                    170:                if (alerts_enabled(w, flags)) {
                    171:                        log_debug("alerts check queued (by @%u)", w->id);
                    172:                        event_once(-1, EV_TIMEOUT, alerts_callback, NULL, NULL);
                    173:                        alerts_fired = 1;
                    174:                }
1.1       nicm      175:        }
                    176: }
                    177:
                    178: int
                    179: alerts_check_bell(struct session *s, struct winlink *wl)
                    180: {
                    181:        struct client   *c;
                    182:        struct window   *w = wl->window;
                    183:        int              action, visual;
                    184:
1.8       nicm      185:        if (!(w->flags & WINDOW_BELL))
1.1       nicm      186:                return (0);
1.8       nicm      187:        if (s->curw != wl) {
1.1       nicm      188:                wl->flags |= WINLINK_BELL;
1.8       nicm      189:                w->flags &= ~WINDOW_BELL;
                    190:        }
1.1       nicm      191:        if (s->curw->window == w)
                    192:                w->flags &= ~WINDOW_BELL;
                    193:
1.4       nicm      194:        action = options_get_number(s->options, "bell-action");
1.1       nicm      195:        if (action == BELL_NONE)
                    196:                return (0);
                    197:
1.4       nicm      198:        visual = options_get_number(s->options, "visual-bell");
1.1       nicm      199:        TAILQ_FOREACH(c, &clients, entry) {
                    200:                if (c->session != s || c->flags & CLIENT_CONTROL)
                    201:                        continue;
                    202:                if (!visual) {
                    203:                        if ((action == BELL_CURRENT &&
                    204:                            c->session->curw->window == w) ||
                    205:                            (action == BELL_OTHER &&
                    206:                            c->session->curw->window != w) ||
                    207:                            action == BELL_ANY)
1.2       nicm      208:                                tty_putcode(&c->tty, TTYC_BEL);
1.1       nicm      209:                        continue;
                    210:                }
                    211:                if (action == BELL_CURRENT && c->session->curw->window == w)
                    212:                        status_message_set(c, "Bell in current window");
                    213:                else if (action == BELL_ANY || (action == BELL_OTHER &&
                    214:                    c->session->curw->window != w))
                    215:                        status_message_set(c, "Bell in window %d", wl->idx);
                    216:        }
                    217:
                    218:        return (WINDOW_BELL);
                    219: }
                    220:
                    221: int
                    222: alerts_check_activity(struct session *s, struct winlink *wl)
                    223: {
                    224:        struct client   *c;
                    225:        struct window   *w = wl->window;
                    226:
                    227:        if (s->curw->window == w)
                    228:                w->flags &= ~WINDOW_ACTIVITY;
                    229:
                    230:        if (!(w->flags & WINDOW_ACTIVITY) || wl->flags & WINLINK_ACTIVITY)
                    231:                return (0);
1.8       nicm      232:        if (s->curw == wl)
1.1       nicm      233:                return (0);
                    234:
1.4       nicm      235:        if (!options_get_number(w->options, "monitor-activity"))
1.1       nicm      236:                return (0);
                    237:
1.4       nicm      238:        if (options_get_number(s->options, "bell-on-alert"))
1.1       nicm      239:                alerts_ring_bell(s);
                    240:        wl->flags |= WINLINK_ACTIVITY;
                    241:
1.4       nicm      242:        if (options_get_number(s->options, "visual-activity")) {
1.1       nicm      243:                TAILQ_FOREACH(c, &clients, entry) {
                    244:                        if (c->session != s)
                    245:                                continue;
                    246:                        status_message_set(c, "Activity in window %d", wl->idx);
                    247:                }
                    248:        }
                    249:
                    250:        return (WINDOW_ACTIVITY);
                    251: }
                    252:
                    253: int
                    254: alerts_check_silence(struct session *s, struct winlink *wl)
                    255: {
                    256:        struct client   *c;
                    257:        struct window   *w = wl->window;
                    258:
                    259:        if (s->curw->window == w)
                    260:                w->flags &= ~WINDOW_SILENCE;
                    261:
                    262:        if (!(w->flags & WINDOW_SILENCE) || wl->flags & WINLINK_SILENCE)
                    263:                return (0);
1.8       nicm      264:        if (s->curw == wl)
1.1       nicm      265:                return (0);
                    266:
1.4       nicm      267:        if (options_get_number(w->options, "monitor-silence") == 0)
1.1       nicm      268:                return (0);
                    269:
1.4       nicm      270:        if (options_get_number(s->options, "bell-on-alert"))
1.1       nicm      271:                alerts_ring_bell(s);
                    272:        wl->flags |= WINLINK_SILENCE;
                    273:
1.4       nicm      274:        if (options_get_number(s->options, "visual-silence")) {
1.1       nicm      275:                TAILQ_FOREACH(c, &clients, entry) {
                    276:                        if (c->session != s)
                    277:                                continue;
                    278:                        status_message_set(c, "Silence in window %d", wl->idx);
                    279:                }
                    280:        }
                    281:
                    282:        return (WINDOW_SILENCE);
                    283: }
                    284:
                    285: void
                    286: alerts_ring_bell(struct session *s)
                    287: {
                    288:        struct client   *c;
                    289:
                    290:        TAILQ_FOREACH(c, &clients, entry) {
                    291:                if (c->session == s && !(c->flags & CLIENT_CONTROL))
1.2       nicm      292:                        tty_putcode(&c->tty, TTYC_BEL);
1.1       nicm      293:        }
                    294: }