Newer
Older
/*
* BRLTTY - A background process providing access to the console screen (when in
* text mode) for a blind person using a refreshable braille display.
*
* Copyright (C) 1995-2018 by The BRLTTY Developers.
*
* BRLTTY comes with ABSOLUTELY NO WARRANTY.
*
* This is free software, placed under the terms of the
* GNU Lesser General Public License, as published by the Free Software
* Foundation; either version 2.1 of the License, or (at your option) any
* later version. Please see the file LICENSE-LGPL for details.
*
* This software is maintained by Dave Mielke <dave@mielke.cc>.
*/
#include "prologue.h"
#include "alert.h"
#include "prefs.h"
#include "tune.h"
#include "message.h"
#include "brl_dots.h"
typedef struct {
unsigned char duration;
BrlDots pattern;
} TactileAlert;
typedef struct {
const char *message;
TactileAlert tactile;
} AlertEntry;
#define ALERT_TACTILE(d,p) {.duration=(d), .pattern=(p)}
static const AlertEntry alertTable[] = {
[ALERT_BRAILLE_ON] = {
},
[ALERT_BRAILLE_OFF] = {
},
[ALERT_COMMAND_DONE] = {
.message = strtext("Done"),
.tune = "n74@40 r@30 n74@40 r@40 n74@140 r@20 n79@50"
},
[ALERT_COMMAND_REJECTED] = {
.tactile = ALERT_TACTILE(50, BRL_DOT_1 | BRL_DOT_3 | BRL_DOT_4 | BRL_DOT_6),
},
[ALERT_CLIPBOARD_BEGIN] = {
},
[ALERT_CLIPBOARD_END] = {
},
[ALERT_NO_CHANGE] = {
.tactile = ALERT_TACTILE(30, BRL_DOT_2 | BRL_DOT_3 | BRL_DOT_5 | BRL_DOT_6),
},
[ALERT_TOGGLE_ON] = {
.tactile = ALERT_TACTILE(30, BRL_DOT_1 | BRL_DOT_2 | BRL_DOT_4 | BRL_DOT_5),
},
[ALERT_TOGGLE_OFF] = {
.tactile = ALERT_TACTILE(30, BRL_DOT_3 | BRL_DOT_7 | BRL_DOT_6 | BRL_DOT_8),
},
[ALERT_CURSOR_LINKED] = {
},
[ALERT_CURSOR_UNLINKED] = {
},
[ALERT_SCREEN_FROZEN] = {
.message = strtext("Frozen"),
.tune = "n58@5 n59 n60 n61 n62 n63 n64 n65 n66 n67 n68 n69 n70 n71 n72 n73 n74 n76 n78 n80 n83 n86 n90 n95"
},
[ALERT_SCREEN_UNFROZEN] = {
.message = strtext("Unfrozen"),
.tune = "n95@5 n90 n86 n83 n80 n78 n76 n74 n73 n72 n71 n70 n69 n68 n67 n66 n65 n64 n63 n62 n61 n60 n59 n58"
},
[ALERT_FREEZE_REMINDER] = {
},
[ALERT_WRAP_DOWN] = {
.tactile = ALERT_TACTILE(20, BRL_DOT_4 | BRL_DOT_5 | BRL_DOT_6 | BRL_DOT_8),
},
[ALERT_WRAP_UP] = {
.tactile = ALERT_TACTILE(20, BRL_DOT_1 | BRL_DOT_2 | BRL_DOT_3 | BRL_DOT_7),
},
[ALERT_SKIP_FIRST] = {
.tactile = ALERT_TACTILE(30, BRL_DOT_1 | BRL_DOT_4 | BRL_DOT_7 | BRL_DOT_8),
[ALERT_SKIP_ONE] = {
.tune = "n74@10 r@18"
[ALERT_SKIP_SEVERAL] = {
.tune = "n73@20 r@1"
},
[ALERT_BOUNCE] = {
.tactile = ALERT_TACTILE(50, BRL_DOT_1 | BRL_DOT_2 | BRL_DOT_3 | BRL_DOT_4 | BRL_DOT_5 | BRL_DOT_6 | BRL_DOT_7 | BRL_DOT_8),
},
[ALERT_ROUTING_STARTED] = {
},
[ALERT_ROUTING_SUCCEEDED] = {
},
[ALERT_ROUTING_FAILED] = {
.tune = "n80@80 n79@90 n78@100 n77@100 r@20 n77@100 r@20 n77@150"
},
[ALERT_CONSOLE_BELL] = {
.message = strtext("Console Bell"),
.tune = "n78@100"
},
[ALERT_KEYS_AUTORELEASED] = {
.message = strtext("Autorelease"),
.tune = "c6@50 b- g e- p50 c@100 c c"
[ALERT_SCROLL_UP] = {
.tune = "b6@10 d7"
},
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
static ToneElement *tuneTable[ARRAY_COUNT(alertTable)] = {NULL};
static TuneBuilder *tuneBuilder = NULL;
static ToneElement emptyTune[] = {TONE_STOP()};
static void
exitAlertTunes (void *data) {
tuneSynchronize();
{
ToneElement **tune = tuneTable;
ToneElement **end = tune + ARRAY_COUNT(tuneTable);
while (tune < end) {
if (*tune) {
if (*tune != emptyTune) free(*tune);
*tune = NULL;
}
tune += 1;
}
}
if (tuneBuilder) {
destroyTuneBuilder(tuneBuilder);
tuneBuilder = NULL;
}
}
static TuneBuilder *
getTuneBuilder (void) {
if (!tuneBuilder) {
if (!(tuneBuilder = newTuneBuilder())) {
return NULL;
}
onProgramExit("alert-tunes", exitAlertTunes, NULL);
}
return tuneBuilder;
}
void
alert (AlertIdentifier identifier) {
const AlertEntry *alert = &alertTable[identifier];
if (prefs.alertTunes && alert->tune && *alert->tune) {
ToneElement **tune = &tuneTable[identifier];
if (!*tune) {
TuneBuilder *tb = getTuneBuilder();
if (tb) {
setTuneSourceName(tuneBuilder, "alert");
setTuneSourceIndex(tb, identifier);
if (parseTuneString(tb, "p100")) {
if (parseTuneString(tb, alert->tune)) {
*tune = getTune(tb);
}
}
resetTuneBuilder(tb);
}
if (!*tune) *tune = emptyTune;
}
tunePlayTones(*tune);
} else if (prefs.alertDots && alert->tactile.duration) {
showDotPattern(alert->tactile.pattern, alert->tactile.duration);
} else if (prefs.alertMessages && alert->message) {
message(NULL, gettext(alert->message), 0);