]> granicus.if.org Git - nethack/commitdiff
add an interface for sound libraries
authornhmall <nhmall@nethack.org>
Thu, 19 Jan 2023 23:51:42 +0000 (18:51 -0500)
committernhmall <nhmall@nethack.org>
Thu, 19 Jan 2023 23:51:42 +0000 (18:51 -0500)
Groundwork for a more versatile interface for using
sound libraries. A lot of sound libraries work across
multiple platforms.

The current NetHack sound stuff is quite limited.

Binaries can have a variety of window ports linked into
them, and it makes sense to have something similar for
sound.

This tries to set things up in a more soundlib-centric way,
rather than inserting things in a platform-centric way.

It establishes a new top-level directory sound (akin to win
for the window interface routines, or "window-port") where
sound-related additions and sndprocs and support files can be
added and used across platforms.

The default interface is nosound and the 'nosound' interface
is in src/sounds.c

The interface for 'windsound', which contains the same minimal
USER_SOUNDS support using built-in routines that has been in the
windows port for a long time is added to
sound/windsound/windsound.c.

For now, the sound interface support for 'qtsound' has been added
to the existing Qt files win/Qt/qt_bind.h and win/Qt/qt_bind.cpp,
and a note has been placed in sound/qtsound/README.md to avoid
confusion.

New header file added: include/sndprocs.h.

24 files changed:
include/config.h
include/decl.h
include/extern.h
include/hack.h
include/optlist.h
include/sndprocs.h [new file with mode: 0644]
include/windconf.h
include/winprocs.h
sound/qtsound/README.md [new file with mode: 0644]
sound/windsound/windsound.c [new file with mode: 0644]
src/allmain.c
src/decl.c
src/insight.c
src/options.c
src/sounds.c
sys/unix/hints/include/multiw-2.370
sys/unix/hints/linux.370
sys/unix/hints/macOS.370
sys/windows/Makefile.mingw32
sys/windows/Makefile.mingw32.depend
sys/windows/Makefile.nmake
sys/windows/windmain.c
win/Qt/qt_bind.cpp
win/Qt/qt_bind.h

index 9226836121aac8b131f7f2068f7877969cb3b6f1..d357fe0ba76f4c53cdde1d24983151f858d672e7 100644 (file)
@@ -99,9 +99,6 @@
 #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
