fix github issue 361 to make user_sounds useful even if MSGTYPE is hidden

fixes #361

Also, experminental introduction of vt_sounddata to enable tty to pass
a sound file index to the terminal side of things where perhaps someone
can add code to something like hterm to take the information relayed by
NetHack to trigger user_sounds locally even if playing on a server.

Compile time option TTY_SOUND_ESCCODES required to build that support in.

It should be independent of TTY_TILE_ESCCODES.
This commit is contained in:
nhmall
2020-07-02 15:49:45 -04:00
parent 3a94f0a9f8
commit e4b18f0545
13 changed files with 151 additions and 32 deletions

View File

@@ -114,6 +114,9 @@ preload_tiles control whether tiles get pre-loaded into RAM at [TRUE]
Boolean option if TTY_TILES_ESCCODES was set at compile time (tty only):
vt_tiledata insert extra data escape code markers into output [FALSE]
Boolean option if TTY_SOUND_ESCCODES was set at compile time (tty only):
vt_sounddata insert sound data escape code markers into output [FALSE]
Any Boolean option can be negated by prefixing it with a '!' or 'no'.

View File

@@ -35,7 +35,7 @@
.ds vr "NetHack 3.7
.ds f0 "\*(vr
.ds f1
.ds f2 "June 20, 2020
.ds f2 "July 2, 2020
.
.\" A note on some special characters:
.\" \(lq = left double quote
@@ -4662,6 +4662,8 @@ the pattern to match;
the sound file to play;
.PL volume
the volume to be set while playing the sound file.
.PL "vt_sounddata index"
optional - the index corresponding to a sound file;
.PE
.lp ""
The pattern should be a POSIX extended regular expression.

View File

@@ -45,7 +45,7 @@
%.au
\author{Original version - Eric S. Raymond\\
(Edited and expanded for 3.7 by Mike Stephenson and others)}
\date{June 20, 2020}
\date{July 2, 2020}
\maketitle
@@ -5110,6 +5110,7 @@ Each SOUND entry is broken down into the following parts:
{\tt pattern } --- the pattern to match;\\
{\tt sound file} --- the sound file to play;\\
{\tt volume } --- the volume to be set while playing the sound file.
{\tt sound index } --- optional - the index corresponding to a sound file.
%.ei
%.ed
\elist

View File

