#define DEFAULT_WC_TILED_MAP /* Default to tiles if users doesn't say \
wc_ascii_map */
#endif
-#ifndef NOUSER_SOUNDS
-#define USER_SOUNDS /* Use sounds */
-#endif
#ifndef USE_XPM
#define USE_XPM /* Use XPM format for images (required) */
#endif
/* shk.c */
boolean auto_credit;
+ /* sounds.c */
+ enum soundlib_ids active_soundlib;
+
/* trap.c */
/* context for water_damage(), managed by water_damage_chain();
when more than one stack of potions of acid explode while processing
/* questpgr.c */
char cvt_buf[CVT_BUF_SIZE];
+ /* sounds.c */
+ enum soundlib_ids chosen_soundlib;
+
/* sp_lev.c */
struct sp_coder *coder;
extern void play_usersound_via_idx(int, int);
#endif
#endif /* USER SOUNDS */
+extern void assign_soundlib(int);
+extern void activate_chosen_soundlib(void);
+extern void get_soundlib_name(char *dest, int maxlen);
/* ### sp_lev.c ### */
#include "region.h"
#include "trap.h"
#include "display.h"
+#include "sndprocs.h"
#include "decl.h"
#include "timeout.h"
NHOPTC(sortvanquished, Advanced, 0, opt_in, set_in_game,
Yes, Yes, No, Yes, NoAlias,
"preferred order when displaying vanquished monsters")
+ NHOPTC(soundlib, Advanced, WINTYPELEN, opt_in, set_gameview,
+ No, Yes, No, No, NoAlias,
+ "soundlib interface to use (if any)")
NHOPTB(sparkle, Map, 0, opt_out, set_in_game,
On, Yes, No, No, NoAlias, &flags.sparkle)
NHOPTB(splash_screen, Advanced, 0, opt_out, set_in_config,
--- /dev/null
+/* NetHack 3.7 sndprocs.h $NHDT-Date: $ $NHDT-Branch: $:$NHDT-Revision: $ */
+/* Copyright (c) Michael Allison, 2022 */
+/* NetHack may be freely redistributed. See license for details. */
+
+#ifndef SNDPROCS_H
+#define SNDPROCS_H
+
+/*
+ *
+ * Types of potential sound supports (all are optional):
+ *
+ * SNDCAP_USERSOUNDS User-specified sounds that play based on config
+ * file entries that identify a regular expression
+ * to match against message window text, and identify
+ * an external sound file to load in response.
+ * The sound interface function pointer used to invoke
+ * it:
+ *
+ * void (*sound_play_usersound)(char *filename,
+ * int32_t volume, int32_t idx);
+ *
+ * SNDCAP_HEROMUSIC Invoked by the core when the in-game hero is
+ * playing a tune on an instrument. The sound
+ * interface function pointer used to invoke it:
+ *
+ * void (*sound_hero_playnotes)(int32_t instrument,
+ * char *str, int32_t volume);
+ *
+ * SNDCAP_ACHIEVEMENTS Invoked by the core when an in-game achievement
+ * is reached. The soundlib routines could play
+ * appropriate theme or mood music in response.
+ * There would need to be a way to map the
+ * achievements to external user-specified sounds.
+ * The sound interface function pointer used to
+ * invoke it:
+ *
+ * void (*sound_achievement)(schar, schar,
+ * int32_t);
+ *
+ * SNDCAP_SOUNDEFFECTS Invoked by the core when something
+ * sound-producing happens in the game. The soundlib
+ * routines could play an appropriate sound effect
+ * in response. They can be public-domain or
+ * suitably-licensed stock sounds included with the
+ * game source and made available during the build
+ * process, or (not-yet-implemented) a way to
+ * tie particular sound effects to a user-specified
+ * sound samples in a config file. The sound
+ * interface function pointer used to invoke it:
+ *
+ * void (*sound_soundeffect)(char *desc, int32_t,
+ * int32_t volume);
+ *
+ * Development notes:
+ * - gc.chosen_soundlib holds the soundlib_id that will be initialized
+ * at the appropriate time (startup or after an option change). It
+ * is initialized to soundlib_nosound, so that is what will be used if
+ * the initial value isn't replaced via an assign_soundlib() call
+ * prior to the call to the activate_chosen_soundlib() in
+ * moveloop_preamble() at the start of the game.
+ * - ga.active_soundlib holds the soundlib_id of the active soundlib.
+ * It is initialized to soundlib_unassigned. It will get changed to
+ * reflect the activated soundlib_id once activate_chosen_soundlib()
+ * has been called.
+ *
+ */
+
+enum soundlib_ids {
+ soundlib_unassigned = 0,
+#ifdef SND_LIB_QTSOUND
+ soundlib_qtsound,
+#endif
+#ifdef SND_LIB_PORTAUDIO
+ soundlib_portaudio,
+#endif
+#ifdef SND_LIB_OPENAL
+ soundlib_openal,
+#endif
+#ifdef SND_LIB_SDL_MIXER
+ soundlib_sdl_mixer,
+#endif
+#ifdef SND_LIB_MINIAUDIO
+ soundlib_miniaudio,
+#endif
+#ifdef SND_LIB_FMOD
+ soundlib_fmod,
+#endif
+#ifdef SND_LIB_SOUND_ESCCODES
+ soundlib_sound_esccodes,
+#endif
+#ifdef SND_LIB_VISSOUND
+ soundlib_vissound,
+#endif
+#ifdef SND_LIB_WINDSOUND
+ soundlib_windsound,
+#endif
+ soundlib_nosound
+};
+
+struct sound_procs {
+ const char *soundname;
+ enum soundlib_ids soundlib_id;
+ unsigned long sndcap; /* capabilities in the port */
+ void (*sound_init_nhsound)(void);
+ void (*sound_exit_nhsound)(const char *);
+ void (*sound_achievement)(schar, schar, int32_t);
+ void (*sound_soundeffect)(char *desc, int32_t, int32_t volume);
+ void (*sound_hero_playnotes)(int32_t instrument, char *str, int32_t volume);
+ void (*sound_play_usersound)(char *filename, int32_t volume, int32_t idx);
+};
+
+extern struct sound_procs sndprocs;
+
+#define SOUNDID(soundname) #soundname, soundlib_##soundname
+
+/*
+ * SOUNDCAP
+ */
+#define SNDCAP_USERSOUNDS 0x0001L
+#define SNDCAP_HEROMUSIC 0x0002L
+#define SNDCAP_ACHIEVEMENTS 0x0004L
+#define SNDCAP_SOUNDEFFECTS 0x0008L
+ /* 28 free bits */
+
+extern struct sound_procs soundprocs;
+
+/* subset for NetHack */
+enum instruments {
+ ins_choir_aahs = 53, ins_trumpet = 57, ins_trombone = 58,
+ ins_french_horn = 61, ins_english_horn = 70, ins_piccolo = 73,
+ ins_flute = 74, ins_pan_flute = 76, ins_blown_bottle = 77,
+ ins_whistle = 79, ins_tinkle_bell = 113, ins_woodblock = 116,
+ ins_taiko_drum = 117, ins_melodic_tom = 118, ins_seashore = 123,
+ ins_fencepost
+};
+
+#if 0
+enum instruments_broad {
+ ins_acoustic_grand_piano = 1, ins_bright_acoustic_piano = 2,
+ ins_electric_grand_piano = 3, ins_honkytonk_piano = 4,
+ ins_electric_piano_1 = 5, ins_electric_piano_2 = 6,
+ ins_harpsichord = 7, ins_clavinet = 8, ins_celesta = 9,
+ ins_glockenspiel = 10, ins_music_box = 11, ins_vibraphone = 12,
+ ins_marimba = 13, ins_xylophone = 14, ins_tubular_bells = 15,
+ ins_dulcimer = 16, ins_drawbar_organ = 17,
+ ins_percussive_organ = 18, ins_rock_organ = 19, ins_church_organ = 20,
+ ins_reed_organ = 21, ins_french_accordion = 22, ins_harmonica = 23,
+ ins_tango_accordion = 24, ins_acoustic_guitar__nylon = 25,
+ ins_acoustic_guitar_steel = 26, ins_electric_guitar_jazz = 27,
+ ins_electric_guitar_clean = 28, ins_electric_guitar_muted = 29,
+ ins_overdriven_guitar = 30, ins_distortion_guitar = 31,
+ ins_guitar_harmonics = 32, ins_acoustic_bass = 33,
+ ins_electric_bass__fingered = 34, ins_electric_bass_picked = 35,
+ ins_fretless_bass = 36, ins_slap_bass_1 = 37, ins_slap_bass_2 = 38,
+ ins_synth_bass_1 = 39, ins_synth_bass_2 = 40, ins_violin = 41,
+ ins_viola = 42, ins_cello = 43, ins_contrabass = 44,
+ ins_tremolo_strings = 45, ins_pizzicato_strings = 46,
+ ins_orchestral_harp = 47, ins_timpani = 48,
+ ins_string_ensemble_1 = 49, ins_string_ensemble_2 = 50,
+ ins_synthstrings_1 = 51, ins_synthstrings_2 = 52, ins_choir_aahs = 53,
+ ins_voice_oohs = 54, ins_synth_voice = 55, ins_orchestra_hit = 56,
+ ins_trumpet = 57, ins_trombone = 58, ins_tuba = 59, ins_muted_trumpet = 60,
+ ins_french_horn = 61, ins_brass_section = 62, ins_synthbrass_1 = 63,
+ ins_synthbrass_2 = 64, ins_soprano_sax = 65, ins_alto_sax = 66,
+ ins_tenor_sax = 67, ins_baritone_sax = 68, ins_oboe = 69,
+ ins_english_horn = 70, ins_bassoon = 71, ins_clarinet = 72,
+ ins_piccolo = 73, ins_flute = 74, ins_recorder = 75,
+ ins_pan_flute = 76, ins_blown_bottle = 77, ins_shakuhachi = 78,
+ ins_whistle = 79, ins_ocarina = 80, ins_sitar = 105, ins_banjo = 106,
+ ins_shamisen = 107, ins_koto = 108, ins_kalimba = 109, ins_bag_pipe = 110,
+ ins_fiddle = 111, ins_shanai = 112, ins_tinkle_bell = 113, ins_agogo = 114,
+ ins_steel_drums = 115, ins_woodblock = 116, ins_taiko_drum = 117,
+ ins_melodic_tom = 118, ins_synth_drum = 119, ins_reverse_cymbal = 120,
+ ins_guitar_fret_noise = 121, ins_breath_noise = 122, ins_seashore = 123,
+ ins_bird_tweet = 124, ins_telephone_ring = 125, ins_helicopter = 126,
+ ins_applause = 127, ins_gunshot = 128,
+ ins_fencepost
+};
+#endif
+#endif /* SNDPROCS_H */
/*#define DUMPLOG_FILE "nethack-%n-%d.log"*/
#define DUMPLOG_MSG_COUNT 50
-#define USER_SOUNDS
-/* #define TTY_SOUND_ESCCODES */
-
/*#define CHANGE_COLOR*/ /* allow palette changes */
#define QWERTZ_SUPPORT /* when swap_yz is True, numpad 7 is 'z' not 'y' */
#define MAP_MODE_ASCII_FIT_TO_SCREEN 10
#define MAP_MODE_TILES_FIT_TO_SCREEN 11
-#if 0
-#define WC_SND_SOUND 0x0001L /* 01 Port has some sound capabilities */
-#define WC_SND_SPEAKER 0x0002L /* 02 Sound supported via built-in speaker */
-#define WC_SND_STEREO 0x0004L /* 03 Stereo sound supported */
-#define WC_SND_RAW 0x0008L /* 04 Raw sound supported */
-#define WC_SND_WAVE 0x0010L /* 05 Wave support */
-#define WC_SND_MIDI 0x0020L /* 06 Midi support */
- /* 26 free bits */
-#endif
-
struct wc_Opt {
const char *wc_name;
unsigned long wc_bit;
--- /dev/null
+19-Jan-2023
+The Qt sound interface is currently housed in win/Qt/qt_bind.h and win/Qt/qt_bind.cpp.
+
--- /dev/null
+/* NetHack 3.7 windsound.c $NHDT-Date: $ $NHDT-Branch: $NHDT-Revision: $ */
+/* Copyright (c) Michael Allison, 2022 */
+/* NetHack may be freely redistributed. See license for details. */
+
+#include "win32api.h"
+#include "hack.h"
+#include <mmsystem.h>
+
+/*
+ * The win32api sound interface
+ *
+ */
+
+#include "win32api.h"
+#include "hack.h"
+
+#ifdef SND_LIB_WINDSOUND
+
+static void windsound_init_nhsound(void);
+static void windsound_exit_nhsound(const char *);
+static void windsound_achievement(schar, schar, int32_t);
+static void windsound_soundeffect(char *, int32_t, int32_t);
+static void windsound_hero_playnotes(int32_t instrument, char *str, int32_t volume);
+static void windsound_play_usersound(char *, int32_t, int32_t);
+
+struct sound_procs windsound_procs = {
+ SOUNDID(windsound),
+ 0L,
+ windsound_init_nhsound,
+ windsound_exit_nhsound,
+ windsound_achievement,
+ windsound_soundeffect,
+ windsound_hero_playnotes,
+ windsound_play_usersound,
+};
+
+void
+windsound_init_nhsound(void)
+{
+ /* No steps required */
+}
+
+void
+windsound_exit_nhsound(const char *reason)
+{
+}
+
+void
+windsound_achievement(schar ach1, schar ach2, int32_t repeat)
+{
+}
+
+void
+windsound_soundeffect(char *desc, int32_t seid, int32_t volume)
+{
+}
+
+void
+windsound_hero_playnotes(int32_t instrument, char *str, int32_t volume)
+{
+}
+
+void
+windsound_play_usersound(char *filename, int32_t volume UNUSED, int32_t idx UNUSED)
+{
+ /* pline("play_usersound: %s (%d).", filename, volume); */
+ (void) sndPlaySound(filename, SND_ASYNC | SND_NODEFAULT);
+}
+
+#endif /* SND_LIB_WINDSOUND */
+
change_luck(-1);
}
+ activate_chosen_soundlib();
+
if (!resuming) { /* new game */
gc.context.rndencode = rnd(9000);
set_wear((struct obj *) 0); /* for side-effects of starting gear */
UNDEFINED_VALUE, /* abort_looting */
/* shk.c */
FALSE, /* auto_credit */
+ /* sounds.c */
+ soundlib_unassigned, /* enum soundlib_ids active_soundlib */
+
/* trap.c */
{ 0, 0, FALSE }, /* acid_ctx */
TRUE, /* havestate*/
FALSE, /* class_filter */
/* questpgr.c */
UNDEFINED_VALUES, /* cvt_buf */
+ /* sounds.c */
+ soundlib_nosound, /* chosen_soundlib */
UNDEFINED_PTR, /* coder */
/* uhitm.c */
NON_PM, /* corpsenm_digested */
record_achievement(schar achidx)
{
int i, absidx;
+ int repeat_achievement = 0;
absidx = abs(achidx);
/* valid achievements range from 1 to N_ACH-1; however, ranks can be
an attempt to duplicate an achievement can happen if any of Bell,
Candelabrum, Book, or Amulet is dropped then picked up again */
for (i = 0; u.uachieved[i]; ++i)
- if (abs(u.uachieved[i]) == absidx)
- return; /* already recorded, don't duplicate it */
+ if (abs(u.uachieved[i]) == absidx) {
+ repeat_achievement = 1;
+ break;
+ }
+
+ /*
+ * We do the sound for an achievement, even if it has already been
+ * achieved before. Some players might have set up level-based
+ * theme music or something. We do let the sound interface know
+ * that it's not the original achievement though.
+ */
+ (*soundprocs.sound_achievement)(achidx, 0, repeat_achievement);
+
+ if (repeat_achievement)
+ return; /* already recorded, don't duplicate it */
u.uachieved[i] = achidx;
/* avoid livelog for achievements recorded during final disclosure:
return optn_ok;
}
+static int
+optfn_soundlib(int optidx, int req, boolean negated UNUSED,
+ char *opts, char *op)
+{
+ char soundlibbuf[WINTYPELEN];
+
+ if (req == do_init) {
+ return optn_ok;
+ }
+ if (req == do_set) {
+ /*
+ * soundlib: option to choose the interface for binaries built
+ * with support for more than the default interface (nosound).
+ *
+ * Option processing sets gc.chosen_soundlib. A later call
+ * to activate_chosen_soundlib() actually activates it, and
+ * sets gc.active_soundlib.
+ */
+ if ((op = string_for_env_opt(allopt[optidx].name, opts, FALSE))
+ != empty_optstr) {
+
+ get_soundlib_name(soundlibbuf, WINTYPELEN);
+ assign_soundlib(gc.chosen_soundlib);
+ } else
+ return optn_err;
+ return optn_ok;
+ }
+ if (req == get_val || req == get_cnf_val) {
+ if (!opts)
+ return optn_err;
+ get_soundlib_name(soundlibbuf, WINTYPELEN);
+ Sprintf(opts, "%s", soundlibbuf);
+ return optn_ok;
+ }
+ return optn_ok;
+}
+
static int
optfn_sortdiscoveries(
int optidx, int req, boolean negated,
void
play_sound_for_message(const char* msg)
{
- audio_mapping *snd = sound_matches_message(msg);
+ audio_mapping *snd;
- if (snd)
- play_usersound(snd->filename, snd->volume);
+ if (soundprocs.sound_play_usersound) {
+ snd = sound_matches_message(msg);
+ if (snd)
+ (*soundprocs.sound_play_usersound)(
+ snd->filename, snd->volume, snd->idx);
+ }
}
void
maybe_play_sound(const char* msg)
{
-#if defined(WIN32) || defined(QT_GRAPHICS) || defined(TTY_SOUND_ESCCODES)
- audio_mapping *snd = sound_matches_message(msg);
+ audio_mapping *snd;
- 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 */
+ if (soundprocs.sound_play_usersound) {
+ snd = sound_matches_message(msg);
+ if (snd)
+ (*soundprocs.sound_play_usersound)(
+ snd->filename, snd->volume, snd->idx);
+ }
}
void
if (sounddir)
free((genericptr_t) sounddir), sounddir = 0;
}
-
#endif /* USER_SOUNDS */
+struct sound_procs soundprocs;
+
+#ifdef SND_LIB_QTSOUND
+extern struct sound_procs qtsound_procs;
+#endif
+#ifdef SND_LIB_PORTAUDIO
+extern struct sound_procs portaudio_procs;
+#endif
+#ifdef SND_LIB_OPENAL
+extern struct sound_procs openal_procs;
+#endif
+#ifdef SND_LIB_SDL_MIXER
+extern struct sound_procs sdl_mixer_procs;
+#endif
+#ifdef SND_LIB_MINIAUDIO
+extern struct sound_procs miniaudio_procs;
+#endif
+#ifdef SND_LIB_FMOD
+extern struct sound_procs fmod_procs;
+#endif
+#ifdef SND_LIB_SOUND_ESCCODES
+extern struct sound_procs esccodes_procs;
+#endif
+#ifdef SND_LIB_VISSOUND
+extern struct sound_procs vissound_procs;
+#endif
+#ifdef SND_LIB_WINDSOUND
+extern struct sound_procs windsound_procs;
+#endif
+extern struct sound_procs nosound_procs;
+
+/* The order of these array entries must match the
+ order of the enum soundlib_ids in sndprocs.h */
+
+static struct sound_choices {
+ struct sound_procs *sndprocs;
+} soundlib_choices[] = {
+ { (struct sound_procs *) 0 },
+#ifdef SND_LIB_QTSOUND
+ { &qtsound_procs },
+#endif
+#ifdef SND_LIB_PORTAUDIO
+ { &portaudio_procs },
+#endif
+#ifdef SND_LIB_OPENAL
+ { &openal_procs },
+#endif
+#ifdef SND_LIB_SDL_MIXER
+ { &sdl_mixer_procs },
+#endif
+#ifdef SND_LIB_MINIAUDIO
+ { &miniaudio_procs },
+#endif
+#ifdef SND_LIB_FMOD
+ { &fmod_procs },
+#endif
+#ifdef SND_LIB_SOUND_ESCCODES
+ { &esccodes_procs },
+#endif
+#ifdef SND_LIB_WINDSOUND
+ { &windsound_procs },
+#endif
+#ifdef SND_LIB_VISSOUND
+ { &vissound_procs },
+#endif
+ { &nosound_procs }, /* default, built-in */
+};
+
+void
+activate_chosen_soundlib(void)
+{
+ enum soundlib_ids idx = gc.chosen_soundlib;
+
+ if (idx <= soundlib_unassigned || idx > soundlib_nosound)
+ idx = soundlib_nosound;
+
+ if (ga.active_soundlib != soundlib_unassigned
+ || ga.active_soundlib != idx) {
+ if (soundprocs.sound_exit_nhsound)
+ (*soundprocs.sound_exit_nhsound)("assigning a new sound library");
+ ga.active_soundlib = soundlib_unassigned;
+ }
+ soundprocs = *soundlib_choices[idx].sndprocs;
+ if (soundprocs.sound_init_nhsound)
+ (*soundprocs.sound_init_nhsound)();
+ ga.active_soundlib = soundprocs.soundlib_id;
+}
+
+void
+assign_soundlib(int idx)
+{
+ if (idx <= soundlib_unassigned || idx > soundlib_nosound)
+ idx = soundlib_nosound;
+
+ if (ga.active_soundlib != soundlib_unassigned) {
+ if (soundprocs.sound_exit_nhsound)
+ (*soundprocs.sound_exit_nhsound)("assigning a new sound library");
+ ga.active_soundlib = soundlib_unassigned;
+ }
+ gc.chosen_soundlib = soundlib_choices[idx].sndprocs->soundlib_id;
+}
+
+#if 0
+static void
+choose_soundlib(const char *s)
+{
+ int i;
+ char *tmps = 0;
+
+ for (i = 1; soundlib_choices[i].sndprocs; i++) {
+ if (!strcmpi(s, soundlib_choices[i].sndprocs->soundname)) {
+ assign_soundlib(i);
+ return;
+ }
+ }
+ assign_soundlib((int) soundlib_nosound);
+
+ /* The code below here mimics that in windows.c error handling
+ for choosing Window type */
+
+ /* 50: arbitrary, no real soundlib names are anywhere near that long;
+ used to prevent potential raw_printf() overflow if user supplies a
+ very long string (on the order of 1200 chars) on the command line
+ (config file options can't get that big; they're truncated at 1023) */
+#define SOUNDLIB_NAME_MAXLEN 50
+ if (strlen(s) >= SOUNDLIB_NAME_MAXLEN) {
+ tmps = (char *) alloc(SOUNDLIB_NAME_MAXLEN);
+ (void) strncpy(tmps, s, SOUNDLIB_NAME_MAXLEN - 1);
+ tmps[SOUNDLIB_NAME_MAXLEN - 1] = '\0';
+ s = tmps;
+ }
+#undef SOUNDLIB_NAME_MAXLEN
+
+ if (!soundlib_choices[1].sndprocs) {
+ config_error_add(
+ "Soundlib type %s not recognized. The only choice is: %s",
+ s, soundlib_choices[0].sndprocs->soundname);
+ } else {
+ char buf[BUFSZ];
+ boolean first = TRUE;
+
+ buf[0] = '\0';
+ for (i = 0; soundlib_choices[i].sndprocs; i++) {
+ Sprintf(eos(buf), "%s%s",
+ first ? "" : ", ", soundlib_choices[i].sndprocs->soundname);
+ first = FALSE;
+ }
+ config_error_add("Soundlib type %s not recognized. Choices are: %s",
+ s, buf);
+ }
+ if (tmps)
+ free((genericptr_t) tmps) /*, tmps = 0*/ ;
+}
+#endif
+
+/* copy up to maxlen-1 characters; 'dest' must be able to hold maxlen;
+ treat comma as alternate end of 'src' */
+void
+get_soundlib_name(char *dest, int maxlen)
+{
+ int count, idx;
+ const char *src;
+
+ idx = ga.active_soundlib;
+ if (idx > soundlib_unassigned && idx <= soundlib_nosound) {
+ src = soundlib_choices[idx].sndprocs->soundname;
+ for (count = 1; count < maxlen; count++) {
+ if (*src == ',' || *src == '\0')
+ break; /*exit on \0 terminator*/
+ *dest++ = *src++;
+ }
+ }
+ *dest = '\0';
+}
+
+/*
+ * The default sound interface
+ *
+ * 3rd party sound_procs should be placed in ../sound/x
+ * and build procedures should reference them there.
+ */
+
+#if 0
+static void nosound_init_nhsound(void);
+static void nosound_exit_nhsound(const char *);
+static void nosound_suspend_nhsound(const char *);
+static void nosound_resume_nhsound(void);
+static void nosound_achievement(schar, schar, int32_t);
+static void nosound_soundeffect(int32_t, int32_t);
+static void nosound_play_usersound(char *, int32_t, int32_t);
+#endif
+
+struct sound_procs nosound_procs = {
+ SOUNDID(nosound),
+ 0L,
+ (void (*)(void)) 0, /* init_nhsound */
+ (void (*)(const char *)) 0, /* exit_nhsound */
+ (void (*)(schar, schar, int32_t)) 0, /* achievement */
+ (void (*)(char *, int32_t, int32_t)) 0, /* sound effect */
+ (void (*)(int32_t, char *, int32_t)) 0, /* hero_playnotes */
+ (void (*)(char *, int32_t, int32_t)) 0, /* play_usersound */
+};
+
+#if 0
+static void
+nosound_init_nhsound(void)
+{
+}
+
+static void
+nosound_exit_nhsound(const char *reason)
+{
+}
+
+static void
+nosound_achievement(schar ach1, schar ach2, int32_t repeat)
+{
+}
+
+static void
+nosound_soundeffect(int32_t seid, int volume)
+{
+}
+
+static void
+nosound_play_usersound(char *filename, int volume, int idx)
+{
+}
+#endif
+
/*sounds.c*/
WINCFLAGS=
WINSRC =
WINOBJ0 =
+SND_CFLAGS=
XTRASRC =
XTRAOBJ =
WINCFLAGS += -DQT_GRAPHICS
WINSRC += $(WINQTSRC)
WINOBJ0 += $(WINQTOBJ)
+SNDCFLAGS += -DSND_LIB_QTSOUND -DUSER_SOUNDS
XTRASRC += tile.c
XTRAOBJ += $(TARGETPFX)tile.o
#
endif #WANT_WIN_CURSES
CFLAGS+= $(WINCFLAGS) #WINCFLAGS set from multiw-2.370
+CFLAGS+= $(SNDCFLAGS) #SNDCFLAGS set from multiw-2.370
CFLAGS+= $(NHCFLAGS)
CCXXFLAGS+= $(WINCFLAGS) #WINCFLAGS set from multiw-2.370
+CCXXFLAGS+= $(SNDCFLAGS) #SNDCFLAGS set from multiw-2.370
CCXXFLAGS+= $(NHCFLAGS)
VARDATND =
endif #MAKEFILE_SRC
CFLAGS+= $(PKGCFLAGS) $(WINCFLAGS) #WINCFLAGS set from multiw-2.370
+CFLAGS+= $(SNDCFLAGS) #SNDCFLAGS set from multiw-2.370
CFLAGS+= $(NHCFLAGS)
CCXXFLAGS+= $(WINCFLAGS) #WINCFLAGS set from multiw-2.370
+CCXXFLAGS+= $(SNDCFLAGS) #SNDCFLAGS set from multiw-2.370
CCXXFLAGS+= $(NHCFLAGS)
VARDATND =
GAMEDIR = ../binary
+#
+#---------------------------------------------------------------
+# Do you want to include any sound libraries? If so leave the
+# appropriate compile macro below uncommented, or add others
+# that are available.
+#
+
+SOUNDLIBDEFS = -DWINDSOUND -DUSER_SOUNDS
+
#
#---------------------------------------------------------------
# Do you want debug information in the executable?
# MSWIN - window port files (win32)
# WCURSES - window port files (curses)
# WSHR - Tile support files
+# SNDSYS - sound suppport files for win32
# QT - QT window support files
INCL =../include
UTIL =../util
SRC =../src
SSYS =../sys/share
+SNDSYS =../sound/windsound
MSWSYS =../sys/windows
TTY =../win/tty
MSWIN =../win/win32
hack hacklib insight invent isaac64 light lock \
mail makemon mcastu mdlib mhitm mhitu minion mklev mkmap mkmaze mkobj mkroom \
mon mondata monmove monst mplayer mthrowu muse music \
- nhlobj nhlsel nhlua ntsound o_init objects objnam options \
+ nhlobj nhlsel nhlua windsound o_init objects objnam options \
pager pickup pline polyself potion pray priest quest questpgr \
random read rect region restore rip rnd role rumors \
safeproc save sfstruct shk shknam sit sounds sp_lev spell steal steed symbols sys \
teleport timeout topten track trap u_init uhitm utf8map vault version vision \
weapon were wield windmain windows windsys wizard worm worn write zap)
-CFLAGSW = $(CFLAGS) $(CFLAGSXTRA) $(COMMONDEF) $(DLBFLG) -DTILES -D_WINDOWS -DMSWIN_GRAPHICS -DSAFEPROCS -DNOTTYGRAPHICS
-CPPFLAGSW = $(CFLAGS) $(CPPFLAGSXTRA) $(COMMONDEF) $(DLBFLG) -DTILES -D_WINDOWS -DMSWIN_GRAPHICS -DSAFEPROCS -DNOTTYGRAPHICS
+CFLAGSW = $(CFLAGS) $(CFLAGSXTRA) $(COMMONDEF) $(DLBFLG) -DTILES -D_WINDOWS -DMSWIN_GRAPHICS -DSAFEPROCS -DNOTTYGRAPHICS $(SOUNDLIBDEFS)
+CPPFLAGSW = $(CFLAGS) $(CPPFLAGSXTRA) $(COMMONDEF) $(DLBFLG) -DTILES -D_WINDOWS -DMSWIN_GRAPHICS -DSAFEPROCS -DNOTTYGRAPHICS $(SOUNDLIBDEFS)
ONHW = $(O)nethackw
NHWONLY = $(addsuffix .o, mhaskyn mhdlg mhfont mhinput mhmain mhmap mhmenu \
$(ONHW)/%.o: $(SSYS)/%.c $(NHLUAH) | $(ONHW)
$(cc) $(CFLAGSW) $< -o$@
+$(ONHW)/%.o: $(SNDSYS)/%.c $(NHLUAH) | $(ONHW)
+ $(cc) $(CFLAGSW) $< -o$@
+
$(ONHW)/%.o: $(MSWSYS)/%.c $(NHLUAH) | $(ONHW)
$(cc) $(CFLAGSW) $< -o$@
#==========================================
# nethack
#==========================================
-CFLAGSNH = $(CFLAGSU) $(CFLAGSXTRA) -DNO_TILE_C -DSAFEPROCS -D_LIB -DWIN32CON
-CPPFLAGSNH = $(CFLAGSU) $(CPPFLAGSXTRA) -DNO_TILE_C -DSAFEPROCS -D_LIB -DWIN32CON
+CFLAGSNH = $(CFLAGSU) $(CFLAGSXTRA) -DNO_TILE_C -DSAFEPROCS -D_LIB -DWIN32CON $(SOUNDLIBDEFS)
+CPPFLAGSNH = $(CFLAGSU) $(CPPFLAGSXTRA) -DNO_TILE_C -DSAFEPROCS -D_LIB -DWIN32CON $(SOUNDLIBDEFS)
ONH = $(O)nethack
$(ONH)/%.o: $(SSYS)/%.c $(NHLUAH) | $(ONH)
$(cc) $(CFLAGSNH) $< -o$@
+$(ONH)/%.o: $(SNDSYS)/%.c $(NHLUAH) | $(ONH)
+ $(cc) $(CFLAGSNH) $< -o$@
+
$(ONH)/%.o: $(MSWSYS)/%.c $(NHLUAH) | $(ONH)
$(cc) $(CFLAGSNH) $< -o$@
$(ONHW)/%.d: $(SSYS)/%.c $(NHLUAH) | $(ONHW)
$(cce) $(CFLAGSW) $< -o$@
+$(ONHW)/%.d: $(SNDSYS)/%.c $(NHLUAH) | $(ONHW)
+ $(cce) $(CFLAGSW) $< -o$@
+
$(ONHW)/%.d: $(MSWSYS)/%.c $(NHLUAH) | $(ONHW)
$(cce) $(CFLAGSW) $< -o$@
$(ONH)/%.d: $(SSYS)/%.c $(NHLUAH) | $(ONH)
$(cce) $(CFLAGSNH) $< -o$@
+$(ONH)/%.d: $(SNDSYS)/%.c $(NHLUAH) | $(ONH)
+ $(cce) $(CFLAGSNH) $< -o$@
+
$(ONH)/%.d: $(MSWSYS)/%.c $(NHLUAH) | $(ONH)
$(cce) $(CFLAGSNH) $< -o$@
$(INCL)\timeout.h $(INCL)\tradstdc.h $(INCL)\trap.h \
$(INCL)\unixconf.h $(INCL)\vision.h $(INCL)\vmsconf.h \
$(INCL)\wintty.h $(INCL)\wincurs.h $(INCL)\winX.h \
- $(INCL)\winprocs.h $(INCL)\wintype.h $(INCL)\you.h \
+ $(INCL)\winprocs.h $(INCL)\sndprocs.h $(INCL)\wintype.h $(INCL)\you.h \
$(INCL)\youprop.h
# all .c that are part of the main NetHack program and are not operating- or
DLBOBJTTY = $(OTTY)dlb.o
REGEXTTY = $(OTTY)cppregex.o
LUAOBJTTY = $(OTTY)nhlua.o $(OTTY)nhlsel.o $(OTTY)nhlobj.o
-SOUNDTTY = $(OTTY)ntsound.o
+SOUNDTTY = $(OTTY)windsound.o
VVOBJTTY = $(OTTY)version.o
SOBJTTY = $(OTTY)windmain.o $(OTTY)windsys.o $(OTTY)win10.o \
DLBOBJGUI = $(OGUI)dlb.o
REGEXGUI = $(OGUI)cppregex.o
LUAOBJGUI = $(OGUI)nhlua.o $(OGUI)nhlsel.o $(OGUI)nhlobj.o
-SOUNDGUI = $(OGUI)ntsound.o
+SOUNDGUI = $(OGUI)windsound.o
VVOBJGUI = $(OGUI)version.o
SOBJGUI = $(OGUI)windmain.o $(OGUI)windsys.o $(OGUI)win10.o \
DLBOBJ_HOST = $(OTTY)dlb$(HOST).o
!ENDIF
+SOUNDLIBDEFS = -DSND_LIB_WINDSOUND -DUSER_SOUNDS
+
#==========================================
# Header file macros
#==========================================
$(INCL)\obj.h $(INCL)\engrave.h $(INCL)\you.h \
$(INCL)\attrib.h $(INCL)\monst.h $(INCL)\mextra.h \
$(INCL)\skills.h $(INCL)\timeout.h $(INCL)\trap.h \
- $(INCL)\flag.h $(INCL)\winprocs.h $(INCL)\sys.h
+ $(INCL)\flag.h $(INCL)\winprocs.h $(INCL)\sndprocs.h \
+ $(INCL)\sys.h
TILE_H = ..\win\share\tile.h
# Util and console builds
#==========================================
-CFLAGS = $(ctmpflags) $(INCLDIR) $(DLBDEF) -DSAFEPROCS
-CPPFLAGS = $(cpptmpflags) $(INCLDIR) $(DLBDEF) -DSAFEPROCS
+CFLAGS = $(ctmpflags) $(INCLDIR) $(DLBDEF) -DSAFEPROCS $(SOUNDLIBDEFS)
+CPPFLAGS = $(cpptmpflags) $(INCLDIR) $(DLBDEF) -DSAFEPROCS $(SOUNDLIBDEFS)
LFLAGS = $(lflags) $(conlibs) $(MACHINE)
#==========================================
{$(SRC)}.c{$(OBJUTIL)}.o:
$(Q)$(CC) $(CFLAGS) $(CROSSCOMPILE) $(CROSSCOMPILE_TARGET) -Fo$@ $<
+#==========================================
+# Rules for files in sound\wind
+#==========================================
+
+{..\sound\windsound}.c{$(OBJTTY)}.o:
+ $(Q)$(CC) $(CFLAGS) -I$(WSHR) $(TTYDEF) $(CROSSCOMPILE) $(CROSSCOMPILE_TARGET) -Fo$@ $<
+
+{..\sound\windsound}.c{$(OBJGUI)}.o:
+ $(Q)$(CC) $(CFLAGS) -I$(WSHR) $(GUIDEF) $(CROSSCOMPILE) $(CROSSCOMPILE_TARGET) -Fo$@ $<
+
#==========================================
# Rules for files in sys\share
#==========================================
$(OTTY)consoletty.o: $(MSWSYS)\consoletty.c $(WINDHDR) $(HACK_H) $(TILE_H)
$(OTTY)win10.o: $(MSWSYS)\win10.c $(WINDHDR) $(HACK_H)
$(OTTY)windsys.o: $(MSWSYS)\windsys.c $(WINDHDR) $(HACK_H)
-$(OTTY)ntsound.o: $(MSWSYS)\ntsound.c $(WINDHDR) $(HACK_H)
+$(OTTY)windsound.o: ..\sound\windsound\windsound.c $(HACK_H)
$(OTTY)windmain.o: $(MSWSYS)\windmain.c $(WINDHDR) $(HACK_H)
$(OTTY)safeproc.o: $(WSHR)\safeproc.c $(WINDHDR) $(HACK_H)
$(OGUI)consoletty.o: $(MSWSYS)\consoletty.c $(WINDHDR) $(HACK_H) $(TILE_H)
$(OGUI)win10.o: $(MSWSYS)\win10.c $(WINDHDR) $(HACK_H)
$(OGUI)windsys.o: $(MSWSYS)\windsys.c $(WINDHDR) $(HACK_H)
-$(OGUI)ntsound.o: $(MSWSYS)\ntsound.c $(WINDHDR) $(HACK_H)
+$(OGUI)windsound.o: ..\sound\windsound\windsound.c $(HACK_H)
$(OGUI)windmain.o: $(MSWSYS)\windmain.c $(WINDHDR) $(HACK_H)
$(OGUI)safeproc.o: $(WSHR)\safeproc.c $(WINDHDR) $(HACK_H)
# $(INCL)\obj.h $(INCL)\engrave.h $(INCL)\you.h \
# $(INCL)\attrib.h $(INCL)\monst.h $(INCL)\mextra.h \
# $(INCL)\skills.h $(INCL)\timeout.h $(INCL)\flag.h \
-# $(INCL)\winprocs.h $(INCL)\sys.h
+# $(INCL)\winprocs.h $(INCL)\sndprocs.h $(INCL)\sys.h
# touch $(HACK_H)
#
$(OTTY)pcmain.o: ..\sys\share\pcmain.c $(HACK_H) $(INCL)\dlb.h
# $(INCL)\obj.h $(INCL)\engrave.h $(INCL)\you.h \
# $(INCL)\attrib.h $(INCL)\monst.h $(INCL)\mextra.h \
# $(INCL)\skills.h $(INCL)\timeout.h $(INCL)\flag.h \
-# $(INCL)\winprocs.h $(INCL)\sys.h
+# $(INCL)\winprocs.h $(INCL)\sndprocs.h $(INCL)\sys.h
# touch $(HACK_H)
#
$(OGUI)pcmain.o: ..\sys\share\pcmain.c $(HACK_H) $(INCL)\dlb.h
windowtype = gc.chosen_windowtype;
}
choose_windows(windowtype);
+ assign_soundlib(soundlib_windsound);
u.uhp = 1; /* prevent RIP on early quits */
u.ux = 0; /* prevent flush_screen() */
// 'statuslines' option can be set in config file but not via 'O'
set_wc2_option_mod_status(WC2_STATUSLINES, set_gameview);
#endif
+#if defined(SND_LIB_QTSOUND) && !defined(QT_NO_SOUND)
+ /* assign_soundlib() just flags to NetHack which soundlib
+ * should be loaded by activate_chosen_soundlib() shortly.
+ * gc.chosen_soundlib is initialized to soundlib_nosound.
+ */
+ if (gc.chosen_soundlib == soundlib_nosound)
+ assign_soundlib(soundlib_qtsound);
+#endif
}
int NetHackQtBind::qt_kbhit()
#if 0
static void Qt_positionbar(char *) {}
#endif
+
+#if defined(SND_LIB_QTSOUND) && !defined(NO_QT_SOUND)
+void NetHackQtBind::qtsound_init_nhsound(void)
+{
+}
+
+void NetHackQtBind::qtsound_exit_nhsound(const char *reason UNUSED)
+{
+}
+
+void NetHackQtBind::qtsound_achievement(schar ach1 UNUSED, schar ach2 UNUSED, int32_t repeat UNUSED)
+{
+}
+
+void NetHackQtBind::qtsound_soundeffect(char *desc UNUSED, int32_t seid UNUSED, int32_t volume UNUSED)
+{
+}
+
+void NetHackQtBind::qtsound_hero_playnotes(int32_t instrument UNUSED, char *str UNUSED, int32_t volume UNUSED)
+{
+}
+#endif
+
+#if defined(USER_SOUNDS) && !defined(QT_NO_SOUND)
+QSoundEffect *effect = NULL;
+#endif
+
+void NetHackQtBind::qtsound_play_usersound(char *filename, int32_t volume, int32_t idx UNUSED)
+{
+#if defined(USER_SOUNDS) && !defined(QT_NO_SOUND)
+ if (!effect)
+ effect = new QSoundEffect(nethack_qt_::NetHackQtBind::mainWidget());
+ if (effect) {
+ effect->setLoopCount(1);
+ effect->setVolume((1.00f * volume) / 100.0f);
+ effect->setSource(QUrl::fromLocalFile(filename));
+ effect->play();
+ }
+#else
+ nhUse(filename);
+ nhUse(volume);
+#endif
+}
+
} // namespace nethack_qt_
struct window_procs Qt_procs = {
nethack_qt_::NetHackQtBind::qt_ctrl_nhwindow,
};
-#ifndef WIN32
-extern "C" void play_usersound(const char *, int);
-
-#if defined(USER_SOUNDS) && !defined(QT_NO_SOUND)
-QSoundEffect *effect = NULL;
-#endif
-
-/* called from core, sounds.c */
-void
-play_usersound(const char *filename, int volume)
-{
-#if defined(USER_SOUNDS) && !defined(QT_NO_SOUND)
- if (!effect)
- effect = new QSoundEffect(nethack_qt_::NetHackQtBind::mainWidget());
- if (effect) {
- effect->setLoopCount(1);
- effect->setVolume((1.00f * volume) / 100.0f);
- effect->setSource(QUrl::fromLocalFile(filename));
- effect->play();
- }
-#else
- nhUse(filename);
- nhUse(volume);
-#endif
-}
-#endif /*!WIN32*/
+#if defined(SND_LIB_QTSOUND) && !defined(QT_NO_SOUND)
+struct sound_procs qtsound_procs = {
+ SOUNDID(qtsound),
+ SNDCAP_USERSOUNDS,
+ nethack_qt_::NetHackQtBind::qtsound_init_nhsound,
+ nethack_qt_::NetHackQtBind::qtsound_exit_nhsound,
+ nethack_qt_::NetHackQtBind::qtsound_achievement,
+ nethack_qt_::NetHackQtBind::qtsound_soundeffect,
+ nethack_qt_::NetHackQtBind::qtsound_hero_playnotes,
+ nethack_qt_::NetHackQtBind::qtsound_play_usersound,
+};
+#endif /* SND_LIB_QTSOUND and !QT_NO_SOUND */
//qt_bind.cpp
public:
static void qt_Splash();
+
+ /* window interface */
+
static void qt_init_nhwindows(int* argc, char** argv);
static void qt_player_selection();
static void qt_askname();
static int qt_kbhit();
static void qt_update_inventory(int);
static win_request_info *qt_ctrl_nhwindow(winid, int, win_request_info *);
-
static QWidget *mainWidget() { return main; }
+#if defined(SND_LIB_QTSOUND) && !defined(QT_NO_SOUND)
+ /* sound interface */
+ static void qtsound_init_nhsound(void);
+ static void qtsound_exit_nhsound(const char *);
+ static void qtsound_achievement(schar, schar, int32_t);
+ static void qtsound_soundeffect(char *, int32_t, int32_t);
+ static void qtsound_hero_playnotes(int32_t instrument, char *str, int32_t volume);
+ static void qtsound_play_usersound(char *, int32_t, int32_t);
+#endif
private:
virtual bool notify(QObject *receiver, QEvent *event);