index 1a8cff2bf3d26cee355753f030b252af5746a342..7a81872dcb5cb9688c21d1bd3a05f254c82ae39d 100644 (file)
@@ -743,6 +743,9 @@ struct instance_globals_a {
     /* 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
@@ -852,6 +855,9 @@ struct instance_globals_c {
     /* questpgr.c */
     char cvt_buf[CVT_BUF_SIZE];
 
+    /* sounds.c */
+    enum soundlib_ids chosen_soundlib;
+
     /* sp_lev.c */
     struct sp_coder *coder;
 
index d32d22899d781dc3716186e7302dd7db736ec0c0..902cacc354428118b7ab0d069683a508cb9e5e1f 100644 (file)
@@ -2600,6 +2600,9 @@ extern void play_usersound(const char *, int);
 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 ### */
 
index 7fe0d79906c22b1bbb4575e0e9beed32eaa74f54..bc86fc616853c9616f672a9f7bad36ac1acf35ca 100644 (file)
@@ -227,6 +227,7 @@ enum misc_arti_nums {
 #include "region.h"
 #include "trap.h"
 #include "display.h"
+#include "sndprocs.h"
 #include "decl.h"
 #include "timeout.h"
 
index c383afb0612ef4c93a3e20f5af713d475b51ca16..11cf4a11af05e83f78157b56f0052d2627ff0fcd 100644 (file)
@@ -540,6 +540,9 @@ static int optfn_##a(int, int, boolean, char *, char *);
     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,
diff --git a/include/sndprocs.h b/include/sndprocs.h
new file mode 100644 (file)
index 0000000..e351342
--- /dev/null
@@ -0,0 +1,180 @@
+/* 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 */
index 69a4a81f1e63cee8781da72837c542223436d8d3..fb9781aa1c7e7761ab928aa46bed860d31d4fb1a 100644 (file)
@@ -28,9 +28,6 @@
 /*#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' */
index 67d228d66bedd19edc5d0a9a9f4841a0f7cee5e2..23239642cfccbc9675a59c0001eda86a510771d3 100644 (file)
@@ -276,16 +276,6 @@ extern
 #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;
diff --git a/sound/qtsound/README.md b/sound/qtsound/README.md
new file mode 100644 (file)
index 0000000..47383b4
--- /dev/null
@@ -0,0 +1,3 @@
+19-Jan-2023
+The Qt sound interface is currently housed in win/Qt/qt_bind.h and win/Qt/qt_bind.cpp.
+
diff --git a/sound/windsound/windsound.c b/sound/windsound/windsound.c
new file mode 100644 (file)
index 0000000..15a4bdf
--- /dev/null
@@ -0,0 +1,71 @@
+/* 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 */
+
index bd33de7a0ddae5c7dd0e4c63cef48e274d53a39c..09e543bf7ef002b9bee1f2f72163d809bb199b14 100644 (file)
@@ -58,6 +58,8 @@ moveloop_preamble(boolean resuming)
         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 */
index 25ad307cde4c0ddd8b652cef7819d3df5130dd10..286cf054fc97790b0e442be153c49d28a2d25dc9 100644 (file)
@@ -206,6 +206,9 @@ const struct instance_globals_a g_init_a = {
     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*/
@@ -284,6 +287,8 @@ const struct instance_globals_c g_init_c = {
     FALSE, /* class_filter */
     /* questpgr.c */
     UNDEFINED_VALUES, /* cvt_buf */
+    /* sounds.c */
+    soundlib_nosound, /* chosen_soundlib */
     UNDEFINED_PTR, /* coder */
     /* uhitm.c */
     NON_PM, /* corpsenm_digested */
index 992006796eec28f48f7796f15273fe3960beb709..5d2c715f8086b8802febbe13e87e9c8613f5d2dc 100644 (file)
@@ -2309,6 +2309,7 @@ void
 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
@@ -2325,8 +2326,21 @@ record_achievement(schar achidx)
        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:
index 312395258932b314663c7a1e08d8645f5301742b..9245d48dee8da8ebf033167433fb29fdee0c7a49 100644 (file)
@@ -3399,6 +3399,43 @@ optfn_scroll_margin(
     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,
index 5221fec5678b26a9867d667ac76adc7ca38e5083..715be8dc602aa265ac05c7d67ec2013ec3c896b7 100644 (file)
@@ -1502,37 +1502,27 @@ sound_matches_message(const char* msg)
 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
@@ -1551,7 +1541,236 @@ release_sound_mappings(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*/
index 9579608f5b1efcc8454549a057e1db261b439cea..3a06bbdd2cf30430ae72074132331bc38e46c866 100644 (file)
@@ -78,6 +78,7 @@ endif
 WINCFLAGS=
 WINSRC =
 WINOBJ0 =
+SND_CFLAGS=
 XTRASRC =
 XTRAOBJ =
 
@@ -144,6 +145,7 @@ ifdef WANT_WIN_QT
 WINCFLAGS += -DQT_GRAPHICS
 WINSRC += $(WINQTSRC)
 WINOBJ0 += $(WINQTOBJ)
+SNDCFLAGS += -DSND_LIB_QTSOUND -DUSER_SOUNDS
 XTRASRC += tile.c
 XTRAOBJ += $(TARGETPFX)tile.o
 #
index 69e9e89932889e2506b252fe66f75004d5883214..b80ffea6d6151ba4c6fdf742dc272dfdd2b8bdc1 100755 (executable)
@@ -114,9 +114,11 @@ endif   #HAVE_NCURSESW
 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 =
index 99c0545dfded4e8a3e0d30f0947b8a4019516b37..39c5886819166202a32fb9af4a4f5cf11b375876 100755 (executable)
@@ -156,9 +156,11 @@ endif   #CURSES_UNIODE=sys
 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 =
index 27b8cd4c3964e74723249f6a93651c2bb779f03d..a85f31a002d6b5ca6e5e9c58d2df353a56d8bd5b 100644 (file)
@@ -37,6 +37,15 @@ default: install
 
 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?
@@ -223,6 +232,7 @@ NHV=$(subst ",,$(NHV1))
 # 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
@@ -231,6 +241,7 @@ DOC     =../doc
 UTIL    =../util
 SRC     =../src
 SSYS    =../sys/share
+SNDSYS  =../sound/windsound
 MSWSYS  =../sys/windows
 TTY     =../win/tty
 MSWIN   =../win/win32
@@ -741,15 +752,15 @@ COREOBJS = $(addsuffix .o, allmain alloc apply artifact attrib ball bones botl c
           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 \
@@ -786,6 +797,9 @@ $(ONHW)/cppregex.o: $(SSYS)/cppregex.cpp $(NHLUAH) | $(ONHW)
 $(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$@
 
@@ -814,8 +828,8 @@ CLEAN_FILE += $(NHWTARGETS) $(NHWOBJS) $(NHWRES) $(BMPS)
 #==========================================
 # 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
 
@@ -855,6 +869,9 @@ $(ONH)/cppregex.o: $(SSYS)/cppregex.cpp $(NHLUAH) | $(ONH)
 $(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$@
 
index 9b6f94ed71d52a7b07a02b72cb8358e328e03976..960df65f438b533e0e1e5af6929f39962eb65ae6 100644 (file)
@@ -66,6 +66,9 @@ $(ONHW)/cppregex.d: $(SSYS)/cppregex.cpp $(NHLUAH) | $(ONHW)
 $(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$@
 
@@ -84,6 +87,9 @@ $(ONH)/cppregex.d: $(SSYS)/cppregex.cpp $(NHLUAH) | $(ONH)
 $(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$@
 
index 3484334e1bead954ced1a2d6bf459337790ae26f..bd6fad19269c7abf75738f0a0fda3e9f5cca2d7a 100644 (file)
@@ -443,7 +443,7 @@ HACKINCL = $(INCL)\align.h $(INCL)\artifact.h $(INCL)\artilist.h \
        $(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
@@ -523,7 +523,7 @@ MDLIBTTY  = $(OTTY)mdlib.o
 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 \
@@ -588,7 +588,7 @@ MDLIBGUI  = $(OGUI)mdlib.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 \
@@ -650,6 +650,8 @@ OPTIONS_FILE = $(DAT)\options
 DLBOBJ_HOST = $(OTTY)dlb$(HOST).o
 !ENDIF
 
+SOUNDLIBDEFS = -DSND_LIB_WINDSOUND -DUSER_SOUNDS
+
 #==========================================
 # Header file macros
 #==========================================
@@ -675,7 +677,8 @@ HACK_H = $(INCL)\hack.h $(CONFIG_H) $(INCL)\lint.h $(INCL)\align.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)\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
 
@@ -898,8 +901,8 @@ INCLDIR= /I..\include /I..\sys\windows $(LUAINCL)
 # 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)
 
 #==========================================
@@ -942,6 +945,16 @@ DLB =
 {$(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
 #==========================================
@@ -1735,14 +1748,14 @@ $(OLUA)lapi.o: $(LUASRC)\lapi.c
 $(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)
 
@@ -2046,7 +2059,7 @@ MOCPATH = moc.exe
 #              $(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
@@ -2465,7 +2478,7 @@ MOCPATH = moc.exe
 #              $(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
index b92ec51640eced45d1dfce3c452c95b07fa4a321..b1e689d8da68dfb1fe267475b74530cc6c36cb0d 100644 (file)
@@ -590,6 +590,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
             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() */
index 482e85fba28d2a5cb76f6dd7f540dc56e5a37f52..f6a83c9d249825d3cd56c2f71bc74df938bcd0c6 100644 (file)
@@ -204,6 +204,14 @@ void NetHackQtBind::qt_init_nhwindows(int *argc, char **argv)
     // '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()
@@ -1030,6 +1038,50 @@ boolean NetHackQtBind::msgs_initd = false;
 #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 = {
@@ -1117,31 +1169,17 @@ 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
index 2044838387d5e35e993445ed4ea094160f274c48..98bf252a1ae18abc74705dc86909584dcbe32734 100644 (file)
@@ -36,6 +36,9 @@ private:
 
 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();
@@ -90,8 +93,16 @@ public:
        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);