@@ -298,6 +298,10 @@ Unix: when user name is used as default character name, keep hyphenated value
intact instead stripping off dash and whatever follows as if that
specified role/race/&c (worked once upon a time; broken since 3.3.0)
Unix: add "ec2-user" to the list of user names 'sysconf' classifies as generic
user_sounds: move the message hook from inside individual window display ports
to the core where it allows MSGTYP_NOSHOW msgtyp's to still trigger
sounds to correct a reported github issue; also fixes a past reported
issue that the curses port on Windows not working with user_sounds
Windows: update for new status condition fields
Windows: include commented-out 'PORTABLE_DEVICE_PATHS' in sysconf.template
X11: substantial overhaul of status display, both 'fancy' and 'tty-style'
@@ -384,6 +388,11 @@ record number of wishes and artifact wishes in xlogfile
Platform- and/or Interface-Specific New Features
------------------------------------------------
user_sounds: provide an experimental mechanism for terminal-side sounds similar
to the method used for vt_tiledata; new option vt_sounddata that also
requires compile-time definition of TTY_SOUND_ESCCODES (also requires
terminal-side code external to NetHack to recognize the sequence and
act on it
NetHack Community Patches (or Variation) Included

View File

@@ -474,7 +474,10 @@ typedef unsigned char uchar;
*/
/* TTY_TILES_ESCCODES: Enable output of special console escape codes
* which act as hints for external programs such as EbonHack.
* which act as hints for external programs such as EbonHack, or hterm.
*
* TTY_SOUND_ESCCODES: Enable output of special console escape codes
* which act as hints for theoretical external programs to play sound effect.
*
* Only for TTY_GRAPHICS.
*
@@ -482,12 +485,14 @@ typedef unsigned char uchar;
* one or more positive integer values, separated by semicolons.
* For example ESC [ 1 ; 0 ; 120 z
*
* Possible codes are:
* Possible TTY_TILES_ESCCODES codes are:
* ESC [ 1 ; 0 ; n ; m z Start a glyph (aka a tile) number n, with flags m
* ESC [ 1 ; 1 z End a glyph.
* ESC [ 1 ; 2 ; n z Select a window n to output to.
* ESC [ 1 ; 3 z End of data. NetHack has finished sending data,
* and is waiting for input.
* Possible TTY_SOUND_ESCCODES codes are:
* ESC [ 1 ; 4 ; n ; m z Play specified sound n, volume m
*
* Whenever NetHack outputs anything, it will first output the "select window"
* code. Whenever NetHack outputs a tile, it will first output the "start
@@ -496,9 +501,10 @@ typedef unsigned char uchar;
*
* To compile NetHack with this, add tile.c to WINSRC and tile.o to WINOBJ
* in the hints file or Makefile.
* Set boolean option vt_tiledata in your config file to turn this on.
* Set boolean option vt_xdata in your config file to turn either of these on.
* Note that gnome-terminal at least doesn't work with this. */
/* #define TTY_TILES_ESCCODES */
/* #define TTY_SOUND_ESCCODES */
/* NetHack will execute an external program whenever a new message-window
* message is shown. The program to execute is given in environment variable

View File

@@ -326,6 +326,9 @@ struct instance_flags {
#endif
#ifdef TTY_TILES_ESCCODES
boolean vt_tiledata; /* output console codes for tile support in TTY */
#endif
#ifdef TTY_SOUND_ESCCODES
boolean vt_sounddata; /* output console codes for sound support in TTY*/
#endif
boolean clicklook; /* allow right-clicking for look */
boolean cmdassist; /* provide detailed assistance for some comnds */

View File

@@ -29,6 +29,7 @@
#define DUMPLOG_MSG_COUNT 50
#define USER_SOUNDS
#define TTY_SOUND_ESCCODES
/*#define CHANGE_COLOR*/ /* allow palette changes */
#define SELECTSAVED /* Provide menu of saved games to choose from at start */

View File

@@ -516,6 +516,13 @@ pfx_##a,
#else
NHOPTB(vt_tiledata, 0, opt_in, set_in_config, Off, Yes, No, No, NoAlias,
(boolean *) 0)
#endif
#ifdef TTY_SOUND_ESCCODES
NHOPTB(vt_sounddata, 0, opt_in, set_in_config, Off, Yes, No, No, NoAlias,
&iflags.vt_sounddata)
#else
NHOPTB(vt_sounddata, 0, opt_in, set_in_config, Off, Yes, No, No, NoAlias,
(boolean *) 0)
#endif
NHOPTC(warnings, 10, opt_in, set_in_config, No, Yes, No, No, NoAlias,
"display characters for warnings")

View File

@@ -15,7 +15,9 @@ static char *FDECL(You_buf, (int));
#if defined(MSGHANDLER) && (defined(POSIX_TYPES) || defined(__GNUC__))
static void FDECL(execplinehandler, (const char *));
#endif
#ifdef USER_SOUNDS
extern void FDECL(maybe_play_sound, (const char *));
#endif
#ifdef DUMPLOG
/* keep the most recent DUMPLOG_MSG_COUNT messages */
@@ -163,6 +165,7 @@ VA_DECL(const char *, line)
pbuf[BUFSZ - 1] = '\0';
line = pbuf;
}
msgtyp = MSGTYP_NORMAL;
#ifdef DUMPLOG
/* We hook here early to have options-agnostic output.
@@ -182,10 +185,13 @@ VA_DECL(const char *, line)
goto pline_done;
}
msgtyp = MSGTYP_NORMAL;
no_repeat = (g.pline_flags & PLINE_NOREPEAT) ? TRUE : FALSE;
if ((g.pline_flags & OVERRIDE_MSGTYPE) == 0) {
msgtyp = msgtype_type(line, no_repeat);
#ifdef USER_SOUNDS
if (msgtyp == MSGTYP_NORMAL || msgtyp == MSGTYP_NOSHOW)
maybe_play_sound(line);
#endif
if ((g.pline_flags & URGENT_MESSAGE) == 0
&& (msgtyp == MSGTYP_NOSHOW
|| (msgtyp == MSGTYP_NOREP && !strcmp(line, g.prevmsg))))

View File

@@ -1258,16 +1258,23 @@ tiphat()
#ifdef USER_SOUNDS
#if defined(WIN32) || defined(QT_GRAPHICS)
extern void FDECL(play_usersound, (const char *, int));
#endif
#if defined(TTY_SOUND_ESCCODES)
extern void FDECL(play_usersound_via_idx, (int, int));
#endif
typedef struct audio_mapping_rec {
struct nhregex *regex;
char *filename;
int volume;
int idx;
struct audio_mapping_rec *next;
} audio_mapping;
static audio_mapping *soundmap = 0;
static audio_mapping *FDECL(sound_matches_message, (const char *));
char *sounddir = 0; /* set in files.c */
@@ -1279,26 +1286,29 @@ const char *mapping;
char text[256];
char filename[256];
char filespec[256];
int volume;
int volume, idx = -1;
boolean toolong = FALSE;
if (sscanf(mapping, "MESG \"%255[^\"]\"%*[\t ]\"%255[^\"]\" %d", text,
if (sscanf(mapping, "MESG \"%255[^\"]\"%*[\t ]\"%255[^\"]\" %d %d", text,
filename, &volume, &idx) == 4
|| sscanf(mapping, "MESG \"%255[^\"]\"%*[\t ]\"%255[^\"]\" %d", text,
filename, &volume) == 3) {
audio_mapping *new_map;
if (!sounddir)
sounddir = dupstr(".");
if (strlen(sounddir) + 1 + strlen(filename) >= sizeof filespec) {
raw_print("sound file name too long");
return 0;
}
}
Sprintf(filespec, "%s/%s", sounddir, filename);
if (can_read_file(filespec)) {
if (idx >= 0 || can_read_file(filespec)) {
new_map = (audio_mapping *) alloc(sizeof *new_map);
new_map->regex = regex_init();
new_map->filename = dupstr(filespec);
new_map->volume = volume;
new_map->idx = idx;
new_map->next = soundmap;
if (!regex_compile(text, new_map->regex)) {
@@ -1325,18 +1335,56 @@ const char *mapping;
return 1;
}
static audio_mapping *
sound_matches_message(msg)
const char *msg;
{
audio_mapping *snd = soundmap;
while (snd) {
if (regex_match(msg, snd->regex))
return snd;
snd = snd->next;
}
return (audio_mapping *) 0;
}
void
play_sound_for_message(msg)
const char *msg;
{
audio_mapping *cursor = soundmap;
audio_mapping *snd = sound_matches_message(msg);
while (cursor) {
if (regex_match(msg, cursor->regex)) {
play_usersound(cursor->filename, cursor->volume);
}
cursor = cursor->next;
}
if (snd)
play_usersound(snd->filename, snd->volume);
}
void
maybe_play_sound(msg)
const char *msg;
{
#if defined(WIN32) || defined(QT_GRAPHICS) || defined(TTY_SOUND_ESCCODES)
audio_mapping *snd = sound_matches_message(msg);
if (snd
#if defined(WIN32) || defined(QT_GRAPHICS)
#ifdef TTY_SOUND_ESCCODES
&& !iflags.vt_sounddata
#endif
#if defined(QT_GRAPHICS)
&& WINDOWPORT("Qt")
#endif
#if defined(WIN32)
&& (WINDOWPORT("tty") || WINDOWPORT("mswin") || WINDOWPORT("curses"))
#endif
#endif /* WIN32 || QT_GRAPHICS */
)
play_usersound(snd->filename, snd->volume);
#if defined(TTY_GRAPHICS) && defined(TTY_SOUND_ESCCODES)
else if (snd && iflags.vt_sounddata && snd->idx >= 0 && WINDOWPORT("tty"))
play_usersound_via_idx(snd->idx, snd->volume);
#endif /* TTY_GRAPHICS && TTY_SOUND_ESCCODES */
#endif /* WIN32 || QT_GRAPHICS || TTY_SOUND_ESCCODES */
}
void

View File

@@ -189,4 +189,13 @@ set_altkeyhandler(const char *inName)
{
return;
}
#if defined(USER_SOUNDS) && defined(TTY_SOUND_ESCCODES)
void
play_usersound_via_idx(idx, volume)
int idx, volume;
{
}
#endif /* USER_SOUNDS && TTY_SOUND_ESCCODES */
#endif /* TTYSTUBS */

View File

@@ -103,10 +103,6 @@ const char * NetHackQtMessageWindow::GetStr(bool init)
void NetHackQtMessageWindow::PutStr(int attr, const QString& text)
{
#ifdef USER_SOUNDS
play_sound_for_message(text.toLatin1().constData());
#endif
changed=true;
// If the line is output from the "/" command, map the first character

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 wintty.c $NHDT-Date: 1587110794 2020/04/17 08:06:34 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.256 $ */
/* NetHack 3.6 wintty.c $NHDT-Date: 1587110794 2020/04/17 08:06:34 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.256 $ */
/* Copyright (c) David Cohrs, 1991 */
/* NetHack may be freely redistributed. See license for details. */
@@ -36,14 +36,19 @@ extern void msmsg(const char *, ...);
#endif
#endif
#if defined(TTY_TILES_ESCCODES) || defined(TTY_SOUND_ESCCODES)
#define VT_ANSI_COMMAND 'z'
#endif
#ifdef TTY_TILES_ESCCODES
extern short glyph2tile[];
#define TILE_ANSI_COMMAND 'z'
#define AVTC_GLYPH_START 0
#define AVTC_GLYPH_END 1
#define AVTC_SELECT_WINDOW 2
#define AVTC_INLINE_SYNC 3
#endif
#ifdef TTY_SOUND_ESCCODES
#define AVTC_SOUND_PLAY 4
#endif
#ifdef HANGUP_HANDLING
/*
@@ -244,11 +249,11 @@ int i, c, d;
vt_tile_current_window = c;
}
if (d >= 0)
printf("\033[1;%d;%d;%d%c", i, c, d, TILE_ANSI_COMMAND);
printf("\033[1;%d;%d;%d%c", i, c, d, VT_ANSI_COMMAND);
else
printf("\033[1;%d;%d%c", i, c, TILE_ANSI_COMMAND);
printf("\033[1;%d;%d%c", i, c, VT_ANSI_COMMAND);
} else {
printf("\033[1;%d%c", i, TILE_ANSI_COMMAND);
printf("\033[1;%d%c", i, VT_ANSI_COMMAND);
}
}
}
@@ -259,6 +264,24 @@ int i, c, d;
#define print_vt_code2(i,c) print_vt_code((i), (c), -1)
#define print_vt_code3(i,c,d) print_vt_code((i), (c), (d))
#ifdef TTY_SOUND_ESCCODES
void
print_vt_soundcode_idx(idx, v)
int idx, v;
{
HUPSKIP();
if (iflags.vt_sounddata) {
if (v >= 0)
printf("\033[1;%d;%d;%d%c", AVTC_SOUND_PLAY,
idx, v, VT_ANSI_COMMAND);
else
printf("\033[1;%d;%d%c", AVTC_SOUND_PLAY,
idx, VT_ANSI_COMMAND);
}
}
#else
# define print_vt_soundcode_idx(idx, v) ;
#endif /* !TTY_SOUND_ESCCODES */
/* clean up and quit */
static void
@@ -2678,10 +2701,6 @@ const char *str;
messages, clear flag mask leaving only display attr */
/*attr &= ~(ATR_URGENT | ATR_NOHISTORY);*/
/* really do this later */
#if defined(USER_SOUNDS) && defined(WIN32CON)
play_sound_for_message(str);
#endif
if (!suppress_history) {
/* normal output; add to current top line if room, else flush
whatever is there to history and then write this */
@@ -4634,6 +4653,15 @@ render_status(VOID_ARGS)
#endif /* STATUS_HILITES */
#if defined(USER_SOUNDS) && defined(TTY_SOUND_ESCCODES)
void
play_usersound_via_idx(idx, volume)
int idx, volume;
{
print_vt_soundcode_idx(idx, volume);
}
#endif /* USER_SOUNDS && TTY_SOUND_ESCCODES */
#endif /* TTY_GRAPHICS */
/*wintty.c*/