From: nhmall Date: Thu, 19 Jan 2023 23:51:42 +0000 (-0500) Subject: add an interface for sound libraries X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ea4a81901da631358014ab2f504511a2748b0f1d;p=nethack add an interface for sound libraries 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. --- diff --git a/include/config.h b/include/config.h index 922683612..d357fe0ba 100644 --- a/include/config.h +++ b/include/config.h @@ -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 diff --git a/include/decl.h b/include/decl.h index 1a8cff2bf..7a81872dc 100644 --- a/include/decl.h +++ b/include/decl.h @@ -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; diff --git a/include/extern.h b/include/extern.h index d32d22899..902cacc35 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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 ### */ diff --git a/include/hack.h b/include/hack.h index 7fe0d7990..bc86fc616 100644 --- a/include/hack.h +++ b/include/hack.h @@ -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" diff --git a/include/optlist.h b/include/optlist.h index c383afb06..11cf4a11a 100644 --- a/include/optlist.h +++ b/include/optlist.h @@ -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 index 000000000..e351342df --- /dev/null +++ b/include/sndprocs.h @@ -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 */ diff --git a/include/windconf.h b/include/windconf.h index 69a4a81f1..fb9781aa1 100644 --- a/include/windconf.h +++ b/include/windconf.h @@ -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' */ diff --git a/include/winprocs.h b/include/winprocs.h index 67d228d66..23239642c 100644 --- a/include/winprocs.h +++ b/include/winprocs.h @@ -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 index 000000000..47383b4d9 --- /dev/null +++ b/sound/qtsound/README.md @@ -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 index 000000000..15a4bdf8f --- /dev/null +++ b/sound/windsound/windsound.c @@ -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 + +/* + * 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 */ + diff --git a/src/allmain.c b/src/allmain.c index bd33de7a0..09e543bf7 100644 --- a/src/allmain.c +++ b/src/allmain.c @@ -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 */ diff --git a/src/decl.c b/src/decl.c index 25ad307cd..286cf054f 100644 --- a/src/decl.c +++ b/src/decl.c @@ -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 */ diff --git a/src/insight.c b/src/insight.c index 992006796..5d2c715f8 100644 --- a/src/insight.c +++ b/src/insight.c @@ -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: diff --git a/src/options.c b/src/options.c index 312395258..9245d48de 100644 --- a/src/options.c +++ b/src/options.c @@ -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, diff --git a/src/sounds.c b/src/sounds.c index 5221fec56..715be8dc6 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -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*/ diff --git a/sys/unix/hints/include/multiw-2.370 b/sys/unix/hints/include/multiw-2.370 index 9579608f5..3a06bbdd2 100644 --- a/sys/unix/hints/include/multiw-2.370 +++ b/sys/unix/hints/include/multiw-2.370 @@ -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 # diff --git a/sys/unix/hints/linux.370 b/sys/unix/hints/linux.370 index 69e9e8993..b80ffea6d 100755 --- a/sys/unix/hints/linux.370 +++ b/sys/unix/hints/linux.370 @@ -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 = diff --git a/sys/unix/hints/macOS.370 b/sys/unix/hints/macOS.370 index 99c0545df..39c588681 100755 --- a/sys/unix/hints/macOS.370 +++ b/sys/unix/hints/macOS.370 @@ -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 = diff --git a/sys/windows/Makefile.mingw32 b/sys/windows/Makefile.mingw32 index 27b8cd4c3..a85f31a00 100644 --- a/sys/windows/Makefile.mingw32 +++ b/sys/windows/Makefile.mingw32 @@ -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$@ diff --git a/sys/windows/Makefile.mingw32.depend b/sys/windows/Makefile.mingw32.depend index 9b6f94ed7..960df65f4 100644 --- a/sys/windows/Makefile.mingw32.depend +++ b/sys/windows/Makefile.mingw32.depend @@ -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$@ diff --git a/sys/windows/Makefile.nmake b/sys/windows/Makefile.nmake index 3484334e1..bd6fad192 100644 --- a/sys/windows/Makefile.nmake +++ b/sys/windows/Makefile.nmake @@ -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 diff --git a/sys/windows/windmain.c b/sys/windows/windmain.c index b92ec5164..b1e689d8d 100644 --- a/sys/windows/windmain.c +++ b/sys/windows/windmain.c @@ -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() */ diff --git a/win/Qt/qt_bind.cpp b/win/Qt/qt_bind.cpp index 482e85fba..f6a83c9d2 100644 --- a/win/Qt/qt_bind.cpp +++ b/win/Qt/qt_bind.cpp @@ -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 diff --git a/win/Qt/qt_bind.h b/win/Qt/qt_bind.h index 204483838..98bf252a1 100644 --- a/win/Qt/qt_bind.h +++ b/win/Qt/qt_bind.h @@ -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);